SlideShare ist ein Scribd-Unternehmen logo
1 von 40
Agiles Modellieren mit
             Domain Specific Languages -
                 Eine DSL für eine
              generische WebApp - API
                                        Dominik Hirt
                                      efinia UG, Leipzig



20. IndustrieTag InformationsTechnologie      IHK Halle-Dessau   20. November 2012
Agiles Modellieren mit
             Domain Specific Languages -
                 Eine DSL‘s für eine
              generische WebApp - API
                                        Dominik Hirt
                                      efinia UG, Leipzig



20. IndustrieTag InformationsTechnologie      IHK Halle-Dessau   20. November 2012
Dominik Hirt
http://www.efinia.de
Personal Finance Management
Das Modellieren mit
Domain Specific Languages
vereinfacht den Entwicklungs-
prozess und erhöht die
Qualität unserer Software.
^[A-Z0-9._%-]+@(?:[A-Z0-9-]+.)+[A-Z]{2,4}$
^[A-Z0-9._%-]+@(?:[A-Z0-9-]+.)+[A-Z]{2,4}$
SELECT COUNT(*)
FROM Account JOIN Customer
WHERE Account.CustID = Customer.ID
WHERE Customer.Name LIKE ‘D%’
SELECT COUNT(*)
FROM Account JOIN Customer
WHERE Account.CustID = Customer.ID
WHERE Customer.Name LIKE ‘D%’
1.e2-e4 e7-e5
2.Lf1-c4 Sb8-c6
3.Dd1-f3 Lf8-c5
4.Df3xf7#
1.e2-e4 e7-e5
2.Lf1-c4 Sb8-c6
3.Dd1-f3 Lf8-c5
4.Df3xf7#
Unified
 Modeling
Language
Das Problem




Browser   Desktop      Mobile   Tablet


                                   API

           Server / Plattform
Die Ursachen




Redundanz     Abstraktion   Wiederverwendung
Mythos Wiederverwendbarkeit



‣   Klassen

‣   Services

‣   Komponenten

‣   Modelle

‣   Prozesse
Model Driven Software Development




Domäne          Modell        MetaModell
Ein [...] Metamodell stellt die Elemente
einer Modellierungssprache und ihre
Beziehungen in einem Modell dar.
                              [Wikipedia]
grammar de.efinia.webapp.WebAPI with org.eclipse.xtext.xbase.Xbase
generate webAPI "http://www.efinia.de/webapp/WebAPI"
WebAPIModel:
	   functions += Function*
;
Function:
    'function' name = ID '{'
         request=Request
         response=Response
    '}'
;
Request:
    'request' '{'
        'url : ' url=URLType
        ('method :' method=HttpRequestMethod)?
        params+=Parameter*
    '}'
;
URLType:
    '/'ID
;
enum HttpRequestMethod:
    GET='GET' | POST='POST'
;
function createAccount {
	    request {
	    	    url : "/konto"
	    	    method : PUT
        param name String
        param kontoNummer String 1..10
        param blz String 8
    }
    response {
        param accountId long 1..8
    }
}

function updateAccount {
	    request {
	    	    url : "/konto/{accountId}"
	    	    method : POST
        param name String
    }
    response {
        param accountId long 1..8
    }
}

function deleteAccount {
	    request {
	    	    url : "/konto"
	    	    method : DELETE
        param id long
    }
    response {
        param success long 1..8
        error deleteAccountError
    }
}

error deleteAccountError "Konto löschen fehlgeschlagen"
function createAccount {
	    request {
	    	    url : "/konto"
	    	    method : PUT                       RESTful Architektur
        param name String
        param kontoNummer String 1..10
        param blz String 8
    }
    response {
        param accountId long 1..8
    }
}

function updateAccount {
	    request {
	    	    url : "/konto/{accountId}"
	    	    method : POST                   RESTful Architektur
        param name String
    }
    response {
        param accountId long 1..8
    }
}

function deleteAccount {
	    request {
	    	    url : "/konto"
	    	    method : DELETE                 RESTful Architektur
        param id long
    }
    response {
        param success long 1..8
        error deleteAccountError
    }
}

