Workshop: Moderne Softwareentwicklungs-Methoden Teil 1: AOP, MDSOC, GP, IP Teil 2: eXtreme Programming Markus Völter markus.voelter@mathema.de Michael.

Slides:



Advertisements
Similar presentations
GenArch: Automatic Product Derivation in Multi-agent Systems Product Line Elder Cirilo.
Advertisements

Profiles Construction Eclipse ECESIS Project Construction of Complex UML Profiles UPM ETSI Telecomunicación Ciudad Universitaria s/n Madrid 28040,
Construction process lasts until coding and testing is completed consists of design and implementation reasons for this phase –analysis model is not sufficiently.
Programming Languages and Paradigms
Object Orientation Chapter SixteenModern Programming Languages, 2nd ed.1 Spring 2012.
Object Orientation Chapter SixteenModern Programming Languages, 2nd ed.1.
Aspect Oriented Programming. AOP Contents 1 Overview 2 Terminology 3 The Problem 4 The Solution 4 Join point models 5 Implementation 6 Terminology Review.
Domain Engineering Arie van Deursen May Software Product Line  Group of products  sharing a common, managed set of features  to satisfy the.
Presented by: Thabet Kacem Spring Outline Contributions Introduction Proposed Approach Related Work Reconception of ADLs XTEAM Tool Chain Discussion.
Component Patterns – Architecture and Applications with EJB copyright © 2001, MATHEMA AG Component Patterns Architecture and Applications with EJB JavaForum.
UML CASE Tool. ABSTRACT Domain analysis enables identifying families of applications and capturing their terminology in order to assist and guide system.
© Copyright Eliyahu Brutman Programming Techniques Course.
Data Abstraction and Object- Oriented Programming CS351 – Programming Paradigms.
Abstract Data Types and Encapsulation Concepts
Generative Programming. Generic vs Generative Generic Programming focuses on representing families of domain concepts Generic Programming focuses on representing.
Object-oriented design CS 345 September 20,2002. Unavoidable Complexity Many software systems are very complex: –Many developers –Ongoing lifespan –Large.
Course Instructor: Aisha Azeem
1 An introduction to design patterns Based on material produced by John Vlissides and Douglas C. Schmidt.
Architecture and Software Product Lines A software architecture represents a significant investment of time and effort, usually by senior talent. So it.
Domain-Specific Software Engineering Alex Adamec.
Computer Systems & Architecture Lesson Software Product Lines.
CIT241 Prerequisite Knowledge ◦ Variables ◦ Operators ◦ C++ Syntax ◦ Program Structure ◦ Classes  Basic Structure of a class  Concept of Data Hiding.
Spectra Software Defined Radio Products Applying Model Driven Design, Generative Programming, and Agile Software Techniques to the SDR Domain OOPSLA '05.
Proceso kintamybių modeliavimas Modelling process variabilities Donatas Čiukšys.
Software Engineering Muhammad Fahad Khan
©Ian Sommerville 2004Software Engineering, 7th edition. Chapter 18 Slide 1 Software Reuse.
Embedded Components CDUF 2002 i n g e n i e u r b ü r o f ü r s o f t w a r e t e c h n o l o g i e © 2002 Markus Völter Embedded.
Design Patterns.
GENERAL CONCEPTS OF OOPS INTRODUCTION With rapidly changing world and highly competitive and versatile nature of industry, the operations are becoming.
Workshop on Integrated Application of Formal Languages, Geneva J.Fischer Mappings, Use of MOF for Language Families Joachim Fischer Workshop on.
1 CS 456 Software Engineering. 2 Contents 3 Chapter 1: Introduction.
1 N Degrees of Separation: Multi-Dimensional Separation of Concern (MDSOC) HyperJ: language and concepts of general concern combination.
An Introduction to Software Architecture
An Introduction to Design Patterns. Introduction Promote reuse. Use the experiences of software developers. A shared library/lingo used by developers.
SAMANVITHA RAMAYANAM 18 TH FEBRUARY 2010 CPE 691 LAYERED APPLICATION.
Aspect Oriented Programming Sumathie Sundaresan CS590 :: Summer 2007 June 30, 2007.
Generative Programming. Automated Assembly Lines.
Programming Language Support for Generic Libraries Jeremy Siek and Walid Taha Abstract The generic programming methodology is revolutionizing the way we.
A language to describe software texture in abstract design models and implementation.
CSE 425: Data Types I Data and Data Types Data may be more abstract than their representation –E.g., integer (unbounded) vs. 64-bit int (bounded) A language.
INRIA - LaBRICharles Consel Jan-06 1 Domain-Specific Software Engineering Charles Consel Phoenix Research Group LaBRI /INRIA-Futurs January 2006.
FDT Foil no 1 On Methodology from Domain to System Descriptions by Rolv Bræk NTNU Workshop on Philosophy and Applicablitiy of Formal Languages Geneve 15.
Object Oriented Software Development
Factory Method Explained. Intent  Define an interface for creating an object, but let subclasses decide which class to instantiate.  Factory Method.
Introducing Allors Applications, Tools & Platform.
Data Structures and Algorithms Dr. Tehseen Zia Assistant Professor Dept. Computer Science and IT University of Sargodha Lecture 1.
Architecture View Models A model is a complete, simplified description of a system from a particular perspective or viewpoint. There is no single view.
Interfaces About Interfaces Interfaces and abstract classes provide more structured way to separate interface from implementation
Methodology First and Language Second -A Way to Teach Object-Oriented Programming Haibin Zhu, PhD Department of Computer Science and Mathematics Nipissing.
Object-Oriented Programming © 2013 Goodrich, Tamassia, Goldwasser1Object-Oriented Programming.
C++ Inheritance Data Structures & OO Development I 1 Computer Science Dept Va Tech June 2007 © McQuain Generalization versus Abstraction Abstraction:simplify.
Introduction to Object-Oriented Programming Lesson 2.
Review of Parnas’ Criteria for Decomposing Systems into Modules Zheng Wang, Yuan Zhang Michigan State University 04/19/2002.
Advanced Software Development Karl Lieberherr CSG 260 Fall Semester
Component Patterns – Architecture and Applications with EJB copyright © 2001, MATHEMA AG Component Patterns Architecture and Applications with EJB Markus.
Banaras Hindu University. A Course on Software Reuse by Design Patterns and Frameworks.
 Description of Inheritance  Base Class Object  Subclass, Subtype, and Substitutability  Forms of Inheritance  Modifiers and Inheritance  The Benefits.
