Download presentation
Presentation is loading. Please wait.
1
LoD in AspectJ Karl Lieberherr
2
Checking LoD in AspectJ
Show the idea, not the details. How can we precisely express it in a programming language?
3
An adaptive aspect: Law of Demeter Checker (Object Form)
aspect Check { … after(): MethodCallSite{ // call (* *(..)); // check whether // thisJoinPoint.getTarget() // is a preferred supplier // object }
4
How can we capture all calls?
pointcut MethodCallSite(): scope() && call(* *(..)); BUT: how to avoid checking calls in Java libraries?
5
Avoiding the Java libraries
pointcut IgnoreCalls(): call(* java..*.*(..)); pointcut MethodCallSite(): scope() && call(* *(..)) && !IgnoreCalls();
7
AspectJ from PARC J DEMETER DHMHTRA AJ (Demeter AspectJ) EMETERJ
8
Observation Many AspectJ programs are adaptive (designed for a family of Java programs) Context: Java program or its execution tree (lexical joinpoints or dynamic join points) Features enabling adaptiveness: *, .. (wildcards) cflow, + (graph transitivity) this(s), target(s), args(a), call (…), … inheritance as wild card pc(Object s, Object t): this(s) && target(t) && call(… f …)
9
AspectJ crosscutting used
in Law of Demeter checker Dynamic call graph cflow(…) target(Object) Connected join points Isolated join points
10
Aspects and lexical join points
Going to the roots of the Northeastern branch of AOP: Law of Demeter. Closing the circle: Write an ultimately adaptive program in AspectJ: Works with all Java programs Checks the object-form of the Law of Demeter: “talk only to your friends”
11
Instrumentation of Java programs with Aspects
Aspect framework Aspect Diagram Supplier ImmediatePartBin TargetBinStack ArgumentBin Checker LocallyConstructedBin uses pointcuts ReturnValueBin Requirements: Statistics GlobalPreferredBin Good Separation of Concerns in Law of Demeter Checker
12
Explanation The *bin* aspects collect potential preferred supplier objects that represent good coupling in the context of a method body. The Checker aspect checks each method call whether the receiver is a preferred supplier object. The Statistics aspect counts events generated by the Checker aspect.
13
AspectJ code In AOSD 2003 paper with David Lorenz and Pengcheng Wu
AspectJ works well. Program uses most adaptive ingredients of AspectJ: *, cflow, this, target, etc.
14
package lawOfDemeter;
public abstract class Any { public pointcut scope(): !within(lawOfDemeter..*) && !cflow(withincode(* lawOfDemeter..*(..))); public pointcut StaticInitialization(): scope() && staticinitialization(*); public pointcut MethodCallSite(): scope() && call(* *(..)); public pointcut ConstructorCall(): scope() && call(*.new (..)); public pointcut MethodExecution(): scope() && execution(* *(..)); public pointcut ConstructorExecution(): scope() && execution(*.new (..)); public pointcut Execution(): ConstructorExecution() || MethodExecution(); public pointcut MethodCall(Object thiz, Object target): MethodCallSite() && this(thiz) && target(target);
15
Class Any continued public pointcut SelfCall(Object thiz,
Object target): MethodCall(thiz, target) && if(thiz == target); public pointcut StaticCall(): scope() && call(static * *(..)); public pointcut Set(Object value): scope() && set(* *.*) && args(value); public pointcut Initialization(): scope() && initialization(*.new(..)); }
16
package lawOfDemeter.objectform;
import java.util.*; abstract class ObjectSupplier { protected boolean containsValue(Object supplier){ return targets.containsValue(supplier); } protected void add(Object key,Object value){ targets.put(key,value); protected void addValue(Object supplier) { add(supplier,supplier); protected void addAll(Object[] suppliers) { for(int i=0; i< suppliers.length; i++) addValue(suppliers[i]); private IdentityHashMap targets = new IdentityHashMap();
17
package lawOfDemeter.objectform;
public aspect Pertarget extends ObjectSupplier pertarget(Any.Initialization()) { before(Object value): Any.Set(value) { add(fieldIdentity(thisJoinPointStaticPart), value); } public boolean contains(Object target) { return super.containsValue(target) || Percflow.aspectOf().containsValue(target); private String fieldIdentity(JoinPoint.StaticPart sp) { … } private static HashMap fieldNames = new HashMap();
18
package lawOfDemeter.objectform;
aspect Check { private pointcut IgnoreCalls(): call(* java..*.*(..)); private pointcut IgnoreTargets(): get(static * java..*.*); after() returning(Object o):IgnoreTargets() { ignoredTargets.put(o,o); } after(Object thiz,Object target): Any.MethodCall(thiz, target) && !IgnoreCalls() { if (!ignoredTargets.containsKey(target) && !Pertarget.aspectOf(thiz).contains(target)) System.out.println( " !! LoD Object Violation !! " + thisJoinPointStaticPart/*[*/ + at(thisJoinPointStaticPart)/*]*/); private IdentityHashMap ignoredTargets = new IdentityHashMap();}
19
package lawOfDemeter.objectform;
aspect Percflow extends ObjectSupplier percflow(Any.Execution() || Any.Initialization()){ before(): Any.Execution() { addValue(thisJoinPoint.getThis()); addAll(thisJoinPoint.getArgs()); } after() returning (Object result): Any.SelfCall(Object,Object) || Any.StaticCall() || Any.ConstructorCall() { addValue(result);
20
Conclusions Aspects and adaptiveness must work closely together to achieve best results. Crosscutting is closely linked to adaptiveness. AP is a specialization of AOP and AOP is a specialization of AP. It goes both ways. AspectJ is a really useful language but we are a little concerned about how difficult it was to debug the Law of Demeter checkers.
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.