error deleteAccountError "Konto löschen fehlgeschlagen"
grammar de.efinia.dsl.MessagesDsl with org.eclipse.xtext.common.Terminals

generate messagesDsl "http://www.efinia.de/dsl/MessagesDsl"


Messages:
    (allMessages += Message)*
;

Message:
    'message' name = JavaIdentifier
    '{'
         (languages += Language)*
    '}'
;

JavaIdentifier :
  ID ('.' ID)*;

Language:
    name = ID ':' value = STRING
;
Vorher                                  Nachher
<?xml version="1.0" encoding="UTF-8"?>    message impressum.pageTitle {
<messages xmlns:xsi="http://www.w3.org/   	   de : "efinia | Impressum"
2001/XMLSchema-instance"                  }
	                                         message impressum.title {
xsi:noNamespaceSchemaLocation="efiniaMe   	   de : "Impressum"
ssages.xsd">                              }
                                          message login.pageTitle {
	   <message key="impressum.pageTitle">   	   de : "efinia | Login"
	   	   <de>efinia | Impressum</de>       }
	   </message>                            message login.title {
      <message key="impressum.title">     	   de : "Willkommen bei efinia"
          <de>Impressum</de>              }
      </message>

	   <message key="login.pageTitle">
	   	   <de>efinia | Login</de>
	   </message>
	   <message key="login.title">
	   	   <de>Willkommen bei efinia</de>
	   </message>
Vorher                                  Nachher
<?xml version="1.0" encoding="UTF-8"?>    message impressum.pageTitle {
<messages xmlns:xsi="http://www.w3.org/   	   de : "efinia | Impressum"
2001/XMLSchema-instance"                  }
	                                         message impressum.title {
xsi:noNamespaceSchemaLocation="efiniaMe   	   de : "Impressum"
ssages.xsd">                              }
                                          message login.pageTitle {
	   <message key="impressum.pageTitle">   	   de : "efinia | Login"
	   	   <de>efinia | Impressum</de>       }
	   </message>                            message login.title {
      <message key="impressum.title">     	   de : "Willkommen bei efinia"
          <de>Impressum</de>              }
      </message>

	   <message key="login.pageTitle">
	   	   <de>efinia | Login</de>
	   </message>
	   <message key="login.title">
	   	   <de>Willkommen bei efinia</de>
	   </message>



                                                60%
grammar de.efinia.categories.Categories with org.eclipse.xtext.common.Terminals

generate categories "http://www.efinia.de/Categories"

CategoryModel:
    elements += AbstractElement*
;

AbstractElement:
    Category | Keyword
;

Category:
    'category' name = STRING ('-->' parent=[Category|STRING])?
;
	
Keyword:
	   'keyword' name = STRING '-->' category=[Category|STRING]
;
// Hauptkategorien
category "Haus/Wohnung"
category "PKW"
category "Ernährung"

// Unterkategorien
category "Telefon" --> "Haus/Wohnung"
category "Miete" --> "Haus/Wohnung"
category "Strom" --> "Haus/Wohnung"
category "Wasser" --> "Haus/Wohnung"

category "Benzin" --> "PKW"
category "Versicherung" --> "PKW"
category "Steuern" --> "PKW"

// Zuweisung von Schlüsselwörtern
keyword "Telekom" --> "Telefon"
keyword "Vodafone" --> "Telefon"
keyword "O2" --> "Telefon"
keyword "ePlus" --> "Telefon"

keyword "Aldi" --> "Ernährung"
keyword "Netto" --> "Ernährung"
keyword "Edeka" --> "Ernährung"
Model Driven Software Development


MetaModell




                                                       lauffähige
  Modell        Generator          Artefakte
                                                       Software
                                          java
                                             sql
                                               html
                Templates /                       js
           Transformationsregeln
Redundanz
Single Source
MetaModell          Modell




             Test
<Demo>

powered by
‣   Routine Implementierungen

‣   Boilerplate Code

‣   Java Bean Hölle
EFinTLModel:
     useCases+=UseCase*
     dialogs+=Dialog*




                                                   Top Secr
     messages+=Message*
     segments+=Segment*
     datenElementGruppen+=DEG*;
UseCase:




                                                                                       et
     'geschaeftsvorfall' name = ID '{'
          dialogs+=[Dialog]*
     '}';
Dialog:
     'dialog' name = ID '{'
          messages+=[Message]*
     '}';
Message:
     'nachricht' name = ID '{'
          'type' ':' type=NachrichtenType
          'sender' ':' sender=SenderType
          'segments' '{'
              segments += [Segment]
          '}'
     '}';
Segment:
     'segment' kennung=ID name=ID '{'
          datenElemente += (DE | DEGRef)*
          //datenGruppenElemente += (DEGRef)*
     '}';
DE:
     'DE' name=ID ':' format=Format length=Length status=Quantity anzahl=INT restriktion=Constraint)?;
DEGRef:
     'DEG' reference=[DEG] ':' status=Quantity anzahl=INT;
DEG:
     'DEG' name = ID '{'
          gruppenDatenElemente+=(DE)*
     '}';
enum Format:
     an="an" | num="num" | dig="dig" | id="id";
MINMAX_LENGTH:
     min=INT '..' max=INT;
MAX_LENGTH:
     ('..')? max=INT;
EXACT_LENGTH:
     len=INT;
enum Quantity:
     M='Muss' | K='Kann';
QualifiedName:
  ID ('.' ID)*;
enum HBCIVersion :
  v201='201' | v210='210' | v220='220' | v300='300';
enum NachrichtenType :
  K='Kundennachricht' | B='Banknachricht';
enum SenderType :
  K='Kunde' | B='Bank';
blog.todo42.net
d.hirt@efinia.de

Weitere ähnliche Inhalte

Ähnlich wie Agiles Modellieren mit Domain Specific Languages

Ähnlich wie Agiles Modellieren mit Domain Specific Languages (20)

Prototype 1.7
Prototype 1.7Prototype 1.7
Prototype 1.7
 
Einstieg in Xpath für SEO (Campixx2021)
Einstieg in Xpath für SEO (Campixx2021)Einstieg in Xpath für SEO (Campixx2021)
Einstieg in Xpath für SEO (Campixx2021)
 
Microservices mit Rust
Microservices mit RustMicroservices mit Rust
Microservices mit Rust
 
Welches Webframework passt zu mir? (WJAX)
Welches Webframework passt zu mir? (WJAX)Welches Webframework passt zu mir? (WJAX)
Welches Webframework passt zu mir? (WJAX)
 
Mvc public
Mvc publicMvc public
Mvc public
 
.NET Summit 2016 in München: ASP.NET Core 1
.NET Summit 2016 in München: ASP.NET Core 1.NET Summit 2016 in München: ASP.NET Core 1
.NET Summit 2016 in München: ASP.NET Core 1
 
Javascript auf Client und Server mit node.js - webtech 2010
Javascript auf Client und Server mit node.js - webtech 2010Javascript auf Client und Server mit node.js - webtech 2010
Javascript auf Client und Server mit node.js - webtech 2010
 
Legacy WebApps mit AngularJS pimpen
Legacy WebApps mit AngularJS pimpenLegacy WebApps mit AngularJS pimpen
Legacy WebApps mit AngularJS pimpen
 
Domain Driven Design in Rails
Domain Driven Design in RailsDomain Driven Design in Rails
Domain Driven Design in Rails
 
Übersicht Skriptsprachen
Übersicht SkriptsprachenÜbersicht Skriptsprachen
Übersicht Skriptsprachen
 
Codesmells
CodesmellsCodesmells
Codesmells
 
Python builds mit ant
Python builds mit antPython builds mit ant
Python builds mit ant
 
Apache CouchDB at PHPUG Karlsruhe, Germany (Jan 27th 2009)
Apache CouchDB at PHPUG Karlsruhe, Germany (Jan 27th 2009)Apache CouchDB at PHPUG Karlsruhe, Germany (Jan 27th 2009)
Apache CouchDB at PHPUG Karlsruhe, Germany (Jan 27th 2009)
 
Wicket Kurzübersicht
Wicket KurzübersichtWicket Kurzübersicht
Wicket Kurzübersicht
 
IPC 2015 Zend Framework 3 Reloaded
IPC 2015 Zend Framework 3 ReloadedIPC 2015 Zend Framework 3 Reloaded
IPC 2015 Zend Framework 3 Reloaded
 
jQueryMobile mit Extbase/Fluid
jQueryMobile mit Extbase/FluidjQueryMobile mit Extbase/Fluid
jQueryMobile mit Extbase/Fluid
 
Angular von 0 auf 100
Angular von 0 auf 100Angular von 0 auf 100
Angular von 0 auf 100
 
Überblick zu Angular2 auf DevCon der Fox-Pro-Usergroup in Frankfurt, Nov 2015
Überblick zu Angular2 auf DevCon der Fox-Pro-Usergroup in Frankfurt, Nov 2015Überblick zu Angular2 auf DevCon der Fox-Pro-Usergroup in Frankfurt, Nov 2015
Überblick zu Angular2 auf DevCon der Fox-Pro-Usergroup in Frankfurt, Nov 2015
 
Vorlesung SOA - DIS AG.pptx
Vorlesung SOA - DIS AG.pptxVorlesung SOA - DIS AG.pptx
Vorlesung SOA - DIS AG.pptx
 
AndroMDA - Einführung in eine Open Source Model Driven Architecture Lösung
AndroMDA - Einführung in eine Open Source Model Driven Architecture LösungAndroMDA - Einführung in eine Open Source Model Driven Architecture Lösung
AndroMDA - Einführung in eine Open Source Model Driven Architecture Lösung
 

Agiles Modellieren mit Domain Specific Languages

  • 1.
  • 2. Agiles Modellieren mit Domain Specific Languages - Eine DSL für eine generische WebApp - API Dominik Hirt efinia UG, Leipzig 20. IndustrieTag InformationsTechnologie IHK Halle-Dessau 20. November 2012
  • 3. Agiles Modellieren mit Domain Specific Languages - Eine DSL‘s für eine generische WebApp - API Dominik Hirt efinia UG, Leipzig 20. IndustrieTag InformationsTechnologie IHK Halle-Dessau 20. November 2012
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12. Das Modellieren mit Domain Specific Languages vereinfacht den Entwicklungs- prozess und erhöht die Qualität unserer Software.
  • 15. SELECT COUNT(*) FROM Account JOIN Customer WHERE Account.CustID = Customer.ID WHERE Customer.Name LIKE ‘D%’
  • 16. SELECT COUNT(*) FROM Account JOIN Customer WHERE Account.CustID = Customer.ID WHERE Customer.Name LIKE ‘D%’
  • 20. Das Problem Browser Desktop Mobile Tablet API Server / Plattform
  • 21. Die Ursachen Redundanz Abstraktion Wiederverwendung
  • 22. Mythos Wiederverwendbarkeit ‣ Klassen ‣ Services ‣ Komponenten ‣ Modelle ‣ Prozesse
  • 23. Model Driven Software Development Domäne Modell MetaModell
  • 24. Ein [...] Metamodell stellt die Elemente einer Modellierungssprache und ihre Beziehungen in einem Modell dar. [Wikipedia]
  • 25. grammar de.efinia.webapp.WebAPI with org.eclipse.xtext.xbase.Xbase generate webAPI "http://www.efinia.de/webapp/WebAPI" WebAPIModel: functions += Function* ; Function: 'function' name = ID '{' request=Request response=Response '}' ; Request: 'request' '{' 'url : ' url=URLType ('method :' method=HttpRequestMethod)? params+=Parameter* '}' ; URLType: '/'ID ; enum HttpRequestMethod: GET='GET' | POST='POST' ;
  • 26. function createAccount { request { url : "/konto" method : PUT param name String param kontoNummer String 1..10 param blz String 8 } response { param accountId long 1..8 } } function updateAccount { request { url : "/konto/{accountId}" method : POST param name String } response { param accountId long 1..8 } } function deleteAccount { request { url : "/konto" method : DELETE param id long } response { param success long 1..8 error deleteAccountError } } error deleteAccountError "Konto löschen fehlgeschlagen"
  • 27. function createAccount { request { url : "/konto" method : PUT RESTful Architektur param name String param kontoNummer String 1..10 param blz String 8 } response { param accountId long 1..8 } } function updateAccount { request { url : "/konto/{accountId}" method : POST RESTful Architektur param name String } response { param accountId long 1..8 } } function deleteAccount { request { url : "/konto" method : DELETE RESTful Architektur param id long } response { param success long 1..8 error deleteAccountError } } error deleteAccountError "Konto löschen fehlgeschlagen"
  • 28. grammar de.efinia.dsl.MessagesDsl with org.eclipse.xtext.common.Terminals generate messagesDsl "http://www.efinia.de/dsl/MessagesDsl" Messages: (allMessages += Message)* ; Message: 'message' name = JavaIdentifier '{' (languages += Language)* '}' ; JavaIdentifier : ID ('.' ID)*; Language: name = ID ':' value = STRING ;
  • 29. Vorher Nachher <?xml version="1.0" encoding="UTF-8"?> message impressum.pageTitle { <messages xmlns:xsi="http://www.w3.org/ de : "efinia | Impressum" 2001/XMLSchema-instance" } message impressum.title { xsi:noNamespaceSchemaLocation="efiniaMe de : "Impressum" ssages.xsd"> } message login.pageTitle { <message key="impressum.pageTitle"> de : "efinia | Login" <de>efinia | Impressum</de> } </message> message login.title { <message key="impressum.title"> de : "Willkommen bei efinia" <de>Impressum</de> } </message> <message key="login.pageTitle"> <de>efinia | Login</de> </message> <message key="login.title"> <de>Willkommen bei efinia</de> </message>
  • 30. Vorher Nachher <?xml version="1.0" encoding="UTF-8"?> message impressum.pageTitle { <messages xmlns:xsi="http://www.w3.org/ de : "efinia | Impressum" 2001/XMLSchema-instance" } message impressum.title { xsi:noNamespaceSchemaLocation="efiniaMe de : "Impressum" ssages.xsd"> } message login.pageTitle { <message key="impressum.pageTitle"> de : "efinia | Login" <de>efinia | Impressum</de> } </message> message login.title { <message key="impressum.title"> de : "Willkommen bei efinia" <de>Impressum</de> } </message> <message key="login.pageTitle"> <de>efinia | Login</de> </message> <message key="login.title"> <de>Willkommen bei efinia</de> </message> 60%
  • 31. grammar de.efinia.categories.Categories with org.eclipse.xtext.common.Terminals generate categories "http://www.efinia.de/Categories" CategoryModel: elements += AbstractElement* ; AbstractElement: Category | Keyword ; Category: 'category' name = STRING ('-->' parent=[Category|STRING])? ; Keyword: 'keyword' name = STRING '-->' category=[Category|STRING] ;
  • 32. // Hauptkategorien category "Haus/Wohnung" category "PKW" category "Ernährung" // Unterkategorien category "Telefon" --> "Haus/Wohnung" category "Miete" --> "Haus/Wohnung" category "Strom" --> "Haus/Wohnung" category "Wasser" --> "Haus/Wohnung" category "Benzin" --> "PKW" category "Versicherung" --> "PKW" category "Steuern" --> "PKW" // Zuweisung von Schlüsselwörtern keyword "Telekom" --> "Telefon" keyword "Vodafone" --> "Telefon" keyword "O2" --> "Telefon" keyword "ePlus" --> "Telefon" keyword "Aldi" --> "Ernährung" keyword "Netto" --> "Ernährung" keyword "Edeka" --> "Ernährung"
  • 33. Model Driven Software Development MetaModell lauffähige Modell Generator Artefakte Software java sql html Templates / js Transformationsregeln
  • 35. MetaModell Modell Test
  • 37. Routine Implementierungen ‣ Boilerplate Code ‣ Java Bean Hölle
  • 38. EFinTLModel: useCases+=UseCase* dialogs+=Dialog* Top Secr messages+=Message* segments+=Segment* datenElementGruppen+=DEG*; UseCase: et 'geschaeftsvorfall' name = ID '{' dialogs+=[Dialog]* '}'; Dialog: 'dialog' name = ID '{' messages+=[Message]* '}'; Message: 'nachricht' name = ID '{' 'type' ':' type=NachrichtenType 'sender' ':' sender=SenderType 'segments' '{' segments += [Segment] '}' '}'; Segment: 'segment' kennung=ID name=ID '{' datenElemente += (DE | DEGRef)* //datenGruppenElemente += (DEGRef)* '}'; DE: 'DE' name=ID ':' format=Format length=Length status=Quantity anzahl=INT restriktion=Constraint)?; DEGRef: 'DEG' reference=[DEG] ':' status=Quantity anzahl=INT; DEG: 'DEG' name = ID '{' gruppenDatenElemente+=(DE)* '}'; enum Format: an="an" | num="num" | dig="dig" | id="id"; MINMAX_LENGTH: min=INT '..' max=INT; MAX_LENGTH: ('..')? max=INT; EXACT_LENGTH: len=INT; enum Quantity: M='Muss' | K='Kann'; QualifiedName: ID ('.' ID)*; enum HBCIVersion : v201='201' | v210='210' | v220='220' | v300='300'; enum NachrichtenType : K='Kundennachricht' | B='Banknachricht'; enum SenderType : K='Kunde' | B='Bank';

Hinweis der Redaktion

  1. - Vor dem Start: alle Programme schliessen ausser keynote &amp; 2x Eclipse\n\n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. wir haben unser B&amp;#xFC;ro in Leipzig\n
  9. das ist zwar in Sachsen\n
  10. aber zu Sachsen-Anhalt\n
  11. und insbesondere zu Halle und zur Martin-Luther-Universit&amp;#xE4;t habe ich ein enges Verh&amp;#xE4;ltniss, da ich hier von 1992-1999 studiert habe.\n
  12. Bevor ich fortfahre ... wer hat schon mit Domain Spec. Lang. gearbeitet ?\n
  13. \n
  14. \n
  15. - die F&amp;#xE4;higkeit f&amp;#xFC;r interne DSL&amp;#x2018;s als Erfolgsgrund f&amp;#xFC;r Frameworks wie RoR, Grails\n- wor&amp;#xFC;ber ich heute aber nicht sprechen m&amp;#xF6;chte ist...\n
  16. - agil klappt nicht mit UML ... das ist meine pers&amp;#xF6;nliche meinung\n jahrelang versucht, mit einer UML Spec. irgendwas anzufangen, weiterzuverarbeiten ... ohne Erfolg\n
  17. - Schnittstellenbeschreibung wichtig f&amp;#xFC;r: \nTechnik\nOrganisation\nzwischenmenschlich\n
  18. \n
  19. \n
  20. - MetaModell beschreibt Modell mit abstrakter Syntax\n- Modell beschreibt die Dom&amp;#xE4;ne mit konkreter Syntax\n- abstrakte Syntax wichtig f&amp;#xFC;r Verarbeitung der Modelle (konkrete Syntax) hingegen nicht\n\n
  21. - als Grundlage f&amp;#xFC;r DSL&amp;#x2018;s dienen ,sprachbasierte Metamodelle&amp;#x2018;\n
  22. - ggf. in Eclipse zeigen\n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. XML Header sind nicht etwa &amp;#xFC;berfl&amp;#xFC;ssig, diese werden f&amp;#xFC;r/von den Editoren ben&amp;#xF6;tigt\n
  31. \n
  32. \n
  33. \n
  34. \n
  35. - roundtrip live demo\n
  36. - roundtrip live demo\n- CMD-H und danach das Dock-Icon anklicken\n\n
  37. \n
  38. - ca. 1000 Seiten Spec\n
  39. \n
  40. \n