Short introduction to Domain Driven Design & Model Driven Development
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Short introduction to Domain Driven Design & Model Driven Development

on

  • 2,727 views

Using Domain Driven Design and Model Driven Development together to create a lean architecture

Using Domain Driven Design and Model Driven Development together to create a lean architecture

Statistics

Views

Total Views
2,727
Views on SlideShare
2,708
Embed Views
19

Actions

Likes
6
Downloads
158
Comments
2

6 Embeds 19

http://www.slideshare.net 8
http://pgonyan.blogspot.com 4
https://www.linkedin.com 4
http://pgonyan.blogspot.com.es 1
http://www.slashdocs.com 1
http://www.linkedin.com 1

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • Thanks for your comment :)

    It's true, that this approach works just a well with a text (DSL) based approach to describing the domain.
    The more complex the domain, the more I believe that Visual models benefit the description of the domain. I've experienced this on quite a few projects already. It's easier to see the complex interrelations between aggregates in a visual model, than in a textual hierarchical description. Even though it might sound odd, even the fairly 'ugly' UML class diagrams have worked very well with non-technical personnel and given a good enough foundation for communication.

    Using the code directly as a model is an idea that I've used quite a lot too, but it's IMO less suited for domain and service models. The more expressive the language (XText/Ruby/Groovy/Scala/etc.) the better, when it comes to using Code as the Model :)

    We're in the process of open sourcing the tool, and during that transition a renaming from xxxxMDSD would definitely be in place :)
    Are you sure you want to
    Your message goes here
    Processing…
  • Interesting presentation about an interesting tool, MDD sure gains a lot of relevance when aware of DDD. However I have the feeling that in this code generation approach most of the value comes not from the model being visual, but rather from using pre-canned patterns such as Temporal Object or other Hibernate-specific usage idioms.

    Looks like as opposed to other tools you go much further than code templates and use smarter meta-model-based wizards to generate the code for each pattern, and I think this is a good thing!

    I'm still not fan of the code generation part of MDD, I prefer using code directly as a model, but I'm glad to see tools getting much better like Tiger MDSD ('MDSD' hard to remember to me by the way). Cheers
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • We need a shared language removed of ambiguity <br />
  • We need a shared language removed of ambiguity <br />
  • An appropriate model makes sense of information and focuses it on a problem. <br /> A domain model is not a diagram -> it is the idea that the diagram is intended to convey. <br /> It&apos;s not the knowledge in the domain experts head -> It is a rigorously organized and selective abstraction of knowledge. <br /> A diagram can represent and communicate a model, as can carefully written code, as can an English sentence <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • Makes changes cheaper <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • Is this creativity? <br /> Imagine throwing in ORM or other mappings - Yikes! <br />
  • Is this creativity? <br /> Imagine throwing in ORM or other mappings - Yikes! <br />
  • Is this creativity? <br /> Imagine throwing in ORM or other mappings - Yikes! <br />
  • Is this creativity? <br /> Imagine throwing in ORM or other mappings - Yikes! <br />
  • You&#x2019;re gonna write this code anyway - why not have full control and ensure quality at all levels? <br />
  • You&#x2019;re gonna write this code anyway - why not have full control and ensure quality at all levels? <br />
  • You&#x2019;re gonna write this code anyway - why not have full control and ensure quality at all levels? <br />
  • You&#x2019;re gonna write this code anyway - why not have full control and ensure quality at all levels? <br />
  • Encapsulation is the keyword - forward engineering and code generation <br />
  • Encapsulation is the keyword - forward engineering and code generation <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • &#x201C;Dumb&#x201D;: We want to focus on what the system is - NOT what the system does <br /> What the System does is captured in use cases and implemented as &#x201C;Contexts&#x201D; where our domain objects play certain &#x201C;Roles&#x201D; (DCI - Data, Context, Interaction) <br />
  • &#x201C;Dumb&#x201D;: We want to focus on what the system is - NOT what the system does <br /> What the System does is captured in use cases and implemented as &#x201C;Contexts&#x201D; where our domain objects play certain &#x201C;Roles&#x201D; (DCI - Data, Context, Interaction) <br />
  • &#x201C;Dumb&#x201D;: We want to focus on what the system is - NOT what the system does <br /> What the System does is captured in use cases and implemented as &#x201C;Contexts&#x201D; where our domain objects play certain &#x201C;Roles&#x201D; (DCI - Data, Context, Interaction) <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />

