Farbe! Generative Software Engineering 3. Integrating Handwritten Code Prof. Dr. Bernhard Rumpe University http://www.se-rwth.de/ Page 2 Generation and Handcoding 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 model Parameterized generator hand written code API generated code + included parts API Predefined Predefined Predefined components runtime system Generator script/template Environment: hardware, GUI, frameworks Map: concept code
Page 3 Goals of Handcoding The goal of handcoding extend domain model add functionality to generated code customizegenerated 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 Page 4 Handwritten Code 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 virtual machine
Page 5 Mixing of HC and Generation in Artifacts 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. Page 6 Mixing of HC and Generation in Artifacts -2 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] */
Page 7 Separation of HC and GC in Artifacts 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 Page 8 Alternatives for Integration of HC 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 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 (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
Page 9 Overview of Product with HC 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 Application Core hand coded generated RTE standard components Persistence hand coded generated RTE standard components Page 10 Generator detects HC, the Principle: 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 University http://www.se-rwth.de/ Page 12 Generated Artifacts in DEX 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 GroupFactory +static Group create() #Group docreate() - String purpose; + String getpurpose(); + void setpurpose(string s)
Page 13 Extending the Implementation and adapting generated functionality by defining HC class XEIMP that inherits GC handcoded class «interface» Group GroupImpl GroupEIMP GroupFactory +static Group create() #Group docreate() 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 Product-CD import GroupEIMP; class GroupFactory protected Group docreate() { return new GroupEIMP(); adapted Factory Page 14 How to add handcoded classes Two steps are required to add handcoded classes in DEX 1. Create handcoded class GroupEIMP 2. Implement the full and the empty constructor of GroupImpl public class GroupEIMP extends GroupImpl { public GroupEIMP() { super(); 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 )
Page 15 How to add attributes to the domain model The domain model can be extended by adding attributes public class GroupEIMP extends GroupImpl { private String newattribute = "My String"; //... new domain model attribute Properties of these attributes not visible in the GUI not saved in the database Page 16 How to add Methods Application functionality can be extended by adding new methods This brings the meat to the application public class GroupEIMP extends GroupImpl { //... public String groupoverview (){ return "Group Overview: " + getpurpose() + " " + getheadcount(); new method Limitations New methods do not appear in the signature of the Group interface
Page 17 How to implement derived Attributes Derived attribute does have an empty default implementation as get/retrieve-method Add meaning to the derived attribute using HC by overriding the getter Model-CD Group /int headcount; 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 Page 18 DEX Example for Derived Attributes derived attributes are shown in the gui
Page 19 Overwriting Generated Methods Generated methods can be adapted by HC Group boolean isopen Date created String purpose /int headcount Model-CD overrride 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 Page 20 Extending the Implementation Advantages: relatively little effort to adapt implementation adaptable reuse of generated implementation smooth integration of HC artefact Product-CD «interface» Group Restriction: Only one subclass supported GroupImpl 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 University http://www.se-rwth.de/ Extending the Signature of a Class Page 22 by defining HC interface XSIG that inherits to GC Product-CD public interface GroupSIG { String getfullname(); «interface» GroupSIG 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 GroupImpl GroupEIMP Signature extensions (methods) are inherited to interface X.java and handcoded in XEIMP.java Sandwich -Principle for extension
Page 25 Signature Extensions Summary 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 University http://www.se-rwth.de/
Page 27 Hot Spot 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. Page 28 Hot Spots in DEX 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/
Page 29 Hot Spot: Menu Extension 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); Page 30 How to Adapt the Home Screen 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;
Page 31 Adapting Panels 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 Product-CD «interface» ITagEditPanelView TagEditPanelView TagEditPanelView TagEditPanelViewEIMP public class TagEditPanelViewEIMP extends TagEditPanelView { //constructors public ITagPanelComponentView gettagpanelcomponent() { //... Page 32 StartUp & TearDown 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
Page 33 Summary Lessons learned 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 University http://www.se-rwth.de/
Page 35 Class Overriding The principle: When X.java exists in handcoded form just use it and generate nothing Required: HC 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 Page 36 Class Overriding plus Prototypes 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. 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
Page 37 Use GUI as Framework 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 Page 38 Delegation to HC 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 String getfullname() Person String getfullname() delegate «interface» PersonDelegate String getfullname() delegator Delegation delegate PersonImpl String getfullname()
Page 39 Partial Classes The principle: The language allows classes to be distributed over several artefacts, called partial classes Advantage: Generation of classes piecewise is possible Disadvantage: doesn t support this (It can be mimicked by a design pattern) Generated functionality cannot be redefined Person String firstname Model-CD String getfullname() partial class Person{ string firstname; // partial class Person{ public string getfullname(){ // C# classes have the same names Page 40 Aspect Orientation for HC-Injection 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) public class Person { // generated impl public void clearmembers() { // default impl AspectJ public aspect PersonAspect { pointcut pcclearmembers(person p): execution(* Person. clearmembers()) && target(p); void around(person p): pcclearmembers (p) { // handwritten impl p = instance on which method shall be executed Handwritten impl. in advice
Page 41 Embed Action Language in Model 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 and python-style UML has its own action language defined Page 42 Model Refers to Actions 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)