Clean Architecture

================================ =

Clean Architecture is an architectural style and design pattern for software development that emphasizes Separation Of Concerns, Testability, and Maintainability. It was first introduced by Robert C. Martin (aka “Uncle Bob”) in his 2008 book “Clean Architecture: A Craftsman’s Guide to Software Structure and Design”.

Overview

Clean Architecture is a holistic approach to software design that involves three main layers:

  1. Entities: Represent business domains, such as Users, products, or orders.
  2. Use Cases: Define the interactions between entities and the outside world.
  3. Interface Adapters: Provide a standardized interface for interacting with external systems.

Layers

1. Entities

  • Represent business domains, such as Users, products, or orders.
  • These entities are self-contained and have their own logic.
  • Entities typically contain Domain Logic and are encapsulated within the Entity class.

2. Use Cases

  • Define the interactions between entities and the outside world.
  • Use cases describe the desired behavior of the system in terms of actions to be performed on entities or objects.
  • Use cases should be clear, concise, and easy to understand.

3. Interface Adapters

  • Provide a standardized interface for interacting with external systems.
  • Interface adapters map Interfaces to specific Implementation Details.
  • Interface adapters are used to decouple the business logic from the external systems.

Benefits

Components

1. Entities

  • <a href="/User" class="missing-article">User</a>: represents a User Entity
  • [Product](/Product): represents a Product Entity
  • <a href="/Order" class="missing-article">Order</a>: represents an Order Entity

2. Use Cases

  • GetUsers()
  • GetProducts()
  • PlaceOrder()

3. Interface Adapters

  • UserRepository: provides a standardized interface for interacting with Users (e.g., Database or File-Based Storage)
  • ProductRepository: provides a standardized interface for interacting with products
  • OrderService: provides a standardized interface for interacting with orders

Example Use Case

Suppose we have an E-commerce System with the following entities and use cases:

Entities

  • <a href="/User" class="missing-article">User</a>
  • [Product](/Product)

Use Cases

  • GetUsers(): returns a list of Users
  • GetProducts(): returns a list of products
  • PlaceOrder(): creates a new Order for a Product

Interface Adapters

  • UserRepository: provides an interface for retrieving User data from a Database
  • ProductRepository: provides an interface for retrieving Product data from a File-Based Storage
  • OrderService: provides an interface for creating and managing orders

Implementation

The Clean Architecture approach involves the following steps:

  1. Entities: Define the business domain entities.
  2. Use Cases: Create use cases that describe the desired behavior of the system.
  3. Interface Adapters: Develop interface adapters to map Interfaces to specific Implementation Details.

Example Implementation

// <a href="/User" class="missing-article">User</a> [Entity](/Entity)
public class <a href="/User" class="missing-article">User</a> {
    private int id;
    private String name;

    // getters and setters
}

// UserRepository interface
public interface UserRepository {
    List<<a href="/User" class="missing-article">User</a>> getUsers();
    void saveUser(<a href="/User" class="missing-article">User</a> <a href="/User" class="missing-article">User</a>);
}

// UserService class
public class UserService {
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public List<<a href="/User" class="missing-article">User</a>> getUsers() {
        return userRepository.getUsers();
    }
}
// [Product](/Product) [Entity](/Entity)
public class [Product](/Product) {
    private int id;
    private String name;

    // getters and setters
}

// ProductRepository interface
public interface ProductRepository {
    List<[Product](/Product)> getProducts();
    void saveProduct([Product](/Product) [Product](/Product));
}

// ProductService class
public class ProductService {
    private final ProductRepository productRepository;

    public ProductService(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }

    public List<[Product](/Product)> getProducts() {
        return productRepository.getProducts();
    }
}
// OrderService interface
public interface OrderService {
    void createOrder(<a href="/Order" class="missing-article">Order</a> <a href="/Order" class="missing-article">Order</a>);
}

// OrderServiceImpl class
public class OrderServiceImpl implements OrderService {
    private final UserRepository userRepository;
    private final ProductRepository productRepository;

    public OrderServiceImpl(UserRepository userRepository, ProductRepository productRepository) {
        this.userRepository = userRepository;
        this.productRepository = productRepository;
    }

    @Override
    public void createOrder(<a href="/Order" class="missing-article">Order</a> <a href="/Order" class="missing-article">Order</a>) {
        // logic to create an <a href="/Order" class="missing-article">Order</a>
    }
}

By following the Clean Architecture approach, developers can create maintainable, testable, and scalable software systems that are easier to understand and extend.