Modular patterns
The modular approach we can cut large monolith software into many vertical smaller monoliths and make the team works more easily because each team only needs to focus on the module that they work. Could anyone remember about the conflicted code in the big project? Could you spend half of day (or more) just to merge the codes? It is really a nightmare, isn’t it?
So in the modular approach, we need to make sure that the modules should be independent enough so that it can be work by the sole developers in different teams. It should be in logical design style and gives us strong points as
- Help our software system is able to extensible, reusable, maintainable, and adaptable.
- Break large monolith stack into a flexible composite of collaborating modules (in monolith style).
- Help newcomers to easy to understand the business features and the functionalities of the system (because it is small enough)
- Open the door to migrate into the microservices architecture
Clean Architecture
In terms of software development, the architecture of the project is really important for the sake of maintenance and re-usability.
The software architecture ensures that the software that you build has a basis of the skeleton. Upon on that, we have the freedom to build anything we want.
Clean architecture helps us solve, or at least mitigate, these common problems with architecture:
- Decisions are taken too early, often at the beginning of a project, when we know the least about the problem that we have to solve
- It’s hard to change, so when we discover new requirements we have to decide if we want to hack them in or go through an expensive and painful re-design. We all know which one usually wins. The best architectures are the ones that allow us to defer commitment to a particular solution and let us change our mind
- It’s centered around frameworks. Frameworks are tools to be used, not architectures to be conformed to. Frameworks often require commitments from you, but they don’t commit to you. They can evolve in different directions, and then you’ll be stuck following their rules and quirks
- It’s centered around the database. We often think about the database first, and then create a CRUD system around it. We end up using the database objects everywhere and treat everything in terms of tables, rows and columns
- We focus on technical aspects and when asked about our architecture we say things like “it’s servlets running in tomcat with an oracle DB using spring”
- It’s hard to find things which makes every change longer and more painful
- Business logic is spread everywhere, scattered across many layers, so when checking how something works our only option is to debug the whole codebase. Even worse, often it’s duplicated in multiple places
- Forces/Encourages slow, heavy tests. Often our only choice for tests is to go through the GUI, either because the GUI has a lot of logic, or because the architecture doesn’t allow us to do otherwise. This makes tests slow to run, heavy and brittle. It results in people not running them and the build behind broken often
- Infrequent deploys because it’s hard to make changes without breaking existing functionalities. People resort to long-lived feature branches that only get integrated at the end and result in big releases, rather than small incremental ones
Clean architecture gives us all these benefits:
- Testable. The effective testing strategy that follows the testing pyramid and gives us a fast and reliable build
- Independent of Frameworks. The architecture does not depend on the existence of some library of feature-laden software. This allows you to use such frameworks as tools, rather than having to cram your system into their limited constraints.
- Independent of UI. The UI can change easily, without changing the rest of the system. A Web UI could be replaced with a console UI, for example, without changing the business rules.
- Independent of Database. You can swap out Oracle or SQL Server, for Mongo, BigTable, CouchDB, or something else. Your business rules are not bound to the database.
- All business logic is in a use case so it’s easy to find and it’s not duplicated anywhere else
- Independent of any external agency. In fact, your business rules simply don’t know anything at all about the outside world.
- Good monolith with clear use cases that you can split in microservices later one, once you’ve learned more about them
Clean Architecture mentions a lot of best practices when using SOLID principles, design patterns in deployment work as well.
- S – Single-responsibility principle.
- O – Open-closed principle.
- L – Liskov substitution principle.
- I – Interface segregation principle.
- D – Dependency Inversion Principle.
And how can we apply SOLID Principle to our project:
This is example code when we used “Dependency Inversion principle”
“Entities must depend on abstractions not on concretions. It states that the high-level module must not depend on the low-level module, but they should depend on abstractions.”
We have an interface (high level)
And it’s an implementation (low level)
And High level should be depended on a high-level not depend on a low-level. And How can we do that
We binding it with a specific interface. And when we have a new requirement to change implementation, we just update new implementation in one place.
In Our business “ReservationService” is high-level
What happened if a high-level is depended on a low-level. So when we have a new requirement to change implementation, we need to search all in the project, to update new implementation.
How to make it work perfectly?
Any project has to analyze and ask the customer about what they want to do for their system and what they need for their system to act for. They will give us a bunch of use cases or user stories.
And the final step, we will have to draw the use case diagram.
For example in the common booking domain. We want to build a blog website that have some of the features like finding a hotel, book a hotel, see the comment of the hotel, add some of the comments in the hotel. We also need to login to the system before we can modify the hotel, booking, and prices. Based on the requirement of features for this application, we’re going to end up with the use case diagram below:
The question is how can we make the architecture to the modular approach? Actually, the key factor is from Domain-Driven Design and in this case, we use Bounded Context design pattern to analysis and design the current business domain. If you look at the diagram above, you will notice that we only have 3 main things for managing as authentication, hotel, and booking. I separate my application domain out to the Access Control Context, Booking Context and Hotel Context, Pricing Context (I divide it into 4 Bounded Contexts because my domain knowledge like that, it will be different from others due to different domain experts, but at least it needs to sort out the business needs). We end up with a diagram as:
Lets explaining a bit about the diagram above, the Hotel Context filled with green color is for hotel management includes create, edit, delete hotel, comment management, manage star rating. The Booking Context with the orange color is for booking management. The Pricing Context with the black color is for price management by arrange date, event and theme the Access Control Context with the red color is for authentication and authorization tasks. For more information about how can we design the Bounded Context (Root aggregate)