You’re still concern about what is the Modern Software Architecture at the moment? You’re searching around to the Best Software Architecture to apply for your project. Go deeply into this article, it’s going to help you answering by your own.
In term of software development, the architecture of project is really important for the sake of maintenance and re-usability during many projects that I have worked. The software architecture ensures that the software that you build has a basis of the skeleton. It just likes the mainframe or the background of a house. Upon on that, we have a freedom to build anything we want.
The question always in my head these days is how can we combine the Clean Architecture and Modular pattern? I have done some of the experiments in the code, and finally, I decided to write it out in this article. The purpose is really straightforward for sharing what I have learned, and learn more what I get from feedback. This article is based on my experience in software development and how the modular approach gives the benefits and applies Clean Architecture concepts on it.
The modular approach for the architecture is also a topic that we have talked a lot in our company. Back to 5 years ago, I worked on the big project that has a lot of people involved, and in that time, we had organized the architecture to the modular approach. And by the time, we know that with the modular we can cut the 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 the 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 (if need, but it is not easy to adopt it from my point of view)
The Clean Architecture has coined since 2012 by Uncle Bob, and by the time, it becomes an important things in the software architecture world. We can see Android using it by combination with MVP pattern to build the software architecture for the mobile app. A couple of articles out there also proposed to use Clean Architecture for the web application. In early this year, Uncle Bob published the book named “Clean Architecture: A Craftsman’s Guide to Software Structure and Design”. If you have never read that book before I highly recommend you to take a look at it. This book mentions a lot of best practices when using SOLID, design patterns and some of tips and tricks in deployment work as well.
A bit overview about the clean architecture, if you have already known, please skip this and jump over to the implementation section. According to Clean Architecture, we need to ensure some of the important points below
1. 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.
2. Testable. The business rules can be tested without the UI, Database, Web Server, or any other external element.
3. 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.
4. 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.
5. Independent of any external agency. In fact your business rules simply don’t know anything at all about the outside world.
And it follows strictly the diagram
“Talk is cheap. Show me the code.” — Linus Torvalds
Let start off with the main story today, 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 bunch of use cases or user stories (if there is an agile project). And the final step, we will have to draw the use case diagram. For those people that could not catch what I said so far, I would like to analyze an example in the blog engine domain. Let say we want to build the blog website that have some of the features like read the blog, see the posts of this blog, add some of the comments in the public interface. And we definitely have a way to CRUD actions on blogs, posts, and comments. Beside of that, we also need to login into the system before we can modify the blogs, posts, and comments. Based on the requirement of features for this application, we’re going to end up with the use case diagram below
Now is the time, I will show you how can I apply the modular pattern to this example. If you look at the diagram above, you will notice that we only have 3 main things for managing are authentication, blog, and post. Grab some ideas from Domain-Driven Design(Tackling Complexity in the Heart of Software and Implementing Domain-Driven Design books are the good starting point from my point of view), in this case is Bounded Context pattern, I separate my application domain out to the Access Control Context, Blog Context and Post Context (I divide it into 3 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). Let put them together, and we have a diagram like
Lets explaining a bit about the diagram above, the Access Control Context with the red color is for authentication and authorization tasks. The Blog Context filled with green color is for blog management includes setting up the blog, status assignment, and theme… The third one is the Post Context which manages its own comments and tags. As you can see, the Post Context has the relationship with others. For more information of how can we design the Bounded Context (Root aggregate) please come to Effective Aggregate Design articles, you will learn the huge of useful things. You have my promise :)
Too much for the theory, let now jump into the code. Due to the limitation of this article, I only can show you one Bounded Context code, and I would like to choose the Post Context because I think this is the most interested in. The rests, you can have a look at my GitHub codes — the link gives you at the end of this article. So far, some of you will question that what the heck Clean Architecture involves into this? Don’t panic. Let me show you the project structure, then you have the rest.
Is it clean for structuring the project? By the time, I found out that the simple structure does not only help new-comers easy to catch up and work on it, but also help code readers easy to figure out what we want to do and navigate through the large code base.
For those people want to run this example project, I use .NET Core 2.0 to implementation so that you need to install at least the run-time environment.
Now I start to explain about the structure above. First, we have the Framework folder in the diagram, that contains all the stuff related to necessary toolkit for the project. Remember that we’re going to avoid using the abstraction in our code, but use the composition (Composition over inheritance in OOP). The BlogCore.Core will not need to depend on any framework or library, but on .NET SDK definitely (some of the cases we call its vanilla code). Additionally, we have 3 projects: BlogCore.Infrastructure, BlogCore.Infrastructure.AspNetCore and BlogCore.Infrastructure.EfCore that will depend on EntityFrameworkCore, AspNetCore and others libraries like Autofac, AutoMapper, FluentValidation, MediatR…
Second, Hosts folder in the middle of the diagram, We use it for putting the host projects there. You can see I have 2 hosts: one for the API (BlogCore.API) and another for the Single Page Application (BlogCore.App).
Third, Migrations folder is used to do the migrating works, in this case, we migrate data for the Access Control Context, Blog Context and Post Context. We can choose to migrate using Entity Framework migration and seed data for them. Otherwise, you can also use the T-SQL scripts to do the migration. It is up to you, I don’t say which one is better than others.
Finally, we have the Modules folder that contains the heart of this application. We have divided it into Bounded Context folders here, and make our architecture more clearly. Each Bounded Context has 2 sub-projects, e.g. BlogCore.PostContext and BlogCore.PostContext.Core. BlogCore.PostContext.Core only contains domain objects, contracts, and interfaces which is really good for another projects references. The rule is if we have another module that wants to use some of the classes, objects so that it should reference the <Module name>.Core and to the interface inside this project(only depends on the interface in another module. This will make loose-coupling for those modules. We will get a lot of benefits with this approach).
Lets see the Post Bounded Context structure in the details
I think we should deep dive into some of the code to understand more about how can we implement the Clean Architecture with the Modular pattern for this project.
We have Post.cs entity that acts like Root Aggregate in the Post Context as
Then, we have the PostGenericRepository.cs
We need to create the DbContext for the PostContext.cs as
In Clean Architecture, the use case is very important and should be designed very carefully. In my project, I named it as ListOutPostByBlogInteractor.cs
After processing the business case for the Post Bounded Context, we need to aggregate some of the data related to the Access Control Bounded Context, and in this case, we get the Author information of it and use the IUserRepository interface to get the author’s details information. So that we introduce another class called ListOutPostByBlogPresenter.cs
And we need to have a place to register these dependency objects. So the Dependency Injection comes into play, and we use Autofac module in this project. The idea is the module will register all the dependency its own.
Yes, that’s enough, then we only need to introduce the API for what we did
Today, I have walked you through the journey of how can we make the modular works well in the Clean Architecture. We at least know what is modular, what it’s actually important. We run through some of the overviews of Clean Architecture, and some of the strong points of it as well. And the last but not least, we know how to implement it using .NET Core 2.0.
What is not covered in this articles are the Data flow, Synchronized between Bounded Contexts, Unit Testing, Deployment for the Clean Architecture…I’m going to write more about them if you guys interested in, just drop the messages in the comment box below.
The source code for this article can be found at https://github.com/thangchung/blog-core
Thanks for reading! If you enjoyed this article, be sure to click 👏 symbol below so others will see it.