Architecture refers to the overall project design. It's the code organization into classes, files, components or modules, and the way how all these code structures relate to each other. It is the architecture that defines
Clean architecture refers to project management aimed to make it easy to understand and flexible to change as the project grows. This requires intentional planning.
The secret to developing a large project that is easy to maintain is based on separating all the files and classes into components and making them possible to change independently of other components. Let’s identify some characteristics of clean architecture:
While dealing with clean architecture, you deal with a similar concept:
The domain layer of the app is the inner circle. This is where all your business rules are put.
The data formats used in the outer circle shouldn’t be used by an inner circle or have any impact on it. Now let’s see what is going on in the inner circle:
The domain layer is subdivided into 3 layers: entities, use cases, and adapters. Let's look at these terms individually.
The entity is a set of related business rules that are critical for the application function. It can be an object with methods or a group of data structures or functions. If you are just writing a single application, then all these entities are considered to be the application’s business objects. They cover the most general and high-level rules and are less likely to change when something external changes. For instance, these objects won’t be affected by a change to page security or navigation. There isn’t any operational change to any particular application that may affect the entity layer.
In the object-oriented programming language, the rules for an entity are grouped together as the methods in a class. Entities have no information about other layers, and neither they depend on anything. This means they don't make use of the names of any other classes and components from outer layers.
The use cases are the business rules for a specific application. The layer covers and implements all of the use cases of the system. The use cases tell how to automate the system. They determine the app behavior and organize the data flow to and from the entities, as well as direct these entities to use their enterprise-wide business rules to achieve the goals of the use case. You won’t see changes in this layer that affect the entities. Neither this layer is affected by external changes such as the database, the UI, etc.
However, sometimes it’s possible that changes to the application operation affect the use cases and the software in this layer. In case details of a use-case change, some code is certainly affected in the layer.
The interface adapters or adapters are translators between domain and infrastructure. In this layer, the software is a group of adapters that convert data from the most convenient format for the use cases and entities. No code of this circle knows anything about the database. In this layer, any other adapter is necessary to convert data from any external form. It may be an external service used by the use-cases and entities.
This layer is where all the I/O (Input/Output) components go. This includes the User Interface, database, frameworks, devices, and more. Infrastructure is the most flexible layer. Things in this layer are likely to change and they are kept as long as possible from more stable domain layers. As the infrastructure layer is kept separate, it's relatively easy to make changes or exchange one component for another.
Have you ever heard the acronym SOLID? This is a set of software development principles. If organized wisely, these principles are intended to guarantee flexible and clean code. Let’s look through these principles:
SRP (single responsibility principle) stands for S. According to this principle, in a specific program, every class or module has responsibility just for a single piece of the functionality of the program. To speak in simple words, classes have a single responsibility and only one reason to change.
This is the O from SOLID. The general idea of this principle is that classes and any other entity are open for the extension, yet close for modification. This principle guides on writing code so that later you may add new functionality without any change in the existing code. The principle also prevents situations when a single change to any class also requires adjusting all dependent classes.
Liskov is L. This principle defines that objects should be replaceable by their subtypes. Objects of a superclass may be exchangeable with objects of its subclasses, not breaking the application.
Here we came to I. Interfaces should be more client-specific than general. As in the Single Responsibility Principle, here also the main idea is to reduce the side effects as well as the frequency of all required changes by breaking the software up into multiple and independent parts.
D depends on abstractions rather than concretions. The main idea of this principle is that high-level modules (that provide complex logic) are easily reusable and impassive by changes in low-level modules (that provide utility features). D principle consists of 2 parts:
It isn’t hard to conform to these simple rules, especially, if you consider that it saves you a lot of headaches going forward. Following the principles of clean architecture, you create a system that is easily testable and clear. And even if an external part of the system (e.g. database, or web framework) is no longer in use, you can replace it with a minimum of fuss. So, you are recommended to work somehow in detail in order to avoid further disorder.