Aspect-Oriented Software Design Karl Lieberherr Theo Skotiniotis AOSD 1 AOSD and AOP • Emerging • Addresses crosscutting concerns • Current technologies: ad-hoc, decrease the benefits of encapsulation, modularization and ease of extensibilty. AOSD 2 Crosscutting Concerns • Concern = system property – Functional property – Constraint of system behavior • Constraints on a system refer to conditions that need to be satisfied when the system runs – Logging of read/write operations on all pumps – Authorization – Synchronization AOSD 3 Crosscutting Concerns • Are those system concerns which take effect over multiple artifacts within a design or program. • Artifact = any tangible object at any level of the software development process. AOSD 4 Aspects • In the context of AOSD, are a new modularity mechanism with which crosscutting concerns can be expressed. • An aspect holds all the information (operations and data) that a crosscutting concern uses/manipulates. • An aspect is bound to a context. AOSD 5 Aspects • Better modularity. Crosscutting concerns are now localized in an aspect. • Easier understanding. The information about a concern is localized. It is less scattered and tangled with other information. • Easier modifiability. Look at one aspect and its binding. AOSD 6 Binding Model • Separating the operations and data which a crosscutting concern deals with is the first step: aspectual data type. • One needs to define at which points within your design implementation an aspect gets to execute its code. Binding of an aspect. • A join point model provides the glue between aspectual data types and the binding of them. AOSD 7 Join Point Models • We want to specify conditions under which methods should execute. Those methods that execute conditionally when an event happens are called advice. • However, there are AOP languages that unify methods and advice. Example: Fred: Doug Orleans, NEU PhD student. AOSD 8 Join Point Models • In this context: dynamic join points, e.g. call join points. • Need a mechanism to specify sets of join points. Use some primitives and the set operations. AOSD 9 OOSD and AOSD • Two common concepts: – Separation of concerns – Modularization • But OOSD does not handle well the crosscutting concerns. AOSD 10 Note on AspectJ • Binding of an aspect (which expresses the details of the crosscutting) is a part of an aspect itself. AOSD 11 HashMap targets = new HashMap(); Looks familiar? aspect Supplier { void add (Object target, String i) {} void around (Object target, String i): call(void Supplier.add(Object, String)) && args(target, i) { targets.put(target,i); }… AOSD 12 Development Aspects • LoD checker! • Tracing, Logging, and Profiling • Pre- and Post-Conditions AOSD 13 Development Aspects aspect SimpleTracing { pointcut tracedCall(): call(void FigureElement.draw(GraphicsContext)); before(): tracedCall() { System.out.println( "Entering: " + thisJoinPoint); } } AOSD 14 Development Aspects When debugging, programmers often invest considerable effort in figuring out a good set of trace points to use when looking for a particular kind of problem. When debugging is complete or appears to be complete it is frustrating to have to lose that investment by deleting trace statements from the code. The alternative of just commenting them out makes the code look bad, and can cause trace statements for one kind of debugging to get confused with trace statements for another kind of debugging. AOSD 15 Very Specific Profiling aspect SetsInRotateCounting { int rotateCount = 0; int setCount = 0; before(): call(void Line.rotate(double)) { rotateCount++; } before(): call(void Point.set*(int)) && cflow(call(void Line.rotate(double))) { setCount++; } } Shape: from LR to PS* We don’t care what is in between. AOSD 16 Pre- and Post- Conditions aspect PointBoundsChecking { pointcut setX(int x): (call(void FigureElement.setXY(int, int)) && args(x, *)) || (call(void Point.setX(int)) && args(x)); pointcut setY(int y): (call(void FigureElement.setXY(int, int)) && args(*, y)) || (call(void Point.setY(int)) && args(y)); before(int x): setX(x) { if ( x < MIN_X || x > MAX_X ) throw new IllegalArgumentException("x is out of bounds."); } before(int y): setY(y) { if ( y < MIN_Y || y > MAX_Y ) throw new AOSD 17 IllegalArgumentException("y is out of bounds."); } Advice Precedence in AspectJ • Multiple pieces of advice may apply to the same join point. In such cases, the resolution order of the advice is based on advice precedence • If the two pieces of advice are defined in – different aspects, then there are three cases: • dominates, subaspect, undefined. – in the same aspect, then there are two cases: • Textual order: After-reverse and other-normal. AOSD 18 Different aspect rules • If aspect A is declared such that it dominates aspect B, then all advice defined in A has precedence over all advice defined in B. • Otherwise, if aspect A is a subaspect of aspect B, then all advice defined in A has precedence over all advice defined in B. So, unless otherwise specified with a dominates keyword, advice in a subaspect dominates advice in a superaspect. • Otherwise, if two pieces of advice are defined in two different aspects, it is undefined which one has precedence. AOSD 19 Same aspect rules • If the two pieces of advice are defined in the same aspect, then there are two cases: – If either are after advice, then the one that appears later in the aspect has precedence over the one that appears earlier. – Otherwise, then the one that appears earlier in the aspect has precedence over the one that appears later. AOSD 20 Circularity These rules can lead to circularity, such as aspect A { before(): execution(void main(String[] args)) {} after(): execution(void main(String[] args)) {} before(): execution(void main(String[] args)) {} } such circularities will result in errors signalled by the compiler. AOSD 21 Effects of precedence • At a particular join point, advice is ordered by precedence. – A piece of around advice controls whether advice of lower precedence will run by calling proceed. The call to proceed will run the advice with next precedence, or the computation under the join point if there is no further advice. AOSD 22 Effects of precedence – A piece of before advice can prevent advice of lower precedence from running by throwing an exception. If it returns normally, however, then the advice of the next precedence, or the computation under the join point if there is no further advice, will run. AOSD 23 Effects of precedence – Running after returning advice will run the advice of next precedence, or the computation under the join point if there is no further advice. Then, if that computation returned normally, the body of the advice will run. AOSD 24 Effects of precedence – Running after throwing advice will run the advice of next precedence, or the computation under the join point if there is no further advice. Then, if that computation threw an exception of an appropriate type, the body of the advice will run. AOSD 25 Effects of precedence – Running after advice will run the advice of next precedence, or the computation under the join point if there is no further advice. Then the body of the advice will run. AOSD 26