1 1
Understanding Design Pattern Density with Aspects A Case Study in - - PowerPoint PPT Presentation
Understanding Design Pattern Density with Aspects A Case Study in - - PowerPoint PPT Presentation
Understanding Design Pattern Density with Aspects A Case Study in JHotDraw with AspectJ Simon Denier, Pierre Cointe OBASCO Project cole des Mines de Nantes / INRIA ETAPS SC 2006 1 1 What is Pattern Density? From JUnit: a Cook's
2 2
What is Pattern Density?
- From “JUnit: a Cook's Tour”, Gamma & Beck
- Mature frameworks show a high density of patterns
- especially around key abstractions (TestCase in JUnit)
- because patterns provide leverage to extend the framework
- but they also make code harder to change (because of tangling)
- “easier to use, harder to change”
- What means “harder to change” exactly?
3 3
Density, Composition, and Aspects
- A high density most probably implies that some design
patterns compose together
- Aspects enable modularization of crosscutting concerns
- Hannemann et al shows some new modular, reusable
implementations of design patterns with AspectJ
- Intuition: better modularization by aspects could ease, or
at least highlight, the composition of design patterns
4 4
Incremental Approach with JHotDraw
- JHotDraw: a framework for structured drawing
- a design exercise with several design patterns (high density of
patterns around Figure, the key abstraction)
- Our incremental approach:
- isolate a base framework (more basic than the current one)
- enhance the base with functions involving design patterns
- have the option to come back to basic framework at no cost
- for example, by a selection of modules at compile-time
- Purpose: show the impact of design patterns composed
together without/with aspects
5 5
Example: View observes Figures
- Purpose: Figures notify View when they change, in order
to optimize redraw with their clipping area
aView aDrawing figure2 figure1 figure3 notify subjects
- bserver
6 6
Example: Observer aspect
aspect FigureOberver { /* Structure by Inter-Type Declaration (ITD) */ private Vector Figure.observers = new Vector(); /* Registration */ pointcut registerObserver(Figure f, View v): (...) after(Figure f, View v): registerObserver(f, v){ f.observers.add(v); } /* Notification Points */ pointcut changed(Figure f): this(f) && execution(void Figure+.move(..)); /* Notification Process */ after(Figure f): changed(f) { for (int i = 0; i < f.observers.size(); i++) f.observers.elementAt(i).invalidate(f); } }
- General case (multiple observers per subject)
7 7
Single View vs Multiple Views
8 8
Singleton-Observer (1)
- Single view on drawing and figures
- Simplification of the Observer pattern when observer is a
Singleton (global access)
- no structure to hold list of observers
- no registration of observer
- simple notification process
View.instance().invalidate(f);
- Object impact: insert notification points in code
- Simple implementation, easy to understand, simple to use
9 9
Singleton-Observer (2)
- Multiple views on drawing and figures
- General case of Observer pattern
- Object impact: invasive modifications
- define list of observers in subjects
- insert (de)registration points for observers
- dispatch notification process
- Notification points: same as for Singleton
- Unfortunately, we have lost the simple collaboration with
singleton view
10 10
Singleton-Observer with Aspects
- Observer pattern is modularized in one aspect
- Aspects can be easily plugged/unplugged
- Solution:
- provide two aspects, one general and one for the Singleton case
- selection by user based on current configuration of framework
(single view or multiple views)
- Future work: automatic selection based on detection of
Singleton?
11 11
Composite-Decorator and Observer
- Add GroupFigure (Composite) and BorderDecorator
- build tree of Figures under Drawing
- Problem: BorderDecorator modifies the clipping area of its
underneath Figure
- the Figure knows when to notify
- the view must get the clipping area from the BorderDecorator
aView aDrawing figure2 figure1 figure3 aGroupFigure aBorderDecorator
12 12
Object Solution: O + C-D → CoR + C-D
- Transform Observer into a Chain of Responsibility
- a Figure notify its parent in the hierarchy of figures, either a
GroupFigure or a BorderDecorator
- the Drawing stops the recursive process and notifies the view(s)
- BorderDecorator can handle notifications from its child and
modify them aView aDrawing figure2 figure1 figure3 aGroupFigure aBorderDecorator
*
13 13
Object Impact
- BorderDecorator and GroupFigure become both
- bservers and subjects
- although GroupFigure is not primarely concerned
- View is involved to stop the recursive process
- All notifications must follow the chain
14 14
O + C-D with Aspects
- A change command defines a recursive control flow
whenever it is sent down the tree of Figures
- use AspectJ pointcuts based on control flow (cflow)
- Only the Observer aspect is modified
- the impact is limited to pointcuts (contrary to the overall impact of
Chain of Responsibility)
- Can we do better? Yes!
- different pointcuts on different actions = different strategies for
notification (not just chained handling)
15 15
Top-Level Observer
- Notify only the top level action, because action necessarily
triggers a change (example: move action)
- Simple (well-known) solution in AspectJ
pointcut changed (Figure f): this(f) && execution(void Figure+.move(..)) && !cflowbelow(execution(void Figure+.move(..)))
aView aDrawing figure2 figure1 figure3 aGroupFigure aBorderDecorator
16 16
Path Observer (BorderDecorator)
- get top-most BorderDecorator (the one which defines the overall
clipping area for the current action)
pointcut topmost(Figure f): this(f) && execution(void Figure+.setAttribute(..)) && !cflowbelow(execution(void Figure+.setAttribute(..)))
- pass it on the underneath join point to replace the current Figure
pointcut changed(Figure f): cflowbelow(topmost(f)) && execution(void Figure+.setAttribute(..))
aView aDrawing figure2 figure1 figure3 aGroupFigure aBorderDecorator
17 17
Impact of Pattern Density on Objects
- What is “harder to change”?
- Inner modification (Singleton-Observer)
- Broad transformation on a set of classes (Chain of
Responsibility)
- Invasive impact, the basic solution is lost
18 18
Contributions of Aspects
- Impact limited to one module or simply pointcuts
- Adaptation is fine grained with pointcuts but has also a
large scale (a control flow across many objects)
- allows reasoning on a large scale, even for small details
- Aspects provide better modularization between classes
- But the pointcut language is tailored to provide meaningful
adaptation following class relationships (e.g. cflow)
19 19
Specificity of Aspects?
- cflow constructs can be emulated if we have an inspector
- n the execution stack
- Inter-type declaration is akin to mixin inheritance or traits
- So nothing specific, but well integrated into aspects
- Why not integrate other mechanisms into language?
- seek for expressiveness on common design pattern structure:
recursivity, indirection
20 20