Chapter 21& Chapter 22: Screaming Architecture & The Clean Architecture_《clean architecture》notes


Chapter 21: Screaming Architecture

Key Concepts
  1. Architectural Intent: The structure of the project should immediately reflect its core purpose (e.g., “hospital management system”), not the frameworks used (e.g., “Spring MVC app”).
  2. Framework Independence: Avoid letting frameworks dictate your architecture. Frameworks are tools, not the central theme.
  3. Testability: A screaming architecture enables easy testing by isolating business rules from technical details.

Code Example: Web-Based Order System

Scenario: Build an order management system where the architecture “screams” the domain (orders), not the web framework.

Project Structure

src/
  orders/
    domain/
      Order.java       // Core business entity
      OrderService.java // Business logic
    infrastructure/
      WebController.java // Framework adapter

Code Snippets

  1. Order Entity (Domain Layer)
// Order.java
public class Order {
    private String id;
    private String product;
    private int quantity;

    public Order(String product, int quantity) {
        this.id = UUID.randomUUID().toString();
        this.product = product;
        this.quantity = quantity;
    }

    // Getters and business methods
    public String getId() { return id; }
    public String getProduct() { return product; }
    public int getQuantity() { return quantity; }
}
  1. Order Service (Business Logic)
// OrderService.java
public class OrderService {
    public Order createOrder(String product, int quantity) {
        return new Order(product, quantity);
    }
}
  1. Web Controller (Framework Adapter)
// WebController.java
public class WebController {
    private final OrderService orderService;

    public WebController(OrderService orderService) {
        this.orderService = orderService;
    }

    public String handleRequest(String product, int quantity) {
        Order order = orderService.createOrder(product, quantity);
        return "Order created: " + order.getId();
    }
}
  1. Main Function (Test Case)
public class Main {
    public static void main(String[] args) {
        OrderService service = new OrderService();
        WebController controller = new WebController(service);

        // Simulate HTTP request
        String response = controller.handleRequest("Laptop", 2);
        System.out.println(response); 
        // Output: "Order created: d3b07384-d113-4ec6..."
    }
}

Key Points:

  • The orders/domain package focuses purely on business rules.
  • The infrastructure layer adapts the domain to the web framework.
  • The project structure emphasizes orders, not the web framework.

Chapter 22: The Clean Architecture

Key Concepts
  1. Dependency Rule: Source code dependencies point inward. Outer layers (UI, DB) depend on inner layers (business rules).
  2. Layers:
    • Entities: Core business objects (e.g., Order).
    • Use Cases: Application-specific business rules.
    • Interface Adapters: Convert data between layers (e.g., database gateways).
    • Frameworks/Drivers: External tools (e.g., Spring, Hibernate).
  3. Independence: Layers can be developed/tested independently.

Code Example: Order Management System

Project Structure

src/
  clean/
    entities/
      Order.java
    usecases/
      OrderInteractor.java
    interfaces/
      OrderPresenter.java
      OrderGateway.java
    main/
      App.java // Composition root

Code Snippets

  1. Entity Layer (Order)
// Order.java (same as Chapter 21)
public class Order { ... }
  1. Use Case Layer (OrderInteractor)
// OrderInteractor.java
public class OrderInteractor {
    private final OrderGateway gateway;

    public OrderInteractor(OrderGateway gateway) {
        this.gateway = gateway;
    }

    public void createOrder(String product, int quantity) {
        Order order = new Order(product, quantity);
        gateway.save(order);
    }
}
  1. Interface Adapters
// OrderPresenter.java (Output boundary)
public interface OrderPresenter {
    void displayOrder(String orderId);
}

// OrderGateway.java (Data access interface)
public interface OrderGateway {
    void save(Order order);
}
  1. Database Adapter (Implements OrderGateway)
// DatabaseAdapter.java
public class DatabaseAdapter implements OrderGateway {
    @Override
    public void save(Order order) {
        System.out.println("Saving order to DB: " + order.getId());
    }
}
  1. Main Function (Dependency Injection)
// App.java
public class App {
    public static void main(String[] args) {
        OrderGateway gateway = new DatabaseAdapter();
        OrderInteractor interactor = new OrderInteractor(gateway);

        interactor.createOrder("Monitor", 1);
        // Output: "Saving order to DB: 6f9b0b3e-..."
    }
}

Key Points:

  • Dependency Inversion: OrderInteractor depends on the abstract OrderGateway, not the concrete DatabaseAdapter.
  • Testability: Mock OrderGateway to test business logic without a real database.
  • Layered Compilation:
    • Entities have no dependencies.
    • Use cases depend only on entities.
    • Adapters depend on use cases and frameworks.

