Clean Web Application Architecture
We would like to share an approach that we have been using for many years in applications development, including web applications. Many developers of desktop, server and mobile applications are familiar with this approach. It is fundamental while building such types of applications. However, it is very poorly represented on the web. At the same time, there are definitely those who want to use this approach.
As a result of applying this approach, you will not be tied to a specific framework and will be able to easily switch the view library inside your application, for example, React, Preact, Vue, Mithril, without rewriting business logic, and in most cases even views. If you have an Angular 1 app, you can easily translate it to Angular 2+, React, Svelte, WebComponents, or even your view library. If you have an application in Angular 2+, but there are no specialists for it, then you can easily transfer the application to a more popular library without rewriting the business logic. And in the end, forget about the problem of migrating from framework to framework altogether. What kind of magic is this?
The best way to understand this is to read Robert C. Martin’s book Clean Architecture.
The main ideas behind clean architecture:
- Framework independence. The architecture does not depend on the existence of any library. This allows you to use the framework as a tool rather than squeezing your system into its limitations.
- Testability. Business rules can be tested without a user interface, database, web server, or any other external component.
- Independent from UI. The user interface can be easily changed without changing the rest of the system. For example, the web interface can be changed to a console one without changing the business rules.
- Database independent. You can swap out Oracle or SQL Server for MongoDB, BigTable, CouchDB, or whatever. Your business rules are not database related.
- Independence from any external service. In fact, your business rules simply don’t know anything about the outside world.
For many years, the ideas described in this book have been the basis for building complex applications in a wide variety of areas.
This flexibility is achieved by dividing the application into Service, Repository, Model layers. We added the MVC approach to Clean Architecture and got the following layers:
- View — displays data to the client, actually renders the state of the logic to the client.
- Controller — responsible for interacting with the user via IO (input-output).
- Service — is responsible for business logic and its reuse between components.
- Repository — responsible for retrieving data from external sources such as database, api, local storage, etc.
- Models — is responsible for transferring data between layers and systems, as well as for the logic of processing this data.
Web development has come a long way, from simple JQuery scripting to the development of large SPA applications. And now web applications have become so large that the amount of business logic has become comparable or even superior to server, desktop and mobile applications.
For developers who write complex and large applications, as well as transfer business logic from server to web applications to save on server costs, Clean Architecture can help organize code and scale the project to huge scales without problems.
At the same time, if your task is just layout and animation of landing pages, then there is simply no room for Clean Architecture. If your business logic is on the backend and your task is to receive data, display it to the client and process the click on the button, then you will not feel the flexibility of Clean Architecture. However, it can serve as an excellent springboard for explosive growth of the application.
Clean Architecture is not tied to any particular framework, platform, or programming language. It has been used to write desktop applications for decades. Its reference implementation can be found in the Asp.Net Core, Java Spring and NestJS server-side application frameworks. It is also very popular when writing iOs and Android applications. But in web development, it appeared in an extremely unfortunate form in the Angular frameworks.
The only framework that tried to use Clean Architecture was Angular. But it turned out just awful, either in 1 or in 2+.
And there are many reasons for this:
- Angular is a monolithic framework. And this is its main problem. Not only are there a lot of problem areas, but it also contradicts the ideology of Clean Architecture.
- Terrible view engine. It is very primitive and falls far short of the simplicity of JSX. Data is not typed at the stage of writing the code, and at the stage of compilation. We learned to identify errors only in version 6, and before this version appeared we had managed to do that only in runtime.
- Old bundler. While the Rollup bundler allowed building ES2015 and making 2 bundles for old and new browsers for 4 years already, the angular builder only learned to do this in version 9.
- And many more problems. In general, modern technologies reach Angular with a delay of 5 years relative to React.
But what about other frameworks? React, Vue, Preact, Mithril and others are purely presentation libraries and do not provide any architecture … and we already have the architecture … the only thing left to do is to collect everything into a single whole!
As a bonus, we got the opportunity to supplement or change the behavior of components of the presentation library. For example, the React does not render the entire application on an error in the view. Using the Clean Architecture approach, the React will render not only the component in which the error occurred. In the same simple way, you can add monitoring, analytics and other features.
In addition to describing data and transferring data between layers, models have a large margin of capabilities. For example, if you connect the class-validator library, then simply by hanging decorators you can validate the data in these models, incl. with a little tweak, you can validate web forms.
In addition, if you need to work with a local database, you can connect the typeorm library and your models will turn into entities by which the database will be generated and operated.
If you like this article — share it with your friends and like-minded people💜
You can find more articles on our Geniusee Blog
Originally published at https://geniusee.com on July 29, 2020.