org.fuin.dsl.ddd - a domain-driven design (ddd) dsl
DESCRIPTION
Describes a DSL that is available as Eclipse Plugin at https://github.com/fuinorg/org.fuin.dsl.dddTRANSCRIPT
org.fuin.dsl.ddd - A Domain-Driven Design (DDD) DSL
Domain-Specific Language (DSL)
Expressing a Domain-Driven Design (DDD) model
Model can be used for any type of „model to text“ (code generation) or
„model to model“ transformation
Xtext based Eclipse Plugin
Syntax Coloring Content Assist Validation and Quick Fixes
Open Source
https://github.com/fuinorg/org.fuin.dsl.ddd LGPL License
org.fuin.dsl.ddd – Basic concepts (Context / Namespace / Type)
context sales {
namespace b.c.d {
type String
type Integer
}
}
File Extension: *.ddd Can contain multiple contexts Filename is completely independent
from content
Context
DDD Term = Bounded Context
Namespace
DDD Term = Module Also known as „Package“ Names separated by a dot
Type
External Type Defined outside the DSL
org.fuin.dsl.ddd – Basic concepts (Import / Constraint)
Import Required when using types from other
namespaces
Constraint
Condition that must be satisfied Also known as „Business Rule“ Has a name unique in the namespace Always is related to a type it restricts
(„on“) – Internal or external type Has zero or more variables used to
customize the condition Defines an error message
All variables from the constraint canbe used
The validated value itself is a predefined variable („vv“)
context x {
namespace constr {
import types.*
/** Makes sure a string has exactly a given size. */
constraint ExactLength on String {
/** Expected length. */
Integer expected
message "Expected an exact length of ${expected},
but value was: '${vv}'"
}
}
}
org.fuin.dsl.ddd – Variables: Basics
Variable
May have a comment (Optional)
Has a type (internal/external) and a name
Is by definition not nullable, except it startswith the nullable keyword
Inherits meta data (slabel, label, …) andcomment from internal types
Can overwrite the meta data
May define invariants (References one ormore constraints)
/** Comment for never-null “a”. */
String a
/** Comment for nullable “b”. */
nullable String b
// Inherits the comment + meta data
CustomerName name
/** Overwrites the CustomerName’s comment. */
nullable CustomerName name2 {
// Overwrites the CustomerName’s short label
slabel “CNA“
}
String name3 invariants Length(1, 50)
org.fuin.dsl.ddd – Variables: Meta Data
Meta data
slabel = Short label used when space in theUI is limited (Example: Table headers)
label = Label for the UI
tooltip = Tooltipp for the UI
prompt = Prompt text (like „ Enter searchkeywords…“ for input fields)
examples = Values that may be used in mockups, tests, … (Separated by a space)
String createdBy {
slabel "Created"
label "Created by user"
tooltip "Name of the user that created the record"
prompt "<Enter>"
examples "pparker mjwatson hosborn“
}
org.fuin.dsl.ddd – Value Objects
Value Object
May have a comment (Optional)
Has a name that is unique in the namspace
Can be based on an external type (Optional)
Define optional meta data (slabel, label, …)
Defines zero or more variables
May define constructors and methods
/** Lanugage specific name. */
value-object ContentName base String {
slabel "CN"
label "Content name"
tooltip "Unique name of the content"
/** Human readable name. */
String name invariants Length(1, 50)
/** Language the name is in. */
Locale locale
}
org.fuin.dsl.ddd – Aggregate ID / Entity ID
Aggregate ID
Is a special form of value object
Identifies an aggregate
Same rules as for value objects
Entity ID
Is a special form of value object
Identifies an entity
Same rules as for value objects
/** Identifies an Xyz aggregate uniquely in the context. */
aggregate-id XyzId identifies Xyz base UUID {
UUID val
}
/**
* Identifies an Abc entity uniquely in the context
* of it’s aggregate.
*/
entity-id AbcId identifies Abc base Integer {
Integer val
}
org.fuin.dsl.ddd – Enums
Enum
Is a special form of value object
Enumeration of values
Defines a fix set of instances
Same rules as for value objects
enum Cards {
String name
instances {
CLUB
SPADE
HEART
DIAMOND
}
}
org.fuin.dsl.ddd – Aggregates: Overview
Aggregate
Has a name that should be unique in thecontext
Has an aggregate identifier
Defines a number of variables (Externaltypes, value objects, services or entitiesbelonging to this aggregate)
Defines one or more constructors andmethods
References to other aggregates are onlyallowed using aggregate identifier
/**
* A customer (sometimes known as a client, buyer,
* or purchaser) is the recipient of a good, service
* or product.
*/
aggregate Customer identifier CustomerId {
CustomerName name
:
constructor createWithA { … }
constructor createWithB { … }
method doSomething { … }
method whatever { … }
}
org.fuin.dsl.ddd – Aggregates/Entities: Constructors & Methods
Constructor / Method
Defines zero or more parameters
Can have constraints
May fires one or more events
Method
May return a result:
returns XyzType
constructor create {
CustomerName newName
:
constraints {
AbcConstraint, DefConstraint, …
}
event CustomerCreatedEvent { … }
event InformTheAdminEvent { … }
:
}
org.fuin.dsl.ddd – Aggregates/Entities: Events
Events
Defines zero or more variables
Defines a message All variables from the event can be
used in the message
Is the result of a successfulconstructor/method execution
It‘s a good style to include all informationthat is available and may be of interest forevent consumers
/**
* The name of a customer was changed.
*/
event CustomerNameChangedEvent {
CustomerId id // Inherits doc from CustomerId
/** Old name before the change. */
CustomerName oldName
/** New (current) name. */
CustomerName newName
message "Changed the name of customer ${id} from
'${oldName}' to '${newName}'"
}
org.fuin.dsl.ddd – Aggregates/Entities: Method References
A method of an aggregate or entity mayreference a method of a direct sub-entity (ref)
Referencing is just a shortcut to avoidenumerating the same parameters again
One can think of this as adding all the variables of the referenced method to the ones defineddirectly in the referencing method
aggregate Customer identifier CustomerId {
method changePersonName ref Person.changeName {
constraints {
PersonExistsConstraint
}
}
}
entity Person identifier PersonId root Customer {
method changeName {
PersonName name
}
}
org.fuin.dsl.ddd – Entity
Entity
Has a name that should be unique in thecontext
Has an entity identifier
References the aggregate root it belongs to
Same functionality as an aggregate
/**
* Contact person for a customer.
*/
entity Person identifier PersonId root Customer {
PersonName name
:
}
org.fuin.dsl.ddd – Service
Service
Has one or more methods
May define a return value (Optional)
Can have constraints
May be referenced from aggregates orentities
Parameters/Return Type in a service cannotreference aggregates/entities directly –Only by their IDs.
/** My service documentation. */
service MyService {
/**
* Loads the display name of a customer.
*/
method loadPersonName {
PersonId id
returns PersonName
constraints { PersonExistsConstraint }
}
}