A change is made to a single code line in one of the modules and we want to make that change. To do that, we need to implement the whole monolith, even those modules that haven’t changed. Everything has to be implemented together, so we have an implementation link. If the structure of our code system changes, it is expensive to handle it, because the cost of the change via the service limits in the distributed systems is very high. Having to make independent changes to one or more deployable services, perhaps in view of the impact of breaking through changes in service contracts, is likely to be a huge burden. The most common example that comes to mind when discussing monoliths is a system that implements all code as one process, as shown in Figure 1-6.
Or you may have created a set of implementation artifacts from multiple sources and versions. Either way, this version for the system is implemented everywhere at once . Continuous implementation is difficult: large monolithic application is also an obstacle to frequent implementations. This interrupts the background tasks (p. E.g. Quartz vacancies in a Java application), regardless of whether they are affected by the change and may cause problems. As a result, it increases the risk associated with redistribution, discouraging frequent updates.
While a monolith may be a valid option for some operating situations, it is generally not suitable for a modern application. Poorly defined internal monolith structures can make code maintenance more difficult, creating a steep learning curve for new developers and creating additional support costs. High clutch and low cohesion can significantly extend the time it takes to add new features and you may not be able to scale individual components based on traffic patterns. Monoliths also require multiple teams to coordinate for a major launch, increasing the burden of collaboration and knowledge transfer.
By encapsulating data and behavior in this way, we get a high coherence of business functionality. By hiding the database that supports our service, we also ensure that strategies for decomposing monoliths the link is reduced. Since a microservice architecture is a distributed system, you must choose and configure the connections between all modules and databases.
Because it can be difficult to understand how to properly implement a change, the quality of the code decreases over time. It is worth noting that practically all systems we classify as “monoliths” are also distributed systems. A single process application probably reads data from a database running on another machine and presents data in a web browser. There are at least three computers in the mix there, with communication between them via networks.
In essence, in a system consisting of multiple independent services, there must be some interaction between the participants. In a microservice architecture, domain linking is the result: interactions between services form interactions in our real domain. If you want to place an order, you need to know which items were in a customer’s shopping cart.
In addition, as long as this application includes independent services, they must all be implemented independently. As we discussed in this chapter, microservices are independently implementable services modeled after a business domain. We use the information principles hidden along with domain-based design to create services with stable limits where it is easier to work independently, and we do what we can to reduce the many forms of coupling.
The difference is the extent to which monolithic systems are distributed compared to microservice architectures. Since you have more computers in the mix that communicate over more networks, you’d rather consider the unpleasant problems associated with distributed systems. These issues that I have briefly discussed may not appear at first, but as your system grows it will likely affect most, if not all, of you. Changes in functionality mainly refer to changes in business functionality. But in Figure 1-1, our commercial functionality extends across all three levels, increasing the likelihood of a change in functionality exceeding layers. This is an architecture in which we have a high coherence of related technology, but a low coherence of business functionality.