We are big fans of DDD and we were lucky enough to assist an event held by Magento, with Vaughn Vernon as a key speaker, presenting his latest book: Domain-Driven Design Distilled. I bet you can imagine how exciting it is to share the room with someone that is recognized in the programming community, especially when you get a few hours off of work because of that.
You are probably already familiar with Vernon’s work, because of the ‘red book’: Implementing Domain-Driven Design, one of the most influential pieces of work of the last decade. If not, I strongly recommend it to any person that is eager to learn about Domain-Driven Design.
The main topic of the meeting was the implementation of microservices with Scala and Akka. This is one complex matter, which I won’t try to tackle in a single article. Instead, I'd like to share some insights of Vernon's on the industry of software architecture that I found interesting.
Domain-Driven Design Distilled
Industry of Extremes
The first statement that drew my attention was that we live in an Industry of Extremes. To illustrate this situation, Vernon used the Single Responsibility Principle as an example. SRP says that a class should have only one responsibility inside the functionality of our software, which is encapsulated in that class. Or, as Robert C. Martin describes it:
“A class should have only one reason to change.”
Yet, it’s not easy to draw red lines between what we call responsibilities to separate them, which gives room for discussion, and therefore, allows us to fall into extremes. Another similar situation happens with data consistency.
Transactionally or Eventually Consistent
To achieve transactional consistency in database transactions we have the ACID set of principles:
- If one part of the transaction fails, the database state remains unchanged (Atomicity).
- The database state can only change from one valid state to another valid state. All existing constraints and triggers should be respected (Consistency).
- The system is immune to concurrent use. Concurrent transactions never access incomplete data changes (Isolation).
- Data is always persisted once the transaction is finished (Durability).
Nevertheless, transactional consistency is not always needed. And it is not a programmer’s responsibility to decide if it is or not.
Monolith or Microservice
Falling in the extreme of pursuing the transactional consistency usually ends up in a monolithic system which is too often pushed to the verge of becoming a ‘Big Ball of Mud,’ where Domain models exist in one big messy place.
Nevertheless, MSA allows us to avoid this situation. But to create actual microservices, there are several rules of thumb that need to be applied. Otherwise, the result will be what Vernon called a Distributed Monolith.
One microservice should cover one Bounded Context.
A microservice should own a separate database, to store all events in an Event Journal.
A microservice coupling with the system must always remain low.
At last, if any of the points described above ended up interesting to you, don’t hesitate to read more about this topic from Vernon himself; you can easily find some of his code samples. I would say trial and error is the best way to learn, so don’t be afraid of “standing on the shoulders of giants,” and give it a try.
I know I’ve mentioned it earlier, but I would like to say it one last time, I really do recommend you read Domain-Driven Design Distilled by Vaughn Vernon, you won’t regret it.