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
© Copyright 2024