Short introduction to Domain Driven Design & Model Driven Development Presentation Transcript

  • 1. Lean architecture using Domain Driven Design & Model Driven Development Cyberseminar 2010 Jeppe Cramon - TigerTeam ApS TIGERTEAM ® LEAN THINKING
  • 2. A little about me
  • 3. A little about me 15 years as a software developer
  • 4. A little about me 15 years as a software developer Been doing Model Driven Development (MDD) since 2001
  • 5. A little about me 15 years as a software developer Been doing Model Driven Development (MDD) since 2001 Partner in TigerTeam - focusing on our tool sets (TigerMDSD)
  • 6. A little about me 15 years as a software developer Been doing Model Driven Development (MDD) since 2001 Partner in TigerTeam - focusing on our tool sets (TigerMDSD) Facilitator for the Danish IT Societies Java competence network
  • 7. What are the trademarks of a lean architecture?
  • 8. What are the trademarks of a lean architecture? • It’s easy to capture the customers mental model
  • 9. What are the trademarks of a lean architecture? • It’s easy to capture the customers mental model • Code easy to understand and modify - change MUST be cheap!
  • 10. What are the trademarks of a lean architecture? • It’s easy to capture the customers mental model • Code easy to understand and modify - change MUST be cheap! • Continuos iterative refinement to eliminate waste
  • 11. What are the trademarks of a lean architecture? • It’s easy to capture the customers mental model • Code easy to understand and modify - change MUST be cheap! • Continuos iterative refinement to eliminate waste Deliver value timely at the right price!
  • 12. Mental model
  • 13. Mental model It’s all about bringing value to the user
  • 14. Mental model It’s all about bringing value to the user 1. step to bringing value is to understand the users domain by understanding their language
  • 15. Building a Ubiquitous Language
  • 16. Building a Ubiquitous Language All team members & the code use the same language
  • 17. Building a Ubiquitous Language All team members & the code use the same language We can talk to the domain experts without translating
  • 18. Models form the backbone of the Ubiquitous Language
  • 19. Models form the backbone of the Ubiquitous Language A model is a selectively simplified and deliberately structured form of knowledge
  • 20. Why models?
  • 21. Why models? Because code typically is too low level and a poor medium for communication with business experts
  • 22. UML:
  • 23. UML:
  • 24. BPMN:
  • 25. 1,0$C#!1/-89$ ! BPMN: ! !"#$%&'()'*+,&%-.&/&.'0$1"2&11'3%+4&11'5+%'67&'8"#7-*&/&.'9:;<=.&' 012#*)3*#14*526'4*%7*8%&46)"9*)"*+,-.:* :"#$)#);#*'"/+$(3$!"#$AD5E$F(!1!/(,$G(*H/,4$I*(&+$*#+*#'#,!'$1$-1*4#$'#4)#,!$(3$!"#$;&'/,#''$
  • 26. MetaEdit+
  • 27. MetaEdit+
  • 28. MetaEdit+
  • 29. Models are not about realism
  • 30. Models are not about realism “Even in a domain of real-world things, our domain model is artificial creation, like movie making...”
  • 31. Core principles of Domain Driven Design
  • 32. Core principles of Domain Driven Design 1. The model and the heart of the design shape each other. It is the link/binding between model and implementation that makes the model relevant and ensures that the analysis that went into it applies to the final product, a running program.
  • 33. Core principles of Domain Driven Design 1. The model and the heart of the design shape each other. It is the link/binding between model and implementation that makes the model relevant and ensures that the analysis that went into it applies to the final product, a running program. 2. The model is the backbone of a ubiquitous language used by all team members. Because of model/implementation binding developers can talk in this language. They can talk to domain experts without translating.
  • 34. Core principles of Domain Driven Design 1. The model and the heart of the design shape each other. It is the link/binding between model and implementation that makes the model relevant and ensures that the analysis that went into it applies to the final product, a running program. 2. The model is the backbone of a ubiquitous language used by all team members. Because of model/implementation binding developers can talk in this language. They can talk to domain experts without translating. 3. The model is distilled knowledge. A model captures how we choose to think about the domain as we select terms, break down concepts and relate them
  • 35. So how do we go about Developing the Model?
  • 36. Write it by hand, draw it on a whiteboard, use DSLs, UML or ...?
  • 37. Use what works best for the project - but focus on enabling automation
  • 38. Use what works best for the project - but focus on enabling automation To make changes as cheap as possible
  • 39. Which would you prefer?
  • 40. This? This?
  • 41. Or this?
  • 42. @javax.persistence.Basic @javax.persistence.Column(name = "comment", nullable = false) private String comment; package dk.tigerteam.mdsd.demo.model.internal; package dk.tigerteam.mdsd.demo.model.internal; @javax.persistence.Basic @javax.persistence.Entity @javax.persistence.Temporal(javax.persistence.TemporalType.TIMESTAMP) @javax.persistence.Table(name = "Customer") @javax.persistence.Entity @javax.persistence.Column(name = "time", nullable = false) public class Customer extends dk.tigerteam.mdsd.demo.model.AbstractEntity { private java.util.Date time; private static final long serialVersionUID = 2098912667L; @javax.persistence.Table(name = "Address") @javax.persistence.Basic @javax.persistence.Basic public class Address extends dk.tigerteam.mdsd.demo.model.AbstractEntity { @javax.persistence.Column(name = "timeslot", nullable = false) @javax.persistence.Column(name = "name", nullable = false) private static final long serialVersionUID = 1697028161L; private int timeslot; private String name; @javax.persistence.ManyToOne(cascade = { @javax.persistence.OneToOne(cascade = { javax.persistence.CascadeType.MERGE, javax.persistence.CascadeType.PERSIST, javax.persistence.CascadeType.REFRESH} javax.persistence.CascadeType.MERGE, javax.persistence.CascadeType.PERSIST, javax.persistence.CascadeType.REFRESH} @javax.persistence.Basic , fetch = javax.persistence.FetchType.LAZY) , fetch = javax.persistence.FetchType.LAZY) @javax.persistence.Column(name = "street", nullable = false) @javax.persistence.JoinColumn(nullable = false, name = "customerId") @javax.persistence.JoinColumn(name = "addressId") private dk.tigerteam.mdsd.demo.model.internal.Customer customer; @org.hibernate.validator.NotNull private String street; private dk.tigerteam.mdsd.demo.model.internal.Address address; public String getComment() { return comment; @javax.persistence.OneToMany(cascade = { @javax.persistence.Basic } javax.persistence.CascadeType.MERGE, javax.persistence.CascadeType.PERSIST, javax.persistence.CascadeType.REFRESH} , targetEntity = dk.tigerteam.mdsd.demo.model.internal.Booking.class, mappedBy = "customer", fetch = javax.persistence.FetchType.LAZY)public void setComment(String parameter) { @javax.persistence.Column(name = "zipCode", nullable = false) private java.util.Set<dk.tigerteam.mdsd.demo.model.internal.Booking> bookingCollection = new java.util.HashSet<dk.tigerteam.mdsd.demo.model.internal.Booking>(); this.comment = parameter; private String zipCode; } public String getName() { public java.util.Date getTime() { return name; return time; @javax.persistence.Basic } } @javax.persistence.Column(name = "city", nullable = false) public void setName(String parameter) { private String city; public void setTime(java.util.Date parameter) { this.name = parameter; this.time = parameter; } } public dk.tigerteam.mdsd.demo.model.internal.Address getAddress() { public String getStreet() { public int getTimeslot() { if (address instanceof org.hibernate.proxy.HibernateProxy) { return street; return timeslot; address = (dk.tigerteam.mdsd.demo.model.internal.Address) ((org.hibernate.impl.SessionImpl) ((org.hibernate.proxy.HibernateProxy) address) } .getHibernateLazyInitializer() } .getSession()).getPersistenceContext() public void setTimeslot(int parameter) { .unproxyAndReassociate(address); this.timeslot = parameter; } public void setStreet(String parameter) { } return address; public dk.tigerteam.mdsd.demo.model.internal.Customer getCustomer() { this.street = parameter; } if (customer instanceof org.hibernate.proxy.HibernateProxy) { } customer = (dk.tigerteam.mdsd.demo.model.internal.Customer) ((org.hibernate.impl.SessionImpl) ((org.hibernate.proxy.HibernateProxy) customer) public void setAddress( .getHibernateLazyInitializer() dk.tigerteam.mdsd.demo.model.internal.Address parameter) { .getSession()).getPersistenceContext() this.address = parameter; .unproxyAndReassociate(customer); public String getZipCode() { } } return zipCode; public java.util.Set<dk.tigerteam.mdsd.demo.model.internal.Booking> getBookingCollection() { } return customer; return new dk.tigerteam.foundation.bean.bidirectional.OneToManySetWrapper<dk.tigerteam.mdsd.demo.model.internal.Customer, } dk.tigerteam.mdsd.demo.model.internal.Booking>((dk.tigerteam.mdsd.demo.model.internal.Customer) this, bookingCollection) { @Override public void setCustomer( public void setZipCode(String parameter) { dk.tigerteam.mdsd.demo.model.internal.Customer parameter) { protected dk.tigerteam.mdsd.demo.model.internal.Customer getOneSideObjectInManySideObject( this.zipCode = parameter; new dk.tigerteam.foundation.bean.bidirectional.ManyToOneWrapper<dk.tigerteam.mdsd.demo.model.internal.Customer, dk.tigerteam.mdsd.demo.model.internal.Booking manySideObject) { dk.tigerteam.mdsd.demo.model.internal.Booking>((dk.tigerteam.mdsd.demo.model.internal.Booking) this) { return manySideObject.getCustomer(); @Override } } protected void addManySideObjectToOneSideCollection( dk.tigerteam.mdsd.demo.model.internal.Customer oneSide, @Override public String getCity() { dk.tigerteam.mdsd.demo.model.internal.Booking manySide) { protected void setOneSideObjectInManySideObject( ((dk.tigerteam.foundation.bean.WrappedSet<dk.tigerteam.mdsd.demo.model.internal.Booking>) oneSide dk.tigerteam.mdsd.demo.model.internal.Booking manySideObject, .getBookingCollection()).getWrappedCollection() return city; dk.tigerteam.mdsd.demo.model.internal.Customer oneSideObject) { manySideObject.setCustomer(oneSideObject); .add(manySide); } } } }; @Override } protected void removeManySideObjectFromOneSideCollection( public void setCity(String parameter) { public dk.tigerteam.mdsd.demo.model.internal.Customer withName(String name) { dk.tigerteam.mdsd.demo.model.internal.Customer oneSide, this.city = parameter; dk.tigerteam.mdsd.demo.model.internal.Booking manySide) { setName(name); } ((dk.tigerteam.foundation.bean.WrappedSet<dk.tigerteam.mdsd.demo.model.internal.Booking>) oneSide .getBookingCollection()).getWrappedCollection() return (dk.tigerteam.mdsd.demo.model.internal.Customer) this; .remove(manySide); } } public dk.tigerteam.mdsd.demo.model.internal.Address withStreet( public dk.tigerteam.mdsd.demo.model.internal.Customer withAddress( String street) { @Override dk.tigerteam.mdsd.demo.model.internal.Address address) { protected dk.tigerteam.mdsd.demo.model.internal.Customer getOneSideObjectInManySideObject( setAddress(address); dk.tigerteam.mdsd.demo.model.internal.Booking manySide) { setStreet(street); return ((dk.tigerteam.mdsd.demo.model.internal.Booking) manySide).customer; return (dk.tigerteam.mdsd.demo.model.internal.Customer) this; } } return (dk.tigerteam.mdsd.demo.model.internal.Address) this; @Override public dk.tigerteam.mdsd.demo.model.internal.Customer addToBookingCollection( protected void setOneSideObjectInManySideObject( } dk.tigerteam.mdsd.demo.model.internal.Booking... values) { dk.tigerteam.mdsd.demo.model.internal.Booking manySide, getBookingCollection().addAll(java.util.Arrays.asList(values)); dk.tigerteam.mdsd.demo.model.internal.Customer oneSide) { ((dk.tigerteam.mdsd.demo.model.internal.Booking) manySide).customer = oneSide; public dk.tigerteam.mdsd.demo.model.internal.Address withZipCode( return (dk.tigerteam.mdsd.demo.model.internal.Customer) this; } } }.updateOneSideObject(parameter); String zipCode) { public dk.tigerteam.foundation.bean.mdsd.runtime.RuntimeMetaClazz getMetaType() { } setZipCode(zipCode); return metaType; public dk.tigerteam.mdsd.demo.model.internal.Booking withComment( } String comment) { } setComment(comment); return (dk.tigerteam.mdsd.demo.model.internal.Address) this; } return (dk.tigerteam.mdsd.demo.model.internal.Booking) this; } public dk.tigerteam.mdsd.demo.model.internal.Booking withTime( public dk.tigerteam.mdsd.demo.model.internal.Address withCity(String city) { setCity(city); Or this? java.util.Date time) { setTime(time); return (dk.tigerteam.mdsd.demo.model.internal.Booking) this; } return (dk.tigerteam.mdsd.demo.model.internal.Address) this; } public dk.tigerteam.mdsd.demo.model.internal.Booking withTimeslot( int timeslot) { setTimeslot(timeslot); public dk.tigerteam.foundation.bean.mdsd.runtime.RuntimeMetaClazz getMetaType() { return (dk.tigerteam.mdsd.demo.model.internal.Booking) this; return metaType; } } public dk.tigerteam.mdsd.demo.model.internal.Booking withCustomer( } dk.tigerteam.mdsd.demo.model.internal.Customer customer) { setCustomer(customer); return (dk.tigerteam.mdsd.demo.model.internal.Booking) this; }
  • 43. Without models things often get too technical and the domain experts are left out of the discussion
  • 44. Wont modeling just get in the way and obstruct my creativity?
  • 45. Wont modeling just get in the way and obstruct my creativity? The only way to manage complexity is to bring order to chaos!
  • 46. and speaking of creativity...
  • 47. and speaking of creativity... Why do we all use IDE’s with code generation features?
  • 48. and speaking of creativity... Why do we all use IDE’s with code generation features? To get out of writing tedious repetitive code. public interface IX { Y getY(); setY(Y y); } public class X implements IX { private Y y; public Y getY() { return y; } public void setY(Y y) { this.y = y; } ... }
  • 49. and speaking of creativity... Why do we all use IDE’s with code generation features? To get out of writing tedious repetitive code. public interface IX { Y getY(); setY(Y y); } public class X implements IX { private Y y; public Y getY() { return y; } public void setY(Y y) { this.y = y; } ... } The IDE’s problem is just the code generation is one-off - you can’t change your mind easily
  • 50. But generated code sucks!
  • 51. But generated code sucks! • Poor quality
  • 52. But generated code sucks! • Poor quality • Bad performance
  • 53. But generated code sucks! • Poor quality • Bad performance • Difficult to understand and maintain
  • 54. But generated code sucks! • Poor quality • Bad performance • Difficult to understand and maintain In the brave new world: You control the code and the quality of what gets generated - not the other way around!
  • 55. Does modeling & code generation result in less superfluous code?
  • 56. Does modeling & code generation result in less superfluous code? Yes + increased abstraction level !
  • 57. Does modeling & code generation result in less superfluous code? Yes + increased abstraction level ! The developers only relies on the API - not the implementation
  • 58. Example: Bi-temporal history
  • 59. Example: Bi-temporal history At any time
  • 60. Example: Bi-temporal history At any time Over a life time
  • 61. Example: Bi-temporal history At any time Over a life time What we model «History»
  • 62. Example: Bi-temporal history At any time Over a life time Gives us the freedom to choose the right implementation without revealing it in the model What we model «History» - a.k.a. encapsulation
  • 63. Example: Bi-temporal history At any time Over a life time Gives us the freedom to choose the right implementation without 1 * revealing it in the model What we model «History» - a.k.a. encapsulation
  • 64. Example: Bi-temporal history At any time Over a life time Gives us the freedom to choose the right implementation without 1 * revealing it in the model What we model «History» - a.k.a. encapsulation 1 1
  • 65. Example:Versioning (Temporal Object Pattern)
  • 66. Example:Versioning (Temporal Object Pattern)
  • 67. Example:Versioning (Temporal Object Pattern)
  • 68. Let’s kill the tedious schematic hand written code so we can focus on the interesting code... Interesting code.. Schematic code (Hand written) Frameworks (e.g. Spring, Hand written Hibernate, ...) Libraries (e.g. Java/.NET)
  • 69. Let’s kill the tedious schematic hand written code so we can focus on the interesting code... Interesting code.. Schematic code (Hand written) Frameworks (e.g. Spring, Hand written Hibernate, ...) Libraries (e.g. Java/.NET)
  • 70. Let’s kill the tedious schematic hand written code so we can focus on the interesting code... Interesting code.. Schematic code (Hand written) Frameworks (e.g. Spring, Hand written Hibernate, ...) Libraries (e.g. Java/.NET)
  • 71. Let’s kill the tedious schematic hand written code so we can focus on the interesting code... Model Interesting code.. Schematic code (Hand written) Frameworks (e.g. Spring, Hand written Hibernate, ...) Libraries (e.g. Java/.NET)
  • 72. Let’s kill the tedious schematic hand written code so we can focus on the interesting code... Model Generator Interesting code.. Schematic code (Hand written) Frameworks (e.g. Spring, Hand written Hibernate, ...) Libraries (e.g. Java/.NET)
  • 73. So let’s get cranking with visual models
  • 74. From UML diagram to code
  • 75. From UML diagram to code UML modeling MagicDraw
  • 76. From UML diagram to code UML modeling XMI Export MagicDraw
  • 77. From UML diagram to code + TigerMDSD UML modeling XMI Export configuration MagicDraw
  • 78. From UML diagram to code + TigerMDSD Java/C# code UML modeling XMI Export configuration JPA configuration Database configuration Integration tests Test data generator WSDL XML Schema MagicDraw ...
  • 79. From UML diagram to code + TigerMDSD Java/C# code UML modeling XMI Export configuration JPA configuration Database configuration Integration tests Test data generator WSDL MagicDraw MODEL is KING XML Schema ...
  • 80. Example: Persist the domain model in a Relational database using JPA/Hibernate
  • 81. TigerMDSD YAML configuration
  • 82. # Setup xmiModelPath: model.xml TigerMDSD umlTool: EA basePackageName: dk.tigerteam.vetapp YAML configuration # Paths generateBaseClassesToPath: src/main/generated generateTestClassesToPath: src/test/generated generateResourcesToPath: src/main/generated-resources mapUmlPropertyTypes: - name: DateTime javaType: org.joda.time.DateTime hibernateCustomTypeMappingType: org.joda.time.contrib.hibernate.PersistentDateTime # JPA Setup jpaSetup: makeBaseClassesIntoMappedSuperClassesIfPossible: true generatePresentFieldInEmbeddables: true defaultToLazyFetchingForAllAssociations: true rootMappedSuperClass: dk.tigerteam.vetapp.model.AbstractEntity resolveTableNames: - defaultTableName: User resolvedTableName: _User # Extensions eventListeners: - dk.tigerteam.mdsd.java.generator.extension.BidirectionalGeneratorEventListener - dk.tigerteam.mdsd.jpa.hibernate.HibernateAssociationUnproxyListener - dk.tigerteam.mdsd.java.generator.extension.SerialVersionUIDGeneratorListener - dk.tigerteam.mdsd.java.generator.extension.PropertySugarMethodsEventListener - dk.tigerteam.mdsd.java.generator.extension.MetaTypeJavaDocListener - dk.tigerteam.mdsd.jpa.hibernate.HibernateDeleteOrphanListener - dk.tigerteam.mdsd.jpa.hibernate.HibernateValidatorNotNullListener - dk.tigerteam.mdsd.jpa.hibernate.HibernateFetchOptimizationListener
  • 83. TigerMDSD - Java configuration
  • 84. TigerMDSD - Java configuration JavaGenerator javaGenerator = new JavaGenerator(); javaGenerator.addEventListeners(new BuiltInTypesListener() { @Override protected void resolveBuiltInTypes(Type type) { if (type.getName().equalsIgnoreCase("DateTime")) { type.setWrappedJavaClass(DateTime.class); } else { super.resolveBuiltInTypes(type); } } }); javaGenerator.addEventListeners(new JPAGeneratorEventListener() .setShouldMakeBaseClazzesMappedSuperClassesIfPossible(true) .setShouldGeneratePresentFieldInEmbeddables(false) .setDefaultToLazyFetchingForAllAssociations(true) ); javaGenerator.addEventListeners(new JPANamedTablesAndColumnsListener()); javaGenerator.addEventListeners(new BidirectionalGeneratorEventListener()); javaGenerator.addEventListeners(new HibernateAssociationUnproxyListener()); javaGenerator.addEventListeners(new SerialVersionUIDGeneratorListener()); javaGenerator.addEventListeners(new PropertySugarMethodsEventListener()); javaGenerator.addEventListeners(new MetaTypeJavaDocListener()); javaGenerator.addEventListeners(new HibernateIndexingListener()); javaGenerator.addEventListeners(new HibernateDeleteOrphanListener()); javaGenerator.addEventListeners(new HibernateValidatorNotNullListener()); javaGenerator.setCreateExtensionClazzes(true);
  • 85. Result: package dk.tigerteam.vetapp.model; @javax.persistence.Entity @javax.persistence.Table(name = "Customer") public class Customer extends dk.tigerteam.vetapp.model.AbstractEntity { private static final long serialVersionUID = 100497609L; @javax.persistence.Lob @javax.persistence.Basic @javax.persistence.Column(name = "comment") private String comment; @javax.persistence.OneToOne(cascade = { javax.persistence.CascadeType.MERGE, javax.persistence.CascadeType.PERSIST, javax.persistence.CascadeType.REFRESH }, fetch = javax.persistence.FetchType.LAZY) @javax.persistence.JoinColumn(name = "addressId") private dk.tigerteam.vetapp.model.Address address; @javax.persistence.Embedded @javax.persistence.AttributeOverrides( { @javax.persistence.AttributeOverride( name = "firstName", column = @javax.persistence.Column(nullable = false, name = "name_firstName")), @javax.persistence.AttributeOverride( name = "lastName", column = @javax.persistence.Column(nullable = false, name = "name_lastName")), @javax.persistence.AttributeOverride( name = "present", column = @javax.persistence.Column(nullable = false, name = "name_present")) }) private dk.tigerteam.vetapp.model.Name name; @javax.persistence.OneToMany(cascade = { javax.persistence.CascadeType.MERGE, javax.persistence.CascadeType.PERSIST, javax.persistence.CascadeType.REFRESH }, fetch = javax.persistence.FetchType.LAZY) @javax.persistence.JoinTable(name = "Customer_invoice", joinColumns = @javax.persistence.JoinColumn(name = "CustomerId"), inverseJoinColumns = @javax.persistence.JoinColumn(name = "invoiceId")) private java.util.Set<dk.tigerteam.vetapp.model.Invoice> invoiceCollection = new java.util.HashSet<dk.tigerteam.vetapp.model.Invoice>();
  • 86. Automate the tedious details - under full control! Examples of configurable built in features:
  • 87. Automate the tedious details - under full control! Examples of configurable built in features: Built-in Types JPA Field based persistence Bidirectional associations JPA Named Tables and Columns Property Sugar methods JPA OptimisticLocking exceptions Get Or New Property methods Hibernate Foreignkey Constraints Constructor (immutable properties) Hibernate Foreignkey Index Class Hierarchy Java doc generator Hibernate Fetch Optimization Serial Version UID generator Hibernate Association Unproxying MetaType Java doc generator Hibernate Table Comments Serializable Pojo’s Hibernate HH-3544 bug fix ToString/Equals/HashCode
  • 88. TigerMDSD - Meta model level
  • 89. TigerMDSD - Meta model level XmiReader reader = new EAXmiReader(); XmiReader reader = new MagicDrawXmiReader(); MetaModel metaModel = reader.read("model.xml");
  • 90. TigerMDSD - Meta model level XmiReader reader = new EAXmiReader(); XmiReader reader = new MagicDrawXmiReader(); MetaModel metaModel = reader.read("model.xml");
  • 91. Where does the meta model fit? UML Don’t be confused about the META - It’s just a description of our model TigerMDSD Meta Model Like a Class is a description of the Objects that can be instances of the Class XML Schema Java
  • 92. Transformation From Meta model to Result UML Model object graf
  • 93. Transformation From Meta model to Result UML Model Transformation object graf
  • 94. Transformation From Meta model to Result UML Model Transformation Destination Model object graf
  • 95. Transformation From Meta model to Result UML Model Transformation Destination Model object graf Java/C# code JPA configuration Database configuration Integration test Test data generator WSDL XML Schema ...
  • 96. TigerMDSD - Java Model
  • 97. TigerMDSD - Java Model
  • 98. TigerMDSD - Event based extension model
  • 99. TigerMDSD - Event based extension model
  • 100. TigerMDSD - Event Listeners
  • 101. TigerMDSD - Event Listeners public interface GeneratorEventListener { boolean handle(GeneratorEvent event); ... }
  • 102. TigerMDSD - Example extension
  • 103. TigerMDSD - Example extension @OneToMany @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) private Set<Tire> tires;
  • 104. TigerMDSD - Example extension @OneToMany @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) private Set<Tire> tires; public class HibernateDeleteOrphanListener extends BaseJpaGeneratorEventListener { @Override protected boolean handleOneToManyOwnerOfAssociation(OneToManyAssociationEvent event) { if (isDeleteOrphanCandidate(event)) { event.getProperty().getField().addAnnotations( new Annotation(Cascade.class).addAnnotationAttribute("value", CascadeType.DELETE_ORPHAN) ); event.getProperty().removeSetterMethod(); } return true; } protected boolean isDeleteOrphanCandidate(OneToManyAssociationEvent event) { ... } }
  • 105. TigerMDSD - Example extension
  • 106. TigerMDSD - Example extension protected boolean isDeleteOrphanCandidate(OneToManyAssociationEvent event) { if (event.getMetaProperty().isOwnerOfAssociation() && !event.getMetaProperty().getAssociation().isBidirectional() && !event.getMetaProperty().getAssociation().isSelfReferencing()) { // Check the clazz of the opposite property to see what kind of associations it has for (MetaProperty subMetaProperty : event.getMetaProperty().getType().getProperties()) { if (subMetaProperty.isPartInAnAssociation()) { if (subMetaProperty.isOwnerOfAssociation()) { if (subMetaProperty.getAssociationType() == AssociationType.ManyToMany || subMetaProperty.getAssociationType() == AssociationType.OneToMany) { return false; } } else if (subMetaProperty.getAssociation().isBidirectional()) { // The type of the our sub property is not an owning association and we have // a java association in both directions (bidirectional), which hibernate doesn't handle return false; } } } return true; } return false; }
  • 107. What else can I get from MDD? You can for instance get a complete combinatorial automated database integration test based on a generated runtime metamodel
  • 108. “I thought it was all about rich domain models! What about my own domain code?”
  • 109. “I thought it was all about rich domain models! What about my own domain code?” It is - but Usecase logic doesn’t belong in domain objects - so in reality very little code should enter the domain objects!
  • 110. “I thought it was all about rich domain models! What about my own domain code?” It is - but Usecase logic doesn’t belong in domain objects - so in reality very little code should enter the domain objects! “Domain object design should focus on WHAT THE SYSTEM IS - NOT on what the system DOES!” James Coplien - DCI Talk at Öredev 2009
  • 111. For the logic that belongs in the domain objects we have several choices... What we model:
  • 112. For the logic that belongs in the domain objects we have several choices... What we model:
  • 113. For the logic that belongs in the domain objects we have several choices... What we model: What we generate using Extension classes: (a.k.a. 3 level inheritance)
  • 114. For the logic that belongs in the domain objects we have several choices... What we model: What we generate al tion using Extension Op classes: (a.k.a. 3 level inheritance)
  • 115. For the logic that belongs in the domain objects we have several choices... What we model: What we generate nal Alternatives: ptio Generator Extensions using Extension O Partial Classes classes: Mixins / Traits (a.k.a. 3 level inheritance) Priviledged Aspects Protected Regions
  • 116. Thank you for your attention! For more information jeppe@tigerteam.dk Twitter: @jeppec