CS 541 Meeting -*- Outline -*- * Overview of AOSD and AspectJ Main reference (esp. for examples): [Kiselev03] Ivan Kiselev. Aspect-Oriented Programming with AspectJ. Sams Publishing, 2003. A better book seems to be AspectJ in Action by Ramnivas Laddad (Manning), see chapters 1-2. See the syllabus and aosd.net for other references. ** What is Aspect-Oriented Software Developement? An evolutionary advance on OOP that allows multi-dimensional separation of concerns *** The problem, tangled code ------------------------------------------ THE PROBLEM CROSS-CUTTING CONCERNS AND TANGLING Some concerns cut across all modules: These have to be handled in many modules, resulting in tangled code ------------------------------------------ ... - performance (buffering, pooling, caching) - security (authentication, authorization) - reliability (logging, tracing) - correctness (assertion checking) Q: Other things like this? can also be functional concerns like navigation, billing, taxes ... draw picture e.g., every time call DriverManager.getConnection() want to get the connection from a pool of open connections. every time call FileOutputSteam.write, want to get buffer the output every time something significant happens, has to be logged Q: Why is it bad to handle this all over the code? it makes the code hard to change for that concern (tangling) imagine having to change the way logging is handled def: A *concern* is a property or quality attribute of a system. E.g., security, availablility, correctness, performance, ... Best to think of parts of these larger properties, i.e., aspects. def: Concerns X and Y are *modularly separated* when (a) X and Y are dealt with in a disjoint set of modules, M_X and M_Y (respectively), and (b) changing decisions in M_X does not affect concern Y, and changing M_Y does not affect concern X. *** Why don't standard (OO) techniques solve the problem? **** watching changes (e.g., logging, tracing, ...) ------------------------------------------ AVOIDING THE PROBLEMS (1) Observer pattern: Every type (Subject) that does logging instead adds: - code for managing listeners - method, named "notify" to call listener's "actionPerformed" method when something should be logged - code to call notify when logging should happen But: ------------------------------------------ Q: What problems would this cause? ... - Code to call "notify" is still in the subjects (tangled) - Code to register listeners is mixed in with other code (tangling), not separated. - Pay a run-time penalty for all calls to "notify", even if don't want to log Conclusion: what we need is automation of this. ------------------------------------------ WHAT'S NEEDED TO SUPPORT WATCHING CHANGES Want to: - avoid writing code in subjects to call notify (separate out decisions) - avoid writing code in observers to register listeners (separate out these decisions) - only pay at run-time when there are listeners ------------------------------------------ This leads to the ideas of... ------------------------------------------ JOIN POINTS In AspectJ, a *join point* is defined at every: - method call, constructor call - method/constructor body execution - initialization of an object - static initialization of a class - get of a field - set of a field - catch block handling an exception POINTCUTS In AspectJ, a *pointcut* is a set of join points. ------------------------------------------ It's easy to confuse these... Q: What's the difference between a join point and a pointcut? Simple join points, but not pointcuts, were found in CLOS (the MOP). ------------------------------------------ ADVICE In AspectJ, *advice* is code that is attached to a pointcut and can be run: - before - after each joinpoint in the pointcut. ------------------------------------------ There are variations, such as after-returning and after-throwing Advice like this was found in CLOS (the MOP). ------------------------------------------ EXAMPLE (Kiselev listing 7.6) public aspect RigidLogger { pointcut logPoint() : execution(* tags.*.*(..)); before() : logPoint() { LogSys.log(thisJoinPoint); } } ------------------------------------------ This is a recommended first step in learning AspectJ **** assisting at run-time (caching, buffering, pooling, authentication, ...) ------------------------------------------ AVOIDING THE PROBLEMS (2) Changing performance by caching (or buffering, pooling, etc.): Instead of using raw type's object, use a proxy for it that: - contains an object of the raw type - delegates to it for basic functions - does the necessary caching, etc. by intercepting calls But: ------------------------------------------ ... - Tedious to write all the delegation code - Runtime overhead (for indirection) on all calls to delegee, even those for which no intervention is required - If multiple concerns impact a single type, but you don't always want them (e.g., in a product family), then would also have to use the Decorator pattern ==> complexity of code - If multiple types of objects are affected by a signle concern, then the different proxy types spread this concern throughout the system, making it hard to change how that concern works (scattering) - If the objects already exist (e.g., in a persistent DB) can't force a proxy into existing references to them ------------------------------------------ WHAT'S NEEDED TO SUPPORT ASSISTANCE Want to: - avoid writing the delegation code, especially when just passing along calls - avoid runtime overhead for delegation when not needed - avoid the use of decorators to deal with layers of proxies - avoid spreading concerns across multiple proxy types - avoid the need to change existing references to point to proxies ------------------------------------------ This leads to the idea of... ------------------------------------------ AROUND ADVICE In AspectJ, *around advice* is advice that is run as follows: - it is called before a join point - it can decide to proceed (delegate) - when a proceed returns, the advice can perform more actions ------------------------------------------ ------------------------------------------ EXAMPLE (Kiselev, from listing 7.6) import java.sql.*; import java.util.*; public aspect ReadCache { public static Map cache = new Hashtable(); pointcut read(String user): call(Collection StoriesDb.retrieve(String)) && args(user); Collection around(String user) throws SQLException : read(user) { Collection res = (Collection)cache.get(user); if (null == res) { res = proceed(); cache.put(user, res); } return res; } } ------------------------------------------ Q: What if multiple pieces of around advice apply at the same join point? Choices include some sort of declaration or an arbitrary order (alphabetical) In AspectJ, you can use declare precdence to declare orders, otherwise based on textual order (arguments to compiler, and within aspects). So - the highest precedence, otherwise the first, wraps around (comes before, follows after) the lower precedence (or second) - ordering matters (sometimes) *** The promise ------------------------------------------ THE PROMISE OF AOSD Modular separation of concerns. Cross-cutting concerns confined to single modules. Systematic way to deal with non-functional requirements in design. Thus systems are: - easier to understand, - easier to change, adapt, evolve Can observe or change behavior without editing existing code. ------------------------------------------ Q: What are the benefits of these benefits? Frees programs from the "tyranny of the dominant decomposition" (i.e., don't have to only cater to data abstraction, information hiding). Allows construction of larger, more complex systems. *** Typical Use ------------------------------------------ TYPICAL USES OF AOSD Uses of AOSD: - modularizing large programs (new code behaves as the old code) e.g., exception handling in telecom code - modularizing to add new behavior (superimpose new behavior on old code) e.g., add authentication to a program - support of product lines (new code is a variant in some aspects) e.g., add code to control new airplane - support performance improvements (treat special cases faster) e.g., bypass code for unused network layers ------------------------------------------ AspectJ can also be used for other things: - glue code for reuse (static introductions) - static policy enforcement (declare error and declare warning) *** Some problems and issues Q: What is the programming methodology for finding crosscutting concerns? Q: When is this a useful technique? at least for large programs and product-lines Q: Are there any privacy issues relating to join points? yes Q: Are join points at the right level of abstraction? probably not, but how to know to define them at the right level? Q: How can we understand code that uses aspects? a good (research) question