DEV Community

Cover image for To Domain Driven Design

To Domain Driven Design

Kevin Mas Ruiz on December 02, 2019

Your company is built on top of a monolith. This monolith is probably your best asset, as your business knowledge is spread inside, however it's al...
Collapse
 
vivien_adnot profile image
Vivien Adnot

Hello Kevin, thanks a lot this article is really great ! Keep the good work :)

I have 2 questions for you:

1) When you write "It might look like a microservices architecture, but it's not, because services are highly coupled between them so neither services nor teams are autonomous."

I understand the collision here and the difficulties of teams working on the same codebase, but I feel that if even if we split it in 2 microservices, the dependency will remain, as the checkout team needs info from stock to complete a checkout.

Hence, the checkout team will ask for more feature to checkout team, and the slowness and coupling will remain

I don't see how to decouple things here, maybe I failed to understand your solution ?

2) When you talk about the term "Products", If I understand well it designates:

  • Profile Sign up
  • 1 click purchase
  • Bestseller page
  • Search by genre and author
  • ...

It sounds a bit odd for me, because I naturally tend to think that the product is Shopping Plateform, and "1 click purchase" and so on are Features.

Is "Product" a term of DDD ?

Collapse
 
kmruiz profile image
Kevin Mas Ruiz

Hi Vivien, thanks for your feedback! Let me try to answer and clarify your questions :).

1) Systems need to interact with other systems to remain useful and when there is interaction, there is some coupling. You can earn some benefits, like availability and team performance, when this coupling is temporary.

For example, if you have a CheckoutService and every time you want to buy a book you need to query the StockService (through a HTTP endpoint or any other way) you have direct coupling every time you need the information.

If you invert the communication, and the StockService or any other peer offers you updates on the stock through a broadcast mechanism, you don't mind if the StockService is down or not, you only need the updates in a place where you can read it and doesn't depend on the availability of the service. You need someone to provide the information, but you only need to agree just on the format and the quantity of information you need.

With Apache Kafka, for example, if you configure your partitions in a specific way (partition key = domain id) and you implement a state-sourcing mechanism, you don't even need any service to replay states when you implement new functionality because you can replay the state by yourself.

2) There is a book named Lean Inception written by a Thoughtworks colleague (Paulo Caroli) that uses the name MVP for defining products that can be deliverable in a predictive way. Those MVPs are bound to a set of personas (you focus on solving the problems of a single type of user), a set of user journeys for that personas, and you define an autonomous way to measure the success of the MVP.

