Clean Architecture provides a clear and modular structure for building software systems, separating business rules from implementation details. It promotes maintainability by allowing for easier updates and changes to specific components without affecting the entire system. It also supports testability and adaptability, enabling developers to write robust and flexible code. Follow along and explore the 15 most common and advanced Clean Architecture interview questions and answers to know before your next Software Architect interview.
The majority of architectural approaches (like Onion or Hexagonal Architecture) have this common set of characteristics:
The architectural approach shall be:
The Clean Architecture is an attempt at integrating all these architectures into a single actionable idea:
An Entity is an object within our software that represents the union of critical business rules operating on critical business data (i.e. data bound to behaviour if you may). For example,the Loan entity could look like:
| Loan |
|---|
| -principle |
| -rate |
| -period |
| :----------------- |
| +makePayment() |
| +applyInterest() |
| +chargeLateFee() |
Following the purple arrow we can see the control flow of a user interacting with a system:
The controller and the presenter are located in the middle of this picture and they appear as a bridge between the user’s world (the view) and the business logic’s world (interactors).
The Dependency Rule states that source code dependencies should always point inward toward higher-level policies or abstractions and should never point outward toward lower-level details or implementations. In other words, the dependencies between different components or modules of a system should follow a specific direction, with higher-level modules depending on lower-level ones, but not the other way around.
The general wisdom is:
Depending on something that carries baggage that you don’t need can cause you troubles that you didn't expect.
The Interface Segregation Principle (ISP) is a design principle in object-oriented programming that emphasizes the importance of keeping interfaces segregated or divided into smaller, cohesive units. It suggests that clients (users or classes) should not be forced to depend on interfaces they do not use.
As an example consider the Repository interface.
To apply the Interface Segregation principle you shall provide your own repository interface that is dedicated to one use case will help to decouple use cases from each other. If all use cases use the same Repository interface, then this interface accumulates all the methods of all use cases. You can easily break one use case by changing the method of this interface.
So I usually apply the interface segregation principle and create repository interfaces named after the use case. E.g.
public interface PlaceOrderRepository {
public void storeOrder(Order order);
}and another use case's interface might look like this:
public interface CancelOrderRepository {
public void removeOrder(Order order);
}In Clean Architecture the Database is at the outer Layer but how would that work in reality?
Nothing in an inner circle can know anything at all about something in an outer circle. In particular, the name of something declared in an outer circle must not be mentioned by the code in an inner circle. That includes functions and classes. variables, or any other named software entity.
For DB Layer you create a technology-independent interface in the use case layer and implement it in the gateway layer:
public interface OrderRepository {
public List<Order> findByCustomer(Customer customer);
}implementation is in the gateway layer
public class HibernateOrderRepository implements OrderRepository {
...
}At runtime, you pass the gateway's implementation instance to the use case's constructor. That would not violate the dependency rule, because the use cases define the interface they need.
It might be even better to extract these use cases' interfaces into their own module. This prevents the db module to depend on the dependencies of the use case module.
Use Cases are business rules that make or save money by defining the way the automated system operates. They wouldn't exist if the business operated in a manual environment.
One aspect Uncle Bob is emphasizing is that the clean architecture is screaming. According to Uncle Bob an architecture “screams” when it clearly expresses its core business purpose.
The top-level folder structure, the project/DLL names, and the namespaces should express business aspects rather than frameworks or other details. That also means that the top-level structure and names should express your business domain and not the technical details and frameworks you use.
Consider non-screaming folder structure:
Consider screaming folder structure:
Both architectural styles apply layers to separate concerns, however, they do that in a different way:
So essentially, When you opt for DI and use interfaces to decouple dependencies in your N-tier architecture, you are transforming your architecture to Onion Architecture. As long as you are observing the direction (and in my case the depth) of your dependencies you moving it to Clean Architecture.
The controller takes user input, converts it into the request model defined by the use case interactor, and passes this to the same.
The request object accepted by the controller is defined by the controller. We do NOT want the controller to depend on the view or types defined in the framework circle. Such request objects are usually simple data transfer objects (DTO).
The job of the Presenter is to repackage the OutputData (Response Model) into viewable form as the ViewModel, which is yet another plain old Java object (POJO). The ViewModel contains mostly Strings and flags that the View uses to display the data. Whereas the OutputData may contain Date objects, the Presenter will load the ViewModel with corresponding Strings already formatted properly for the user.
Whenever a request is made to get a "full product", the client will ping the endpoint for the full product, it will grab that, and use its id to ping my Images and Reviews services to get all images and reviews for that product.
Where should I implement the external API calls logic in Clean Architecture?
Obtaining the images and reviews from the perspective of your product use case is just like database access. The only difference is that you don't query a database, you query another service instead.
When you take a look at the clean architecture you will realize that the controllers and gateways are on the same architectural layer - the interface adapters. This layer is named "interface adapters" because it adapts interfaces of the lower layer.
As you can see gateways can be a DB or an external interface (a service).
Thus you should structure your application in this way:
+------------------+
| product use case |
+------------------+
|
+------------------+---------------------+
| | |
V V V
+-----------------+ +------------------+ +-------------------+
| ImageRepository | | ReviewRepository | | ProductRepository |
+-----------------+ +------------------+ +-------------------+
^ ^ ^
| | |
===========+=====================+====================+================
| | |
+--------------------+ +--------------------+ +--------------------+
| ImageRestClient | | ReviewRestClient | | JDBCConnector |
+--------------------+ +--------------------+ +--------------------+Easy to test and if you decide one day that the images should be managed in the product microservice instead of a separate service you can replace the ImageRestClient with a JDBCConnector.
Rust has been Stack Overflow’s most loved language for four years in a row and emerged as a compelling language choice for both backend and system developers, offering a unique combination of memory safety, performance, concurrency without Data races...
Clean Architecture provides a clear and modular structure for building software systems, separating business rules from implementation details. It promotes maintainability by allowing for easier updates and changes to specific components without affe...
Azure Service Bus is a crucial component for Azure cloud developers as it provides reliable and scalable messaging capabilities. It enables decoupled communication between different components of a distributed system, promoting flexibility and resili...