Common software architectures are full of well-established assumptions. But some of them are flawed, no longer valid or relevant. Changing the rules of the game using DDD, CQRS and Event Sourcing can lead to systems which are more scalable, maintainable and performing. And which are fun to code as well.
14. Non tutti i regali sono necessariamente graditi...
15. Vantaggi dell’Anaemic Domain Model 1) Il codice business è localizzato in un solo posto: Più facile da leggere per sviluppatori giovani non familiari con OOP. Spiacente ...non c’è il numero 2 :-(
16. Svantaggi dell’Anemic Domain Model Triste come un pasto in ospedale difficile da matenere difficile da testare alimenta la duplicazione
17.
18.
19.
20.
21.
22.
23.
24. Come dovremmo implementare un Domain Model? Fate in modo che il codice parli lo Ubiquitous Language Proteggete il vostro modello con dei Bounded Contexts Usate gli Aggregati come unità di consistenza nel vostro domain model Il comportamento dovrebbe risiedere nel Domain Model
27. TDD e DDD Riscritture frequenti Exploratory coding Domain Objects minimali Focus sugli Unit Tests Tiny Domain Objects Tiny Domain Objects Cicli corti e frequenti Codice autoesplicativo Feedback rapido Libertà di cambiare
28. Aggregate Un gruppo di oggetti naturalmente vicini Unità di consistenza nel domain model modificati nella stessa transazione cancellati insieme trasferiti insieme
33. Hmm... Una volta che l’accoppiamento tra gli aggregati è ridotto... potrei anche pensare di scegliere una strategia di persistenza differente per ogni aggregato...
34. dalla cara vecchia architettura... UI Remote facade Application Services DTO DTO ORM
37. Come implementereste queste? As a Marketing Office I want to assign discount points to customer on every purchase In order to enable more deals in the future As a Sales Office I want to ship order on purchase command In order to deliver purchased goods to the customer
38.
39.
40.
41. a qualcuno ricorda SOA ? ...proviamo a disegnare le cose diversamente e pensare alla “granularità dei servizi” ...proviamo a disegnare le cose diversamente e pensare alla “granularità dei servizi”
62. voilà UI Remote facade Application Services ORM? Remote facade Thin Read Layer DTO publish subscribe Specialized data model does it really need to be relational? Commands Eventually
63.
64. The paper-based system Molti tipi di azienda nascono prima dei computers Le transazioni non sono un problema bisiness I Dati possono essere disallineati...capita CHIEDIAMO al Business
73. Gli aggregati disaccoppiati permettono semplificazioni nello sviluppo La terra delle opportunità Polyglot persistence migliore scalabilità Polyglot persistence Polyglot persistence Polyglot persistence SOA indolore Applicazioni riavvolgibili
74. Una cosa alla volta Non è detto che abbiate bisogno di tutto Ogni step è un miglioramento Anche in piccole architetture ...Mettiamo in discussione un’assunzione alla volta ...Mettiamo in discussione un’assunzione alla volta ...Mettiamo in discussione un’assunzione alla volta ...Mettiamo in discussione un’assunzione alla volta ...Mettiamo in discussione un’assunzione alla volta
75.
76.
77.
78.
Editor's Notes
And that’s the company I started one year ago.
Disclaimer: this is second-hand talk. 99% of the ideas come from these three guys. In the last couple of years a little revolution has being going on in the DDD community: Udi Dahan (left) and Greg Young (right) have brought new ideas in the DDD landscape.
Ok, let's start from a familiar architecture, what's wrong with that?
Ok, if that’s the answer... If you really like that and think that’s the best possible world... then I don’t have so much to tell you.
On the other hand, if you really think about it, there are a few things in your familiar architecture that you’ve been probably too used to. Enough to forget that there might be a different way.
Let’s try again, with a clear mind.
Here are some of the things we might not like.
And here are some of the questions we might ask ourselves
Ok, let’s start from the anaemic domain model: in the picture red is where the logic is. As you might see, there’s not so mouch in the Order class...
How did we get there? Well sometimes it’s just a matter of features that came for free, like a tool that allows you to reverse engineering your database to create domain classes.
Ok, but anaemic domain model is probably the dominant pattern throughout the world, so it must have some advantages: let’s dig into them.
Let’s look at the drawbacks instead... in two words it provides all the architetural complexity of an OOP system with the advantages in maintenance of a procedural one. :-P
So what should we do instead?
I think this is a really sensible resolution :-)
... you got the point ;-) Let’s try to be a little more constructive
For example, Mr. Eric Evans has something really interesting to say about how should we implement a Domain Model:
What does it mean to “put behaviour in the domain model”? Here is our starting point: all the logic is in the service class.
In a “Rich” Domain Model (I really don’t know why is Rich vs Anaemic, maybe “bloody domain model” or “poor domain model” weren’t ok for the job) le logic is “where it belongs” according to Single Responsibility Principle (Martin) or Information Expert (Larman). It’s not spread equally... Customer doesn’t do much, while Money for example looks like a pure data type, but has a lot of math-related behaviour in it.
Interestingly, TDD and DDD form a perfect match: DDD needs TDD for many of the key practices, while TDD naturally enforces DDD-like coding styles. It’s just perfect.
The next key DDD building block is Aggregates. The Domain Model isn’t flat. Some links are stronger than others (and UML doesn’t really help much in rendering it). If we start considering consistency and behaviour as the primary drivers for modeling our domain we’ll end up with something quite different from a 1-1 projection of the data model.
For example, in this case we’ll notice some duplication, related to customer. But lifecycles of the customer and of the order are different. If a customer moves, we don’t want to have all of our past orders changed, at the same time if an order needs to be canceled, we don’t want the user to get down the sink as well. A little duplication is what allows aggregate lifecycles to be independent.
Some data-driven analyst are probably really good in spotting these problems just out of their experience.
But really, this part of modeling is our everyday work, and should be easy as walking back home in a sunny day.
Shouldn’t really have to rely on the experience of some rarely available guy that knows all the traps and hidden perils of data modeling.
But here’s something to think about: this modeling style enforces loose coupling between aggregates. As a side effect, queries tend to be a lot simpler and focused. In many situations, this opens the door for some alternative persistence strategy.
Ok, so let’s see how DDD can improve our application architecture.
Not so many things are happening at the service layer, just basic coordination. Bounded contexts are enforced, and aggregate boundaries within them. But other portions of the architecture don’t change that much. ... is there anything else that we can do?
Using DO in the UI seemed like a good idea (I confess I hated the abuse of DTOs so much that I tried it myself), but then you run into objects which are potentially inconsistent. A common solution is to have every DO in 2 possible states: valid and invalid, and valid state must be enforced before any business method is invoked on the object. So why not make it mandatory, with aspects or template method pattern. Why not make this solution available/mandatory to all the domain classes? ... well ...No.
Ok, question for the audience: two Stories, hitting different portions of the application, triggered by the same external event. How would you model them? I must admit that in a similar situation I spent some time wondering: “Is it better to have order.purchase(customer, ...) or customer.purchase(order, ...)?” or many other variation on the theme.
That’s the very specific Greg Young’s definition. I like it.
Domain Events as a communication means between aggregates really simplify things a lot, even at the conceptual level. - Do they really belong to the same transaction? - Would you want the order to roll-bak if you are unable to process the discount for the next order bu the same customer? ... but really, how the two things should be related, is a business choice! We just have more and more possibilites in our arsenal.
There’s been a never ending debate in the SOA community (and many dollars and euros wasted) about “service granularity”. A good read of the blue book could have helped a lot, the solution was already there...
Let’s start to bite something bigger
Which one is the right shoe for you? Well ...it depends :-) each one serves a particular use. We change shoes according to what we want to do.
So why should we have only one architecture?
CQS existed before DDD and was part of the DDD toolkit collection, basically at the class design level. It really enhances scalability and maintainability.
But CQRS promotes the same concept at the architectural level. Commands and quesries have different needs.
When we ask, there is generally no behavior involved. Just data.
So one first step might be to evolve the “classical” DDD architecture...
... into something more specialized: the domain model is used only in the command side, while the query side is definitely thinner.
Let’s dive into the query side. Udi Dahan pointed out that sometimes the biggest source of optimization is to have a look at what the users are really doing: capturing user intent might surprise you.
Also, the fact that we can sometimes provide real time data, doesn’t really mean that we must alway provide them. Most of the time a little of delay is absolutely acceptable. Sometimes requirements are not even coming from the business, it’s just IT people showing off...
Wow, that is a kind of shock for DDD zealots. Objects are there for the behavior. The domain model is an efficient way to represent behavior. If there’s no behavior then there’s no real need for objects as well. Did I mention that we could get rid of some of our assumptions? ;-)
How would you optimize a Query Only architecture? - we could just use some of the tools vendor provide us to manage straight data. - we could have a specialized model for the view, with different table structure, eventually updated by a background process. - ... and many other cool ideas!
Also, even stale data could be a great help in managing pleliminary validation of the commands. We can still perform validation on the presentation layer and make sure that most of the commands simply won’t fail .
Let’s see the consequences on the command side. More trust means less burden, and a little less synchronicity, meaning less load.
Commands are a lot closer to user intent. It’s not just editing data. Is ding it with a purpose.
... so why should show entities in the presentation layer?
The domain model turns out to become even simpler: it’s write only. Classes are always in a consistent state and a command issued to the class, triggers an action and/or a state transition. Just that.
Let’s get back to the gorilla... what do we need to persist? and How? What’s the most efficient strategy for persisting a domain model?
Let’s shake things a little bit more :-)
The next little revolution is to have 2 different persistence storage: one optimized fopr working with the domain model? the other one optimized for the Query Only model. The two are eventually consistent. Just think about how many locking issues are blown away by separating the two...
Objects are tiny now. No collections, no mapping. Intersting things might happen...
Surprisingly, but Udi Dahan and Greg Young in their speeches at last DDDx put the paper-based system at the center of their concern. If a complex system could work without computers ...there must be a reason for that. Some times computers just loeded the systems with more unnecessary complexity.
Let’s now face another assumption...
You might also want to have a look to Alistair Cockburn exagonal architecture, you might find quite a few similarities in the problem setting.
There might be inconsistencies in the data or between the data and the paper. In many system (especially those data-entry based) the paper used to be the Single Source of Truth, but larger integrated systems Events are probably a better candidate.
So Events are passing from the command side to the Query side in a publish-subscribe fashion, they need to ba made persistent as well
In such a model, what’s the best way to model an entity? Our aggregates are receiveng entities and updating state, can we achieve the same result with a more efficient strategy?
The Specification pattern turns out really useful for that, but also note that entities are a little less mutable than they used to be.
This might be a blast! Think about the amount of opportunities
Ok, this one is a picture I really like, and reuse over and over... DDD has a lot to do with learning. But Event sourcing is a learning tool as well! Only, stop assuming that Business People know everything about the business, there’s a lot more to learn for them also! Why not doing it together?
Surprisingly, googling “land of opportunity” leads to Arkansas. But I like this picture... :-)
One important lesson: you don’t need all of this at once. But every little step brings an improvement, and it’s worth taking.
despite how cool this stuff looks ...be pragmatic.