Below you will find pages that utilize the taxonomy term “Domain-Driven Design”
Don't test constructors
@ediar asked me on Twitter if I still think a constructor should not be tested. It depends on the type of object you’re working with, so I think it’ll be useful to elaborate here.
Would you test the constructor of a service that just gets some dependencies injected? No. You’ll test the behavior of the service by calling one of its public methods. The injected dependencies are collaborating services and the service as a whole won’t work if anything went wrong in the constructor.
Relying on the database to validate your data
One of my pet peeves is using the database schema to validate data.
Several ways in which this normally happens:
- Specifying a column as “required”, e.g.
email VARCHAR(255) NOT NULL
- Adding an index to force column values to be unique (e.g.
CREATE UNIQUE INDEX email_idx ON users(email)
) - Adding an index for foreign key integrity, including cascading deletes, etc.
Yes, I want data integrity too. No, I don’t want to rely on the database for that.
DDD and your database
The introduction of Domain-Driven Design (DDD) to a larger audience has led to a few really damaging ideas among developers, like this one (maybe it’s more a sentiment than an idea):
Data is bad, behavior is good. The domain model is great, the database awful.
(We’re not even discussing CRUD in this article, which apparently is the worst of the worst.)
By now many of us feel ashamed of using an ORM alongside a “DDD domain model”, putting some mapping configuration in it, doing things inside your entities (or do you call them aggregates?) just to make them easily serializable to the database.
DDD Europe notes - Day 2
Cyrille Martraire: Domain modeling towards First Principles
This was a talk from the first day, but it required some more processing before writing about it. Cyrille is one of my favorite speakers. He’s fast, funny and brings a lot of interesting topics to the table. So many that it’s sometimes hard to keep following his train of thought, and writing down some notes at the same time.
A central concept from his talk was what he called the waterline between IT and the business. In a traditional scenario, developers get provided with “work” on a case-by-case basis. They don’t learn about the general idea or plan, or even the vision, goal or need that’s behind the “work item”. They just have to “implement” it. It leads to badly designed code. But it also leads to the wrong solutions being delivered. If only developers could have talked with the people who actually have the problem for which they build the solution. Maybe there’s another problem behind it, or maybe the business has provided the developer with a solution, instead of a problem. To higher the waterline means to get more involved with the customers and users, to understand their problems, and work together on a solution. Make sure you get involved.
DDD Europe notes - Day 1
Eric Evans: Keynote (“Language in Context”)
Starting out with the basics (words have meaning within a context; when we make the boundary of this context explicit we end up with a bounded context), Eric discussed two main topics: the Big Ball of Mud, and bounded contexts in the context (no pun intended) of microservices.
Legacy applications are always framed in a negative way, as if it’s something to get away from. Personally, I’ve come to enjoy them a lot. However, there will always be the urge to work around legacy code. The Bubble Context (PDF) can be a great way of creating a new model that works well next to the already existing models. To keep a safe buffer between the new and the old model, you could build an Anti-Corruption Layer (ACL). A fun thing Eric mentioned is that the buffer works in two directions. The ACL also allows the old model to keep functioning without being disturbed by all the new things that are going on in the Bubble Context.
Reusing domain code
Last week I wrote about when to add an interface to a class. The article finishes with the claim that classes from the application’s domain don’t usually need an interface. The reason is that domain code isn’t going to be swapped out with something else. This code is the result of careful modelling work that’s done based on the business domain that you work with. And even if you’d work on, say, two financial software projects in a row, you’ll find that the models you produce for each of them will be different in many subtle (if not radical) ways. Paradoxically you’ll find that in practice a domain model can sometimes be reused after all. There are some great examples out there. In this article I explain different scenarios of where and how reuse could work.
Negative architecture, and assumptions about code
In “Negative Architecture”, Michael Feathers speaks about certain aspects of software architecture leading to some kind of negative architecture. Feathers mentions the IO Monad from Haskell (functional programming) as an example, but there are parallel examples in object-oriented programming. For example, by using layers and the dependency inversion principle you can “guarantee” that a certain class, in a certain layer (e.g. domain, application) won’t do any IO - no talking to a database, no HTTP requests to some remote service, etc.
Objects should be constructed in one go
Consider the following rule:
When you create an object, it should be complete, consistent and valid in one go.
It is derived from the more general principle that it should not be possible for an object to exist in an inconsistent state. I think this is a very important rule, one that will gradually lead everyone from the swamps of those dreaded “anemic” domain models. However, the question still remains: what does all of this mean?
Testing actual behavior
The downsides of starting with the domain model
All the architectural focus on having a clean and infrastructure-free domain model is great. It’s awesome to be able to develop your domain model in complete isolation; just a bunch of unit tests helping you design the most beautiful objects. And all the “impure” stuff comes later (like the database, UI interactions, etc.).
However, there’s a big downside to starting with the domain model: it leads to inside-out development. The first negative effect of this is that when you start with designing your aggregates (entities and value objects), you will definitely need to revise them when you end up actually using them from the UI. Some aspects may turn out to be not so well-designed at all, and will make no sense from the user’s perspective. Some functionality may have been designed well, but only theoretically, since it will never actually be used by any real client, except for the unit test you wrote for it.
Doctrine ORM and DDD aggregates
I’d like to start this article with a quote from Ross Tuck’s article “Persisting Value Objects in Doctrine”. He describes different ways of persisting value objects when using Doctrine ORM. At the end of the page he gives us the following option - the “nuclear” one:
[…] Doctrine is great for the vast majority of applications but if you’ve got edge cases that are making your entity code messy, don’t be afraid to toss Doctrine out. Setup an interface for your repositories and create an alternate implementation where you do the querying or mapping by hand. It might be a PITA but it might also be less frustration in the long run.
When and where to determine the ID of an entity
This is a question that always pops up during my workshops: when and where to determine the ID of an entity? There are different answers, no best answer. Well, there are two best answers, but they apply to two different situations.
Auto-incrementing IDs, by the database
Traditionally, all you need for an entity to have an ID is to designate one integer column in the database as the primary key, and mark it as “auto-incrementing”. So, once a new entity gets persisted as a record in the database (using your favorite ORM), it will get an ID. That is, the entity has no identity until it has been persisted. Even though this happens everywhere, and almost always; it’s a bit weird, because:
Exceptions and talking back to the user
Exceptions - for exceptional situations?
From the Domain-Driven Design movement we’ve learned to go somewhat back to the roots of object-oriented design. Designing domain objects is all about offering meaningful behavior and insights through a carefully designed API. We know now that domain objects with setters for every attribute will allow for the objects to be in an inconsistent state. By removing setters and replacing them with methods which only modify the object’s state in valid ways, we can protect an object from violating domain invariants.
Mocking the network
In this series, we’ve discussed several topics already. We talked about persistence and time, the filesystem and randomness. The conclusion for all these areas: whenever you want to “mock” these things, you may look for a solution at the level of programming tools used (use database or filesystem abstraction library, replace built-in PHP functions, etc.). But the better solution is always: add your own abstraction. Start by introducing your own interface (including custom return types), which describes exactly what you need. Then mock this interface freely in your application. But also provide an implementation for it, which uses “the real thing”, and write an integration test for just this class.
Modelling quantities - an exercise in designing value objects
I recently came across two interesting methods that were part of a bigger class that I had to redesign:
class OrderLine
{
/**
* @var float
*/
private $quantityOrdered;
// ...
/**
* @param float $quantity
*/
public function processDelivery($quantity)
{
$this->quantityDelivered += $quantity;
$this->quantityOpen = $this->quantityOrdered - $quantity;
if ($this->quantityOpen < 0) {
$this->quantityOpen = 0;
}
}
/**
* @param float $quantity
*/
public function undoDelivery($quantity)
{
$this->quantityDelivered -= $quantity;
if ($this->quantityDelivered < 0) {
$this->quantityDelivered = 0;
}
$this->quantityOpen += $quantity;
if ($this->quantityOpen > $this->quantityOrdered) {
$this->quantityOpen = $this->quantityOrdered;
}
}
}
Of course, I’ve already cleaned up the code here to allow you to better understand it.
DDD Europe Conference Report - part III
In previous articles I’ve already spent a few words on some of the talks I watched at DDD Europe that made quite an impact on my thoughts about software development and design. The design part is often the most philosophical one. Design talks are often less practical. Speakers use metaphors to bring their message across and take note of other disciplines than software engineering to discover useful design principles and heuristics.
Rebecca Wirfs-Brock: Design Matters
The opening keynote of the second day was particularly philosophical. To be honest, I didn’t know Rebecca. She is co-author of several important books on object design: “Designing Object-Oriented Software” and “Object Design: Roles, Responsibilities, and Collaborations”. It should be interesting to take a look at these some time.
DDD Europe Conference Report - part II
In a previous post I discussed some of the talks I attended at the DDD Europe conference in Amsterdam. This conference has offered a lot more amazing content and I’d like to continue to tell you about it.
Lately I’ve been thinking about why Domain-Driven Design (DDD) has such a great attractive force on me. In particular when at the same time I’m strongly attracted by technology like Docker and its surrounding ecosystem of tools that are finally helping us to fulfill the ideal of continuous delivery, with relative ease. Configuring servers, deploying them, connecting them, etc. is what we previously would have called “operations” work. Now that developers themselves get to do more and more operations work, a movement was called to life: devops, where two previously separated responsibilities are merged into one: writing software and running it in production is part of the same, single task: shipping working software.
DDD Europe Conference Report - part I
I’m currently attending the DDD Europe conference in Amsterdam and thought it might be interesting for people at home to read up on some of the topics that this interesting (and well-organized) conference covers.
Mel Conway: Consider the development feedback loop
On Twitter there were outbursts of “The legend on stage” and “This is the Conway of ‘Conway’s Law’” when Mel Conway entered the stage. I knew about the law, which amounts to the observation that software systems tend to be shaped by the way the teams working on it communicate.
Meeting the Broadway team - talking DDD, CQRS and event sourcing
Visiting Qandidate in Rotterdam
Last Thursday I had the honor of meeting (part of the) Broadway team: three very smart developers working for Qandidate in central Rotterdam: Gediminas Šedbaras, Willem-Jan Zijderveld and Fritsjan. A short walk from the train station brought me to their office, where we talked about CQRS, event sourcing and some of the practical aspects of using the Broadway framework.
As you may have read I’ve been experimenting with Broadway extensively during these last weeks. Knowing a lot about the theory behind it, it was really nice to see how everything worked so smoothly. I had some questions however, which have now been answered (thank you guys for taking the time to do this!).
Experimenting with Broadway
Event sourcing with Broadway
At the Dutch PHP Conference I attended a workshop by Beau Simensen and Willem-Jan Zijderveld. They showed us some examples of how to work with Broadway, a framework for event sourcing, with full Symfony integration, created by the smart people at Qandidate.
During my two weeks of funemployment, before starting my new job at Ibuildings, I decided to recreate one of my previous projects using Broadway. As it turns out, it’s a great framework that’s quite easy to use and is very powerful at the same time. Even though it’s not a stable package (as in, it’s still in the 0.x
version range), I think it’s safe to depend on it.
The Hexagonal Architecture training tour
An ever recurring pattern in my life is this one:
- I stumble upon some interesting piece of code, an intriguing book chapter, a fascinating concept, etc.
- Slowly, over the next couple of weeks, my brain realises that, yes, this is some very interesting stuff.
- Then I want to become all productive about it - writing things on my blog, speaking about it in public, maybe even writing a book about it.
This time it was domain-driven design (DDD), command-query responsibility segregation (CQRS) and in particular its architectural and technical aspects. While playing with existing libraries I soon recognized the huge benefits of applying hexagonal architecture and some of the tactical DDD patterns to a (Symfony) codebase.