Sponsorship is available! If you’d like to sponsor CodeOpinion.com and have your product or service advertised exclusively (no AdSense) on every post, contact me.
Entity Services are services that are centered around an Entity. For example, a CustomerService or a ProductService. Most times these services focus on data and CRUD operations. These services can cause low cohesion and in turn cause high coupling. Instead, focus on capabilities of services, the data encapsulated and owned by the service. Focusing on capabilities will increase cohesion and lower coupling.
Check out my YouTube channel where I post all kinds of content that accompanies my posts including this video showing everything that is in this post.
I believe that the default way that systems are built and designed today in 2021 is still revolving around large data models. This can be illustrated by a question on Reddit, which was asking if a microservices architecture where each table represented its own microservices was the best approach.
The answer is no. Absolutely not.
I don’t blame the user for posting this question. There is so much content around creating CRUD apps that it’s not really surprising. Also, when creating a large monolith, having a large schema is also typical. So the idea to split a large monolith and schema into microservices, would seem like you would create services around tables/data.
Also, I would guess most developers relate Entities to tables. This is likely because of ORMs like Entity Framework.
For my example throughout this post, I’m going to use the concept of a product in a warehouse.
This entity has a few different properties that would probably be managed by CRUD. If you’re talking about an HTTP API, it would probably follow a CRUD to HTTP Methods.
For example, if you wanted to create a product you would call:
Or if you wanted to update a product you would call the route:
These are the typical examples you’ll find in blogs/tutorials/videos.
If you’re looking at an API, it would contain just CRUD type methods:
The alternative is to focus on the capabilities of your service. Instead of grouping your entities by their data, rather group them by the capabilities they provide that relate to each other.
A service is the authority of a set of business capabilities.
If you look at the entity, which properties relate to each other? What are the actions users would take in order that would change those properties?
If the quantity on hand of a product is changing, why is that? What would a user be doing that would change the QuantityOnHand?
Does the QuantityOnHand have any relation to the cost? Would QuantityOnHand ever change at the same time as the price?
If you decompose the capabilities that you need to expose to users, they are driven by commands/actions/tasks. What are the things users are trying to do?
Moving away from CRUD and exposing explicit capabilities will then expose which capabilities are concerned with what pieces of data.
The QuantityOnHand is affected by shipping and receiving products. The capabilities of shipping and receiving products belong to the warehouse.
The Name, Description, Price, and Cost have nothing to do with shipping and receiving products. So why are the other properties on the product entity?
If you do this to the other properties, you will realize that the capabilities define the data they own. Group related capabilities together into their own service/boundary, then you will realize that you do not have a single entity, but multiple concepts of the same entity that reside in multiple services.
The concept of a product now lives in multiple different boundaries/services. They all share the common SKU, but each service owns a set of capabilities. Behind those capabilities are the relevant data it owns.
Focusing on capabilities will increase cohesion and reduce coupling. Coupling is reduced because of increasing cohesion. You do not need to call other services to get/change data because you have the required data within a service for the capabilities that it owns.