Business Components as mini systems
In my High Availability article I mentioned business components and questions were asked in the comments, what these business components actually are. This post is a follow up to my previous post about the autonomy of those business components. I’ll specifically try to answer the question in the first comment.
Is “Business Component” a mini system that owns ui, app services, domain model and db? or it owns everything mentioned above except ui layer?
This was asked because I said that I could change a business component “knowing that the chance of breaking code somewhere else is practically nonexistent”. When you start to understand this, you’ll see the benefit of true real-time autonomy of your services, by adding events to your Service Oriented Architecture. Since the beginning of software development, a lot of thought has gone into modularity and the effort into trying to get rid of the big ball of mud that your software can become. What I initially didn’t understand was the fact that most coupling is practically invisible, inside your database. But this also crawls into your layers, creating more and more coupling. Not just at design-time, but especially at run-time! That’s why you need to separate your components. And in such a way, that it’s the most logical choice for everyone involved in the software being build. Not just developers, but also engineers, DBAs and especially the business!
On the Particular website there’s a great post about layering. It’s actually about microservices, but I love the part about loose coupling and high cohesion in your application. For some reason we’ve all learned to split the layers in our system. But the article says this is like splitting an atom, which will likely result in a lot of mess. So instead of trying to split the layers horizontally, we can identify vertical slices and end up with the business components I’ve blogged about previously.
Why I mentioned this, is because of the original question about what a business component owns. If we don’t split the horizontal layers, but do identify vertical slices, and separate data among these verticals, how can we create a user interface where products, prices, shopping carts, invoices, etc. are joined together? If Business Component A within the Sales Bounded Context cannot share data with Business Component B within the Finance Bounded Context, how can we visualize a product on screen, show its price and also show popular products in the same category? The person asking the question was right, the Business Component does own everything, from database up ’till the user interface. And in the user interface, everything is joined together visually.
- UI Composition When we want to visualize data on screen, we want to bring data together in a composite user interface. This means we’re composing a screen of multiple smaller parts. We could call these small parts micro views.
- Dependencies in data When you’re displaying a product, it’s likely you know which product to display due to the url containing some reference to your product.
- When displaying the details of the product, supply the business component of the Sales Bounded Context the product identifier to retrieve these details.
- When displaying the price of the product, supply the business component of the Finance Bounded Context the product identifier to retrieve the price, possibly including discounts.
- When displaying products in the same category, have another business component (of perhaps another Bounded Context) provide a list with products of the same category. When a list of identifiers is retrieved, use the same method as described above to retrieve data of every single product. Of course it’d be great if these calls could be batched to reduce the number of HTTP calls, but that’s another topic.
- Read models The result might be a bit chatty towards your business components. If you need to be able to retrieve data extremely fast, you might want read models. Instead of querying a relational schema with a lot of references and creating a lot of locks, while reading and updating the data, you can also copy and prepare data, just for a specific micro view. This is achieved quite simply by publishing an event and have several subscribers, that all exist, just to update their counterpart of a micro view.
It doesn’t mean you can’t do relational data and have to do everything with some NoSQL solution. You might do relational data as regular storage and have some NoSQL alternative for read models. You can also have read models in distributed cache like Redis, for example. When you have high contention on some data in your relational database, you might want to transform the data after querying and then store the result in memory, in Redis, or somewhere else. When so many resources access only a small amount of your data, there might be no need to prepare the data ahead in a read model. You might just transform and store it after initial retrieval. For quite some time, it’s perfectly fine to have this as a read model in some fast but temporary storage. And mind yourself that caching is eventual consistency. But it’s important to have options and select the best solution possible for every issue you’re working on.
Due to these topics, the data isn’t (as) coupled inside the database as before, nor in your code. This makes it extremely easy to change code in your Business Components and change your database schema, without having to worry about your code breaking in an entirely different Bounded Context or even Business Component. I’ve experienced this first hand, and it’s as if an entire new world opens up to you, once you start realizing the possibilities and extensibility of this way of designing your system.