Design Patterns Creational Patterns. Abstract the instantiation process Help make the system independent of how its objects are created, composed and.
TTCN-3 Testing and Test Control Notation Version 3.
CSCE 240 – Intro to Software Engineering Lecture 3.
The PLA Model: On the Combination of Product-Line Analyses 강태준.
Motivation for Generic Programming in C++
Modern Programming Tools And Techniques-I
Design Patterns: MORE Examples
Week 4 Object-Oriented Programming (1): Inheritance
An Introduction to Software Architecture
On the notion of Variability in Software Product Lines
Ponder policy toolkit Jovana Balkoski, Rashid Mijumbi
Presentation transcript:

Workshop: Moderne Softwareentwicklungs-Methoden Teil 1: AOP, MDSOC, GP, IP Teil 2: eXtreme Programming Markus Völter markus.voelter@mathema.de Michael Wiedeking michael.wiedeking@mathema.de

Contents (I) The big picture Generative Programming Product Line Engineering Variability Analysis How AOP, GP, IP and MDSOC can help Generative Programming Principles Compile-time Metaprogramming (using templates) Jenerator – Generative Programming for Java Other GP tools Aspect-Oriented Programming Patterns for AOP AspectJ Sally Jenerator and AOP

Contents (II) Multidimensional Separation of Concerns Problem revisited: Multidimensional Variability Example introduced: SEE Hyper/J concepts Example continued Intentional Programming Background Basic Concepts IP System Architecture Active Source Stunning Features  Thanks Resources

The big picture Product Line Engineering Variability Analysis How AOP, GP, IP and MDSOC can help

Common Roots: Product Line Engineering Instead of developing one single system, development focuses on a family of related systems.Reasons: different target platforms (operating system, middleware) different quality of service (QoS) requirements, potential for future growth Systems are built from product-specific parts and reusable part: the common platform Creation of concrete systems should be done with the help of a (semi-)automatic process industrialized production of software „build software like they build cars“

Common Roots: Product Line Engineering Software Family as defined by Parnas in 1976: We consider a set of programs to constitute a family whenever it is worthwhile to study programs from the set by first studying the common properties of the set and then determining the special properties of the individual family members. Instead of developing one single system, development focuses on a family of related systems.Reasons: different target platforms (operating system, middleware) different quality of service (QoS) requirements, potential for future growth Creation of concrete systems should be done with the help of a (semi-)automatic process industrialized production of software „build software like they build cars“

Product Line Engineering: Process Domain Scoping Variability Analysis Domain Structuring Define common architecture Define Production Plan Define Building Blocks Components DSLs & Generators Production Process

Product Line Engineering: Process AOP, IP, GP & MDSOC are located here. But first...

Domain Analysis Goal: A domain model Scoping defines, what is part of the domain, and what is not (defines the range of possible products) Example: GQM (Goal Question Metric) A common vocabulary defines the terms in which the domain can be described The commonalities and the differences between different products in the domain have to be defined  Variability Analysis

Variability Analysis Variability analysis discovers the variable and fixed parts of a product in a domain. Parts can be structural, or behavioral (functional) non-functional (technical) To define variable aspects, we need to have a commonality base: something fixed There are two kinds of variability: positive variability: add something (optional) negative variability: removes something (essential) Positive variability leaves the concept intact, while netative variability does not.

Domain Analysis: Feature Modelling Feature Modelling is more abstract than OO analysis and design because it does not prescribe the realization of features A feature model describes the (sub-)features of a concept Subfeatures can be Mandatory Optional Alternative N of M A feature model can be multi-dimensional A graphical notation exists: feature diagrams

Feature Diagram: Aircraft example Example products: An aircraft with a low wing, piston engine and made of metal, wood and cloth: Robin DR-400 An aircraft with shoulder wing, no engine and made of plastic: ASW-27 An aircraft with low wing, jet engine(s) and made of metal: Airbus A320

More features of feature diagrams They can contain constraints on the combinations of features They can define „names“ for specific combinations of features; feature groups Features can be open: additional subfeatures can be added Features can be incomplete: the subfeatures are not yet defined Multiplicity of subfeatures can be added

Exercise 1: Feature Models Describe a feature model for a specific concept using a feature diagram. You may use a suitable editor for that purpose. Possible concepts: Personal Computer, Vehicle, JVM, curriculum, list (software)

Binding Times A feature diagram defines the common and variable aspects of a system. It has to be defined, when the variable aspects are fixed for a particular product. This is called binding time. Usually, binding time has consequences on flexibility performance code size type safety and: on the technique used to implement the variable aspect

Typical Binding Times source time: manual programming, template parameters compile time: function overloading, precompiler, template evaluation link time: DLLs, class loading run time: virtual functions, inheritance & polymorphism, factory-based instance creation, delegation deployment/configuration time: component deployment (impl. for an interface), environment variables

Binding Times and consequences (at runtime)

Exercise 2: Binding Times Depending on the programming language used, there are different techniques how the binding times can be realised. Some may even be impossible. Select one of the following languages and describe the possible realization of the binding times, as well as potential advantages and drawbacks: Languages: C++, Java, Eiffel, Ada, Smalltalk, Perl

