Creating Domain-Specific Modeling Languages that Work: Hands-on
Juha-Pekka Tolvanen
© MetaCase/JPT
1
Schedule 9:00 Introducing Domain-Specific Modelling – –
Where to apply – and why Real life examples from various domains
9:40 Building modelling languages – –
Identifying language concepts Group work
(10:30-11:00 Coffee)
12:30 Lunch 14:00 Group work continues –
Language rules, notation, model reuse
(16:00-16:30 Coffee)
16:30 Building code generators – –
Patterns for generators by type of output Adding a Domain Framework
17:40 Questions & discussion 18:00 End © MetaCase/JPT
2
What is Domain-Specific Modelling? Why do we need something new? Introducing Domain-Specific Modelling (DSM) Where to apply – and why Real life examples Industrial experience reports
© MetaCase/JPT
3
How has productivity improved? "The entire history of software engineering is that of the rise in levels of abstraction" Grady Booch
New general purpose programming languages have not increased productivity UML and visualization of code have not increased productivity Abstraction of development can be raised above current level... ... and still generate full production code *Software Productivity Research & Capers Jones, 2002 © MetaCase/JPT
4
How do we use models? Separate model & code
CASE
Model
Model
Code
Code
?
Finished product
?
Finished product
Code Roundtrip visualization
MDA®
DSM
'Model'
'Model'
Model Model Model 2n
Model
Code
Code
Code
Code
Finished product
Finished product
Finished product
Finished product
Model alone should be sufficient in most cases – No need to look at code © MetaCase/JPT
5
Domain Idea
Solve problem in domain terms
Modelling functionality vs. modelling code Map to code, implement
Map to code, implement
Finished Product
Code
Generate, Add bodies Map to UML
No need to map!
© MetaCase/JPT
Assembler
Model in DSM language
UML Model
Generate code
Domain Framework
6
Example: Digital wristwatch Domain Idea
Product family – Models: His, Hers, Sport, Kid, Traveler, Diver…
Finished Product
Reusable component applications – Time, Alarm, Timer, WorldTime, StopWatch…
Hide complexity from modeller – Model-View-Controller separation – Separate thread for real-time display
Implementation in Java – Also in MIDP and in C
No need to map!
© MetaCase/JPT
Model in DSM language
Generate code
Domain Framework
7
What is domain-specific modelling Captures domain knowledge (as opposed to code) – – – –
Raise abstraction from implementation world Uses domain abstractions Applies domain concepts and rules as modelling constructs Narrow down the design space
Leverages in-house expertise to build automation – Best developer defines modelling language and generators
Lets developers design products using domain terms Apply familiar terminology Solve the RIGHT problems Solve problems only ONCE! – directly in models, not again by writing code, round-trip etc.
© MetaCase/JPT
8
Why is the vision possible (now)? Need to fit only one company’s requirements! – Focus on single range of products
Modelling is Domain-Specific – Works for one application domain, framework, product family etc. – Language has concepts people are already familiar with – Models used to solve the problem, not to visualize code
Generator is Domain-Specific – Generate just the code needed from models • Efficient full code • No manual coding afterwards • No reason for round-tripping
– Generator links to existing primitives/components/platform services etc. – Can generate 3GL, Assembler, object-oriented, XML, etc. © MetaCase/JPT
9
Where to apply? Repetitive development tasks – Large portion of the work similar to earlier products (or several products made in parallel)
Domain expertise needed – Non-programmers can participate
These normally include: – – – – –
Product Family Platform-based development Configuration Business rule definitions Embedded devices
© MetaCase/JPT
10
What is Domain-Specific Modelling? Why do we need something new? Introducing Domain-Specific Modelling (DSM) Where to apply – and why Real life examples Industrial experience reports
© MetaCase/JPT
11
Case: Insurance products & eCommerce Developing portal for insurances and financial products Need to specify several hundred financial products Insurance experts visually specify insurance products and generate code to the portal Comparison to hand-writing Java after first 30 products = DSM at least 3 times faster, fewer errors
© MetaCase/JPT
12
© MetaCase/JPT
13
© MetaCase/JPT
14
Case: VoiceMenu for microcontroller Home automation system to remote control lights, heating, alarms, etc. VoiceMenus are programmed straight to the device with assembler-like language (8bit) Modelling language to define overall menu structure and individual voice prompts Code generator produces 100% of menu implementation Development time for a feature from a week to a day!
© MetaCase/JPT
15
© MetaCase/JPT
16
© MetaCase/JPT
17
What is Domain-Specific Modelling? Why do we need something new? Introducing Domain-Specific Modelling (DSM) Where to apply – and why Real life examples Industrial experience reports
© MetaCase/JPT
18
Let’s look at industry experience: Some reported cases Nokia; Mobile Phone product line Bell Labs / AT&T / Lucent; 5ESS telecommunications switch, EADS: Tetra terminals Panasonic: embedded UI Honeywell; embedded software architectures Polar Electro: heart rate monitors ORGA; SIM toolkit & JavaCard Pecunet; B2B E-Business: insurance LexiFi; mlFi, financial contracts DuPont; Activity Modelling NASA; Architecture Definition Language NASA ASE group; Amphion NASA JPL; embedded measurement systems USAF; Message Transformation and Validation … See reported cases at www.DSMForum.org © MetaCase/JPT
19
Experiences from practice "5-fold productivity increase when compared to standard development methods" "A module that was expected to take 2 weeks now took 1 day from the start of the design to the finished product" "The quality of the generated code is clearly better, simply because the modelling language rules out errors, eliminating them already in the design stage" "Eliminated our need to software development activities" © MetaCase/JPT
outsource
20
Productivity increase from DSM
* Productivity proportional to earlier practice © MetaCase/JPT
21
Detailed comparison studies Panasonic (Safa, 2007) Creating DSM solution
Coding
Product 1 Product 2 DSM
Product 3 Product 4 0
5
10
15
20
Polar (Kärnä et al., 2009)
25
DSM
5
10
15
20
35
Product 5
Days
Coding
0
30
25 Days
Creating DSM solution Product 1 Product 2 Product 3 Product 4 Product 5 Product 6 Product 7
Language workbenches make moving to DSM feasible – Can focus on language design, not on creating tooling © MetaCase/JPT
22
What engineers say: DSM solution development time "I could define a domain-specific language in about six hours - design, testing and one failed trial included," Laurent Safa "Creation of the DSM solution took 60 hours, covering the development of the modeling language and the code generator", Juha Kärnä "It's easy to make modifications when the AUTOSAR version is changed--implementation and testing requirements are both reduced," Yohsuke Satoh "Implementing a DSM language is not a timeconsuming process. After a few man-weeks from the expert, all other developers can develop like experts too," Antti Raunio © MetaCase/JPT
23
DSM Solution Development Time 63 language concepts XML generator
60 language concepts C, HTML, build script generators
36 language concepts Assembler generator
77 language concepts Python generator
Java generator for simulation
143 language concepts J2EE generator
Man days
© MetaCase/JPT
24
DSM Pros & Cons + Fundamental productivity and quality improvements + 300% faster in academic study, 1000% reported by companies + 50% less errors in academic study
+ Gives full control to the company + Experienced developers are sitting in the driver’s seat
– Requires expertise and resources from the company + Minimal vendor lock + Metamodel-driven tools are open + You can translate & transform models to other tools and formats
– Only few industry strength tools available – Scalability to a larger number of developers – Do not handle evolution and maintenance
© MetaCase/JPT
25
Building your modelling language Overview Identifying language concepts Metamodelling Medical Mixin Machine example Language rules Language notations © MetaCase/JPT
26
Domain Idea
Solve problem in domain terms
Modelling domain vs. modelling code Map to code, implement
Map to code, implement
Finished Product
Code
Generate, Add bodies Map to UML
Model in DSM to map! Language
No need
© MetaCase/JPT
Assembler
UML Model
Generate code
Domain Framework
27
How to implement DSM Done a few times before!
Domain Idea
Expert (few)
Normal (many)
Easy!
© MetaCase/JPT
DSM language
Code generator
Framework code
Model in DSM language
Generate code
Domain Framework
Finished Product
28
The steps of defining a DSM solution 1. Identify abstractions – Concepts and how they work together
2. Specify the metamodel – Language concepts and their rules
3. Create the notation – Representation of models
4. Define the generators – Various outputs and analysis of the models
Apply and refine existing components and libraries The process is iterative: try solution with examples – Define part of the metamodel, model with it, define generator, extend the metamodel, model some more, ... © MetaCase/JPT
29
Implementing modelling languages The most important asset of a DSM environment – Application engineers use it – Generator and framework largely invisible
Often includes elements of familiar modelling paradigms – State machine – Flow model – Data structure, etc.
DSM environment DOMAINSPECIFIC Modelling LANGUAGE
DOMAINSPECIFIC CODE GENERATOR
Language specified as a metamodel – Apply a suitable metamodelling language that helps to identify various constructs (metatypes) in languages © MetaCase/JPT
DOMAIN FRAMEWORK
30
Approaches to identify concepts “How do I start to do DSM?” – Hard problem for DSM beginners – Analyzed over 20 cases to find good toolbox of approaches
Initial analysis suggested five approaches: 1. 2. 3. 4. 5.
Domain expert’s or developer’s concepts Generation output Physical structure Look and feel of the system built Variability space
© MetaCase/JPT
31
Problem domain
Solution domain/ generation target
Approach
Telecom services
Configuration scripts
1
Insurance products
J2EE
1
Business processes
Rule engine language
1
Industrial automation
3 GL
1, (2)
Platform installation
XML
1, (2)
Medical device configuration
XML
1, (2)
Machine control
3 GL
1, 2
Call processing
CPL
2, (1)
Geographic Information System
3 GL, propriety rule language, data structures
2
SIM card profiles
Configuration scripts and parameters
2
Phone switch services
CPL, Voice XML, 3 GL
2, (4)
eCommerce marketplaces
J2EE, XML
2, (4)
Automation network
C
3, 4
Crane operations
C/C++
3, (5)
SIM card applications
3 GL
4
Applications in microcontroller
8-bit assembler
4
Household appliance features
3 GL
4
Smartphone UI applications
Scripting language
4
ERP configuration
3 GL
4, 5
ERP configuration
3 GL
4, 5
Handheld device applications
3 GL
4, 5
Phone UI applications
C
5, (4)
C++
5, (4)
Phone UI applications © MetaCase/JPT
32
1. Domain expert’s concepts
Concepts from domain Mostly made without help Simple MoC Simple code generation OK in established domain Usable by non-coders
Insurance products/J2EE
© MetaCase/JPT
33
2. Generation output Modelling constructs come from code artefacts Static parts are easy – Data structures – Core XML elements
Dynamic behaviour hard – Full programming language? – Need domain framework
Danger: low level of abstraction – Little productivity gain
But works well with DSL or XML
Internet telephony/CPL
– As opposed to generic 3GL
© MetaCase/JPT
34
3. Physical structure Best for physical systems – Networks, logistic systems, HW architecture, train control, factory automation, etc.
Often static data model MoC – Also describes connections and dependencies – May include behavioural elements
Visible domain concepts – Easy to identify – High level of abstraction
Usually linked to other models (and DSLs) to achieve more comprehensive code generation
© MetaCase/JPT
Automotive HW architecture 35
4. Look and feel of the system Best for physical end product – UI on PC, embedded, speech
Often state machine MoC – Also data & control flow – Power of relationships
Visible domain concepts – Easy to identify – High level of abstraction
Domain framework hides code – Don’t write code in models… – …unless you really have to!
Generators considered easy
© MetaCase/JPT
Smartphone apps/Python
36
5. Variability space Language concepts capture variability space Modeller makes variant choices – Composition, relationships, values
Infinite variability space (Czarnecki) – Not just feature tree: unbounded product family
Used to create hardest DSM languages – Handled most complex domains, kept modelling simple
Static variance easy, dynamic harder Consultant should be good coder Customer expert in his domain and code – Consultant should also be able to program
Predict future variability high level of abstraction © MetaCase/JPT
37
Evaluation of the Approaches Only certain pairs of approaches occurred Hierarchy of approaches –
From less to more experienced DSM practitioners
1. Domain expert’s concepts – "we just did it" 2. Generation output – –
Generic/ad hoc language not so good Established DSL good
3. Physical structure –
To support specifications in other DSM languages
4. Look and feel: common, easy, true DSM 5. Variability space: adds power to handle complexity –
Found in very different domains
Best results combined 4 (L&F) and 5 (Variability) –
4 gives objects, 5 gives relationships and properties
© MetaCase/JPT
38
Defining the concepts with metamodelling Enrich chosen computational models with domainspecific concepts and rules – look at the type of design languages already used
Investigate various alternatives for describing domain with the chosen models, e.g. – – – – –
model element(s) element properties certain collection of elements relationships between elements model organization structures
Specify as a metamodel in some format – – – –
draft samples with pen & paper document early as a metamodel implement in some metamodel-based tool test it with real models
© MetaCase/JPT
39
Rules [1/2] The domain concepts of a modelling language are bound together with rules Putting the rules into the language: – prevents creation of illegal models – informs about missing data – ensures model consistency
Prefer having rules as part of metamodel to having separate checker – Support early error prevention and provide guidance – But going overboard can hinder flow of modeller
© MetaCase/JPT
40
Rules [2/2] How rules are visible to modellers – – – –
During modelling action Inform when illegal design is made In a separate model check window By highlighting element(s) with errors or missing data
When to run a separate model check – – – – –
On demand After certain model editing actions Before code generation Show in produced review documentation Before versioning etc.
© MetaCase/JPT
41
Example: Medical mixing machine
© MetaCase/JPT
42
Example: Medical mixing machine
Single fixed physical machine Product variability in software: how to mix Platform has 11 cups, syringe to transfer between Problems in hand-coded software quality: – Syringe broken, operator died, patient treatment error
© MetaCase/JPT
43
Exercise Getting started with the tool & language Version 0: Unityped Modelling Language – Based on generic code concepts
Version 1: Domain-specific concepts – Entirely new metamodel, notation, semantics – Code generator
Version 2: Add logical grouping Version 3: Add model reuse Version 4: Higher-level concepts – Entirely new metamodel – Code generator
Summary and what next?
© MetaCase/JPT
44
Getting started with the tool On the CD/USB, locate the folder for your platform – Windows, Mac OS X, Linux
Copy the whole folder to your desktop Open the folder from the desktop – You can now pass the CD/USB on
Folder contents: – Installer (.exe in Windows, .dmg in Mac OS X, .tar.gx in Linux) – Hands-on.pdf = this slide set – GOPRR.mxt = the metamodelling language definitions – *.svg = pre-defined graphical symbols in SVG format
© MetaCase/JPT
45
Getting started with the tool Windows – Run the installer and accept defaults – After installation you will have: MetaEdit+ app → C:\Program Files\MetaEdit+ 4.5 Evaluation User files & repositories → ...\My Documents\MetaEdit+ 4.5
– MetaEdit+ starts automatically after installation • Can also start it from the Start Menu
Mac OS X – Open the distribution .dmg and drag the MetaEdit+ application into the Applications folder – Execute MetaEdit+ by clicking its icon in Applications • First execution of MetaEdit+ will create required folders and files under your Documents folder – takes about 20 seconds
© MetaCase/JPT
46
Getting started with the tool Linux – Execute the following set of commands from shell (requires root privileges or sudo): cd /usr/local sudo mkdir mep45eval cd mep45eval sudo tar -xzvf ~/Desktop/Linux/MetaEdit+EVAL-4.5-1.i386.tar.gz export PATH=$PATH:/usr/local/mep45eval cd ~ mesetup
– Executing mesetup will create ~/metaedit and place user files and repositories there – Start MetaEdit+ by executing: cd ~/metaedit metaedit
© MetaCase/JPT
47
Getting started with the tool Creating and logging into the repository 1. Choose File | Create Repository...
2. Enter: • Database name: ECMFA2011 • Database root directory: ECMFA2011 • Your name: user • Your password: user
3. Confirm the password 4. Allow creation of new ’ECMFA2011’ directory 5. Enter evaluation code qfntd to activate the 31day evaluation period © MetaCase/JPT
48
Getting started with the tool Create new project 1. In Projects list popup menu choose New... 2. Answer Yes when prompted for committing current transaction 3. Enter Mixing as name for the new project 4. Accept all prompts 5. Press Commit ( )
Import the graphical metamodelling language 1. Press Import ( ) 2. Select and open GOPRR.mxt from the file dialog 3. Press Commit ( ) again © MetaCase/JPT
49
Getting started with the language The assignment: Medical Mixing Machine
“take from the second cup 5 units with filter A and put 2 units to cup 6 and 3 units to cup 7 and then clean the needle” © MetaCase/JPT
01 02 03 04 05
move(-3); filt(1); suck(5); move(4); filt(0); blow(2); move(1); blow(3); move(-3); suck(30); move(1); blow(30); 50
Version 0: Unitype Modelling Language Creating the version 0 language – Have a box representing a command – Show execution flow with relationships move(-3); filt(1); suck(5); move(4); filt(0); blow(2); move(1); blow(3); move(-3); suck(30); move(1); blow(30); © MetaCase/JPT
51
GOPRR concepts A Graph is one individual model – often shown as a diagram
Objects are the main elements of graphs – often shown as boxes or circles
A Property is an attribute characterizing another element – often shown as a label
A Relationship connects objects together, – often shown as a label over the connection
A Role connects an object into a relationship, – often shown as a line and arrow-head – A Binding connects a Relationship, Roles and Objects Property Role
Relationship
Property
Role Object
Object
Binding © MetaCase/JPT
52
Graphical GOPRR in MetaEdit+ Graph
Object
Property
Role
Relationship
Binding
© MetaCase/JPT
53
Initial target metamodel Command objects represent Function calls (move, filter, suck, etc.) with their Parameters Transition relationships and From and To roles define the procedural order of commands
© MetaCase/JPT
54
Creating a Graph type 1. Press Create Graph in toolbar ( ) → Create Graph dialog opens 2. Select Metamodel [GOPRR] from the list 3. Press Ok → graph definition dialog opens
1
2
3
continues... © MetaCase/JPT
55
Creating a Graph type 4
4. Enter Mixing 0 as Graph Name 5. In Properties list popup menu choose Add Element... → Property definition dialog opens 6. Enter Name as Property name 7. Press OK in property definition dialog 8. Press OK in graph definition dialog → a Diagram Editor for new GOPRR metamodel opens
5
8
6
7
© MetaCase/JPT
56
Diagram Editor Graphical metamodels are defined in Diagram Editor
Action toolbar Types toolbar Tree view Drawing area Property sheet
© MetaCase/JPT
57
Creating an Object type 1. Click Object on types toolbar to select it 2. Click on drawing area → object definition dialog opens 3. Enter Command as Object name 3 1
2 CLICK
© MetaCase/JPT
continues... 58
Defining Property types 1. In Properties list popup menu, Add Element... → property definition dialog opens 2. Enter Function as Property name 3. Press OK → the new Property appears in object definition dialog’s Properties list 2
1
3
© MetaCase/JPT
continues...
59
Completing the Object type 1. Create another property called Parameter for Command object 2. Press OK in object definition dialog 3. New Command object will appear in Diagram Editor 1
3 2
© MetaCase/JPT
60
Creating a Binding 1. Click Binding on types toolbar to select it 2. Click on the Command object, then click for two breakpoints outside it 3. Double-click Command → binding definition dialog opens
1CLICK
CLICK
CLICK
2
DOUBLE CLICK
3 CLICK
continues... © MetaCase/JPT
61
Creating Relationship type 1. In Relationship field popup menu, Attach New Object... → relationship definition dialog opens 2. Enter Transition as Relationship name 3. Press OK → the Transition relationship will now appear as part of the binding definition –
Don’t press All OK yet! 2 1
3
continues... © MetaCase/JPT
62
Creating first Role type 1. Activate the First role tab 2. In Role field popup menu, Attach New Object... → role definition dialog opens 3. Enter From as Role name 4. Press OK → the From role appears as part of the Binding definition 3 1 2
4
continues... © MetaCase/JPT
63
Creating last Role type 1. 2. 3. 4.
Activate the Last role tab In Role field popup menu, Attach New Object... In role definition dialog, enter To as Role name Press OK → the To role appears as part of the binding definition 3 1 2 4
continues... © MetaCase/JPT
64
Finalizing Binding type 1. Press All OK in binding dialog → new Binding will appear in Diagram Editor
1
© MetaCase/JPT
65
Complete initial metamodel Command objects represent Function calls (move, filter, suck, etc.) with their Parameters Transition relationships and From and To roles define the procedural order of commands
© MetaCase/JPT
66
Metamodel build 1. Save the current metamodel by pressing Commit in the main MetaEdit+ window 2. In the Diagram Editor, press the Build button in the action toolbar 3. MetaEdit+ will build the metamodel automatically 4. Close the Generated Files info dialog that appears
1
© MetaCase/JPT
2
67
Creating a new Graph 1. In the main MetaEdit+ window, press Create Graph in toolbar 2. Select Mixing 0 graph type from graph creation dialog and press Ok 3. Enter Test 0 as name for the new graph 4. Press OK → Diagram Editor for the new model opens 1 2
3 © MetaCase/JPT
4
68
Diagram Editor revisited Basic behaviour the same as with graphical GOPRR Types toolbar now contains the types of the new language (i.e. Command and Transition)
© MetaCase/JPT
69
Creating Objects 1. Ctrl-click Command in types toolbar to enable sticky creation mode 2. Click on drawing area to start creating a Command 3. Enter Function name and Parameter value in property dialog 4. Press OK → new object will appear on drawing area
1
CLICK
3
2
4 © MetaCase/JPT
continues... 70
Creating Objects 5. Click again on drawing area to create another Command 6. Enter Function name and Parameter value in property dialog and press OK –
Parameter values to enter are shown below in red
7. Repeat 5 – 6 to create all required objects 8. Press right mouse button to end sticky creation
© MetaCase/JPT
71
Creating Bindings 1. Ctrl-click Transition in types toolbar to enable sticky creation mode 2. Click and hold on top of the first object 3. Drag on top of the other object and release the mouse button → new binding is placed between the objects
1 2
© MetaCase/JPT
3
continues... 72
Creating Bindings 4. Click and hold on top of an object 5. Drag on top of the next object and release the mouse button to create a binding 6. Repeat 4 – 5 to create all required bindings 7. Press right mouse button to end sticky creation 8. Press Commit in main MetaEdit+ window to save your work
© MetaCase/JPT
73
Creating symbols for objects 1. Select one Command object in diagram 2. In property sheet, shift-double-click Object type row, → Symbol Editor for roles opens
1
continues... © MetaCase/JPT
74
Symbol Editor: drawing rectangle 1. Toggle on grid’s Snap and Show in status bar 2. Click on Rectangle in toolbar 3. Click and hold on drawing area to place rectangle’s top-left corner 4. Drag for the bottom-right corner and release
2 CLICK + HOLD
3
4 RELEASE
1 © MetaCase/JPT
continues... 75
Symbol Editor: adding text 1. Click on Text in toolbar 2. Click and hold on drawing area to place text box’s top-left corner 3. Drag for the bottom-right corner and release → format dialog for text source and other properties opens 1 2 CLICK + HOLD
3
RELEASE
continues... © MetaCase/JPT
76
Symbol Editor: text properties To make the text show the Function property: 1. On the Content page, select Property radio button and select Function from the pulldown list 2. Go to Text Settings page and set alignment centered 3. Press OK → the Function text box will appear
1 2
3 © MetaCase/JPT
continues... 77
Symbol Editor: text properties 4. Set both line colour and fill as transparent for the new text element
4
continues... © MetaCase/JPT
78
Symbol Editor: saving symbol 1. Create another text element for Parameter property (use centered text and bold font type) 2. Press Save on toolbar → the symbols in Diagram Editor update automatically 3. Close Symbol Editor
2
1
© MetaCase/JPT
79
Creating symbols for roles 1. Select one To role in diagram 2. In property sheet, shift-double-click Role type row, → Symbol Editor for roles opens In Symbol Editor for roles a fixed line segment represents the role line, ending at the object’s edge
1
2
© MetaCase/JPT
continues... 80
Symbol Editor: roles 1. Set grid as 5-by-5 (View | Choose Grid...) 2. Draw two short diagonal lines (2 squares by 1) back from the line end to get the arrow head 3. Press Save → role symbols update in Diagram Editor 4. Close Symbol Editor 3
2
© MetaCase/JPT
81
That’s it! Diagram Editor provides normal editing features... – – – – – –
Undo/redo Cut/Copy/Paste/Paste special... Replace for refactoring Info for tracing Grid operations: snap, align, etc. Import/export, autolayout...
... integrated with generators – – – –
Code generator Document generators Model checking and analysis Metrics etc.
Along with other tools for browsing, importing and exporting, programmatic API etc.
© MetaCase/JPT
82
Version 1: Domain-specific concepts Make each command into its own type – Cf. Object-oriented approach, e.g. Command pattern
Create a new metamodel, Mixing 1, as shown here move(-3); filt(1); suck(5); move(4); filt(0); blow(2); move(1); blow(3); move(-3); suck(30); move(1); blow(30); © MetaCase/JPT
83
Version 1: Type-specific parameters Different types have different parameter lists – E.g. filter values are different from move values – Filter {0,1,2}, move -10..10, suck/blow 0..30 move(-3); filt(1); suck(5); move(4); filt(0); blow(2); move(1); blow(3); move(-3); suck(30); move(1); blow(30); © MetaCase/JPT
84
Creating second metamodel 1. In MetaEdit+ main window, press Create Graph... in toolbar 2. Select Metamodel [GOPRR] from Graph type list and press Ok 3. Enter Mixing 1 as Graph name
continues... © MetaCase/JPT
85
Creating second metamodel Reuse existing Name property 4. Choose Add Existing... from Properties list popup menu → component tool opens 5. Double-click on Name on Selection list → Name will appear on Already selected list 6. Press OK to accept Already selected list → Name is now reused as a property for the new graph 7. Press OK in graph definition dialog
4
5
6 © MetaCase/JPT
7
86
Creating abstract object 1. 2. 3. 4. 5. 6.
Hint: Set grid as 75-by-50 Click on Object in types toolbar Click on drawing area → object definition dialog opens Enter Abstract as Object name Set Occurrence as 0 (this defines the object as abstract) Press OK → new Abstract object appears
4
2 5 3
CLICK
6 © MetaCase/JPT
87
More objects and properties 1. Create Move object and define Distance property for it 2. Create Filter object and define Filter property – Select Radio Button Set as datatype for property – Enter 0, 1 and 2 as Default values, one per line
3. Create Suck object and define Amount property 4. Create Blow object and reuse Amount property created in previous step (Add Existing...)
3
© MetaCase/JPT
88
Using inheritance Move, Filter, Suck and Blow are descendants of Abstract → use Inheritance relationship N-ary binding = binding with more than 2 roles
© MetaCase/JPT
89
Using inheritance 1. Click Inheritance on types toolbar 2. Click on drawing area to place the inheritance join-point 3. Click on Move, Filter, Suck and Blow to connect them –
Choosing them first makes them the descendants
4. Double-click on Abstract to connect it and finish creation –
Since it is the last one, it becomes the ancestor
1 CLICK DOUBLE CLICK
4
CLICK
CLICK
3 CLICK
© MetaCase/JPT
CLICK
2
CLICK
CLICK
90
Finalizing second metamodel 1. Finalize the n-ary binding for inheritance visually –
Click role line then drag a point on it to add breakpoint
2. Add Transition binding (as in version 0) Reuse existing Transition relationship and From and To role types (Add Existing... in binding definition dialog) 2
1
© MetaCase/JPT
91
Testing Version 1 Press Build to generate the new metamodel Test the language in a new Mixing 1 graph, Test 1 – Create the model structure below, with grid 100x100 – You’ll just see default symbols, without ’move’ etc.
© MetaCase/JPT
92
Version 1: Distinct meaningful symbols Cf. intention-revealing names, syntax colouring
© MetaCase/JPT
93
Version 1: Code generator Writes out command for an object Follow relationship to recurse to next object move(-3); filt(1); suck(5); move(4); filt(0); blow(2); move(1); blow(3); move(-3); suck(30); move(1); blow(30); © MetaCase/JPT
94
Opening Generator Editor Choose Graph | Edit Generators... in Diagram Editor → Generator Editor opens
© MetaCase/JPT
95
Generator Editor Categories
Concepts/ commands
Generators
Editing area
Errors © MetaCase/JPT
96
Creating a new generator 1. Choose Generator | New... 2. Enter Code as name for new generator and accept → new empty generator script appears on editing area 1
2
© MetaCase/JPT
97
Creating a new generator 1. Enter generator definition in editing area For generator script content, see next slide
2. Press Save in toolbar → Code will appear on generator list 3. Similarly, create another generator called _next 2
1
© MetaCase/JPT
3
98
The generator scripts The Code generator script Report 'Code' foreach .() where not ~To { subreport '_next' run } endreport
The _next script Report '_next' type '(' id ');' newline do ~From~To.() { subreport '_next' run } endreport © MetaCase/JPT
99
Testing generators 1. Select Code from the generator list 2. Press Generate... in toolbar 3. Select Test 1 from the list → the generator output will open in Generator Output window 2 1
3
© MetaCase/JPT
100
Generators explained The Code generator script Report 'Code' foreach .() where not ~To { subreport '_next' run
For each object that does not have a To role (= start from the first command)... ..execute ’_next’ subgenerator
} endreport
© MetaCase/JPT
101
Generators explained The _next generator script Report '_next' type '(' id ');' newline;
do ~From~To.() { subreport '_next' run
Output current object’s type (e.g. Move) and id (first property, i.e. parameter) and newline
Navigate through From and To roles to the next object in sequence Execute ’_next’ subgenerator recursively
}
endreport
© MetaCase/JPT
102
Version 2: Logical grouping Collect logical groups of code into visual blocks or chunks – Enclosing boxes (cf. commented code regions) – Boxes + relationships (cf. goto) move(-3); filt(1); suck(5); move(4); filt(0); blow(2); move(1); blow(3); move(-3); suck(30); move(1); blow(30); © MetaCase/JPT
} } }
} 103
Version 2: Add ’Step’ objects Update the metamodel by adding Step subtype Use ”Add Existing” for Name property Add one more role into the inheritance relationship: 1. 2. 3. 4.
Click Inheritance on toolbar Click on existing Inheritance relationship join point Click for breakpoint Finalize by clicking Step object
Press Build to update the metamodel
CLICK CLICK
2
3 DOUBLE CLICK
4 © MetaCase/JPT
104
Version 2: Refactor into Steps Add a Step object Shift-double click Object type row to edit symbol – Make a wide rectangle with transparent fill, plus small text
Add rest of steps – Drag edges with ctrl to scale
Connect Steps with Transitions Delete old diagonal Transitions
© MetaCase/JPT
105
Version 3: Support model reuse Enable model hierarchies with Steps – Support reuse of models
© MetaCase/JPT
106
Version 3: Allow subgraphs Create metamodel showing modelling language hierarchy – Create Graph... from Graphs list popup menu – Select Metamodel for multiple graphs [GOPRR] from the list – Enter the same metamodel name, Mixing 1
Add Graph element to the diagram – – – – –
Click Graph button in toolbar Click in diagram to create Graph box Scale resulting Graph box bigger Right-click Graph box, Decompositions... Choose the current metamodel, Mixing 1, and press OK
© MetaCase/JPT
107
Version 3: Allow subgraphs Add model hierarchy – Copy Step from the existing metamodel and paste it inside the newly created Mixing 1 Graph box – Draw a Decomposition relationship from Step to Mixing 1 – A Step in a Mixing 1 graph can decompose to another Mixing 1 graph
Press Build to generate the new metamodel © MetaCase/JPT
108
Version 3: Refactor to subgraphs Go back to the Test 1 model Refactor the model hierarchy: for each Step – Select the objects in the Step and Cut them – Select Step, choose Decompositions... in pop-up menu – Select Create a new graph... – Enter name of Step as graph name and press OK – Paste cut content into the graph
© MetaCase/JPT
109
Version 4: Higher level domain concepts Make reusable chunks into types – Give types properties to parameterize reuse
From:
To:
Take
Put
Clean
Note: the Move commands are now handled with a new property in the relationship between operations © MetaCase/JPT
110
Version 4: New metamodel Create new Metamodel [GOPRR] graph, Mixing 4 Add new objects Take, Put, Clean as shown below – Reuse Amount, but make new Using Filter {None, A, B} – Add Abstract and make it their ancestor
Add new relationship Move reusing Distance Reuse From & To Don’t Build yet!
© MetaCase/JPT
111
Version 4: Add rules Add Start object, Occurrence 1 (singleton for 1st move) Analysing domain further: – Take can follow anything (Abstract) – Put can follow Take or Put • Add new supertype Needle for Take & Put. Cut&Paste Amount.
– Clean can only follow Put
© MetaCase/JPT
112
Version 4: symbol for relationship 1. Select relationship on Diagram Editor 2. Shift-double-click on property sheet’s Relationship row to open Symbol Editor 3. Place textbox for Distance property on drawing area 4. Select Point Connectable from toolbar and place it in the middle of the textbox 5. Press Save and close Symbol Editor 4 3 1 2
© MetaCase/JPT
113
Version 4: Reqs Model Code “take from the second cup 5 units with filter A
01 02 03 04 05 © MetaCase/JPT
put 2 units to cup 6
put 3 units to cup 7
then clean the needle”
move(-3); filt(1); suck(5); move(4); filt(0); blow(2); move(1); blow(3); move(-3); suck(30); move(1); blow(30); 114
Modeling effort?
12 objects 11 relationships 12 properties 35 elements in total
© MetaCase/JPT
5 objects 4 relationship 7 properties 16 elements in total 115
Where are the concepts?
“take from the second cup 5 units with filter A and put 2 units to cup 6 and 3 units to cup 7 and then clean the needle” © MetaCase/JPT
01 02 03 04 05
move(-3); filt(1); suck(5); move(4); filt(0); blow(2); move(1); blow(3); move(-3); suck(30); move(1); blow(30); 116
Modeling effort?
12 objects 11 relationships 12 properties 35 elements in total
© MetaCase/JPT
2 objects 1 relationship 5 properties 8 elements in total 117
Plan model structures for reuse Deeper commonality / variability analysis – What is in several applications but not all?
Normal aims for high cohesion, low coupling – Remember parameter passing, interfaces
How does your tool allow model sharing? Will models be shared between: – multiple developers? – multiple applications? – multiple versions?
Often, these questions are too hard for an early stage – Only build support for a single clearly needed reuse case – Let later use show you where more reuse is needed © MetaCase/JPT
118
Defining notation [1/2] Vital for acceptance and usability Symbols can vary from boxes to photorealism – Best to resemble closely the actual domain representation – Worst is having everything a box and special text to show the difference (cf. stereotypes) – Design information needs space: compromise
Don’t create notation from scratch – Use known/existing elements (and, or, start, stop etc)
Hint: ask users to define the notation – It is much easier to introduce their own language than something you created – Remember also model readers • managers, test engineers, customers, deployment, configuration, packaging and even sales © MetaCase/JPT
119
Defining notation [2/2] Consider also other representational styles – Matrices focus on relationships, avoid line-crossings, help identify high cohesion and low coupling – Tables and forms show details and support sorting, categorization, comparison – Diagrams good in finding patterns and organizing model elements into non-linear structures
Multiple representations possible for the same data – E.g. as a relationship line and as an object – Can also make symbols and texts retrieve others' info – Changes in one representation update the others
Use common symbol elements to improve readability – Show if concept is reused, has a submodel etc.
Use symbols to indicate the state of the model – Missing information, errors, default value is not used etc. © MetaCase/JPT
120
Visual variables Symbols should use full range of visual variables
© MetaCase/JPT
121
© MetaCase/JPT
«Person»
«Laptop»
«Output»
«Input»
122
«Person»
«Laptop»
«Output»
«Input»
pictogram > geometric > photo
© MetaCase/JPT
123
Case: Automotive infotainment
© MetaCase/JPT
124
Case: Track control of railway systems
© MetaCase/JPT
125
Case: Sports computer
© MetaCase/JPT
126
Building a Generator
© MetaCase/JPT
127
Generator DSM environment
Generator translates the models into the required output 1. crawls through the models navigation according to metamodel
DOMAINSPECIFIC Modelling LANGUAGE
2. extracts required information access data in models
3. translates it into the code
translation semantics and rules
4. using some output format
DOMAINSPECIFIC CODE GENERATOR
possibility to define output format DOMAIN FRAMEWORK
© MetaCase/JPT
128
How to design a generator, 1 Make generator for your situation only • Trying to make general purpose generator often fails
Make generation process complete, target 100% output – Never modify the generated code • Do you want to edit Assembler after compiling?
– Correct the generator or framework instead • No round-trip-related problems • Do you want to edit Assembler and keep C in synch with it?
Use modelling languages to raise abstraction • Don’t visualize code • Generating a class from a diagram to a class in code helps very little, if at all…
Put domain rules up-front to the language • Generator definition becomes easier when the input is correct • Models should be impossible to draw wrongly for generation © MetaCase/JPT
129
How to design a generator, 2 Try to generate as little code as possible – Glue code only, rest in domain framework or platform
Keep generator as simple as possible – Raise variation to the specification language – Push low-level common implementation issues to the framework
Keep generator modular to reflect changes – e.g. structure generator based on modelling languages, generated files, modelling concepts – e.g. use common generator subroutines for common needs
Make generated code readable (“good looking”) – To be used later while debugging the code, executing it in a simulator, and while implementing the generator – Follow good coding standards, include comments, have data to link back to models (e.g. in comment or via e.g. simulator) © MetaCase/JPT
130
Generator degrees of freedom Different levels of generators: modular / tree structure 1. Generator per file to be generated 2. Generator per section in a file 3. Generator per metamodel element
Different Model of Computation implementations – – – –
Sequential Function calls Switch-case structure Transition tables, etc.
Different levels of code that generated code can call or subclass – Other generated code – Domain framework components – Platform functions
Different generation options for different runs – Different top-level generators – Top-level graph for generation options © MetaCase/JPT
131
"Here's one I made earlier" Write some good, working code by hand – Can only automate what can be done well by hand – Aim for simplicity, what you would teach, not cleverness
Build the model that represents the same system – Aim for one instance each of 3-4 main object types
Analyse the code from the viewpoint of the generator Simplest parts of generator are the extreme cases: – Fixed text, always output the same – Values directly from the model, e.g. names
Between the extremes is the meat of the generator: – Conditional sections, inclusion depends on model values – Repeated sections, e.g. once per model element
© MetaCase/JPT
132
Code + model generator 1. Paste output code as entire content of generator 2. Reduce repeated sections One occurrence for each Generator loop visits each model structure for section
3. Collect sections with two or more alternative forms Surround them with generator conditional Condition gets its input from model
4. Replace output that comes from property values Navigate to and read value from model Massage value as necessary, e.g. space to underscore
In practice, 2-4 normally occur in parallel
© MetaCase/JPT
133
Types of generator facilities Programming language accessing model through API – Direct access, but low level, high coupling with tool – Need something better, designed just for generation
Model visitor – Map each model structure to a code structure – Limited to simple one-to-one mappings
Output template – Single file, code + escaped
Crawler: Model navigation and output streams – Multi-file, code quoted, native generator commands
Generator generators – Tempting, alluring, mostly unnecessary © MetaCase/JPT
134
Patterns for Generators by Type of Output Simple text Model checking Documentation XML Flow machine State machine © MetaCase/JPT
135
Generating simple text Simple text tends to fall into three categories – Largely boilerplate – Configuration and settings files – Simple script files
Configuration files can be tricky – Reader of file has no intelligence, expects exact format – E.g. model specifies value in decimal, but file uses hex – DSL generator may not have conversion: postprocess
Script files easier – Reader of file has intelligence, leave conversion to it
© MetaCase/JPT
136
Model checking by generators Most rules should be in modelling language – Easiest for modeller, guarantees good generator input
Model checking output different from other output: – Read by modeller, not a program – Read at design time, not compile or run-time
Favours integrated generator facilities, "live" output – E.g. results displayed in model symbol – If results elsewhere, hyperlink to model element useful
Bespoke tools exist for more complex checks – E.g. for state machines: output in required format
© MetaCase/JPT
137
Generating documentation Models in the tool are the best documentation: – High-level, precise, always up-to-date – Tool offers best environment for reading docs
Access and familiarity motivate traditional formats – Everyone can use Word, HTML browser
Include model images as vectors or bitmaps – SVG >= PNG > GIF > JPEG
Separate formatting from content – Make fixed CSS or Word template with generator
Use macros or scripts to make generation easier – E.g. Word AutoOpen macro for ToC, .rtf->.doc
© MetaCase/JPT
138
Generating XML Generating simple, first-cut XML is easy '' newline foreach .() { ' ' newline } '' newline
Generating watertight XML is an ugly mess – – – –
Element names: letter, underscore or colon, not xml* Attribute values: quoted, " ", white space Text elements: CDATA allows all except CR Encoding: use UTF-8 or platform native • In platform native, beware smart quotes
© MetaCase/JPT
139
Generating flow machines (1) A
B
C
A; B; C;
Chain of model elements sequential instructions – Simplest case: no cycles, forks or joins
Requires some thought, often recursion in generator: Report "handleObject" :Command /* output for this object */ do ~From~To.() /* traverse to next object(s) */ { subreport "handleObject" run /* recurse */ }
API-based generators can iterate: do { System.out.println(currObj.Command()); currObj = currObj.nextObject(); } while (currObj != null) © MetaCase/JPT
140
Mixin machine version 4: Implement generator with Generator Editor – Diagram Editor: Graph | Edit Generators... – Generator | New... Report 'Code' Begin from Start element foreach .Start and execute ’_MoveAndDo’ { subreport '_MoveAndDo' run subgenerator for it } endreport Navigate through From role to the relationship Output Distance property Navigate through To role to the object and execute subgenerator named ’_Do’ + object type (e.g. ’_DoTake’) © MetaCase/JPT
Report '_MoveAndDo' do ~From>() { 'move(' :Distance ');' newline do ~To.() { subreport '_Do' type run } } endreport 141
Mixin machine version 4: Add rest of generators – one for each object type – Below a generator for ’Take’ object If filter is used output filter code Translate filter value given in a model to a legal value for code (A->1, B->2) Output amount If filter is used remove filter by outputting ’filt(0)’ Execute ’_MoveAndDo’ subgenerator © MetaCase/JPT
Report '_DoTake' if :Using Filter; 'None' then 'filt(' to 'AB 12' translate :Using Filter; endto ');' newline endif 'suck(' :Amount ');' newline if :Using Filter; 'None' then 'filt(0);' newline endif subreport '_MoveAndDo' run endreport
142
Mixin machine version 4: Add rest of generators – one for each object type – Below a generator for ’Put’ and ’Clean’ objects Output amount Execute ’_MoveAndDo’ subgenerator
Output fixed code for cleaning the needle Execute ’_MoveAndDo’ subgenerator
© MetaCase/JPT
Report '_DoPut' 'blow(' :Amount ');' newline subreport '_MoveAndDo' run endreport Report '_DoClean' 'suck(30); move(1); blow(30);' newline subreport '_MoveAndDo' run endreport
143
Generating flow machines (2) Real programs need more – Sequence + IF + GOTO
Conditions and jumps hard – Naive generator will duplicate all from Mail on – In more complex cases, even visited list is no help
So change DSM language: – IF's successor after ENDIF – THEN & ELSE subordinate
GOTO OK in models – Can see flow of control – Spaghetti instantly visible
© MetaCase/JPT
144
Assembler for 8-bit microcontroller VoiceMenu for home automation systems Language concepts deal with – basic operations like accessing memory addresses, calculation, comparison and jump – menu specific operations like speaking out menu items – flow of execution and conditional jumps appear as relationships
100% code generation – No framework code to support generation, all code from models
© MetaCase/JPT
145
Assembler for 8-bit microcontroller Generator follows the flow of execution via relationships, generating out chunks of operations related to each design element 01 Speak 0x01 (Pause for 0.5 sec) 02 Speak 0x02 (the...) 03 Speak 0x03 (...current...) 04 Speak 0x04 (...lifestyle...) 05 Speak 0x05 (...is...) 06 GetLifeStyle 07 Speaks Lifestyle 08 Speak 0x06 (Pause 0.3 sec) 09 Speak 0x07 (select...) 10 Speak 0x08 (...another...) 11 Speak 0x04 (...lifestyle...) 12 FillMemB 00 13 :3_844 14 Add to MemB 01 15 Speak 0x09 (for...) 16 Speaks Lifestyle 17 Speak 0x10 (...press...) 18 Speak number MemB 19 Is MemB >= 0F 20 IFNot 21 Goto 3_844
© MetaCase/JPT
146
Assembler for 8-bit microcontroller Generator follows the flow of execution via relationships, generating out chunks of operations related to each design element 01 Speak 0x01 (Pause for 0.5 sec) 02 Speak 0x02 (the...) 03 Speak 0x03 (...current...) 04 Speak 0x04 (...lifestyle...) 05 Speak 0x05 (...is...) 06 GetLifeStyle 07 Speaks Lifestyle 08 Speak 0x06 (Pause 0.3 sec) 09 Speak 0x07 (select...) 10 Speak 0x08 (...another...) 11 Speak 0x04 (...lifestyle...) 12 FillMemB 00 13 :3_844 14 Add to MemB 01 15 Speak 0x09 (for...) 16 Speaks Lifestyle 17 Speak 0x10 (...press...) 18 Speak number MemB 19 Is MemB >= 0F 20 IFNot 21 Goto 3_844
© MetaCase/JPT
147
Assembler for 8-bit microcontroller Generator follows the flow of execution via relationships, generating out chunks of operations related to each design element
The lifestyle voice sample is reused to save the memory space
© MetaCase/JPT
01 Speak 0x01 (Pause for 0.5 sec) 02 Speak 0x02 (the...) 03 Speak 0x03 (...current...) 04 Speak 0x04 (...lifestyle...) 05 Speak 0x05 (...is...) 06 GetLifeStyle 07 Speaks Lifestyle 08 Speak 0x06 (Pause 0.3 sec) 09 Speak 0x07 (select...) 10 Speak 0x08 (...another...) 11 Speak 0x04 (...lifestyle...) 12 FillMemB 00 13 :3_844 14 Add to MemB 01 15 Speak 0x09 (for...) 16 Speaks Lifestyle 17 Speak 0x10 (...press...) 18 Speak number MemB 19 Is MemB >= 0F 20 IFNot 21 Goto 3_844
148
Assembler for 8-bit microcontroller Generator follows the flow of execution via relationships, generating out chunks of operations related to each design element 01 Speak 0x01 (Pause for 0.5 sec) 02 Speak 0x02 (the...) 03 Speak 0x03 (...current...) 04 Speak 0x04 (...lifestyle...) 05 Speak 0x05 (...is...) 06 GetLifeStyle 07 Speaks Lifestyle 08 Speak 0x06 (Pause 0.3 sec) 09 Speak 0x07 (select...) 10 Speak 0x08 (...another...) 11 Speak 0x04 (...lifestyle...) 12 FillMemB 00 13 :3_844 14 Add to MemB 01 15 Speak 0x09 (for...) 16 Speaks Lifestyle 17 Speak 0x10 (...press...) 18 Speak number MemB 19 Is MemB >= 0F 20 IFNot 21 Goto 3_844
© MetaCase/JPT
149
Assembler for 8-bit microcontroller Generator follows the flow of execution via relationships, generating out chunks of operations related to each design element 01 Speak 0x01 (Pause for 0.5 sec) 02 Speak 0x02 (the...) 03 Speak 0x03 (...current...) 04 Speak 0x04 (...lifestyle...) 05 Speak 0x05 (...is...) 06 GetLifeStyle 07 Speaks Lifestyle 08 Speak 0x06 (Pause 0.3 sec) 09 Speak 0x07 (select...) 10 Speak 0x08 (...another...) 11 Speak 0x04 (...lifestyle...) 12 FillMemB 00 13 :3_844 14 Add to MemB 01 15 Speak 0x09 (for...) 16 Speaks Lifestyle 17 Speak 0x10 (...press...) 18 Speak number MemB 19 Is MemB >= 0F 20 IFNot 21 Goto 3_844
© MetaCase/JPT
150
Generating flow machines (3) Higher level constructs: GOTO GOSUB Functions Map each object to its own function – Actual action • Will normally be more than a line or two
– Specification of next function(s) to call • Conditions to pick which to call
Simplest implementation: function calls next directly – Stack depth problems
Better: return pointer to next function – Requires language support: easy in C, Smalltalk, LISP – Java: invoke() – C#: Type.InvokeMember() © MetaCase/JPT
151
Python for smartphones Modeling language based on phone widgets and services Enforces the UI programming model and phone framework rules, e.g. – SMS sending – Notification handling – View management
© MetaCase/JPT
152
Function calls – Series 60/Python
Generator definition
Generator output
Report '_Note' /* Produces Note code */ 'def ' type;oid '():' ‘ appuifw.note(u"‘ :Text or code; '", ''' :Note type ''')' subreport '_next element' run endreport
def Note3_2227(): appuifw.note(u"Registration made", 'conf') return Stop3_983
Report '_next element' /* reports next flow element*/ do ~From>Flow { do :Function used {' ' :Function name;} '(' :Code ')' do ~To.() {‘ return ' subreport '_Internal name' run} } endreport
def Note3_2543(): appuifw.note(u“Conference registration: Welcome", ‘info') return Popup_menu3_2520
© MetaCase/JPT
def Note3_6109(): appuifw.note(u“Registration cancelled", ‘info') return Stop3_983
def Stop3_983(): # This applications stops here return appuifw.app.set_exit
...
153
Generating state machines (1) Can generate as double switch case, e.g. in C: switch (state) { case : switch (event) { Transition %> case : if () { ; ; ; state = ; } break; default: break; } default: break; }
© MetaCase/JPT
154
C for wristwatch applications Typical for embedded devices – e.g. medical devices, diving instruments, car infotainment Modeling language to define application logic using basic domain concepts, using extended state machine Uses services from the domain-specific platform – e.g. in case of digital wristwatch: time, display, button etc
Code generator produces 100% of variant implementation
© MetaCase/JPT
155
Switch-Case – Watch/C C from the extended state machine; Watch
Generator ouput void handleEvent() int = Start; typedef enum { Start, EditHours, EditMinutes, Show, Stop } States; { state int switch button = {None; pseudo-button for following buttonless transitions */ typedef enum(state) None,/*Mode, Set } Buttons; { void runWatch() case EditHours: { switch (button) while (state != Stop) { { case Set: handleEvent(); state = EditHours; button = getButton(); /* waits for and returns increment_and_roll(tempOffset, HOURS, next UP); button press */ } break; } case Mode: icon (editHours, OFF); icon (editMinutes, ON); state = EditMinutes; break; default: break; }
© MetaCase/JPT
156
Generating state machines (2) Can represent as data not code, e.g. in OO languages – Transition table: {State {Event (Action, State)}} – State names, decompositions
Behaviour of state machine in abstract superclass – Domain-specific, good for any state machine in domain
Each model is a concrete subclass of abstract class – Initialisers for tables
Each kind of action has its own type in DSM language – Own sub-generator per action type – Generates "real" code from model data – Actions can be specified in many ways • closures, blocks, inner classes, functions invoked by name, cases switched by id, if..elseif by id etc.
© MetaCase/JPT
157
Java for wristwatch applications The same design language as in case of C implementation Uses OO capabilities – subclass abstract state machine – class initialization and data from the model • State machine treated as data
Based on domain framework – Framework can have different implementations • E.g. plain Java, micro Java, MIDP Java
© MetaCase/JPT
158
Code generator structure Modular implementation to manage complexity
Report '_Roll’ Report 'Autobuild' /* Create compilation script, HTML files etc. */ subreport '_create make for ' :Generation target platform; run /* Create static shared Java components */ subreport '_JavaComponents' run
'get' do ~Set.() {id} '().' 'roll(METime.' :Time unit; ', ' if :Up? = 'T’ then 'true' else 'false' endif ', displayTime());' endreport
/* Create Java code for Watch models */ subreport '_Models' run /* Compile and execute */ filename subreport '_default directory' run 'alldone.txt' write close subreport '_compile and execute for ' :Generation target platform; run
endreport
© MetaCase/JPT
159
Code generator example [2/3] Generating watch applications
Generator ouput public SimpleTime(Master master) { super(master); addTransition addTransition addTransition addTransition addTransition addTransition
("Start [Watch]", "", 0, "Show"); ("Show", "Mode", 0, "EditHours"); ("EditHours", "Set", a22_2926, "EditHours"); ("EditHours", "Mode", 0, "EditMinutes"); ("EditMinutes", "Set", a22_1405, "EditMinutes"); ("EditMinutes", "Mode", 0, "Show");
addStateDisplay("Show", -1, METime.MINUTE, d22_977); addStateDisplay("EditHours", METime.HOUR_OF_DAY, METime.MINUTE, d22_977); addStateDisplay("EditMinutes", METime.MINUTE, METime.MINUTE, d22_977); };
© MetaCase/JPT
160
Code generator example [2/3] Generating watch applications
Generator ouput public SimpleTime(Master master) { super(master); addTransition addTransition addTransition addTransition addTransition addTransition
("Start [Watch]", "", 0, "Show"); ("Show", "Mode", 0, "EditHours"); ("EditHours", "Set", a22_2926, "EditHours"); ("EditHours", "Mode", 0, "EditMinutes"); ("EditMinutes", "Set", a22_1405, "EditMinutes"); ("EditMinutes", "Mode", 0, "Show");
addStateDisplay("Show", -1, METime.MINUTE, d22_977); addStateDisplay("EditHours", METime.HOUR_OF_DAY, METime.MINUTE, d22_977); addStateDisplay("EditMinutes", METime.MINUTE, METime.MINUTE, d22_977); };
© MetaCase/JPT
161
Code generator example [2/3] Generating watch applications
Generator ouput public SimpleTime(Master master) { super(master); addTransition addTransition addTransition addTransition addTransition addTransition
("Start [Watch]", "", 0, "Show"); ("Show", "Mode", 0, "EditHours"); ("EditHours", "Set", a22_2926, "EditHours"); ("EditHours", "Mode", 0, "EditMinutes"); ("EditMinutes", "Set", a22_1405, "EditMinutes"); ("EditMinutes", "Mode", 0, "Show");
addStateDisplay("Show", -1, METime.MINUTE, d22_977); addStateDisplay("EditHours", METime.HOUR_OF_DAY, METime.MINUTE, d22_977); addStateDisplay("EditMinutes", METime.MINUTE, METime.MINUTE, d22_977); };
© MetaCase/JPT
162
Code generator example [3/3] Generating watch applications
Generator output public Object perform(int methodId) { switch (methodId) { case a22_2926: getclockOffset().roll(METime.HOUR_OF_DAY, true, displayTime()); return null; case a22_1405: getclockOffset().roll(METime.MINUTE, true, displayTime()); return null; case d22_977: return getclockTime(); } return null; }
© MetaCase/JPT
163
Code generator example [3/3] Generating watch applications
Generator output public Object perform(int methodId) { switch (methodId) { case a22_2926: getclockOffset().roll(METime.HOUR_OF_DAY, true, displayTime()); return null; case a22_1405: getclockOffset().roll(METime.MINUTE, true, displayTime()); return null; case d22_977: return getclockTime(); } return null; }
© MetaCase/JPT
164
Code generator example [3/3] Generating watch applications
Generator output public Object perform(int methodId) { switch (methodId) { case a22_2926: getclockOffset().roll(METime.HOUR_OF_DAY, true, displayTime()); return null; case a22_1405: getclockOffset().roll(METime.MINUTE, true, displayTime()); return null; case d22_977: return getclockTime(); } return null; }
© MetaCase/JPT
165
Code generator example [3/3] Generating watch applications
Generator output public Object perform(int methodId) { switch (methodId) { case a22_2926: getclockOffset().roll(METime.HOUR_OF_DAY, true, displayTime()); return null; case a22_1405: getclockOffset().roll(METime.MINUTE, true, displayTime()); return null; case d22_977: return getclockTime(); } return null; }
© MetaCase/JPT
166
Code generator example [3/3] Generating watch applications
Generator output public Object perform(int methodId) { switch (methodId) { case a22_2926: getclockOffset().roll(METime.HOUR_OF_DAY, true, displayTime()); return null; case a22_1405: getclockOffset().roll(METime.MINUTE, true, displayTime()); return null; case d22_977: return getclockTime(); } return null; }
© MetaCase/JPT
167
Code generator example [3/3] Generating watch applications
Generator output public Object perform(int methodId) { switch (methodId) { case a22_2926: getclockOffset().roll(METime.HOUR_OF_DAY, true, displayTime()); return null; case a22_1405: getclockOffset().roll(METime.MINUTE, true, displayTime()); return null; case d22_977: return getclockTime(); } return null; }
© MetaCase/JPT
168
The importance of autobuild Autobuild = move straight from model to live testing 1. Generate all files from models and submodels 2. Run compiler on files 3. Start resulting application • In emulator if necessary • With execution visually traced back in model if possible
Saves time, avoids manual errors, keeps consistency Most importantly, saves brain from context switching – Models describe application on high level – Never need to think about code
Autobuild via batch or makefile – Good reference for batch and shell scripts: www.ss64.com
© MetaCase/JPT
169
Domain Framework
© MetaCase/JPT
170
Domain framework DSM environment
Provides an interface for the target platform and programming language Raise the level of abstraction on the platform side Achieved by atomic implementations of commonalities and variabilities – especially for behaviour – implementation as templates and components
Include interface for the code to be generated – often the only needed part for static variation (e.g. for XML schema)
© MetaCase/JPT
DOMAINSPECIFIC Modelling LANGUAGE
DOMAINSPECIFIC CODE GENERATOR
DOMAIN FRAMEWORK
171
Manual coding vs Wizards vs DSM
HandWritten Code
Wizard
Model
Generated & HandWritten Code
Generated Code
Domain Framework Component Framework
Component Framework
Component Framework
Platform
Platform
Platform
© MetaCase/JPT
172
Why have a domain framework? Removing duplication from generated code – Automates reuse, cf. duplication in hand-written code – Edit long sections of static code in IDE, not generator
DSM takes broader + longer view bigger framework – Code:1 developer writes 2 file dialog calls per application • Not worth writing a framework function copy & paste
– DSM: 1 developer writes 1 generator for 100 applications • Big payback from framework function: size, simplicity
Hiding platform details – Bypassing bugs and platform evolution – Extending a framework from one platform to many • Model, generators and generated code remain the same • Interface to framework remains the same • Just switch in a different framework version © MetaCase/JPT
173
Combining generated code and other code Different levels of code to integrate – Other generated code – Domain framework, components, platform functions – Hand-made code
Separation of generated and non-generated code – Best to keep them in separate files (or sections in files)
Generated code… – – – –
can can can can
call existing code, instantiate data structures be called from existing code be subclassed from existing code form base classes
Model
Generated code
Non-generated © MetaCase/JPT
174
Tools for DSM creation and use
6 ways to get the tools we need for DSM 1. 2. 3. 4. 5. 6.
Good tools minimize resource use (few man-weeks) – – –
Write own modelling tool from scratch Write own modelling tool based on frameworks Metamodel, generate modelling tool skeleton, add code Metamodel, generate full modelling tool over a framework Metamodel, output configuration for generic modelling tool Integrated modelling and metamodelling environment creating modelling tools and generators data-like, not code guide in DSM creation allow you to test DSM throughout domain design process
Good tools allow DSML to change and reflect changes – –
to modelling tools to design models already made
© MetaCase/JPT
175
Summary Domain-specific modelling radically improves productivity (5-10x) DSM leverages expert developers’ abilities to empower other developers in a team Good language workbenches provide a costeffective way to create DSM infrastructure Anything you can write & model, you can generate – If you can’t write it yet, you can’t generate it yet
Building DSM solutions is great fun – The ultimate refactoring!
More info: – www.DSMforum.org – www.DSMbook.com © MetaCase/JPT
176
Thank you! Questions?
Contact: Juha-Pekka Tolvanen
[email protected] www.metacase.com/blogs/jpt © MetaCase/JPT
177
Further reading Kelly, S., Pohjonen, R., Worst Practices for DomainSpecific Modeling, IEEE Software, July/Aug, 2009. Kärnä et al. Evaluating the use of DSM in practice, OOPSLA workshop on Domain-Specific Modeling, 2009 Kelly, S., Tolvanen, J.-P., Domain-Specific Modeling: Enabling Full Code Generation, Wiley, 2008. http://dsmbook.com Kieburtz, R. et al., A Software Engineering Experiment in Software Component Generation, Proceedings of 18th International Conference on Software Engineering, Berlin, IEEE Computer Society Press, 1996. Pohjonen, R., Kelly, S., Domain-Specific Modeling, Dr. Dobb's, 8, 2002. Safa, The Making Of User-Interface Designer: A Proprietary DSM Tool, OOPSLA workshop on Domain-Specific Modeling, 2007 Weiss, D., Lai, C. T. R., Software Product-line Engineering, Addison Wesley Longman, 1999. © MetaCase/JPT
178