Farbe! Generative Software Engineering 3. Integrating Handwritten Code Prof. Dr. Bernhard Rumpe Software Engineering RWTH Aachen University http://www.se-rwth.de/ Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Generation and Handcoding Page 2 Not everything shall and can be generated • Code is fine, when model would not be more abstract How to integrate hand written code with generated code • General principles • How they apply in DEX hand written code Parameterized generator Generator script/template Map: concept code API generated code + included parts components components components API model Predefined Predefined Predefined runtime system Environment: hardware, GUI, frameworks Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Goals of Handcoding Page 3 The goal of handcoding • extend domain model • add functionality to generated code • customize generated code Benefits of handcoding • Normally re-generation is not needed • Reuse of existing handwritten code • Tooling (e.g. editor) for the programming language can be used DEX supports extensions for • domain model with attributes and method bodies • domain model with signatures • generated GUI code Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Handwritten Code Page 4 Handcoding (HC) = the process of writing code manually (by hand) vs. generating code (GC), where the code comes from the generator. Important questions to decide: • Artefacts of interest for users? • What to write, what to read and understand • Generating and handcoding in which order? • Repeatable generation? • Dependences between the forms of code? • Methodical alignment • Which knowledge is necessary for • the developer • the generating tool • the compiler, linker and Java virtual machine Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Mixing of HC and Generation in Artifacts Page 5 Scenario A: • 1. Let the generator produce code frames in files • 2. Add code manually, e.g. method implementations Advantage: • HC is well integrated inside GC Disadvantage: • “One shot” generation only • Model becomes irrelevant because useless after generation, • Changes in models impossible • Doesn’t support evolution Decision: • Strict separation of handcoding and generation on artifacts! • Each artifact (= file) is either handcoded or generated. Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Mixing of HC and Generation in Artifacts -2 Page 6 Scenario B: • 1. Let the generator produce code frames in files • Generate explicit markers to protect regions of HC • 2. Add code manually in protected regions Advantage: • Easy to use and easy to identify where to handcode Necessary: • Extraction of HC for inclusion in next generation step Disadvantages: • Not robust e.g. against editing • Vulnerable against advanced tools (e.g. beautifiers) • No clean full generation possible • Generated code needs to be version controlled public class Person { public String getFullname () { /* [protected GEN#XwgHEge23qp (method getFullname)] */ // to be handcoded /* [/protected GEN#XwgHEge23qp] */ } } Java «gen» «hc» «gen» Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Separation of HC and GC in Artifacts Page 7 Each artifact (file) is either HC or GC. Advantages: • Only sources (HC and models) need to be versioned • this greatly reduces conflicts • and helps understanding progress from the version control logs • Developers normally don’t read generated code • just understand the interfaces • Clean & regenerate always works Necessary: • HC needs to be written and integrated Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Alternatives for Integration of HC Page 8 1. Reference it from the model. • Ch. 2 for attributes & • DEX would allow method signatures & bodies in a CD, but that pollutes the CD (not recommended) 2. Compiler: no that doesn’t work • We would need “partial classes”, not provided by Java 3. When starting at runtime • 3a) Write your own main()-function and call HC to configure GC • that is fine and actually used by many frameworks • 3b) write static-code pieces: no, because classes are loaded lazy in Java (and thus static code may be never called) 4. Config file • Works, but is error prone because it looses type safety. 5. Generator identifies HC and integrates references to it • HC to follow naming conventions to be identified Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Overview of Product with HC Page 9 Generated DEX product has this architecture • HC internal architecture is out of generators control: • But it is recommended to maintain the architecture GUI hand coded generated RTE standard components hand coded generated RTE standard components hand coded generated RTE standard components Application Core Persistence Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Generator detects HC, the Principle: Page 10 Approaches DEX uses: (Placeholder X) 1. Extending signature and implementation of domain class X.java • When XSIG.java exists inherit it in X.java • When XEIMP.java exists use it in the factory (assuming it is a subclass of XIMP) 2. Specific Hot Spots documented in the generator handbook. Extending signature, implementation and hot spots • is based on naming conventions (e.g. XSIG, XEIMP) Farbe! Generative Software Engineering 3. Integrating Handwritten Code 3.1. Extension of Generated Code Prof. Dr. Bernhard Rumpe Software Engineering RWTH Aachen University http://www.se-rwth.de/ Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Generated Artifacts in DEX Page 12 What DEX does: One class is mapped to • an interface • an implementation, and • a factory for object creation CD SocNet class Group extends Profile { // … String purpose; } «interface» Group + String getPurpose(); + void setPurpose(String s) GroupImpl Java … … - String purpose; + String getPurpose(); + void setPurpose(String s) «gen» GroupFactory +static Group create() #Group doCreate() … Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Extending the Implementation Page 13 … and adapting generated functionality by defining HC class XEIMP that inherits GC «gen» «interface» Group «gen» «gen» GroupFactory Product-CD +static Group create() #Group doCreate() … GroupImpl «gen» handcoded Java class «hc» GroupEIMP import GroupEIMP; … class GroupFactory … protected Group doCreate() { return new GroupEIMP(); } Generator adapts only the GroupFactory • now GroupEIMP objects are created Necessary: • GroupEIMP is subclass of GroupImpl • “EIMP” was chosen to prevent occasional use • “EIMP” = extended implementation Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen adapted Factory How to add handcoded Java classes Page 14 Two steps are required to add handcoded Java classes in DEX • 1. Create handcoded Java class GroupEIMP • 2. Implement the full and the empty constructor of GroupImpl Java public class GroupEIMP extends GroupImpl { public GroupEIMP() { super(); } «hc» attributes of class GroupImpl protected GroupEIMP(String profileName, boolean isOpen, Date created, String purpose) { super(profileName, isOpen, created, purpose); } } • (3. Override methods and add attributes/methods …) Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen How to add attributes to the domain model Page 15 The domain model can be extended by adding attributes Java public class GroupEIMP extends GroupImpl { «hc» private String newAttribute = "My String"; // ... } new domain model attribute Properties of these attributes • not visible in the GUI • not saved in the database Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen How to add Methods Page 16 Application functionality can be extended by adding new methods • This brings the “meat” to the application Java public class GroupEIMP extends GroupImpl { // ... public String groupOverview (){ return "Group Overview: " + getPurpose() + " " + getHeadcount(); } } Limitations • New methods do not appear in the signature of the Group interface «hc» new method Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen How to implement derived Attributes Page 17 Derived attribute does have an empty default implementation as get/retrieve-method Add meaning to the derived attribute using HC by overriding the getter public class GroupEIMP extends GroupImpl { // ... @Override public int getHeadcount() { return sizeMembers()+ sizeOrganizers(); } } Every generated method can be overwritten • Incl. ordinary get/setters for attributes • Association methods Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen DEX Example for Derived Attributes Page 18 derived attributes are shown in the gui Model-CD Group /int headcount; … Java «hc» Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Overwriting Generated Methods Page 19 Generated methods can be adapted by HC Java Model-CD Group boolean isOpen Date created String purpose /int headcount overrride «hc» public class GroupEIMP extends GroupImpl { //constructors ... public void setPurpose(String pname) { StatusBar.write("Group "+profileName +" new purpose "+pname) super.setPurpose(pname); } } Log result is shown in the bottom line on the GUI Logging Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Extending the Implementation Page 20 Advantages: • relatively little effort to adapt implementation • adaptable reuse of generated implementation • smooth integration of HC artefact Product-CD «gen» «interface» Group «gen» Restriction: • Only one subclass supported GroupImpl «hc» GroupEIMP Disadvantages: • IDEs don’t assist when superclass hasn’t been generated yet • = many false errors are reported after fresh checkout or a clean • some risk of unwanted occasional detection of “*EIMP” • re-generation necessary after EIMP-class is created (or deleted) to get adapted factory Farbe! Generative Software Engineering 3. Integrating Handwritten Code 3.2. Extending Data Model Signature Prof. Dr. Bernhard Rumpe Software Engineering RWTH Aachen University http://www.se-rwth.de/ Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Extending the Signature of a Class Page 22 by defining HC interface XSIG that inherits to GC Product-CD «hc» public interface GroupSIG { String getFullname(); } «interface» GroupSIG «gen» 1. Generator detects XSIG.java 2. Generated code is adapted to implement the new interface 3. Generator also expects XEIMP.java, because XImpl is now abstract «interface» Group «gen» GroupImpl «hc» GroupEIMP Signature extensions (methods) are inherited to interface X.java and handcoded in XEIMP.java “Sandwich”-Principle for extension Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen How to add signature extensions Page 23 Required steps • 1. Add handwritten Java interface XSIG • 2. Add handwritten Java class XEIMP • 3. Implement new methods in XEIMP Product-CD «hc» «interface» GroupSIG handwritten Java interface Java «gen» public interface Group extends dex.socnet.GroupSIG { //... } public abstract class GroupImpl implements dex.socnet.Group { //... } «gen» «interface» Group «gen» GroupImpl «hc» GroupEIMP Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Mapping Model Inheritance and HC Extension Page 24 Inheritance and implementation relation is preserved DEIMP inherits CEIMP indirectly through DImpl Model-CD interface A; interface B; class C implements A; class D extends C implements B; «interface» ASIG «interface» CSIG «interface» A «interface» C «interface» BSIG «interface» DSIG «interface» B «interface» D Product-CD «gen» «abstract» CImpl CEIMP «abstract» DImpl DEIMP Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Signature Extensions Summary Page 25 Advantages • Separation of generated and handwritten artifacts • Signature extensions in HC interfaces • Supports redefinition of generated functionality • Supports implementation of internally available methods and attributes Disadvantages/problems • Signature of methods need to be repeated at implementation • Re-generation is necessary when SIG/EIMP-class is added or removed Farbe! Generative Software Engineering 3. Integrating Handwritten Code 3.3. Hot Spots for the DEX GUI Prof. Dr. Bernhard Rumpe Software Engineering RWTH Aachen University http://www.se-rwth.de/ Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Hot Spot Page 27 A hot spot is a place in the generated code that is planned for adaptation by handwritten code. The adaptation is carried out through the generator detecting and including appropriate HC. Hot spot documentation needs: • A) How does a hot spot look like • e.g. naming conventions for the class • B) Signature the hot spot has to provide • C) What is the API the hot spot can use The approach is similar to framework hot spots. Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Hot Spots in DEX Page 28 Often the GUI of a DEX product needs adaptation • More functions, more screens, nicer appearance, … • GUI can be customized by adding handwritten extensions DEX has e.g. hot spots prepared for • Menu Extension • Home Screen Adaptation • Panel Extensions • Startup and TearDown Phases Adapting a hot spot needs some knowledge about the mechanisms of the adapted GUI. Examples of DEX SocNet adaptations: • see DEX website: http://www.monticore.de/dex/ Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Hot Spot: Menu Extension Page 29 Purpose: Add menu items Hot spot class: MainWindowViewEIMP Methods to override: • extendMenu() Available API: • addMenuItem(), … public class MainWindowViewEIMP extends MainWindowView { //constructors public void extendMenu() { JideMenu m = new JideMenu("StatusBar"); JMenuItem item = new JMenuItem("print"); m.add(item); item.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { StatusBar.write("Menue item print was clicked"); }}); addMenuItem(m); } } Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Java «hc» How to Adapt the Home Screen Page 30 Purpose: Customize home screen Hot spot class: MainWindowPresenterEIMP Methods to override: • setHomeTitle() Available API (see code): • Swing public class MainWindowPresenterEIMP extends MainWindowPresenter { //constructors public JPanel setHomeTitle() { JPanel panel = new JPanel(); panel.setLayout(null); JLabel lblSystem = new JLabel("SocNet System"); lblSystem.setHorizontalTextPosition(SwingConstants.CENTER); lblSystem.setHorizontalAlignment(SwingConstants.CENTER); lblSystem.setFont(new Font("Tahoma", Font.PLAIN, 40)); panel.setLayout(new BorderLayout(0, 0)); panel.add(lblSystem, BorderLayout.CENTER); return panel; } } Java «hc» Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Adapting Panels Page 31 Purpose: Customize Panel for Specific Domain Class “X” Hot spot class: XEditPanelViewEIMP Methods to override: • getXPanelComponent() Available API (see code): • Swing • Reusable: Methods from XEditPanelView TagEditPanelView Product-CD «gen» «interface» ITagEditPanelView «gen» TagEditPanelView «hc» TagEditPanelViewEIMP public class TagEditPanelViewEIMP extends TagEditPanelView { //constructors public ITagPanelComponentView getTagPanelComponent() { //... } } Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen StartUp & TearDown Page 32 Purpose: Add startup and teardown actions or takeover control completely Hot spot class: XControllerEIMP (for model X.cd) Methods to override: • startUp() • tearDown() Available API (see code): • Reusable: Methods from AbstractController public class SocNetControllerEIMP extends SocNetController{ //constructors protected void startUp() { //... some startUp actions } protected void tearDown() { //... some tearDown actions } } Java «hc» Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Summary – Lessons learned Page 33 Hot spots are HC classes that replace generated classes • and at the same time inherit their functionality for reuse Hot spots can be used for various purposes: • Signature extension • Method overwriting • Functionality extension Hot spots allow to inject HC into a generated system, thus adapting it for specific needs Hot spots are filled during the generation process • and identified through naming conventions Hot spots are usually model-specific Farbe! Generative Software Engineering 3. Integrating Handwritten Code 3.4. More Adaptation Mechanisms Prof. Dr. Bernhard Rumpe Software Engineering RWTH Aachen University http://www.se-rwth.de/ Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Class Overriding Page 35 The principle: • When X.java exists in handcoded form just use it and generate nothing Required: • HC Java can be distinguished from GC • e.g. disjoint directories for HC and GC Advantage: • Anything can easily be adapted Disadvantage: • X.java: nothing is generated anymore; no reuse • Brittle: adaptations of model need to be tracked manually in HC Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Class Overriding plus Prototypes Page 36 The principle: • When X.java exists in handcoded form use it, but generate XProto.java instead • Xproto.java can be used as superclass for HC X.Java Advantage: • Anything can easily be adapted • Reuse of generated code possible, which is still there Disadvantage: • Brittle: adaptations of model need to be tracked manually in HC Remark: very similar to the Dex approach using EIMPL Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Use GUI as Framework Page 37 The principle: • The generated code may be adaptable by classic programming techniques, e.g. usable as framework Required: • Explicit hot spots (= empty methods) that can be overwritten in subclasses • Possibilities to adapt / configure in the generated code Advantage: • Traditional form of adaptation, no interaction with generator Disadvantage: • Generated code needs to be a framework Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Delegation to HC Page 38 The principle: • The generated code uses delegation to hot spots Similar to the used inheritance approach Advantage: • More flexible, e.g. individual delegators for each method Disadvantage: • More complex: more objects to manage, • Objects have substructure Product-CD Model-CD Person Person «gen» delegate «gen» «interface» PersonDelegate String getFullName() String getFullName() String getFullName() delegator «hc» PersonImpl Delegation delegate String getFullName() Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Partial Classes Page 39 The principle: • The language allows classes to be distributed over several artefacts, called “partial classes” Advantage: • Generation of classes piecewise is possible Disadvantage: • Java doesn’t support this (It can be mimicked by a design pattern) • Generated functionality cannot be redefined «gen» partial class Person{ string firstName; //… } Model-CD Person String firstName C# classes have the same names String getFullName() «hc» partial class Person{ public string getFullname(){ //… } } Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Aspect Orientation for HC-Injection Page 40 The principle: • Use an Aspect-Oriented Language • Add functionality in form of Aspects Disadvantage: • From SE point of view aspects are harmful. Not recommended to use an AOP language for coding. (Much worse than goto) Java public class Person { «gen» //… generated impl AspectJ «hc» public aspect PersonAspect { pointcut pcClearMembers(Person p): execution(* Person. clearMembers()) && target(p); public void clearMembers() { //… default impl } void around(Person p): pcClearMembers (p) { // … handwritten impl } } } p = instance on which method shall be executed Handwritten impl. in advice Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Embed Action Language in Model Page 41 The principle: • Embed a language for method implementation within the modelling language Advantage: • We get completely rid of handcoding! Disadvantage: • Large model: confusing? • IDEs are less elaborated for such kind of programming Examples: • MontiCore (DEX) provides possibilities to add methods and method bodies, e.g. in Java and python-style • UML has its own action language defined Prof. Dr. B. Rumpe Lehrstuhl für Software Engineering RWTH Aachen Model Refers to Actions Page 42 The principle: • Add references to the implementations in the model Variants: • 1) GC calls the referenced HC: like delegation • 2) Generator weaves the referenced artefact into the GC Disadvantage: • Model gets polluted • Model contains references to artefacts that should be developed after the model unnecessary • IDEs are less elaborated for such kind of programming • For 2: Checking of syntactical correctness is deferred to the compiler (and thus too late)