Source Time binding Source time binding is tedious and error prone, because it has to be programmed manually. However, it has significant advantages: High performance, low code size Of course, some flexibility is sacrificed To make source time binding more efficiently usable, generative programming can be used.

Multi-Dimensional Variability A software system, and a family of systems in a domain, is usually decomposed, or structured using one dimension only.

What is multi-dimensional variability Multi-Dimensional means: The variability aspects can vary independently They cannot be decomposed in one hierarchy Typically, the result is many possible combinations (permutations) of the dimensions

Multi-Dimensional Variability What, if an certain feature cannot be decomposed along this same dimension?

Multi-Dimensional Variability: Apache Example Logging Session Expiration

Multi-Dimensional Variability Things that are tangled all through the primary decomposition structure are called cross-cutting concerns. have a well-defined purpose have a non-obvious structure Thus, Aspects are a way to separate concerns. It catches cross-cutting concerns in a single syntactic entity

AOP generalized AOP uses one primary decomposition structure (classes) and several additional aspects that cross-cut this structure. New aspects can be added after the system is designed A more generalized approach to realizing multi-dimensional variability is Multi-Dimensional Separation of Concerns (MDSOC): There is no primary decomposition structure, all dimensions are treated equal. each concerns is specified in its decomposition structure, and combined with other concerns in a second step.

MDSOC-Techniques Help to modularize the different concerns (dimensions) that arise from the feature model of a product family. Examples of MDSOC are adaptive programming aspect oriented programming (AOP) composition filters role-modelling subject-oriented programming (SOP) hyperspaces

Specifying products A product in a software family can be specified by combining the features in a specific, legal way. Such a specification can become quite complex, because Several different techniques might be used Constraints on the feature model have to be enforced It might be very low-level (programming-language dependent) To overcome these problems, Domain-Specific Languages can be used.

Domain-Specific Languages (DSLs) Allow to specify systems (or products of a family) in terms (vocabulary) of the software family. A higher level of expressiveness is thus reached. Thus, Intentional Programming can be seen as a construction kit for multilevel-DSLs: represents general and domain specific abstractions as intentions provides an extensible environment that allows to load (domain-specific) extensions represents source code as active entities extensions can affect the complete environment; the editor, compiler, debugger, version control, ...

Relations among the mentioned techniques

Domain Engineering: Can it be used today? It has been in use by several institutions, e.g. SEI, Mobile Phone manufacturers Feature models and diagrams are useable today and very helpful, so is variability analysis. Frameworks are a way to realize product lines, as well as components. Both are in use today. Thinking about binding times other than runtime is also very useful. Ok, this is not really part of the tutorial, but anyway 

Generative Programming Principles Compile-time Metaprogramming Jenerator – Generative Programming for Java Other GP tools

Generative Programming (GP) Industrialized production of products from a product line/system family Take care of the different binding times by using appropriate tools For example code generation to take care of source time variability, Reflection at runtime Optimization wherever possible and useful Improve performance by remove runtime decisions Reduce code size by only including the really needed parts

GP Elements Generative Domain Model consists of the following elements A way to specify products (family members) Implementation components from which these members can be assembled And configuration knowledge, which maps between the spec of a member and its implementation The terms problem space and solution space are used for specification and implementation components

Product Specification Product specification is usually done by using feature models (in textual or graphical notation) declarative languages (DSLs) regular programming with generators

Configuration Knowledge Constraints on the configuration space, i.e. legal and illegal product configurations Defaults configurations (default components and dependencies) Feature mapping (which implementation components satisfy which feature) Optimizations (optimzing for performance, or for code size, or for safety)

Implementation Components Active Libraries (such as template libraries that generate code) DSLs and their mappings code generators code transformers

GP Example: C++ Template Metaprogramming Also called compile-time metaprogramming, because metaprograms „run“ while the program is compiled Uses the features of C++ template instantiation Programming style is „functional“ and operates on types Note that some awkward constructs are required, because C++ templates were not originally intended for this purpose and many generally unknown and non-trivial features of the standard are used. Error reporting is usually clumsy