Testing the Code

  1. Compile & Run
    Save files in the above structure and compile:

    javac clean/entities/*.java clean/usecases/*.java clean/interfaces/*.java clean/main/App.java
    java clean/main/App
    
  2. Expected Output

    Saving order to DB: 6f9b0b3e-...
    

Summary

  • Screaming Architecture: Structure reflects domain, not frameworks.
  • Clean Architecture Layers:
    • Inner layers (entities, use cases) are framework-agnostic.
    • Outer layers (adapters, UI) depend inward.
  • Dependency Rule: High-level policies (business rules) never depend on low-level details (databases).

Multiple-Choice Questions

  1. Which principles ensure the core business logic remains independent of frameworks?
    A. Use the Humble Object Pattern for UI logic.
    B. Define all database schemas in the Entities layer.
    C. Let the web framework dictate package structure.
    D. Invert dependencies using interfaces.

  2. Which layers in Clean Architecture are allowed to depend on external libraries?
    A. Entities
    B. Use Cases
    C. Interface Adapters
    D. Frameworks & Drivers

  3. How should data transfer between layers be handled?
    A. Pass raw database entities directly to the UI.
    B. Use DTOs to decouple layers.
    C. Allow inner layers to reference outer-layer data structures.
    D. Share domain objects across all layers.

  4. What violates the Dependency Rule in Clean Architecture?
    A. A REST controller depending on a Use Case interface.
    B. A Use Case depending on a database gateway interface.
    C. An Entity importing a web framework class.
    D. A database implementation depending on an Entity.

  5. Which practices make architecture “scream” the system’s purpose?
    A. Naming packages controllers and models.
    B. Organizing code around domain concepts like Loan or Invoice.
    C. Using framework-specific annotations in core logic.
    D. Isolate I/O operations using the Humble Object Pattern.

  6. Which are true about the Humble Object Pattern?
    A. It separates UI logic from business rules.
    B. It allows direct database access in Entities.
    C. It ensures testable core logic by isolating volatile code.
    D. It requires frameworks to define business rules.

  7. What ensures inner layers remain stable?
    A. Keeping inner layers free of framework dependencies.
    B. Allowing Use Cases to depend on UI components.
    C. Defining interfaces in outer layers for inner layers to implement.
    D. Using dependency injection to invert control.

  8. Which scenarios violate the Interface Segregation Principle (ISP) in Clean Architecture?
    A. A Use Case interface with methods for both createOrder and generateReport.
    B. Separate interfaces for OrderRepository and ReportRepository.
    C. A single User entity containing both authentication and profile data.
    D. A REST controller implementing a Use Case interface.

  9. How does the Dependency Inversion Principle (DIP) apply to Clean Architecture?
    A. Inner layers define interfaces implemented by outer layers.
    B. Use Cases depend on concrete database implementations.
    C. Entities contain framework-specific annotations.
    D. Outer layers define interfaces for inner layers to use.

  10. Which code snippets follow Clean Architecture principles?
    A. A Use Case class importing a Spring @RestController.
    B. A database gateway implementing an interface defined in the Use Case layer.
    C. An Entity class with JPA annotations.
    D. A DTO passed from a controller to a Use Case.


Answers & Explanations

1. A, D

  • A: The Humble Object Pattern isolates UI/database logic.
  • D: Dependency inversion decouples core logic from implementations.
  • B/C violate independence by tying core logic to frameworks.

2. C, D

  • C/D: Only outer layers (Interface Adapters, Frameworks) depend on external tools.
  • A/B (inner layers) must remain pure.

3. B

  • B: DTOs prevent layer coupling.
  • A/C/D create unwanted dependencies or expose internals.

4. C

  • C: Entities (inner layer) must not reference outer layers (e.g., web frameworks).
  • A/B/D follow the Dependency Rule.

5. B, D

  • B: Domain-centric naming reflects purpose.
  • D: Isolating I/O keeps core logic focused.
  • A/C prioritize frameworks over domain.

6. A, C

  • A/C: The pattern isolates testable logic from I/O.
  • B/D mix concerns or invert dependencies.

7. A, D

  • A: No framework ties in inner layers.
  • D: Dependency injection inverts control.
  • B/C violate the Dependency Rule.

8. A, C

  • A: Fat interfaces force unnecessary dependencies.
  • C: Mixing concerns in entities violates ISP.
  • B/D adhere to ISP.

9. A

  • A: Inner layers define abstractions; outer layers implement them.
  • B/C/D invert or violate dependencies.

10. B, D

  • B: Gateways implement inner-layer interfaces.
  • D: DTOs decouple layers.
  • A/C tie core logic to frameworks.

Code Example (Java)

// Inner Layers (Entities and Use Cases)
interface OrderRepository {
    void save(Order order);
}

class Order {
    private String id;
    // No framework annotations or dependencies!
}

class PlaceOrderUseCase {
    private final OrderRepository repository;
    
    public PlaceOrderUseCase(OrderRepository repository) {
        this.repository = repository;
    }
    
    public void execute(Order order) {
        // Business logic here
        repository.save(order);
    }
}

// Outer Layer (Interface Adapter)
class DatabaseGateway implements OrderRepository {
    @Override
    public void save(Order order) {
        // JPA/Hibernate implementation
    }
}

// Framework Layer (Spring Controller)
@RestController
class OrderController {
    private final PlaceOrderUseCase useCase;
    
    public OrderController(PlaceOrderUseCase useCase) {
        this.useCase = useCase;
    }
    
    @PostMapping("/order")
    public void createOrder(@RequestBody OrderDto dto) {
        Order order = convertToEntity(dto);
        useCase.execute(order);
    }
    
    private Order convertToEntity(OrderDto dto) {
        // Convert DTO to Entity
    }
}

// DTO for data transfer
class OrderDto {
    public String id;
}

// Main (Test Case)
public class Main {
    public static void main(String[] args) {
        OrderRepository repository = new DatabaseGateway();
        PlaceOrderUseCase useCase = new PlaceOrderUseCase(repository);
        OrderController controller = new OrderController(useCase);
        
        OrderDto dto = new OrderDto();
        dto.id = "123";
        controller.createOrder(dto); // Output: Order saved via gateway
    }
}

Key Compliance:

  • Inner layers (Order, PlaceOrderUseCase) have no framework dependencies.
  • Dependencies point inward (e.g., OrderController depends on PlaceOrderUseCase).
  • DTOs isolate data transfer.
  • Interfaces (OrderRepository) invert dependencies.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值