Detecting aspect-specific code smells using Ekeko for AspectJ


Published on

Presentation about work in progress at the 11th edition of the BElgian-NEtherlands software eVOLution symposium (BENEVOL 2012).

  • Be the first to comment

  • Be the first to like this

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Detecting aspect-specific code smells using Ekeko for AspectJ

  1. 1. Detecting aspect-specific code smells using Ekeko for AspectJ Coen De Roover Johan FabrySoftware Languages Lab Pleiad Lab - DCCVrije Universiteit Brussel University of Chile
  2. 2. Aspect-oriented programming... modularizes cross-cutting concerns aspect 1 aspect 3 aspect 2 Aspect Weaver core application functionality woven output code pointcut specifies program points at which the aspect intervenes advice behavior to invoke at points selected by a pointcut
  3. 3. Code smells in aspect-oriented programs 2.3 Detecting Lazy Aspects This bad smell, initially defined in [M.P. Monteiro, 2005], occurs if an aspect has... symptoms of suboptimal implementation few responsibilities, and its elimination could result in benefits during mainte- nance activities. Sometimes, this responsibility reduction is related to previous refactoring or to unexpected changes in requirements (planned changes that did not occur, for instance).e.g., [Piveta07] Definition 03 Consider an aspect α. The crosscutting members of α are the collection of all advice, pointcuts, declare constructions and inter type declara- large aspects tions directly defined in α. Consider η as the number of crosscutting members of α. An aspect is considered a lazy one whenever the predicate η == 0 holds. The advices with anonymous pointcuts function could be defined as: f (α) = η == 0 To detect lazy aspects, a similar approach to the Large Aspect bad smell is lazy aspects taken. The LazyAspectASTVisitor creates bad smell events whenever an aspect without crosscutting members is found (see Listing 4). 1 public c l a s s LazyAspectASTVisitor extends BadSmellsASTVisitor { 2 public void e n d V i s i t ( T y p e D e c l a r a t i o n node ) { 3 super . e n d V i s i t ( node ) ; 4 i f ( ( ( A j T y p e D e c l a r a t i o n ) node ) . i s A s p e c t ( ) ) 5 i f ( getNumberOfMembers ( ) == 0 ) { 6 BadSmellsEvent e v e n t = new BadSmellsEvent ( ) ; 7 e v e n t . setType ( ” Lazy Aspect ” ) ; 8 ... 9 } 10 } 11 } but: Listing 4: AST visitor responsible for the detection of the Lazy Aspect bad smell extrapolated from OO smells rather informal specification
  4. 4. Assumption-based code smells... aspect/aspect aspect/base assumptions Aspect–Aspect Coordination Inter-Aspect Inter-Advice Inter-Process Deployment ITDs Super-Aspect Wormhole Advice Execution Structure Sequence Sub-Aspect Precedence Aspect Structure [Zschaler11] Assumptions Aspect–Base Coordination Synchronisation Architecture Coding Patterns Managed Monitor Communication Data Code Code by Context Sharing Advised Called Figure 1: Top-level aspect assumption categories identified assumption: Examples. The Glassbox aspect JxtaSocketMonitor assumes to have precedence over its super-aspect AbstractMonitor. thread t. Conversely, let ef (a, t) indicate that ad executing in thread t.3 Then, we might formal This is the default semantics of AspectJ. However, an assumption that advice a1 ∈ A assumes previous executio remains that this is not changed by any declare precedence behaviour A1 introduces or to introduce base behaviour that A1 ψ aspect 1 .G¬es (a1 , t )U∃t2 .ef (a2 , t2 ).4 among other things, this A ⇒ ∀tassumes that 1the Observer-Pattern can then modify. If A1 requires Aanywhere in the code. clauses 2 to be deployed because it uses aspect is only woven into the system for data updates (and not, for as Examples. For example, MobileMedia has an inter-type definitions (ITDs) defined in A2 , this may be influenced by declare prece- creation). Discussion. Precedence is classified with example, for data MusicAndVideo, which is deployed when a the other ITD assumptionsdence clauses directly referencing a set of aspects, but also quite below. Beyond the general case, we have identified a specifictwo pieces o tures are selected. This provides variation,tool support: warn when advice precedence DAG is not completely connected indirectly. For example, AbstractMonitor defines an interface defines a marker interface that isother reacting to A special case is when an aspect A1 has been introduced to re- between two other aspects aspect A3 where one aspect forming some setup code, the then used by solve a feature interactionLowerPrecedence. AnyA2 and implementing this aspect in a declare parents clause. In thisClearly, ther another interface items installed by the first advice. case, the (or more). In this case, will automatically receive lower precedence thansecond aspect assumes deployment of the first, so that the semantics there will be an inclusion assumption AbstractMo- here that the first advice has run before the seco warn about aspects that override implicit precedence ψA1 ⇒ d(A2 ) ∧ d(A3 ). nitor. Discussion. If broken, this type of assumptio of the marker interface are operationalised. However, AspectJ’s declare precedence clause can also pected behaviour or errors at runtime. For ex Examples. MobileMedia uses aspects to configure different prod- For example, Glassbox defines interface MonitoredType. be used to make precedence assumptions explicit. Then, if they are bileMedia case, if the setup code were not to be ucts of a product line. For example, deploying PhotoAndMu- has been done for the a top-level interface, but is documented touser, bec continuously check assumptions made explicit in code violated, ajc will produce an error. This sicAspect implies features for both photo and music manage- This is defined as feature would not be accessible to the “start [the] agent when loading any such type. Should be added to any
  5. 5. Eclipse plugin causally connectedEkeko applications program querying program transformation corpus miningmeta-programming libraryfor Clojure’s core.logic logic meta-programming specify code characteristics declaratively, leave search to logic engine applicative meta-programming script queries over workspace manipulate workspace
  6. 6. selectprograms to query start REPLlaunch query browse results
  7. 7. Applicative logic meta-programming... core.logic in a nutshell embedding of logic programming port of Kanren [Friedman, Kiselyov, Bird] to Clojure by David Nolen no operational impurities (e.g., cut), yet high performance features tabling, extensible constraints, extensible unification protocols core.logic logic goals functions that take a substitution either return a possibly infinite stream of substitutions (success) or nil (failure) constructors: always success: s#, always failure: f#, success if arguments unify: == composing goals introduces lexically scoped variables chains goals together abstraction (fresh  [?x  ?y] (defn  g  [?y] (fresh  [?x  ?y]      (conde      (fresh  []      (==  ?x  ?y)        [(==  ?x  1)  ..]          (==  ?y  5)))        (==  ?x  5)))        [(==  ?x  5)  ..]))   (fresh  [?x] interleaves substitutions from goals    (g  ?x))  
  8. 8. Applicative logic meta-programming... using relations provided by the Ekeko library syntactic concern characteristics { structural control flow data flow JDT DOM derived from { JDT Model control flow graph SOOT data flow analyses AspectJ weaver(defn aspect-declaredsuper+ "Relation between an aspect and one of its declared ancestors.” [?aspect ?ancestor] (conde [(aspect-declaredsuper ?aspect ?ancestor) ] [(fresh [?super] (aspect-declaredsuper ?aspect ?super) (aspect-declaredsuper+ ?super ?ancestor))]))
  9. 9. Example queries... using Ekeko for AspectJ(ekeko* [?advice1 ?advice2 ?shadow] two advices operating on the (advice-shadow ?advice1 ?shadow) same join point shadow (advice-shadow ?advice2 ?shadow) (!= ?advice1 ?advice2))(ekeko* [?declaringaspect ?intertype ?member ?targettype] (aspect-intertype ?declaringaspect ?intertype) (intertype-member-type ?intertype ?member ?targettype) (aspect ?targettype)) aspect adding a member to another aspect through an intertype declaration advice operating on a join point shadow stemming from an intertype declaration(ekeko* [?advice ?shadow ?intertype] (intertype-element ?intertype ?shadow) (advice-shadow ?advice ?shadow))
  10. 10. Code smells... related to precedence graph(defn incomplete-precedence precedence DAG is not fully connected [?first ?second] (all (aspect ?first) an aspect may assume default (aspect ?second) precedence is never changed (!= ?first ?second) (fails (aspect-dominates-aspect ?first ?second)) (fails (aspect-dominates-aspect ?second ?first)))) (defn overriden-implicit-precedence aspect overrides implicit precedence [?first ?second] (all (aspect-dominates-aspect ?second ?first) (aspect-dominates-aspect-implicitly+ ?first ?second))) inverse assumption made explicit
  11. 11. Code smells... related to aspect hierarchy(defn pointcut concretizing pointcut-concretizedby abstract pointcut from [?abstractpc ?concretepc] super aspect (fresh [?abaspect ?concaspect ?name] (aspect-super+ ?concaspect ?abaspect) (aspect-pointcutdefinition ?abaspect ?abstractpc) (aspect-pointcutdefinition ?concaspect ?concretepc) (pointcut-name ?abstractpc ?name) (pointcut-name ?concretepc ?name))) aspect introducing pointcut assumes it is not already defined unless behavior of super does not need to be maintained(defn abstractpointcut-concretized-reconcretized pointcut [?abpointcut ?concpointcut1 ?concpointcut2] concretized twice (all (pointcut-concretizedby ?abpointcut ?concpointcut1) (pointcut-concretizedby ?concpointcut1 ?concpointcut2)))
  12. 12. Code smells... related to intertype declarations (defn modifies-aspect [?modifier ?modified] (fresh [?advice ?shadow] (aspect-advice ?modifier ?advice) aspect modifies (advice-shadow ?advice ?shadow) another aspect (shadow-enclosingtypedeclaration ?shadow ?modified) (aspect ?modified)))(defn an intertype declaration introduces a method that is never called intertypemethod-unused [?itmethod] (fresh [?caller] (intertypemethod ?itmethod) (fails (soot-method-called-by-method ?itmethod ?caller)))))
  13. 13. Code smells... related to behavioral patternspublic aspect WormholeAspect { pointcut entry(int save): execution(* BaseClass.method1(int)) && args(save); pointcut exit() : execution(* BaseClass.method2()); int store; before(int savedarg) : entry (savedarg) { = savedarg; } before() : exit() { System.out.println("Wormholed value is: "+ store); }} assumes it is the wormholed value
  14. 14. (defnCode smells assigns-field [?unit ?field]... related to behavioral patterns (fresh [?lhs] (soot-unit-assign-leftop ?unit ?lhs) (soot-value :JInstanceFieldRef ?lhs) (equals ?field (.getField ?lhs)))) (defn brokenwormhole-entry-exit-field [?aspect ?entryadvice ?exitadvice ?field] (aspect-field ?aspect ?field) (aspect-advice ?aspect ?entryadvice) (aspect-advice ?aspect ?exitadvice) (fresh [?icfg] (soot-method-icfg ?entryadvice ?icfg) (qwal ?icfg ?entryadvice ?exitadvice [] (q=>*) (qcurrent [[?entryadvice ?unit]] regexp describing (assigns-field ?unit ?field)) path through the (q=>+) cfg of a broken wormhole (qcurrent [[?method ?unit]] (differs ?entryadvice ?method) (assigns-field ?unit ?field)) (q=>+) (qcurrent [[?exitadvice ?unit]] (reads-field ?unit ?field)))))
  15. 15. Conclusions logic-based specifications Ekeko provides actual tool support of smells related to implicit aspect assumptions moving from structurally to behaviorally characterizedOngoing work designing annotation library for making assumptions explicit continuously cross-check explicit and derived assumptions empirical study script Ekeko against AspectJ corpus [.aspectj]