Domain Driven Design & Nameko


#1

Hi @mattbennett,

I am sorry I am reaching you personally but my question is related to the following topics Who is using on production and Versioning apis, that you have answered long time ago.

I have been following nameko-examples repository alongside nameko documentation in order to get familiar with nameko and it’s concepts. The following sentence on README file

Aim to apply Domain Driven Design concepts and try to place only services that belong to the same bounded context in one repository e.g., Product (main service responsible for serving products) and Product Indexer (a service responsible for listening for product change events and indexing product data within search database).

triggered me and after searching this site I have found out that you are following a specific design pattern. Since I wasn’t familiar with Domain Driven Design, I have read about it. Moreover, It seems that the decoupling
of domain services and facades that you follow at Student.com results in a clean architecture. I have been trying to identify the DDD patterns on nameko-example repository while trying to figure out how I would apply DDD in a set nameko of microservices. I have understood that on nameko-examples, gateway acts as a facade. My question is if product & orders are two distinct domain services or under the same bounded context?

In general do you encourage to have a facade not strictly connected to a bounded context / nameko service ? Furthermore is it correct to define that rpc entrypoints act as Aggregate roots and orders/models.py act as a combination of Value Objects & Repository? (DDD theory). As you can understand, I am trying to find an analogy of Domain Driven Design with nameko-example project :slight_smile:

Finally in a hypothetical case of an airtickets company, a domain service would be the ticket reservations service and another domain service would be a loyalty service. If my assumption is correct, then multiple facades can proxy requests to these services. Furthermore is any rule how big a database (e.g. number of tables) of domain service can be or the only constrain is the bounded context ?

I understand that my questions are very specific to DDD but I would be grateful I you could find some time and answer to me.

Thank you in advance,

Spyros


#2

Hi Spyros,

Sorry for the slow reply here.

Domain Driven Design is a really interesting but complicated discipline, and I’m afraid that I am no expert! I think it is very well suited to microservices though, and the general concepts have been helpful to us at Student.com in separating the concerns between different services.

We do not strictly follow DDD. We don’t have explicitly defined Aggregates or Bounded Contexts, for example. If we did the full modelling exercise I think we’d find that our service boundaries tend to encapsulate multiple aggregates in most cases, and we wouldn’t find any aggregates that span multiple services (which is much better than the other way around!). As we refactor our services we often find ourselves splitting them into multiple parts, each of which probably correspond to a single aggregate.

I think it is valid to say that RPC entrypoints would be methods on your aggregate roots. I also think that models.py could act as the repository, although DDD theory says that your domain model should be completely divorced from the persistence mechanism. At Student.com we use what we call the Storage pattern, which is a DependencyProvider that returns an object with methods on it that query the models, rather than return the database session directly. I think this matches the DDD definition of Repository quite well.

Once you’ve segregated your domain logic into multiple microservices, you need some way of re-combining them into useful responses for your applications. The facade pattern is one way of doing this, and I think it’s analogous to the Application Service pattern in DDD.

At Student.com we’ve actually moved away from facades now, and expose our whole API service using GraphQL. This has been a very powerful tool in decoupling our frontend and backend teams. GraphQL works very well indeed with microservices, and I’m interested in finding out more about what the DDD community thinks of it as a tool.

With my personal interpretation (and limited understanding), this is how I currently map DDD concepts to microservices:

Aggregate: a single microservice
Aggregate Root: the public methods on that microservice
ValueObject: an immutable SQLAlchemy model or POPO (Plain Old Python Object) with some other persistence
Entity: a mutable SQLAlchemy model or POPO, with methods for manipulation
Repository: something equivalent to the Storage pattern, abstracts away the persistence layer
Domain Event: a Nameko Event or similar – very important for keeping services decoupled
Bounded Context: a collection of microservices that share the same ubiquitous language; there’s no technical component to this at the service level, but using GraphQL (or facades) you’d have different a different graph for each Bounded Context.

Somewhere on my (long) todo list is a project to implement the canonical DDD shipping example in Nameko, strictly using the DDD tactical patterns. There’s a nice example of a “pure” DDD implementation in Python here and a talk by the authors here. This example uses also event sourcing which is a powerful concept that could be implemented quite nicely in Nameko.

Hope that helps! Let me know where you end up with it and whether you have any more questions.

Matt.


#3

Hi Matt,

Thank you for spending some time answering my question. I think I have got an idea of how you have modeled your microservices having DDD in mind. Although you don’t strictly follow DDD I can understand that they way you structure your services resembles actual DDD patterns. I have been trying to do the same thing on the project I am currently working on. Currently I have build multiple microservices that some of them may have a persistence layer. Furthermore I am writing facades in a such way to isolate the consumer groups, since there is big diversity of the exposed APIs. Having said that, on every facade I am building the business logic and combine rpc calls to “backend” microservices. I will definitely try to apply the concepts that you have described. Especially I like the Storage pattern that you are using since it adds an extra layer of decoupling logic from data in very convenient way, DependencyProvider.

Regarding GraphQL I have been experimenting with it and I really liked it. Unfortunately due to the fact that end consumers will be some customers I cannot “force” them to switch from a REST API to GraphQL. I am planning though to add it on later stage when some administrative actions will be exposed using a UI ( not top priority for now).

Be sure that I will definitely have a look on the canonical DDD shipping example whenever you do it :smiley:
I would like to thank you once again for your detailed response and for the resources you have provided to me. Since you have mentioned it, I was looking also how I can implement event sourcing in Nameko. Any ideas on achieving it, I will be grateful :slight_smile:

Spyros