Document 261456

5/23/2007
Alan Cameron Wills
Agile development with DSLs
Wizard sample
Visual Studio SDK is supplied
with a set of examples. We’ll look
at a DSL that helps developers
design wizards.
1
5/23/2007
The code in this project defines
an editor for a diagrammatic
domain-specific language.
Wizard sample
This file is the DSL definition.
Most of the code for the DSL
editor is generated from it.
Wizard sample
Build and start the project – this starts a new instance of
Visual Studio, containing code for a wizard.
Most of the code in this project is generated from the DSL.
2
5/23/2007
Wizard sample
Roles
Build and start the wizard project – this runs the sample
wizard.
Normally the wizard project would be part of a larger
application solution.
After debugging the DSL, its author will create and publish
an installer enabling other developers to use it.
Designing Wizard
framework and DSL
Architect
The developers create
applications with
wizards in them.
Wizard DSL &
framework helps
with wizard
Developer
Designing an
app containing a
wizard
using an
app with
a wizard
Hotel booking
3
5/23/2007
The DSL author has to create the DSL
definition, the templates for turning it into
code, and the framework code in which
the generated code runs.
Build model
Application
FeatureDSL
definition
Feature
Framework
templates
MyFeature Model
code
code
Code
generator
Graphical
Editor
Config
Configfiles
files
“feature” = “wizard”
in the case of our
example.
Serialized
model
Templates
Model
<xxx><y
yy
title=“xx”
><zzz>
…
The application developer has to create
an instance of the DSL (and the parts of
the application that the DSL doesn’t deal
with, of course.)
In MS DSL Tools, generation is done with templates.
The DSL author creates code that queries the
developer’s model. In the template, the query code
and material being generated are mixed.
The generated material need not be code.
Parameterized template code: Generated code:
Wizard
Namesp=
UIPSample
Page
Page
Name=
MyFirstWiza
rdPage
Field
Field
Field
Name=
MyFirstField
namespace <#= wizard.Namesp #>
{
<# foreach (Page page in wizard.Pages)
{
#>
namespace UIPSample
{
public partial class MyFirstWizardPage
{
public MyFirstWizardPage()
public partial class <#= page.Name #>
{
{
InitializeComponent();
public <#= page.Name #>()
InitializeDelegates();
{
}
InitializeComponent();
public object GetFieldValue(string fieldName)
InitializeDelegates();
{
}
switch(fieldName)
public object GetFieldValue(string fieldName)
{
{
case “MyFirstField": …
switch(fieldName)
{
<#
foreach (Field field in page.Fields)
{
#>
case “<#= field.Name #> ": …
4
5/23/2007
Combining generated and
handwritten code
Local modifications
templates
Inevitably, the DSL author cannot anticipate every
application, and developers will want to adapt it.
Feature
Framework
My Model
generator
Generated
stuff
What if I don’t like all of the generated stuff?
And there’s some of the Framework I don’t like either…
5
5/23/2007
Local modifications
So there has to be some way of providing for handwritten material to be combined with generated
material.
templates
Feature
Framework
My Model
Generated
stuff
generator
Combined
stuff
+
Handwritten
stuff
?
One-off generation
templates
One approach is just to edit the generated material.
Unless you have a round-trip mechanism (which
only works in some cases) you’ ve lost the
connection, and so the generated material can only
be a start.
Feature
Framework
My Model
generator
Generated
stuff
Generate first time only
Hand edited
stuff
Model initial design
Hand edit
afterwards
Edit the framework too
Not recommended
6
5/23/2007
Combining generated and hand code
One-off generation
– Only get the advantage of prewritten framework
and initial code from model
– Model useless after code is edited
Customizable generation
– Developer never edits generated code
– Generated code designed for customization
• Hooks and overridable code
Customizable generation
templates
Feature
Framework
My Model
generator
superclasses
compile
Combined
code
More
superclasses
Subclass
overrides
Event definitions
Rule definitions
“Generation gap” pattern
7
5/23/2007
Generation Gap
Generate
– Methods to superclass
– Constructors to subclass
Add handwritten code to subclass
– Can override generated methods
Partial classes
Generated
public partial class FoundRoom
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
…
Handwritten
public partial class FoundRoom
{
public override void InitializeDelegates()
{
base.InitializeDelegates();
…
8
5/23/2007
Postprocess composition
For material other than C#, post-processing is the
answer.
Works for general files
A variant of this approach allows the generator to
edit only certain marked-out parts of a file.
templates
My Model
Generated
config file
generator
Postprocess
Feature
Framework
Combined
config file
Handwritten
config file
Edit the templates
Good for mass changes
templates
Edit
Feature
Framework
My Model
generator
Generated
Generated
Generated
files
files
files
Less easy to debug
9
5/23/2007
Round-tripping
templates
My Model
generator
Generated
file
parser
Much more difficult to generalize
Much more difficult to write
than templates
rules
edit
edit
Round-trip tools keep
model close to code
MS DSL Tools currently
don’t do round-trip
Diff
templates
Highlight changes and
flag need for review
My Model
generator
edit
Old version
Generated
file
!
occasional
edit
10
5/23/2007
Dynamic configuration
Direct API
Application
Wizard DSL
definition
Feature
Framework
templates
MyWizard Model
translator
API
Graphical
Editor
Serialized
model
<wizard
><state
title=“xx”
><transit
ion>…
11
5/23/2007
DSL embedded in
bigger application
Workflow
Server
Edits work item state
chart
Evolving a DSL and
Framework
12
5/23/2007
Template parameters
Original unparameterised code:
Parameterized template code:
namespace Fabrikam.DSL.WizardUIP.UIPSample
{
namespace <#= wizard.Namespace#>
{
<# foreach (Page page in wizard.Pages)
{
#>
public partial class MyFirstWizardPage
{
public MyFirstWizardPage()
{
InitializeComponent();
InitializeDelegates();
}
public object GetFieldValue(string fieldName)
{
switch(fieldName)
{
case “MyFirstField": …
public partial class <#= page.Name #>
{
public <#= page.Name #>()
{
InitializeComponent();
InitializeDelegates();
}
public object GetFieldValue(string fieldName)
{
switch(fieldName)
{
<#
foreach (Field field in page.Fields)
{
#>
case “<#= field.Name #> ": …
Wizard
page
page
field
field
field
Evolving a framework
Original code
Templatized code
Model
Syntax
<wizard
><state
title=“xx”
><transit
ion>…
13
5/23/2007
Separation of variability
Fixed
Wizard DSL
definition
templates
Application
Patterns of
implementation
in this domain
Wizard
Framework
MyWizard Model
MyWizard Code
generator
Hand code
Config files
Language of
requirements
in this domain
Variable
Architectural refactoring
Generalize to
framework, templat
es and DSL
Enhance
Develop
instance
solutions
Use in further
instances
14
5/23/2007
Development feedback loops
Architect
Wizard framework
Developer
Application
(uses Wizards)
Customer
Summary
Domain-specific language provides a
means to express the variable requirements
in a domain
Framework represents the patterns of
implementation in the domain
DSL and Framework are developed
– Together
– By evolution from instances
15
5/23/2007
Software factories
Benefits of Domain Specific Language
=
Benefits of clean API:
– separation of concerns
– opportunity for clearly-defined contract
+ Benefits of good language:
– Communication and comprehension
•
•
•
•
Focus on domain abstractions
Readability
Clear mental model
Communication with customers
– Explicit grammar
• Constraint validation
+ Benefits of suitable modern editor:
- Prompting and contextual guidance – what’s [not] allowed
- Navigation and search
- Holophraxis – collapse/expand, zoom
16
5/23/2007
Stabilizing the architecture
sys 1
sys 2
sys 3
sys 11
developers
architects
sys 12
developers
framework
patterns
guidelines
little languages
templates
tools
recipes
sys 13
developers
developers
Software
Factory
Architecture
sys14
Patterns, Guidance,
& Recipes
Process
and roles
Framework,
Components
domain
model
Languages
and Editors
Tools
Call
base rate: £/s
Record
<CallRecord>
×
<caller><number>07713248</number>
call length
call
store
class Magnox : NuclearPowerStation
{
public void dropRods ()
17
5/23/2007
Domain-specific …
Framework, Components, Architecture
– Implements design patterns in this domain
Language
– Use to understand or define
• requirements; or
• design (of some aspect)
– And maybe generate (some of) solution
Tools and Recipes
– Common refactorings, patterns, in this domain
– Style guideline conformance
Process and roles – e.g.:
– Customer-facing vs framework developers
– Methods for creating and verifying models in DSLs
• Nouns and verbs; legacy mining; client doc mining; genetic evolution;
• consistency tests; reviews; prototyping; run-it-and-see; …
– Sync of hardware and software deployment
Patterns and Guidance
– Written by lead developers to guide implementation of choices
Software ‘Factories’
19th Century sweatshop
– Thousands of people doing repetitive backbreaking labour from scratch with primitive tools
21st Century Mass Customization
– Repetitive stuff done by automatic tools
– People do the interesting stuff that varies
between instances
18
5/23/2007
Software Factory =
Domain-specific
•
•
•
•
•
•
•
Languages
Guidance
Tools
Recipes
Patterns
Templates
Frameworks
– Relationships/constraints between viewpoints
Templates
Template =
– Parameterised structure of source files
•
•
•
•
•
•
Skeleton source code in Java, C#, …
Resource files (icons etc)
make / config / build control files
Debug info
IDE parameters
Recipes
Instantiated template
Template defines a type of solution
Wizard
Template
fill in template
parameters
19
5/23/2007
Recipes
Recipe = operation on a type of solution item
– arguments gathered from context and user
Add command
Add web command
Validate command set
--Add Item
New …
Rename
--Build
Debug
--Delete
MyNewToolIcon.bmp
new toolbox icon
skeleton for new
command
Skeleton code for
command coupling
Summary
An integrated domain-specific package of
– DSLs
– Tools
accelerates development in that area
But requires development – good for repeated tasks
– Repeated development tasks – if you do a lot of work with
• The same vertical domain
• The same horizontal technology
20
5/23/2007
DSLs in the software
development process
Brainstorm Requirements
21
5/23/2007
Refine requirements model
Many ways of modeling
requirements, depending on domain...
22
5/23/2007
Use factories to define project backlog
500
400
300
200
100
0
Actual
Jan
Feb
Mar
Apr
May
Predicte
d
Interact with architecture models
23
5/23/2007
Trace architecture to requirements
“Software Factory”
window, allowing users
to select from all of the
products being worked
on.
Each view has an
editing experience
optimized for the
problem domain
Logical view of the
product being
developed, constrained
by the factory schema
…and a standard way of
viewing the work
products belonging to
each view.
24
5/23/2007
Each activity has a
number of associated
assets
The factory guides the
Detail pane shows the user through the
activities associatedsequence of activities
with the selected viewrequired to build the
product
Summary
DSLs can be used at several stages in the
software development process
And in planning
25
5/23/2007
Bibliography
26