GP Example: C++ Template Metaprogramming struct SimpleBoundsChecker; template<class ElementType, class BoundsChecker=SimpleBoundsChecker> class Vector { public: //... ElementType& at(const int& i) { BoundsChecker::checkBounds(i,length); } }; struct OutOfBounds {}; struct SimpleBoundsChecker { static void checkBounds(const int& i,const int& length) { if(i<0 || i>=length) throw OutOfBounds(); struct EmptyBoundsChecker { static void checkBounds(const int& i,const int& length) { } }; //... int main() { Vector<int> v1; //v1 uses SimpleBoundsChecker Vector<int, EmptyBoundsChecker> v2; //v2 uses EmptyBoundsChecker return 0;

GP Example: C++ Template Metaprogramming struct SimpleBoundsChecker; template<class ElementType, class BoundsChecker=SimpleBoundsChecker> class Vector { public: //... ElementType& at(const int& i) { BoundsChecker::checkBounds(i,length); } }; struct OutOfBounds {}; struct SimpleBoundsChecker { static void checkBounds(const int& i,const int& length) { if(i<0 || i>=length) throw OutOfBounds(); struct EmptyBoundsChecker { static void checkBounds(const int& i,const int& length) { } }; //... int main() { Vector<int> v1; //v1 uses SimpleBoundsChecker Vector<int, EmptyBoundsChecker> v2; //v2 uses EmptyBoundsChecker return 0; „combines“ the classes at compile time Creates only those versions that are really used Inlining is used to improve runtime performance (or reduce code size) Calls to empty operations are eliminated

Template Metaprogramming: IF A static if can be used to check boolean conditions on types at compile time. #include <iostream> using namespace std; template<bool condition, class Then, class Else> struct IF { typedef Then RET; }; //specialization for condition==false template<class Then, class Else> struct IF<false, Then, Else> { typedef Else RET; void main() { cout << "sizeof(short) = " << sizeof(short) << endl << "sizeof(int) = " << sizeof(int) << endl << "sizeof(IF<(1+2>4), short, int>::RET) = " << sizeof(IF<(1+2>4), short, int>::RET) << endl; IF<(1+2>4), short, int>::RET i; //the type of i is int! }

Compile Time Factorial Statically calculates the factorial of an int at compile time! At runtime, the result is a constant! #include <iostream> using namespace std; #include "../meta/meta.h" using namespace meta; struct Stop { enum { RET = 1 }; }; template<int n> struct Factorial { typedef IF<n==0, Stop, Factorial<n-1> >::RET PreviousFactorial; enum { RET = (n==0) ? PreviousFactorial::RET : PreviousFactorial::RET * n }; void main() { cout << Factorial<3>::RET << endl; }

Other compile time functions Static versions of switch, while, do-while for etc... It has been shown that the C++ template facility can be used as a full-blown functional programming language. Its data are the types and constant integral values of the C++ language. In generative programming, these and other constructs are used to select code to be included in the final program.

Exercise 3: Template Metaprogramming Below you can find a static version of switch. Try(!) to explain how it works. #include <iostream> using namespace std; #include "../meta/meta.h" using meta::IF; const int DEFAULT = ~(~0u >> 1); //initialize with smallest struct NilCase {}; template <int tag_, class Type_, class Next_ = NilCase> struct CASE { enum { tag = tag_ }; typedef Type_ Type; typedef Next_ Next; }; // SWITCH<> template<int tag, class Case> class SWITCH { typedef typename Case::Next NextCase; enum { caseTag = Case::tag, found = (caseTag == tag || caseTag == DEFAULT) }; public: typedef IF<found, typename Case::Type, typename SWITCH<tag, NextCase>::RET >::RET RET; template<int tag> class SWITCH<tag, NilCase> {public: typedef NilCase RET; // test struct A {static void exec(){ cout << "A" << endl;} }; struct B {static void exec(){ cout << "B" << endl;} }; struct D {static void exec(){ cout << "Def" << endl;}}; void main() { SWITCH<(1+1-2), CASE<1,A, CASE<2,B, CASE<DEFAULT,D > > > > ::RET::exec(); }

Why use template metaprogramming Allows you to „modify“ or adapt your program at compile time to achieve Performance Optimizations, Inlining, Loop unrolling Size-specific adaptions Type-specific adaptions Memory Optimizations Code size Optimizations Keep out all the code that is not necessary Use code optimized for specific cases Other stuff Adapt Interfaces at compile time Impress and scare other people 

Example: Generic Container

Example: Generic Container template<class Generator> class PtrList { public: //make Config available as a member type typedef typename Generator::Config Config; private: typedef typename Config::ElementType ElementType; typedef typename Config::SetHeadElementType SetHeadElementType; typedef typename Config::ReturnType ReturnType; typedef typename Config::Destroyer Destroyer; typedef typename Config::TypeChecker TypeChecker; typedef typename Config::Copier Copier; public: PtrList(SetHeadElementType& h, ReturnType *t = 0) : head_(0), tail_(t) { setHead(h); } ~PtrList() { Destroyer::destroy(head_); void setHead(SetHeadElementType& h) { TypeChecker::check(h); head_ = Copier::copy(h); ElementType& head() { return *head_; } void setTail(ReturnType *t) { tail_ = t; } ReturnType *tail() const { return tail_; } private: ElementType* head_; ReturnType *tail_; };

Example: Generic Container template<class Generator> class PtrList { public: //make Config available as a member type typedef typename Generator::Config Config; private: typedef typename Config::ElementType ElementType; typedef typename Config::SetHeadElementType SetHeadElementType; typedef typename Config::ReturnType ReturnType; typedef typename Config::Destroyer Destroyer; typedef typename Config::TypeChecker TypeChecker; typedef typename Config::Copier Copier; public: PtrList(SetHeadElementType& h, ReturnType *t = 0) : head_(0), tail_(t) { setHead(h); } ~PtrList() { Destroyer::destroy(head_); void setHead(SetHeadElementType& h) { TypeChecker::check(h); head_ = Copier::copy(h); ElementType& head() { return *head_; } void setTail(ReturnType *t) { tail_ = t; } ReturnType *tail() const { return tail_; } private: ElementType* head_; ReturnType *tail_; }; specific specialized templated classes exist for Copier, TypeChecker and Destroyer (kind of static subclassing) Config serves as the configuration repository and defines, which of them is used in a particular generation

Example: Generic Container Config serves as the configuration repository for a specific List instantiation struct RefPolyPersonListConfig { typedef Person ElementType; typedef ElementType SetHeadElementType; typedef EmptyDestroyer<ElementType> Destroyer; typedef EmptyTypeChecker<ElementType> TypeChecker; typedef EmptyCopier<ElementType> Copier; typedef PtrList<RefPolyPersonListConfig> ReturnType; } // use it! Typedef RefPolyPersonListConfig::ReturnType PersonList; PersonList list = new PersonList();

Example: Generic Container Last step: A Generator that takes a config structure and returns the generated product. It uses enums, static IFs and static SWITCHes heavily. Provides useful defaults Usage example: LIST_GEN< Person, ext_ref, poly >::RET someList;

Example: Generative Programming in Java Java provides no templates. Template metaprogramming thus cannot work! Also, GJ or Java 1.5 templates or Ada can‘t do it, because they are implemented differently. One approach is Jenerator, a code generation framework in and for Java. It is implemented by MATHEMA and used in several projects EJB generation Component Container generation ...

Example: Hello Jenerator public class HelloJenerator { public HelloJenerator() { CClass createdClass = new CClass( “jenerator", "HelloWorld" ); CMethod mainMethod = new CMethod( CVisibility.PUBLIC, CType.VOID, "main" ); mainMethod.addParameter( new CParameter( CType.user( "String[]" ), "args" ) ); mainMethod.addToBody( new ClassInstantiation( createdClass.getName(), "app", true ) );   CConstructor cons = new CConstructor( CVisibility.PUBLIC ); cons.addToBody( new CCode( "System.out.println(\"Hello World!\");" ) ); createdClass.addConstructor( cons ); createdClass.addMethod( mainMethod ); new CodeGenerator().createCode( createdClass ); }

Jenerator Guiding Principle Every interesting part of the AST can be modelled explicitly

Jenerator: Principles for extension – building generative components Jenerator applies the usual OO concepts on the generator level: Subclassing: By subclassing generator classes, higher-level, domain specific generators can be created. Parametrization: By parametrizing the generator classes, the behaviour of a generator can be easily controlled. Delegation: Generator classes can use each other, creating more complex results.

Exercise 4: Jenerator You have seen the „Hello World“ program for Jenerator. It creates a CMethod object and prints out hello world. Try to outline how a CMainMethod could look like. It should contain the typical signature of main() and allow the programmer to add arbitrary code to the body of the operation.

Jenerator: More Advanced Techniques: Macros A macro is an entity that modifies a CClass. Example: JavaBean properties can also operate on ClassGroups (see EJB generation) class SomeClass { private String id; public void setId( String _id ) { id = _id; } public String getId() { return id; } } new Property( "name", CType.STRING ).execute( createdClass );

Jenerator Examples: Interceptor proxy Goal: For each class, a Proxy should be generated Proxy allows to insert Interceptors to the invocation chain Good performance Must work for any class!! Implementation alternatives: Java‘s Proxy API can do that dynamically, but with significant runtime overhead. Jenerator does it in a generative fashion, i.e. almost no overhead.

Jenerator Examples: Interceptor proxy Goal: Be able to attach Interceptors to any object public class Test { public void addInterceptors( Interceptable ic ) { ic.addInterceptor( new NonNullInterceptor() ); } public Test() { TestGenerated tg = new TestGenerated(); tg = new TestGeneratedInterceptor( tg ); addInterceptors( (Interceptable)tg ); tg.test2(); tg.test3(null); public static void main( String[] args ) { new Test();

Jenerator Examples: Interceptor proxy Some interfaces are required Example interceptor: Throws exception in case of null argument public abstract class DynamicInterceptor { public abstract void preInvoke( Object target, String opName, Object[] params, String[] paramNames ) throws Stop; } public interface Interceptable { void addInterceptor( DynamicInterceptor interceptor ); public class NonNullInterceptor extends DynamicInterceptor { public void preInvoke( Object target, String opName, Object[] params, String[] paramNames ) throws Stop { for ( int i=0; i<params.length; i++ ) { if ( params[i] == null ) throw new Stop( "null value caught: "+paramNames[i] ); } } }

Jenerator Examples: Interceptor proxy Once the generators are implemented, their use is fairly simple (their implementation isn‘t hard either, it‘s just too much code to show here ) CClass testClass = new CClass( "generated", "TestGenerated" ); CMethod testMethod = new CMethod( CVisibility.PUBLIC, CType.INT, "test2" ); testMethod.addChild( new CSysOut( "Test2" ) ); testMethod.addChild( new CCode( "return 0;" ) ); testClass.addMethod( testMethod ); CMethod am = new CMethod( CVisibility.PUBLIC, CType.VOID, "test3" ); am.addParameter( new CParameter( CType.OBJECT, "aParam" ) ); am.addChild( new CSysOut( "Test3" ) ); testClass.addMethod( am ); am = new CMethod( CVisibility.PUBLIC, CType.VOID, "test6" ); am.addParameter( new CParameter( CType.INT, "aParam" ) ); gen = new InterceptorProxy( testClass ); CClass proxy2 = gen.generateProxy( null );

Exercise 5: Jenerator II The example just seen creates a proxy for an aribitrary class and provides an interface to plug-in interceptors at runtime (runtime of the generated program). This still has some performance overhead, because at runtime the system has to iterate over the interceptors and do quite a lot of method invocations... Try to optimize this by inlining the interceptors calls directly at the call sites. Of course, the configuration of which interceptors to use will have to happen at generation time.

Other GP examples: COMPOST COMPOST is a software composition system to engineer reengineer evolve software by program transformations. COMPOST supports invasive composition COMPOST's architectural language is Java Technically, COMPOST is a set of tools cooperating to attack the problems described above. COMPOST is still a research tool. URL: i44s11.info.uni-karlsruhe.de/~compost/

Other GP examples: COMPOST (II) COMPOST Recorder. It provides Parsing and unparsing of Java sources Simple preprocessors, simple code generators, source code beautification tools Name and type analysis for Java programs Software visualization tools, software metrics, Lint-like semantic problem detection tools, design problem detection tools (anti-patterns), cross-referencing tools Transformation of Java sources Preprocessors for language extensions, semantic macros, aspect weavers, source code obfuscation tools, compilers Incremental analysis and transformation of Java sources Source code optimization, refactoring tool, software migration programs (Smart Patches), design pattern, clichés and idiom synthesis, architectural connector synthesis, adaptive programming environments, invasive software composition

Other GP examples: FUUT-je FUUT-je (The Fantastic, Unique UML Fool for the Java Environment) Generates code from (simple) UML models Uses a mix of Java code and UML for code generation. Has been used by the author to generate code for IBM‘s San Francisco URL: www.bronstee.com/spider/fuutoverview.html

Other GP examples: FUUT-je (II) <Rule> <Target>Attributes</Target> <Condition> scope = public </Condition> /** * Gets the #<attribute.name># property */ public #<type># get#<u.name>#() { return #<name>#; } </Rule> * Sets the #<name># property (#<type>#) value. public void set#<u.name>#(#<type># p#<u.name>#) { #<name># = p#<u.name>#; /**Gets the description property */ public String getDescription() { return description; } /** Sets the owner property */ public void setOwner(String pOwner) { owner = pOwner;

Other GP examples: MDA (ok, to some extent) MDA is OMG‘s new initiative Generate application code from plattform independent domain models (UML) using well-defined rules and transformations. URL: www.omg.org/mda

? GP: Can it be used today? Generating code is not completely new and is used today. Template metaprogramming is used increasingly in C++, for example in the BOOST library. Several approach exist and can be used, others are still subject to research.

Aspect Oriented Programming Principles Patterns for AOP AspectJ Sally Jenerator and AOP

AOP principles AOP is a „mind set“ and can be used with ordinary programming languages. Key point is Separation of Concerns. Some design patterns can help to realize AOP concepts in normal languages.

Exercise 6: Aspects Join up in groups, agree on a well-known kind of application and try to identify some typical aspects, things, that are usually scattered all over the place.

DIY-AOP: Decorator Es kann transparent zu einem Objekt neue Funktionalität hinzugefügt werden, z.B. pre/post operations

DIY-AOP: Decorator

DIY-AOP: Proxy Proxies können Methodenaufrufe „abfangen“ und deren Semantik verändern Beispiel: Remote Proxy

DIY-AOP: Factory Factories abstrahieren den Erstellungsprozess von Objektes Damit können z.B. Proxies, Singletons oder Decorators erstellt werden

Exercise 7: Aspects and Patterns You want to provide a Logging aspect for method invocations and for object creation for your applications. It should be possible to run the application with or without logging enabled. Use the above mentioned patterns to implement these requirements as separate entities. Discuss advantages and drawbacks of implementing aspects this way.

AOP compared to Frameworks Frameworks require an identification of hot spots as part of its design. AOP allows you to inject aspects into a completely designed system without prior planning. Thus, many of the goals of frameworks can also be realized by AOP, of course with a different approach.

AOP tools: AspectJ AspectJ is an AOP extension to Java. It allows to define aspects as separate source entities They are woven together with the regular code before compilation. The result of the weaving process is normal Java source.

Java and Aspects in AspectJ Join points connect normal Java programs and Aspects “points in the execution” of Java programs 4 small additions to Java Pointcuts pick out join points and values at those points Advices define additional action to take at join points in a pointcut Introductions add additional fields/methods/constructors to classes Aspects are crosscutting types comprised of advice, introduction, field,constructor and method declarations

Typical Join Points Usually, join points are concerned with the message exchange between objects, i.e. method calls. several kinds of join points method & constructor call join points method & constructor execution join points field get & set join points exception handler execution join points static & dynamic initialization join points

Example: Figures in Drawing application Goal: Display has to be updated when figures move. class Line implements FigureElement{ private Point p1, p2; Point getP1() { return p1; } Point getP2() { return p2; } void setP1(Point p1) { this.p1 = p1; } void setP2(Point p2) { this.p2 = p2; } } class Point implements FigureElement { private int x = 0, y = 0; int getX() { return x; } int getY() { return y; } void setX(int x) { this.x = x; } void setY(int y) { this.y = y; }

Example without aspects Invasive change required because it is a cross-cutting concern. class Line { private Point p1, p2; Point getP1() { return p1; } Point getP2() { return p2; } void setP1(Point p1) { this.p1 = p1; MoveTracking.setFlag(); } void setP2(Point p2) { this.p2 = p2; class MoveTracking { private static boolean flag = false; public static void setFlag() { flag = true; } public static boolean testAndClear() { boolean result = flag; flag = false; return result;

Example: Figures in Drawing application each time a Line receives a void setP1(Point) or void setP2(Point) method call The following pointcut captures this situation: We want to „step in“ after the point has been updated: pointcut move(): call(void Line.setP1(Point)) || call(void Line.setP2(Point));

Aspect declaration that does just that aspect MoveTracking { private boolean flag = false; public boolean testAndClear() { boolean result = flag; flag = false; return result; } pointcut move(): call(void Line.setP1(Point)) || call(void Line.setP2(Point)); after() returning: move() { flag = true; // and update display

Aspect declaration that does just that public boolean testAndClear() { boolean result = flag; flag = false; return result; } pointcut move(): call(void Line.setP1(Point)) || call(void Line.setP2(Point)); after() returning: move() { flag = true; // and update display Advising several classes is also possible: pointcut move(): call(void Line.setP1(Point)) || call(void Line.setP2(Point)) || call(void Point.setX(int)) || call(void Point.setY(int));

Combining aspects and normal code Advising several classes is also possible: ajc Point.java Line.java MoveTracking.java Or: Result is ordinary Java class files.

AspectJ features Join Points Aspects method & cons calls & executions field gets and sets exception handler executions intializations Aspects pertarget perthis percflow percflowbelow Pointcuts call execution handler get set initialization this target within withincode cflow cflowbelow Advice before after around

Exercise 8: Aspects and AspectJ Again: You want to provide a Logging aspect for method invocations and for object creation for your applications. It should be possible to run the application with or without logging enabled. This time, use AspectJ to implement these requirements as separate entities. Discuss advantages and drawbacks of implementing aspects this way.

Sally – an object model for aspect languages Join Points are declared by 4-tuple A pointcut is an interaction between two join points. Advices are special methods. joinpoint j1 {B, void, methodB, null} joinpoint j1 {B, void, methodB, null} joinpoint j2 {C, int, methodC, null} pointcut pc {j1, j2} public void beforePC() before pc { // insert code here }

Sally (II) Aspects are declared like classes, with additionally join point, pointcut and advice method declarations. Aspects can be abstract (with abstract join points) and can be extended by inheritance. aspect SomeAspect { joinpoint j1 {B, void, methodB, null} joinpoint j2 {C, int, methodC, null} pointcut pc {j1, j2} public void beforePC() before pc { // insert code here }

Exercise 9: Different Aspect Languages Compare the way Sally and AspectJ implement aspects. What are the commonalities, the differences? Which approach do you like better? Which is more versatile? Can you think of other ways how aspects can be implemented? Consider Templates in C++, or Java‘s Dynamic Proxies

Jenerator: Aspects Jenerator also supports aspect. In Jenerator, an aspect consists of introduce() jointPointClass() appliesTo() apply() package de.mathema.jenerator.paper; // imports… public class LogObjectCreationAspect extends Aspect { public Class joinPointClass() { return ClassInstantiation.class; }   public void apply( CodeSnippet cs ) { ClassInstantiation inst = (ClassInstantiation)cs; CodeContainer container = inst.parent(); CMethod m = (CMethod)inst.parent( CMethod.class ); CClass c = (CClass)inst.parent( CClass.class ); String log = "System.out.println( //logmessage container.addChildBefore( new CCode( log ), cs );

AOP: Can it be used today? The concept of separating out certain aspects into separate units is certainly worthwhile. Using patterns, or native language mechanisms to represent aspects works fine. AspectJ can be used in certain environments, however, for example debugging support is limited; it is not so simple to use it together with e.g. EJB.

Multidimensional Separation of Concerns (MDSOC) Problem revisited: Multidimensional Variability Example introduced: SEE Hyper/J concepts Example continued

MDSOC Basics Goals are somewhat similar to AOP, only a bit more general. Separation of concerns is an approach to decomposing software into modules, each of which deals with, and encapsulates, a particular area of interest, called a concern. Examples of concerns are functions, data types or classes, features (e.g., "persistence,„ "print," or "concurrency control"), variants, and roles. Object-oriented languages permit decomposition only by class. (Tyranny of the dominant decomposition).

Multi-Dimensional Variability What, if an certain feature cannot be decomposed along this same dimension?

Exercise 10: Decomposition Tyranny The Tyranny of the dominant decomposition states that a programming paradigm usually only allows one way, the dominant way, of decomposing a system. You have seen this for procedural and object-oriented languages. What are the dominant decompositions in other programming languages, and which techniques are available to break this tyranny?

MDSOC Basics (II) It is thus necessary, to This will: decompose a system into as many concerns as necessary combine them as required ideally, to do this decomposition after the system has been developed. This will: reduce software complexity and improve comprehensibility. promote traceability within and across artifacts limit the impact of change, facilitating evolution and non-invasive adaptation and customization. facilitate reuse. simplify component integration.

IBM‘s Hyperspaces and Hyper/J IBM uses the notion of hyperspaces for MDSOC. The research tool they use is Hyper/J. Hyper/J provides a powerful composition capability, to combine separated concerns selectively into an integrated program Hyper/J can be used at any stage of the software lifecycle: Design, Implementation, Integration, Evolution, Reengineering It uses standard Java and uses bytecode rewriting

Hyper/J Example: Simple Expression Editor Tool to edit expressions of the form a = b + c * x It contains a set of tools that share a common representation of expressions, the AST. The set of tools should include the following: Evaluation tool: Determines the result Display tool: Depicts an expression program Check tool: Checks an expression program for syntactic and semantic correctness.

Hyper/J Example: Simple Expression Editor Tools are implemented as operations on the AST classes. The following concerns can be identified: Classes/Objects Features

SEE: Manual Solution: Visitor Pattern Implementing visitor requires design decision before implementation specific design and programming model

Exercise 11: Features and Visitor Implement the different features „operating“ on the AST using the visitor pattern. Discuss advantages and especially the drawbacks of this solution. Assuming, Hyper/J solves these problems – what features would you like Hyper/J to have?

Hyper/J Example: Additional Requirements It should be possible to have versions of the SEE that include subsets of the tools and capabilities. It should be possible to impose, optionally, checks for conformance to one or more programming styles. It should be possible to log, selectively, the execution of the SEE. Results in more concerns: configurations logging:

Hyper/J: Features to solve the problems Multiple, arbitrary dimensions of concern. Separation along these dimensions simultaneously. No dominant dimension! The ability to handle new concerns, and new dimensions of concern, dynamically a posteriori. Overlapping and interacting concerns; usually they are not orthogonal

Hyper/J: Concepts A hyperspace is the problem space to be separated into concerns. Each dimension in that space is a concern. A unit is a program artifact, in Hyper/J only Java: packages, interfaces, classes and members. A concern mapping associates units (classes, interfaces, etc.) with a dimension and a concern. A hyperslice is set of concerns that is declaratively complete. I.e. it must declare everything to which they refer, it need not implement it! This requirement reduces coupling. artifact: dimension.concern

Hyper/J: Declarative completeness example A hyperslice contains unit Plus.display(), which uses Plus.getOperand() defined in Kernel hyperslice To make the slice declaratively complete (i.e. compilable), it must supply its own version of Plus.getOperand(), however, it need not implement it (abstract declaration). Plus.display() then refers to this declaration Later on, the local declaration is mapped to a suitable implementation in another hyperslice.

Hyper/J: Concepts A hypermodule is a set of hyperslices being integrated and a set of integration relationships, which specify how the hyperslices relate to one another. Hyper/J provides a compositor tool to specify concerns, hyperslices, hypermodules, etc. and to compose them.

Hyper/J: Example continued The Java classes are implemented as usual (see class diagram) We now want to factor out the the Feature dimension and its concerns. First, we create a hyperspace specification file that specifies the complete space: hyperspace DemoHyperspace composable class demo.ObjectDimension.*;

Hyper/J: Example continued Then, we have to define the concerns mapping. Here, operations are mapped to concerns. package demo.ObjectDimension : Feature.Kernel operation check : Feature.Check operation display : Feature.Display operation eval : Feature.Eval operation check_process : Feature.Check operation display_process : Feature.Display operation eval_process : Feature.Eval operation process : Feature.None

Hyper/J: Example continued As a last step, we define the hypermodule specification file, which defines how the dimensions and concerns can be composed. hypermodule DemoSEE hyperslices: Feature.Kernel, Feature.Check, Feature.Display; Relationships: mergeByName; equate operation Feature.Kernel.process, Feature.Check.check_process, Feature.Display.display_process; end hypermodule;

Hyper/J: Example continued We then have to run the compositor tool: And then, we can run the application. Simple, isn‘t it? By changing the hypermodule definition file, we can easily change the included concerns. java com.ibm.hyperj.hyperj -hyperspace %HYPERJ_DIR%/demo/ObjectDimension.hs -concerns %HYPERJ_DIR%/demo/ObjectDimension/concerns.cm -hypermodules %HYPERJ_DIR%/demo/CheckDisplay.hm -verbose

Hyper/J: Example, adding a new Feature We want to add the StyleChecking Feature, after the system is finished! New package: Add this to the hyperspace configuration file: ... and the concern mapping: demo.StyleChecker hyperspace DemoHyperspace composable class demo.ObjectDimension.*; composable class demo.StyleChecker.*; package demo.StyleChecker : Feature.StyleChecker

Hyper/J: Example continued The hypermodule configuration file: hypermodule DemoSEE hyperslices: Feature.Kernel, Feature.Check, Feature.Display, Feature.StyleChecker; relationships: mergeByName; equate operation Feature.Kernel.process, Feature.Check.check_process, Feature.Display.display_process; set summary function for action DemoSEE.BinaryOperator.check to action DemoSEE.Expression.summarizeCheck; end hypermodule;

Exercise 12: Hyper/J The source on the previous page contains the set summary function specification. What do you think is it good for?

MDOSC: Can it be used today? Again, the concept is simple and can be used today. Hyper/J as an implementation has been around for a while and is quite stable. However, I would not recommend using it in industry projects, because it is not an established tool and approach.

Intentional Programming Background Basic Concepts IP System Architecture Active Source Stunning Features 

IP Background Intentional Programming (IP) has been a research project by Microsoft, lead by Charles Simonyi. It has since been transferred to the Visual Tools development division. As a consequence, it is very hard to obtain substantial information on the project. The best description I found is in Eisenecker and Czarnecki‘s book.

IP Basics IP is an extendible (meta)programming environment. The environment and the language can be extended to contain (domain-specific) higher-level abstractions. Extension libraries are used to supply the exetensions. It allows extensions to the Language Compiler Debugger Editor Version control

IP System itself The IP system supports the extensibility by providing a code transformation framework compilation support protocols debugging facilities that also allow the debugging of metacode and standard APIs for accessing the various parts of the system. Developers of extension libraries can make use of other extension libaries.

IP System Architectural Overview Important components Editor & Browser Reduction Engine Debugger VCS Import Parsers Reduction engine ±Compiler No parser! Creates R-Code Reduction is applied repeatedly Backend and Linker creates machine code

IP System Architectural Overview int x; x = 1; while ( x < 5 ) ++x; Reduction engine ±Compiler No parser! Creates R-Code Reduction is applied repeatedly Backend and Linkter creates machine code TEST: if ( x < 5 ) { ++x; goto TEST; } 0FAB12CF AFCD DF12

IP Core: Active Source Source is not represented as ASCII text, instead it is Active Source: Source elements are graph-structure, a kind of enhanced AST Each element has a reference to its declaration, which can be in an extension libary. methods operate on this tree, i.e. programming time behaviour can be specified

Active Source Example int x; x = 1; while ( x < 5 ) ++x;

Active Source at Programming-Time The declarations of elements in an active source tree can point to definitions inside libraries. These „types“ can contain operations to render type-in reduce debug refactor They are called by the framework at appropriate times.

AST methods example: Type-In The following shows support for typing in a simple expression:

More advanced support for type-in The following shows support for handling matrices.

More advanced support for type-in (II) The following shows support for handling general mathematical formulas.

More advanced support for type-in (III) ... electrical circuits

More advanced support for type-in (IV) ... or just some help in typing in normal code

More advanced support for type-in (V) ... or chinese

? IP: Can it be used today? Yes, probably, but only by Microsoft  Parts have probably gone into .NET

Thanks... to the aspectj team for letting me use some material from their tutorial Ulrich Eisenecker and Krzysztof Czarnecki for the permission to use some code examples and illustrations from their book „Generative Programming“ The Hyper/J team for allowing me to use some of their material Krzysztof Czarnecki for reviewing the slides and giving useful feedback Andreas Bohn for scanning illustrations.

Resources You will find information on many of the topics in this tutorial in the book Generative Programming by Ulrich Eisenecker and Krzysztof Czarnecki, Addison Wesley, 2000 Information on generative programming on the web can be found at www.generative-programming.org and various conference workshop pages. Information on aspect orientation can be found at aosd.net and www.aspectj.org. The former of the two contains a really good link collection.

Resources (II) Information about Multi-Dimensional Separation of Concerns can be found at www.research.ibm.com/hyperspace/MDSOC.htm Information on Intentional Programming is not available on the web anymore. Read E&C‘s book. In general, all of these topics are still (at least partly) subject to ongoing research – chances are that you will find information at conferences and associated workshops. Examples: OOPSLA, ECOOP, OT, ...

The end. Questions? Criticism? Opinions? build software like they build cars!