This mechanism (that's from my side, not part of the book) allows business to define a set of products that have a relationship between them and can be evolved independently of other products. You usually will build new products when you want to widen the impact of your platform or experiment on new business slices, and you will implement new features on a MVP when you want to optimize the revenue you have from an already known subset of personas.

Thinking in a business as a "platform" of products allows us to define boundaries that are relevant for the business, autonomous, and have impact on business metrics. It's just a way of defining boundaries that is a bit different, but it doesn't necessarily mean it's right :D. I've used it a couple of times in different teams and it worked quite well.

Please feel free to follow up here if the answers were not clear enough.

Thanks!

Collapse
 
yaser profile image
Yaser Al-Najjar

Beside the great points Kevin (@kmruiz ) already mentioned, I would like to add couple of points:

  • If the services are "chatty" when they talk to each others (via HTTP or whatsoever), you might wanna combine them into one service.

  • It's better to start by writing all the business capabilities (aka features) that a service should handle, and that's ideally before writing any line of code so that you could set the boundaries clearly.

  • Sometimes, it's very very OK to put everything into one service, and separate them later when the boundaries are clearer.

  • You won't get this right from the first iteration, DDD is like a programming-style that goes beyond the initial design, but also during the whole development.

Collapse
 
vivien_adnot profile image
Vivien Adnot

Thank you a lot for your great advices @kmruiz and @yaser they are inspiring !

Collapse
 
philou profile image
Philippe Bourgau

Hi Kevin. I like your metaphor with muscles and the body. I found that the link between team organization and microservice boundaries is too often ignored.

I found that using Event Storming is a great tool to explore the problem space. It's very useful to draw bounded context boundaries and can also be used to organize teams.

Thanks for this post!

Collapse
 
mjremijan profile image
Michael Remijan

Hi Kevin, in this blog, you stated a "product" (or feature) of the platform is a Bounded Context in the DDD world. After you have the "product", you show how to "slice the product into modules". Would you consider the "module" you describe as an Aggregate/Entity inside a Bounded Context? It seems like that is what they would be based on their names...Buyer, Book, Stock, etc.

Collapse
 
kmruiz profile image
Kevin Mas Ruiz

Hi Michael!

Some of the modules can be aggregate roots, and others can be just query models, depending on the business logic.

What I've found is that usually you would have only once an aggregate. For example, the aggregate root Book, which handles the consistency of book info, will be in a single product. The reason is to guarantee consistency of business invariants. Other books will be some variant of read models.

Collapse
 
mjremijan profile image
Michael Remijan

Ok that gets to another question. When you say "Other books will be some variant of read models", how would get that book data to the other "products"? I like your body analogy when it comes to coupling Microservices with direct calls. Even with small applications I can see a "death star" pattern emerging quickly. So would use a Domain Event to push aggregate book data to other products with the caveat they must remain read-only? Or would the other products use the same database as the aggregate book data? Or (like in most situations) is it a combination based on the situation. What have you found to be most successful based on past experience?

Thread Thread
 
kmruiz profile image
Kevin Mas Ruiz

You can use both of them, I would suggest usually sharing snapshots of data. For example, sending the snapshot through SQS, Kinesis or even better Kafka so you can replay the state.

This way you give data ownership to the writer, guaranteeing data consistency, and you let the readers consume the information they need. However, this kind of infrastructure is quite expensive and teams can have a hard time learning about them.

As always, consider the cheapest solution. For example, right now, in a project, we are using just materialized views in a Oracle database as it's easier, trading off availability for simplicity (which most of the times makes sense).

The most successful approach to CQRS that I've seen is using Kafka to share snapshots, partitioned by the aggregate id, and a topic per type of domain entity. This allowed teams to consume from Kafka without fear of breaking other services, as they just need another consumer group. New services can just plug in to the topic, consume the whole state, and generate a view in whatever fits better for them.

Thanks!

Collapse
 
achimoraites profile image
Achilles Moraites

Hello Kevin ,
the article is well written and to the point !

Thanks for sharing!

Collapse
 
edudobay profile image
Eduardo Dobay

Nice article! Your comment on the UserService makes me wonder: is it customary to duplicate user data e.g. in all services that have some need to display the user's name? Or would it be more appropriate to keep that in a centralized service?

Collapse
 
kmruiz profile image
Kevin Mas Ruiz • Edited

I always try to balance team autonomy and crossfunctional requirements.

If having some piece of information across all components that have a dependency and moving data is too expensive, it's a good decision to centralise the user information in a single service.

This comes with several tradeoffs: all those teams will depend entirely on a new platform team, slowing down value delivery. This, from a pragmatic point of view, is not dramatic because teams usually have other blockers before that.

However I always ask, in terms of data locality, what would be the difference between propagating data with state sourcing or events, and having a cache in the client service after an HTTP request.

I hope I answered 😊.

Thanks for reading!

Collapse
 
mjremijan profile image
Michael Remijan

Hi Kevin. You say "Those products are a set of features that apply to a persona". From this I'm assuming that a product may contain multiple features, but do all the features in the product apply to only 1 persona? Meaning if a feature applies to a different persona, is that an indication that feature belongs in a different product?

Collapse
 
kmruiz profile image
Kevin Mas Ruiz

Hi Michael! thanks for the question!

Not necessarily, it depends on the size of your user segmentation. You might want a product for a bigger more abstract segmentation if you prioritise quantity of traffic instead of quality.
For example, in classifieds, you usually have just a single search webpage for everyone because quantity of traffic is your most valuable source of income (advertisement). In this post, the example is the registration form.

There are some situations when you prefer quality traffic and a more seamless user experience. For example, again in classifieds, you can have a product for luxury real estate with a different user experience to generate a different type of income from that user segment. In this post, for example, you have two checkouts, the normal one and the fast one.

It is a matter of tradeoffs, you should always consider at least business opportunities (probability of change), business maturity (platform stability) and business boundaries (team performance).

Collapse
 
imdanwu profile image
Daniel Wu

Hey thanks for this article. I think there are some great ideas to dive into, especially for fast growing startups where business requirements change frequently and people join or leave constantly.

Do you have any more recommended reading for someone who's never heard of domain driven design?

Collapse
 
kmruiz profile image
Kevin Mas Ruiz

Hi Daniel! Thank you for your feedback!

If you are brand new to Domain Driven Design, the best way to start is with the tactical patterns, which are easier to apply to already existing code and benefits are more obvious to developers.

Said that, the easiest book to start with is Domain Driven Design Distilled, by Vaughn Vernon. It's not expensive, is quite short and it's a good introduction to it.

Thanks!

Collapse
 
fipil profile image
Filip Nowak

Hi Kevin, great artice, thank you very much.
Did you mean Event Sourcing by the "State Sourcing"?
Thanks.

Collapse
 
kmruiz profile image
Kevin Mas Ruiz

Hi Filip, thanks for the feedback!

I think I should have elaborated a bit more on the topic. When I mean state sourcing is something that I've implemented a few times on different projects that is based on propagating the whole state of an aggregate every time it changes.

We used this pattern for example with Kafka, where we had a topic per aggregate type, and we were sending the aggregate state partitioning using the domain id. This allowed us to replay the whole story of states of an aggregate easily to materialize new views.

You could do something similar with event sourcing, the difference is that events are meant to share domain knowledge, and state snapshots are meant to share information.

Thanks for reading!

Collapse
 
fipil profile image
Filip Nowak

Hi Kevin, thank you for deep explanation!
Filip

Collapse
 
bulsyusuf profile image
Bulama Yusuf

Hello Kevin. Can you recommend the best book to read on Domain Driven Design?

Collapse
 
kmruiz profile image
Kevin Mas Ruiz

That's definitely a really hard question 😊. I don't know which one is the best book, it depends a lot on your expertise on DDD.

For a beginner, I would recommend Domain Driven Design Distilled from Vaughn Vernon.

If you have more experience and you prefer a lighter read, I would recommend Implementing Domain Driven Design from Vaughn Vernon also.

If you like more dense reading, Domain Driven Design by Eric Evans is really good.