Modellierung statischer Domänenmodelle mit Xtext · PDF fileXtext Java User Group Saxony...
Transcript of Modellierung statischer Domänenmodelle mit Xtext · PDF fileXtext Java User Group Saxony...
Modellierung statischer Domänenmodelle mit
Xtext
Java User Group Saxony
Frank Schwarz
buschmais GbR
InhaberTorsten Busch, Frank Schwarz, Dirk Mahler und Tobias Israel
[email protected]://www.buschmais.de/author/frank
Leipzig, 15. Januar 2009
Motivation
Grundlagen
Sprachentwurf
Code-Generierung
Motivation
Code-Generierung
Sprachentwurf
Grundlagen
Modellierung statischer Domänenmodelle mit Xtext
IIII
IIII
IIII
IIIIIIII
IIIIIIIIIIII
IIII IIII
IIII
IIII
IIII
IIII
IIII
Die Hölle des Modellierers
produktIDverpackungsKZhoehebreitetiefegewicht
Produkt
IIIIIII
IIII
IIIIII
IUI IIOI IIIIIIII
IIII
IIIII
IUIII
IIOIII
IIIOI
IIUII
IIIII
II
IOOII IIIIII
OTR
IIIIIII
II IIIII
IIIIII
IIIII
IILILI
LLILII III
Objekte::Lager::Umlagerung::Produkt
gesperrt
gesperrt
gesperrt
gesperrt
IIII
Die Hölle des Konfigurationsmanagers
Ist in 5 Jahren noch das Modell zugänglich, welches
dem Anwendungssystem in Version 2.12.2-1 zugrunde liegt?
Kann der Entwicklungsprozess später nochvollständig ausgeführt werden.
Zielkonflikt modellgetriebener Softwareentwicklung
Aufwand für das KMWerkzeugverfügbarkeit
Kommunizierbarkeit
Kooperatives ModellierenAnpassbarkeit (z.B. durch Profile)
Problemangemessenheit
gering
hoch
hoch
gut
gut
hoch
UML-ModelleXML-Modelle
Ein kleines Beispiel zum Einstieg
entitytype Person {
attribute name : String;
attribute birthday : Date;
attribute salary : Currency;
}
entitytype Invoice {
attribute invoiceNumber : String;
attribute paymentTarget : Date;
attribute total : Currency;
}
Xtext
domänenspezifische Sprache auf Basis von Xtext
ANTLR
oAWEMF
Ecore/EMF-Modelle
Workflows Xpand
Xtend
Parser-Generator mit der Mächtigkeit LL(*)
Modellbeziehungen
Ecore
Xtext
DataLayer-Grammatik
Xtext
Xtext-Grammatik
Ecore
DataLayer-DSL
DataLayer-Modell
EModelElement
EAnnotation ENamedElement EFactory
EGenericType
EClassifierEEnumLiteral EPackage
EClassEDataType
EEnum
ETypedElement ETypeParameter
1
-eAnnotations
*
EOperation EParameter
EStructuralFeature
EReference EAttribute
1 -eOperations *1
-eSuperTypes
*
1
-eLiterals
0..* 1
-eClassifiers
*
1
-eOpposite 0..1
1
-eStructuralFeatures
*
1-eSubpackages *
ecore EObject
*
-eType
0..1
XTextFile
Rule
1
-rules
*
NativeLexerRule RuleWithType StringRule
EnumRule TypeRule
Element
GroupAlternatives
1
-children
*
1
-alternatives
*
AbstractToken
CrossReferenceEnumLiteral FileRef ImportKeyword MetamodelImport
RuleName
1
-ruleName
1
TypeName 1
-type
1
1
-mmImports *
1
-imports *
1
-content1
1
-content1
1
-literals
*
Assignment
1-token 1
xtext
Ziel-Produkte
(oAW5)
oAW
oAW
Model: ( elements += ModelElement )*;
Enum PrimitiveType :^String='String' | Currency='Currency' | Date='Date';
ModelElement:Entitytype;
Entitytype:
'entitytype' name=ID '{' (attributes += Attribute ';')*
'}';
Attribute:'attribute' name=ID ':' PrimitiveType;
EnumRule
TypeRule
Group
Assignment
Keyword
Model
Entities
ModelElement
AttributeEntitytype
1
-elements
0..*
1
-attributes
0..*
+NULL = 1+String = 1+Currency = 2+Date = 3
«enumeration»PrimitiveType
entitytype Person {attribute name : String;attribute birthday : Date;attribute salary : Currency;
}
entitytype Invoice {attribute invoiceNumber : String;attribute paymentTarget : Date;attribute total : Currency;
}
org.eclipse.emf.ecore.extension_parser
Transformationen
1. DataLayer-Grammatik Entities-DSL (Erzeugung der Werkzeuge)
2. DataLayer-Modell Entities-DSL (Anwendung der Werkzeuge)
EMF
• MM Ecore• MM XMI• Factory und
Implementierung für Modell-Parser (und Dummy-Serialisierer)
ANTLR
• Grammatik• Lexer• Parser
Editor-Plug-in
• DataLayer-Editor (Linker, Checks, Style, Content-Assist, Outline, Navigation)
• New-Model-Wizard• New-Project-Wizard
oAW-Workflow
(Parser.oaw)
• Parser• Xtext-Linker• oAW-Checker
IFileText
ANTLR
Lexer & Parser
EMF-Modell
ohne Cross-
Referenzen
Xtext-Linker
EMF-Modellmit Cross-
Referenzen
oAW-Check
Geprüftes
EMF-Modell
GenLinker.ext/Linker.extGenLinking.ext/Linking.ext
GenChecks.extChecks.ext
Beschreibung der Domäne
Konzepte Entitätstypen Attribute Entitäts-“Ergänzungen“ Primitive Datentypen Enumerationen Referenzen: Existenz-Semantik,
Änderungssemantik, Ordnung/Sortierung Vererbung: Delegation,
Mehrfachvererbung Datenbank-Mapping
Spalten-/Tabellen-Namen Spaltengrößen Indizes und Constraints
O/R-Mapper-Konfiguration Caching Fetch-Strategien Historisierung
-Name : String-Alter : Duration-Geburtstag : LocalDate-Beschreibung : Text-Foto : JPEGImage-Einkommen : Currency
Person
AdresseLieferung
1
-lieferadresse
1
AdressePerson
1 *
Erstlieferung Ersatzlieferung
Datenbank-Mapping von Relationstypen
Problemfall Java Persistence API 1.0 Join-Tabelle vs. Join-Spalte bei 1-1- oder 1-N-Beziehungen
Reihenfolgeerhalt bei Listen
Collections von primitiven Datentypen
ToOne-Beziehungen als Teil der Objektidentität
Geschachtelte Einbettung von Embeddable-Typen
JPA1 Unidirektionale1-N-Beziehung
Bidirektionale1-N-Beziehung
Join-Table Join-Column
Sprach-Syntax
Kriterien Konsistenz der abstrakten Grammatik (Konzept-Konsistenz)
Parsebarkeit (Xtext-Freundlichkeit)
Kompaktheit vs. Lesbarkeit/Verständlichkeit
Zweckmäßigkeit („When in doubt, leave it out!“)
Beispiel:entitytype Person { superclass : Akteur; complement : Änderungsverfolgung; attribute name : String is-indexed; reference adresse : Adresse is-historized; reference projektHistorie : List<Projekt> # mitglieder is-ordered-by(endeDatum desc); reference kompetenzen : Set<Kompetenz> # many-to-many;
}
Generierbare Artefakte
Java-Beans
Mapping-Deskriptoren (orm.xml vs. hbm.xml)
Meta-Klassen ähnlich dem Java-Reflection-API bzw. EMF-Modellen
Spalten-/Tabellen-Namen, Spalten-Präzision, direkte und geerbte Klassen-Attribute, direkte und indirekte Subklassen, …
typsichere Criteria-Queries
SQL-Schema Create-Table-Skripte
Indizes / Constraints
Purge-Table-Skripte
Unterstützung der Schema-Migration
"SELECT p FROM Person p WHERE p.name = :name"
DomainObject fromPerson = queryDefinition.addRoot(Person.class);
fromPerson.where(fromPerson.get("name").equal(queryDefinition.param("name")));
fromPerson = PersonEntity.newQueryRoot()
fromPerson.where(PersonEntity.name.equal(myQueryParameter));
openArchitectureWare kompakt
Template-Sprache Xpand«DEFINE main FOR Model»
«EXPAND JavaBean FOREACH this.eContents.typeSelect(EntityType)»«ENDDEFINE»
«DEFINE JavaBean FOR EntityType»«FILE this.name+'.java'»«EXPAND attribute FOREACH this.attributes()»
«ENDFILE»«ENDDEFINE»
Modell-Prüfung mit Checkcontext EntityType
ERROR "Name of Entity '" + this.name + "' is not unique" :this.siblings().select(e|e.name == this.name).size == 0
;
Funktionale Erweiterungen über XtendList[EntityType] siblings(EntityType type):
type.eContainer.eContents.typeSelect(EntityType).remove(this);
Generierungsstrategien
Redundanz in den Templates ist OK
IF-Blöcke in Templates sind nur für „Ein-Zeiler“ empfehlenswert
verschachtelte IF-Blöcke machen Template unwartbar
besser sind selbstgeschriebene Funktionen als komplizierte Operationen in den Templates«name.toFirstUpper()+'Type'» «name.entityName()»
Es ist besser Model-zu-Model-Transformationen zur Auflösung von Konventionen nutzen (z.B. Namenskonventionen) als If-Not-Null-Abfragen in den Templates
Neben der üblichen Typ-Selektion in den Templates kann eine semantische Selektionen IF-Abfragen reduzieren«EXPAND oneToManyReference FOREACH this.oneToManyReferences()»«EXPAND manyToManyReference FOREACH this.manyToManyReferences()»
Fragen & Antworten
nächster Xtext Workshop: 19.03.2009 in Dresden