710 likes | 851 Views
Declarative Meta Programming. Programming Technology Lab Dept. Computer Science Vrije Universiteit Brussel Pleinlaan 2 – 1050 Brussel http://prog.vub.ac.be October 6, 2000. Today’s Schedule. 14:00 14:20 Tom Mens Welcome and introduction 14:20 14:50 Roel Wuyts
E N D
Declarative Meta Programming Programming Technology Lab Dept. Computer Science Vrije Universiteit Brussel Pleinlaan 2 – 1050 Brussel http://prog.vub.ac.be October 6, 2000
Today’s Schedule • 14:00 14:20 Tom Mens • Welcome and introduction • 14:20 14:50 Roel Wuyts • Demonstration of SOUL • 14:50 15:15 Kim Mens • Presentation of architectural conformance checking • 15:15 15:30 • Short coffee break
Today’s Schedule ctd. • 15:30 16:00 Tom Tourwe • Presentation of code optimisation • Demonstration of change propagation • 16:00 16:30 Johan Brichau • Short summary of TyRuBa • Demonstration of declarative combination of aspects • 16:30 17:00 Wolfgang De Meuter • Presentation of reuser-assisting wizards
1. Welcome and Introduction Programming Technology Lab Tom Mens tommens@vub.ac.be http://prog.vub.ac.be/~tommens
What is DMP? • merging declarative meta language with a standard object-oriented base language • e.g. SOUL and Smalltalk (Squeak) • explicit symbiosis between meta language and base language • base-level programs are expressed as terms, facts or rules in the meta level • allows declarative reasoning over, and manipulation of, object-oriented programs
What is DMP used for? • To build state-of-the-art software development tools • To support co-evolution in all facets and phases of software life-cycle • As a unifying approach that combines the research of many PROG researchers
Applications of DMP • Roel Wuyts: SOUL • Reasoning about the structure of OO systems using the Smalltalk Open Unification Language • Synchronisation of design and implementation • Kim Mens: architectural conformance checking • use logic programs to describe software architectures declaratively and check them against the implementation • (PhD dissertation, 2000) • Tom Tourwe: code optimisation & change propagation • a functional language with logic extensions to write declarative code transformations that • detect propagation of changes to source code • replace design patterns by optimized implementations
Applications of DMP ctd. • Kris De Volder: TyRuBa • a very expressive type system • a precompiler that uses logic programs to generate Java-code • (PhD dissertation, 1999) • Aspect-Oriented Programming (AOP) • Kris De Volder: using TyRuBa for AOP • Maja D'Hondt: expressing domain knowledge as a separate aspect that can be factored out from the base program • Johan Brichau: declarative combination of aspects • Wolfgang De Meuter & Maja D’Hondt • Using DMP techniques for guiding black-box and white-box reuse
2. SOUL Demonstration Programming Technology Lab RoelWuyts rwuyts@vub.ac.be Demonstration only. No slides available.
3. ArchitecturalConformance Checking Programming Technology Lab Kim Mens kimmens@vub.ac.be http://prog.vub.ac.be/~kimmens
Software architectures • describe the overall structure of a software system, abstracting away from its implementation details • provide a simple mental picture that allows software engineers to grasp the global structure • facilitate the understanding of software systems • improve maintainability, adaptability, reusability, … • … if they are up to date
Architectural drift • Architectural erosion and drift • implementation tends to drift away from the original architecture • changes are often made only at implementation level • Solution • architecture is more than documentation • architectural constraints should explicitly constrain the implementation • need to ensure conformance of the implementation to these architectural constraints
Conformance checking • How to keep architecture and implementation synchronised? • Architectural conformance checking • explicit description of the software architecture • bi-directional mapping between architecture and implementation • automated support for checking conformance of a software implementation to its architecture(s) • support for solving problems in case of conformance breaches
Declarative metaprogramming • use declarative meta programming to express and enforce architectural constraints • meta programming: • allows reasoning about some base language • declarative programming: • Prolog-like logic language as meta language • use logic expressions at meta-level to: • explicitly describe the software architecture • declare its mapping to the implementation • (implementation of conformance checking algorithm)
Case study: SOUL • SOUL • “Smalltalk Open Unification Language” • Prolog-like logic language that can reason about Smalltalk code • SOUL implementation • entirely in Smalltalk • contains about 100 classes • fairly well designed (coding conventions, design patterns) • class hierarchy resembles SOUL abstract syntax tree • 3 architectural views • ‘rule-based interpreter’ • ‘user interaction’ • ‘application architecture’
Clause Basic Clause Clauses Rule Query Abstract Term Cached Rule Fact Generate Predicate Term True Term Named Term Smalltalk Term Terms SOUL implementation Clauses: Terms: ... ...
Working Memory Working Memory Knowledge Base Knowledge Base Rule Interpreter Rule Interpreter Clause Selector Clause Selector Uses Data1 Uses Data1 Uses Data2 Uses Data2 Updates1 Updates1 Asks2 Asks2 Asks1 Asks1 Architecture: ‘rule-based interpreter’ view(ruleBasedInterpreter). … concept(ruleBasedInterpreter,'Rule Interpreter'). relation(ruleBasedInterpreter,'Updates_1'). … port(ruleBasedInterpreter,'Rule Interpreter', 'interpret'). role(ruleBasedInterpreter,’Asks_1','interrogator'). … link(ruleBasedInterpreter,'Rule Interpreter','unify', 'Asks_1','interrogator'). link(ruleBasedInterpreter, 'Clause Selector’, 'matching clauses’,'Asks_1','interrogated’). …
Uses Data2 Uses Data1 Clause Selector Knowledge Base Updates1 Asks1 Rule Interpreter Working Memory Asks2 Architectural mapping (1) Architecture Architectural mapping Implementation ?
Uses Data2 Implementation Uses Data1 qzfdxgf Clause Selector Knowledge Base qzfdxgf qzfdxgf Updates1 qzfdxgf Asks1 Rule Interpreter Working Memory qzfdxgf qzfdxgf Asks2 qzfdxgf qzfdxgf qzfdxgf Architectural mapping (2) Architecture Architectural Abstraction Architectural Instantiation ?
Uses Data2 Implementation Uses Data1 qzfdxgf Clause Selector Knowledge Base qzfdxgf qzfdxgf Updates1 qzfdxgf Asks1 Rule Interpreter Working Memory qzfdxgf qzfdxgf Asks2 qzfdxgf qzfdxgf qzfdxgf “Cross-cutting” mappings Architecture Architectural Abstraction Architectural Instantiation
Uses Data2 Implementation Uses Data1 qzfdxgf Clause Selector Knowledge Base qzfdxgf qzfdxgf Updates1 qzfdxgf queryInterpreter Asks1 Rule Interpreter Working Memory qzfdxgf qzfdxgf Asks2 qzfdxgf qzfdxgf qzfdxgf Software classifications Architecture Architectural Abstraction Architectural Instantiation
Uses Data2 Implementation Uses Data1 qzfdxgf Clause Selector Knowledge Base qzfdxgf qzfdxgf Updates1 qzfdxgf Asks1 Rule Interpreter Working Memory qzfdxgf qzfdxgf Asks2 qzfdxgf qzfdxgf qzfdxgf Virtual classifications (1) Architecture Architectural Abstraction Architectural Instantiation classifiedAs(method('queryInterpreter’), Method) :- classifiedAs(class('soul'), Class), interpretingProtocolName(ProtocolName), protocolName(Protocol, ProtocolName), methodInProtocol(Class, Protocol, Method).
queryInterpreter Rule Interpreter Predicate for checking classified artefacts or generating a collection of artefacts Generated or checked artefact Virtual classifications (2) classifiedAs(method('queryInterpreter'),Artef):- classifiedAs(class('soul'), Class), interpretingProtocolName(ProtocolName), protocolName(Protocol, ProtocolName), methodInProtocol(Class, Protocol, Artef). interpretingProtocolName('interpreting'). interpretingProtocolName('interpretation'). …
Virtual classifications (3) • “intentional” • describe how to “compute” their elements • described as logic predicates over implementation • expressive, readable and concise • can be used in multiple ways • Generating: which artifacts belong to classification? • Checking: does artifact belong to this classification?
Uses Data2 Uses Data1 Clause Selector Knowledge Base Updates1 Asks1 Rule Interpreter Working Memory Asks2 Virtual dependencies (1) Architecture Architectural Abstraction Implementation Architectural Instantiation asks_M_M(M1, M2) :- isAskedBy_M_M(M2, M1). isAskedBy_M_M(M2, M1) :- classImplementsMethodNamed(C1, M1N, M1), className(C1, C1N), methodName(M2, M2N), … qzfdxgf qzfdxgf qzfdxgf qzfdxgf
Virtual dependencies (2) Asks1 asks_M_M(M1, M2) :- isAskedBy_M_M(M2, M1). isAskedBy_M_M(M2, M1) :- classImplementsMethodNamed(C1, M1Name, M1), className(C1, C1Name), methodName(M2, M2Name), isSentTo(C1Name, M1Name, Rcvr, M2Name, Args), mayHaveType_E_M_C(Rcvr, M1, RcvrClass), classImplementsMethod(RcvrClass, M2), isUsedBy_E_M(send(Rcvr, M2Name, Args), M1). asks_M_M(M1, M2) :- isAskedBy_M_M(M2, M1).
Virtual dependencies (3) • declare high-level relationships among implementation artifacts • “derived” from primitive implementation dependencies • e.g., transitive closures, complex interactions, … • described as logic predicates over implementation • Expressive, concise, readable, intentional • can be used in multiple ways • Checking: does relationship hold between artifacts? • Generating: find all artifacts for which relationship holds. • Browsing/searching: find artifacts related to a given one.
Architecture Architectural mapping Implementation Implementation Abstraction Architectural Instantiation qzfdxgf Clause Selector Knowledge Base Asks 2 qzfdxgf qzfdxgf Quantifier qzfdxgf Virtual dependency Asks1 Uses Data2 Argument Filter Uses Data1 qzfdxgf qzfdxgf Rule Interpreter Working Memory Virtual classification qzfdxgf qzfdxgf Updates1 qzfdxgf qzfdxgf Arch. mapping: summary
Uses Data2 Implementation Uses Data1 qzfdxgf Clause Selector Knowledge Base qzfdxgf qzfdxgf Updates1 qzfdxgf Asks1 Rule Interpreter Working Memory qzfdxgf qzfdxgf queryInterpreter Asks2 qzfdxgf qzfdxgf qzfdxgf Conformance checking Architecture Architectural Abstraction Architectural Instantiation ruleSelection asks_M_M(M1, M2)
exists exists queryInterpreter ruleSelection 1 2 methodFilter methodFilter asks_M_M Conf. checking algorithm Rule Interpreter Asks1 Clause Selector exists(filteredIsClassifiedAs(queryInterpreter, methodFilter,X1), exists(filteredIsClassifiedAs(ruleSelection, methodFilter,X2), asks_M_M(X1,X2))) r
Conclusion: strengths • Architectural mapping is • very expressive • full expressive power of LMP • intentional • virtual classifications and dependencies • concise and intuitive • declarative nature of LMP • well-chosen implementation abstractions: • virtual classifications, filters and set qualifiers • virtual dependencies
Conclusion: weaknesses • Architectural mapping • lacks efficiency • is defined manually • requires experience • can be abused • may contain bugs • Partial solution • predefined library of mapping predicates • optimisations, e.g. caching techniques
4. Code Optimisation Programming Technology Lab Tom Tourwe ttourwe@vub.ac.be
Research Topic(s) • Make high-level design information about a system explicitly available so that it can be used for: • documentation purposes • (more efficient) code generation purposes • impact analysis purposes
Efficient Code Generation: Motivation • Frameworks must be as flexible as possible • need to be reusable, adaptable, maintainable, ... • use polymorphism, late binding, abstractions and indirections (see e.g. Design Patterns) • This comes at a certain cost • many more message sends • compiler cannot easily reduce the number of messages • most of the ‘real’ work is done in only 10% of the methods
Efficient Code Generation: Main Idea • FW developer has detailed knowledge about the design & implementation of the FW • FW user has detailed knowledge about the specific FW instantiations • Make this knowledge explicit and use it to perform more significant optimizations • break unnecessary abstractions • remove extra indirections • replace dynamic message sends with static ones • ...
Efficient Code Generation:Main Idea • What we are doing • automatically perform those optimizations that normally only a developer would do to optimize the performance • Benefits • original flexible code is still available • much less error prone • the behavior of the system is preserved
Efficient Code Generation: In Practice • use declarative medium to express high-level design information (using rules + facts) • specify design information by describing the design patterns used in the FW • describe instantiations of the FW by pointing out how they use the patterns • use declarative medium to describe source-to-source transformations based on the available information (using functions)
Example: Pattern Description (assert classParticipant ([#AbstractFactoryDP] [#Example] [#AbstractFactory] [#AbstractFactory])) (assert classParticipant ([#AbstractFactoryDP] [#Example] [#ConcreteFactory] [#ConcreteFactory1])) (assert classParticipant ([#AbstractFactoryDP] [#Example] [#ConcreteFactory] [#ConcreteFactory2])) (assert methodParticipant ([#AbstractFactoryDP] [#Example] [#FactoryMethod] [#AbstractFactory] [#newProductA])) (assert methodParticipant ([#AbstractFactoryDP] [#Example] [#FactoryMethod] [#AbstractFactory] [#newProductB])) (assert classParticipant ([#AbstractFactoryDP] [#Example] [#ConcreteProduct] [#ConcreteProductA1])) (assert classParticipant ([#AbstractFactoryDP] [#Example] [#ConcreteProduct] [#ConcreteProductB1])) ….
Example:Instantiation Description (assert framework ([#MyFramework])) (assert instance ([#MyFramework] [#MyFirstInstance])) (assert instance ([#MyFramework] [#MySecondInstance])) (assert usesParticipant ( [#MyFirstInstance] [#AbstractFactoryDP] [#Example] [#ConcreteFactory1])) (assert usesParticipant ([#MySecondInstance] [[#AbstractFactoryDP] [#Example] [# ConcreteFactory2]))
Example:Transformation Description (define (optimizeAbstractFactoryForFWInstance anInstanceName) (define result (concreteFactoryAndSelectorForFWInstance anInstanceName (var [#aClass]) (var [#aSelector]))) (define concreteFactory (assoc [#aClass] result)) (define selector (assoc [#aSelector] result)) (do (sendersOf selector) (lambda (aMethodPT) (inline aMethodPT selector (getMethodBody (getMethod concreteFactory selector)))))) (definerel (concreteFactoryAndSelectorForFWInstance aFWInstance aConcreteFactory aSelector) (land (usesParticipant aFWInstance [#AbstractFactoryDP] [#Example] aConcreteFactory) (methodParticipant [#AbstractFactoryDP] [#Example] [#FactoryMethod] (wildcard) aSelector))) (optimizeAbstractFactoryForFWInstance [#MyFirstInstance])
Efficient Code Generation:Furthermore ... • Numerous other examples are available • various other design patterns • combination of patterns • Impact of these techniques on more traditional techniques • e.g. if we know the concrete factory object that is used, we know the concrete objects a system uses and we can replace many dynamic message sends with static ones.
5. TyRuBa Programming Technology Lab Johan Brichau johan.brichau@vub.ac.be