470 likes | 594 Views
Features Meet Aspects Software Development with. Motivation for CaesarJ …. OO languages lack support for: Higher-level modules beyond classes to capture features Crosscutting composition of features AO languages have support for crosscutting composition
E N D
Features Meet Aspects Software Development with
Motivation for CaesarJ … • OO languages lack support for: • Higher-level modules beyond classes to capture features • Crosscutting composition of features • AO languages have support for crosscutting composition • But they poorly support feature modularization and refinement
Higher-Level Modules ... • Existing languages lack sufficient means for organizing collaborating classes • e.g., packages and namespaces • Problems • no means to express variants of a collaboration • no polymorphism • no runtime semantics • Mechanisms that proved useful for single classes not available for sets of collaborating classes
HierarchyDisplay getRoot() Node generateLayout() child draw(g) shape: Shape refresh() children getText() textFits(text) 0-* Connection calculateLayout() initShape(pt) conn: Connector draw(g) init(parent, child) initShape(pt) draw(g) CompositeNode connections 0-* getChildAt(int) getChildCount() calculateLayout() parent draw(g) Higher-Level Modules ... Example: a component for displaying hierarchical structures … can you imagine putting it into one class-like module?
Higher-Level Modules ... … can you imagine extending the hierarchy display component … by overriding only affected classes, … just as one extends single classes by overriding affected methods?
Crosscutting Composition … generic component P2 reused P3 P1 with a family of applications in a domain C1 C1 C2 C4 C2 C3 C3 C4 C5 APPL 1 APPL n
CompanyModel getRoot() Node generateLayout() child draw(g) shape: Shape refresh() children getText() textFits(text) Connection calculateLayout() initShape(pt) conn: Connector draw(g) init(parent, child) initShape(pt) draw(g) CompositeNode connections 0-* getChildAt(int) getChildCount() calculateLayout() parent draw(g) Crosscutting Composition ... … want to use for displayng a company’s structure … and for a window’s structure … HierarchyDisplay CEO Department Managers Workers
adopt generic display logic for company model after certain changes refresh display or recalculate layout Aspects of Crosscutting Composition structural mapping needed behavioral mapping needed Let us try patterns …
cast down to DepartmentNode cast down to EmployeeNode Adapters CompanyNode DepartmentNode EmployeeNode CompanyHierarchyDisplay wrappee : Company wrappee : Department wrappee : Employee root : Company getText() getText() getText() getChildAt() getChildAt() getRoot() getChildCount() getChildCount() cast down to CompanyNode Patterns for Integration… HierarchyDisplay Node view : JComponent CompositeNode shape: Shape getChildAt(int) getRoot() getText() getChildCount() draw() textFits(text) calculateLayout() setView() calculateLayout() draw(g) refresh() initShape(pt) generateLayout() draw(g) 1 0-* 0-* Company Department Employee workers 1 ceo 1 manager
Observers Patterns for Integration…
CaesarJ in a Nutshell … aspects and features inside … focus on feature modularization, extension and integration … beyond “typical crosscutting concerns“ (security, persistence …)
Outline • Multi-class modules and hierarchical refinements • Defining and extending components with virtual classes • Hierarchical composition • Crosscutting composition • Defining wrapper classes • Observing events with pointcuts • Aspects as classes • Dynamic aspect deployment • Variability management • State of the art
Virtual Classes • Originates in Beta [Madsen et al] • Idea: Give inner classes the same status as (virtual) methods Overriding and late binding should also apply to nested classes, similarly to overriding and late binding of methods. • Consequence: Virtual classes are properties of objects of the enclosing class • Talk about class expr.C, similarly to method expr.m()
Virtual Classes - Example cclass HierarchyDisplayImpl { cclass Node {} cclass CompositeNode extends Node { ... } cclass Connection { void positionNode() {...} } void foo(Node n) { Connection c = new Connection(); } } cclass HierarchyDisplayImplA extends HierarchyDisplayImpl { cclass Node { int maxwidth; ... } void foo(Node n) { … n.maxwidth … } } cclass HierarchyDisplayImplB extends HierarchyDisplayImpl { cclass Connection { void positionNode() { … super.positionNode(); …} } }
Virtual Classes - Example cclass HierarchyDisplayImpl { cclass Node {} cclass CompositeNode extendsthis.Node { ... } cclass Connection { void positionNode() {...} } void foo(this.Node n) { this.Connection c = this.new Connection(); } } cclass HierarchyDisplayImplA extends HierarchyDisplayImpl { cclass Node extends super.Node { int maxwidth; ... } void foo(this.Node n) { … n.maxwidth … } } cclass HierarchyDisplayImplB extends HierarchyDisplayImpl { cclass Connection extends super.Connection { void positionNode() { … super.positionNode(); …} } } Implicit Scoping!
Virtual Classes - Example cclass HierarchyDisplayImpl { cclass Node {} cclass CompositeNode extendsthis.Node { ... } cclass Connection { void positionNode() {...} } void foo(this.Node n) { this.Connection c = this.new Connection(); } } cclass HierarchyDisplayImplA extends HierarchyDisplayImpl { cclass Node extends super.Node { int maxwidth; ... } void foo(this.Node n) { … n.maxwidth … } } cclass HierarchyDisplayImplB extends HierarchyDisplayImpl { cclass Connection extends super.Connection { void positionNode() { … super.positionNode(); …} } } …if instance of HierarchyDisplayImplA
Virtual Classes - Example cclass HierarchyDisplayImpl { cclass Node {} cclass CompositeNode extendsthis.Node { ... } cclass Connection { void positionNode() {...} } void foo(this.Node n) { this.Connection c = this.new Connection(); } } cclass HierarchyDisplayImplA extends HierarchyDisplayImpl { cclass Node extends super.Node { int maxwidth; ... } void foo(this.Node n) { … n.maxwidth … } } cclass HierarchyDisplayImplB extends HierarchyDisplayImpl { cclass Connection extends super.Connection { void positionNode() { … super.positionNode(); …} } } …if instance of HierarchyDisplayImplB
Virtual Classes - Example cclass HierarchyDisplayImpl { cclass Node {} cclass CompositeNode extendsthis.Node { ... } cclass Connection { void positionNode() {...} } void foo(this.Node n) { this.Connection c = this.new Connection(); } } cclass HierarchyDisplayImplA extends HierarchyDisplayImpl { cclass Node extends super.Node { int maxwidth; ... } void foo(this.Node n) { … n.maxwidth … } } cclass HierarchyDisplayImplB extends HierarchyDisplayImpl { cclass Connection extends super.Connection { void positionNode() { … super.positionNode(); …} } } No type cast necessary
Composition of Extensions cclass HierarchyDisplayAB extends HierarchyDisplayA & HierarchyDisplayB • Can compose classes via „&“ operator • Class composition via mixin linearization
Propagating Mixin Composition • Class composition and virtual classes interact by means of their respective influence/dependency on thisand super. • Composition: this refers to the composed class, super is determined by mixin linearization. • Virtual Classes: All virtual type annotations are declared via the enclosing this and super, respectively.
Composition of Layers cclass HierarchyDisplayImplAB extends HierarchyDisplayImplA & HierarchyDisplayImplB {}
Composition of Layers cclass HierarchyDisplayImplAB extends HierarchyDisplayImplA & HierarchyDisplayImplB {}
Family Polymorphism • Subclasses are subtypes! hd.Node findChild(final HdI hd, hd.CompositeNode n, String str) { for (int i = 0; i < n.getChildCount(); i++) hd.Node m = n.getChildAt(i); if (m.getText().equals(str)) return m; } return null; } ... final HierachyDisplayA hda = new HierarchyDisplayA(); hda.CompositeNode cna = …; final HierachyDisplayB hdb = new HierarchyDisplayB(); hdb.CompositeNode cnb = …; hda.Node n = findChild(hda, cna, someString); // ok hdb.Node n = findChild(hdb, cnb, someString); // ok hda.Node n = findChild(hdb, cna, someString); // static error
Family Polymorphism • In our case, objects can be repositories of collaborating classes • Type system makes sure that objects from different families never mix! • Otherwise we could easily produce type errors • Type system uses „path-dependent types“ • Type name is prefixed with path to family • All fields in a path must be „final“ final HierarchyDisplay hd = new HierarchyDisplayA(); final HierarchyDisplay hd2 = new HierarchyDisplayB(); hd.Node n = hd.new Node(); // ok hd.foo(n); // ok hd2.Node n = hd.new Node(); // static error hd2.foo(n); // static error
Outline • Hierarchical Refinements • Extending component with virtual classes • Combining different extensions • Feature-oriented decomposition • Crosscutting Integration • Defining wrapper classes • Observing events with pointcuts • Variability management • State of the art
HierarchyDisplay getRoot() generateLayout() Node draw(g) child refresh() getText() children textFits(text) calculateLayout() 0-* Connection initShape(pt) init(parent, child) draw(g) initShape(pt) draw(g) connections 0-* CompositeNode getChildAt(int) getChildCount() calculateLayout() parent draw(g) Feature Integration Display uses data and relationships of company objects structural mapping behavioral mapping After certain changes display must be refreshed or layout recalculated Design Goal: Keep components independent of each other
Feature Integration Collaboration Interface Visualization Concern Binding to Company Model Concrete Component
Feature Integration - Bindings Adapting company model objects to visual nodes cclass WorkerNode extends Node wraps Employee { String getText() { return wrappee.getFullName(); } }
Wrapper Recycling cclass CompanyHierarchyBinding { cclass WorkerNode extends Node wraps Employee { ... } ... } wrapper is created on demand void test() { CompanyHierarchyBinding hier = new CompanyHierarchyDisplay(); Employee anna = new Employee(); assert(hier.WorkerNode(anna) == hier.WorkerNode(anna)); Employee peter = new Employee(); assert(hier.WorkerNode(anna) != hier.WorkerNode(peter)); } wrapper is reused for the same object wrapper is destroyed by garbage collector
Feature Integration - Pointcuts After certain changes display must be updated Call when redraw is needed Call after text change Call after children changed
Changes in Company Model Affects text of a node Affects children of a node No direct effect
Observing Changes in Company Model pointcut departmChildrenChange() : execution( Department.addWorker(..)) || execution( Department.removeWorker(..)); pointcut companyChildrenChange() : execution( Company.addDepartment(..)) || execution( Company.removeDepartment(..)); pointcut displayChange() : execution( company..setName(..)) || departmChildrenChange() || companyChildrenChange(); after(Department d) : departmChildrenChange() && this(d) { DepartmentNode(d).calculateLayout(); } after(Company c) : companyChildrenChange() && this(c) { CompanyNode(c).calculateLayout(); } after() : displayChange() && !cflowbelow(displayChange()) { refresh(); }
Support for Variability • Several dimensions of variations • Two dimensions in our example: • HierarchyDisplay implementation variations • Data model variations • All defined to a common interface • Implement different facets of the interface • All parameterized over other facets • Collaboration interface abstraction makes them composable
Combining Variations Collaboration Interface Component Bindings IHierarchyDisplay CompanyHierarchyBinding GUIHierarchyBinding Component Implementations Components HierarchyDisplay CompanyHierarchyDisplay GUIHierarchyDisplay Adjusted- Adjusted- Adjusted- HierarchyDisplay CompanyHierarchyDisplay GUIHierarchyDisplay Angular- Angular- Angular- HierarchyDisplay CompanyHierarchyDisplay GUIHierarchyDisplay AdjustedAngular- AdjustedAngular- AdjustedAngular- HierarchyDisplay CompanyHierarchyDisplay GUIHierarchyDisplay
CaesarJ Aspects are Objects • Aspects can be instantiated and referenced as any other object • References to aspects can be polymorphic • aspectual polymorphism • Multiple instances of an aspect can be created and used simultaneously • Aspects can contain state • To parameterize their behavior • To accumulate results of observation • Aspects can be deployed on different scopes
CaesarJ Aspects are Objects • Aspects in CaesarJ are classes that have pointcuts and advice • Keyword deployed creates and activates a singleton instance of the class public deployed cclass CompanyChangeTracer { pointcut change() : execution(void company.*.set*(..)) || execution(void company.*.add*(..)) || execution(void company.*.remove*(..)) || execution(void Company.transferTo(..)); after(Object o): change() && this(o) { System.out.println( "Object '" + o.toString() + "' changed"); } }
Dynamic Aspect Deployment CompanyChangeTracer asp1 = new CompanyChangeTracer(); CompanyChangeTracer asp2 = new CompanyChangeTracer(); dept.setName(“DeptA”); /* not intercepted */ deploy asp1; dept.setName(“DeptB”); /* intercepted by asp1 */ deploy asp2; dept.setName(“DeptC”); /* intercepted by asp1 and asp2 */ undeploy asp1; undeploy asp2; dept.setName(“DeptD”); /* not intercepted */
Aspect Scoping Thread local deployment: CompanyChangeTracer asp1 = new CompanyChangeTracer(); deploy(asp1) { new deptm.setName(“DeptA”); } Object local deployment: CompanyChangeTracer asp1 = new CompanyChangeTracer(); CompanyChangeTracer asp1 = new CompanyChangeTracer(); Department dept1 = new Department(“deptA”); Department dept2 = new Department(“deptB”); DeploySupport.deployOnObject(asp1, dept1); DeploySupport.deployOnObject(asp2, dept2); dept1.setName(“deptC”); /* intercepted by asp1 */ dept2.setName(“deptD”); /* intercepted by asp2 */ dept3.setName(“deptF”); /* not intercepted */ DeploySupport.undeployFromObject(asp1, dept1); DeploySupport.undeployFromObject(asp2, dept2);
Integrating Distributed Components rmi://server.net/Company method calls host.deployAspect(h) advice calls
Remote Aspect Deployment • Use execution pointcut, because calls can cross process boundaries • Pointcut cflow cannot cross thread boundaries • Prepare aspect classes with Caesar RMI compiler Server side: CaesarHost host = new CaesarHost(“rmi://localhost/”); host.activateAspectDeployment(); Client side: CaesarHost host = new CaesarHost(“rmi://localhost/”); ICompanyHierarchyDisplay hier = new CompanyHierarchyDisplay(); host.deployAspect(hier); ... host.undeployAspect(hier);
Deployment on a Distributed Flow deployedpubliccclass CompanyDisplayLogging { voidaround(): execution(draw(..)) &&this(CompanyHierarchyDisplay) { CompanyLogger logger = new CompanyLogger(); deploy (logger) { proceed(); } } } deployedpubliccclass CompanyDisplayLogging { voidaround() : execution(draw(..)) &&this(CompanyHierarchyDisplay) { CompanyLogger logger = new CompanyLogger(); RemoteDeployment.deployOnControlFlow(logger); proceed(); RemoteDeployment.undeployFromControlFlow(logger); } }
Outline • Hierarchical Refinements • Extending component with virtual classes • Combining different extensions • Feature-oriented decomposition • Crosscutting Integration • Defining wrapper classes • Observing events with pointcuts • Variability management • State of the art
CaesarJ Development Tools • CaesarJ IDE is available as a Eclipse plug-in • Integrated compiler and editor • Specialized visualization • Debugging support
More on CaesarJ • Visit http://caesarj.org for more information • Download plug-in and examples • Read documentation and tutorial • Subscribe to mailing list • Case studies • An interpreter of an experimental OO language • A real-time computer game • Access Control Service (by KU-Leuven, Belgium) • Mobile order management system (running)
References • E. Ernst, K. Ostermann and W. Cook. A Virtual Class Calculus. ACM Symposium on Principles of Programming Languages (POPL'06), ACM SIGPLAN-SIGACT, 2006. • I. Aracic, V. Gasiunas, M. Mezini and K.Ostermann. Overview of CaesarJ. Transactions on Aspect-Oriented Software Development I. LNCS, Vol. 3880, pp. 135 - 173, Feb 2006. • M. Mezini and K. Ostermann. Variability Management with Feature-Oriented Programming and Aspects. Foundations of Software Engineering (FSE-12), ACM SIGSOFT, 2004. • M. Mezini and K.Ostermann. Conquering Aspects with Caesar. In (M. Aksit ed.) Proceedings of the 2nd International Conference on Aspect-Oriented Software Development (AOSD)2003, ACM Press, pp. 90-100. • M. Mezini and K. Ostermann. Integrating Independent Components with On-Demand Remodularisation. 17th ACM Conference on Object-Oriented Programming, Systems, Languages, and Applications (OOSPLA), 2002, Sigplan Notices, 37 (11), pp. 52 - 67. • M. Mezini, L. Seiter, K. Lieberherr. Component Integration with Plug-and-Play Adapters. In M. Aksit (ed.) "Software Architectures and Component Technology: The State of the Art in Software Development", Kluwer Academic Publishers • S´. Herrmann and M. Mezini. LAC: Aspectual Components in Lua. Workshop on Advanced Separation of Concerns, International Conference on Software-Engineering 2001 (ICSE '01) • S. Herrmann and M. Mezini. Connectors for bridging mismatches between the components of a software engineering environment. IEE Proceedings - Software Engineering Special Issue: Aspect-oriented and component-based Software Development • S. Herrmann and M. Mezini. Pirol: A Case-Study for Multi-Dimensional Separation of Concerns in Software-Engineering Environments. ACM Conference on Object-Oriented Programming, Systems, Languages and Applications (OOPSLA '00), Sigplan Notices, Vol. 35, No. 10 • L. Seiter, M. Mezini and K. Lieberherr. Dynamic Component Gluing. Proceedings of the 1st International Conference on Generative and Component-Based Software Engineering (GCSE '99)}, LNCS 1477 • M. Mezini and K. Lieberherr. Adaptive Plug-and-Play Components for Evolutionary Software Development. ACM 13th Annual Conference on Object-Oriented Programming, Systems, Languages and Applications (OOPSLA '98), Vancouver, Sigplan Notices, Vol. 33, No. 10., pp. 97-116. • K. Lieberherr D. Lorenz, M. Mezini. Programming with Aspectual Components. Tech. Report. College of Computer Science, Northeastern University
People • Project Leads • Prof. Mira Mezini • Prof. Klaus Ostermann • Developers • Ivica Aracic • Vaidas Gasiunas • Karl Klose • Thiago Tonelli Bartolomei • Christian Meffert • Jochen Ungers • Daniel Zwicker • Andreas Wittmann • Walter A. Werner • Jürgen Hallpap Mira Mezini Klaus Ostermann Vaidas Gasiunas Ivica Aracic
Thank you! http://caesarj.org