What is Screaming Architecture?
What is Screaming Architecture?

What is Screaming Architecture?

https://www.nilebits.com/blog/2024/09/what-is-screaming-architecture/

Screaming Architecture is a concept introduced by renowned software developer and thought leader Robert C. Martin, often referred to as "Uncle Bob." The term may sound unconventional, but it represents a powerful principle in software design, focusing on making the architecture of a system reflect the primary concerns and use cases of the application. In simpler terms, your software's architecture should "scream" its intent and purpose.

In this comprehensive guide, we’ll explore the fundamentals of Screaming Architecture, how it contrasts with traditional software architecture, its significance in domain-driven design, and how you can implement this architecture in your projects. We’ll also cover practical examples and scenarios where Screaming Architecture can improve code readability, maintainability, and long-term scalability.

Why "Screaming" Architecture?

The idea behind Screaming Architecture is that the primary structure of your codebase should immediately convey its business purpose. This contrasts with traditional architectures, which might emphasize technical frameworks, tools, or other secondary concerns. In Screaming Architecture, domain concerns take precedence over implementation details.

Uncle Bob Martin illustrated this with an analogy: imagine walking up to a building and seeing its architecture. Without needing a sign, you can often tell whether it’s a library, school, or office. The same should apply to software architecture. When you look at the folder structure and design of an application, you should immediately understand what it’s for. If you’re building an accounting system, the architecture should scream "accounting," not "Django," "Spring Boot," or "React."

The Problems with Framework-Centric Architecture

In many projects, the focus on technology frameworks overshadows the business or domain logic. You’ll find file structures like:

  • controllers/
  • services/
  • repositories/
  • models/

While these directories are useful, they describe technical roles rather than reflecting the core problem the software solves. For example, this structure tells you that the system uses MVC (Model-View-Controller) but gives no insight into whether the system handles financial data, user management, or content creation.

The Framework Trap

The overemphasis on frameworks results in codebases where the business logic is obscured by technical boilerplate. A system built around framework conventions becomes tightly coupled to those frameworks. If you ever want to change frameworks or technology stacks, refactoring becomes a major effort. Screaming Architecture advocates for keeping your domain logic clean and separate, so the choice of framework becomes an implementation detail rather than the core structure of your codebase.

Screaming Architecture in Domain-Driven Design (DDD)

Domain-Driven Design (DDD) and Screaming Architecture often go hand-in-hand. DDD is an approach to software development that emphasizes collaboration between technical and domain experts, and it focuses on modeling the core business logic in a way that aligns closely with real-world operations.

In Screaming Architecture, the domain model and business logic are at the center of the application, and everything else—frameworks, databases, UI, and services—becomes peripheral. The key idea is that the code structure should reflect the domain model rather than technical implementation details.

Here’s how you can structure your project in a way that "screams" its intent using domain-driven principles:

/src
    /accounting
        Ledger.cs
        Transaction.cs
        Account.cs
        TaxService.cs
    /sales
        Order.cs
        Invoice.cs
        Customer.cs
        DiscountPolicy.cs        

In this example, the folder names directly reflect the business concerns: accounting and sales. Each domain-specific class, like Ledger, Transaction, and Order, is placed within its relevant domain context. This structure makes it immediately clear what the system is about and where each component fits.

Code Example 1: A Simple Domain-Centric Structure

Consider an e-commerce application that handles orders and inventory. With Screaming Architecture, the folder structure should reflect the business logic rather than technical roles:

/src
    /orders
        Order.cs
        OrderService.cs
        OrderRepository.cs
    /inventory
        InventoryItem.cs
        InventoryService.cs
        InventoryRepository.cs        

Here’s a basic code example from the orders context:

public class Order
{
    public Guid Id { get; set; }
    public DateTime OrderDate { get; set; }
    public List<OrderItem> Items { get; set; }
    public decimal TotalAmount { get; set; }

    public Order(List<OrderItem> items)
    {
        Id = Guid.NewGuid();
        OrderDate = DateTime.Now;
        Items = items;
        TotalAmount = CalculateTotal(items);
    }

    private decimal CalculateTotal(List<OrderItem> items)
    {
        return items.Sum(item => item.Price * item.Quantity);
    }
}

public class OrderItem
{
    public string ProductName { get; set; }
    public decimal Price { get; set; }
    public int Quantity { get; set; }
}        

In this code, the domain concept (Order) is front and center, with supporting logic like OrderService and OrderRepository kept in separate files. The business logic (CalculateTotal) is part of the Order entity, rather than hidden away in a service or controller.

Avoiding Technical Distractions

Frameworks and libraries are crucial for software development, but they shouldn't dictate how your business logic is structured. Screaming Architecture advocates for pushing technical details like HTTP controllers, persistence layers, and database frameworks to the periphery.

Here’s an example that contrasts the traditional and screaming architectures:

Traditional Architecture:

/src
    /controllers
        OrderController.cs
    /services
        OrderService.cs
    /repositories
        OrderRepository.cs
    /models
        Order.cs
        OrderItem.cs        

While this is technically correct, it doesn’t tell you what the system is for. The folder structure reveals nothing about the domain. Is it an e-commerce system? A financial application? It’s impossible to know without diving deep into the code.

Screaming Architecture:

/src
    /orders
        OrderController.cs
        OrderService.cs
        OrderRepository.cs
        Order.cs
        OrderItem.cs
    /inventory
        InventoryController.cs
        InventoryService.cs
        InventoryRepository.cs
        InventoryItem.cs        

This structure immediately clarifies that the system handles orders and inventory. If you add more domains in the future (e.g., customers, payments), they’ll have a dedicated place in the architecture.

The Role of Clean Architecture

Screaming Architecture often aligns with Uncle Bob’s broader Clean Architecture principles. Clean Architecture promotes a separation of concerns, focusing on ensuring that business rules are independent of frameworks, UI, and databases. Screaming Architecture takes this a step further by suggesting that the project’s structure should reveal the core business logic.

Here’s a quick recap of Clean Architecture:

  1. Entities: Core business objects and logic.
  2. Use Cases: Application-specific business rules.
  3. Interfaces: Gateways for frameworks and external systems.
  4. Frameworks & Drivers: UI, databases, and other external components.

In a Clean Architecture project, domain concepts like Order, Customer, and Invoice are part of the central layer. Frameworks like ASP.NET Core, Django, or Rails are relegated to the outer layers, serving as mechanisms to deliver the core functionality.

Code Example 2: Applying Clean Architecture in Screaming Architecture

In a Screaming Architecture, you’d structure the use cases and entities in a way that reflects the business domain. Let’s extend our e-commerce example:

/src
    /orders
        CreateOrderUseCase.cs
        OrderRepository.cs
        Order.cs
        OrderItem.cs
    /inventory
        AddInventoryItemUseCase.cs
        InventoryRepository.cs
        InventoryItem.cs        

Here’s an example use case for creating an order:

public class CreateOrderUseCase
{
    private readonly IOrderRepository _orderRepository;
    private readonly IInventoryService _inventoryService;

    public CreateOrderUseCase(IOrderRepository orderRepository, IInventoryService inventoryService)
    {
        _orderRepository = orderRepository;
        _inventoryService = inventoryService;
    }

    public Order Execute(List<OrderItem> items)
    {
        // Ensure all items are available in inventory
        foreach (var item in items)
        {
            _inventoryService.CheckInventory(item.ProductName, item.Quantity);
        }

        var order = new Order(items);
        _orderRepository.Save(order);
        return order;
    }
}        

In this example, the CreateOrderUseCase is part of the domain logic and interacts with the OrderRepository and InventoryService to fulfill the business need of creating an order.

Benefits of Screaming Architecture

  1. Improved Readability: Anyone who opens your codebase will immediately understand what the system does.
  2. Separation of Concerns: Business logic remains isolated from technical details, making it easier to change frameworks or technologies later.
  3. Scalability: As the system grows, the domain structure remains consistent, allowing for easy addition of new features and modules.
  4. Maintainability: Domain logic is easier to maintain when it’s cleanly separated from external dependencies and frameworks.
  5. Framework Agnostic: Screaming Architecture allows the business logic to remain portable across different technical stacks, avoiding tight coupling with any particular framework.

Criticisms of Screaming Architecture

While Screaming Architecture has many benefits, it’s not without its criticisms:

  1. Perceived Complexity: Developers unfamiliar with domain-driven design may find the separation of domain logic from technical details unnecessary or overly complex for small applications. 2

. Overhead: In small projects or simple CRUD applications, implementing Screaming Architecture may seem like overkill.

  1. Learning Curve: For teams used to framework-first approaches, adopting Screaming Architecture requires a shift in thinking that may take time to internalize.

When to Use Screaming Architecture

Screaming Architecture is particularly useful in the following scenarios:

  • Domain-Driven Systems: Applications with complex business rules and domain logic.
  • Long-Term Projects: Systems expected to evolve over time, where scalability and maintainability are critical.
  • Cross-Platform Development: Systems that may switch frameworks or platforms, making a clean separation of business logic essential.

Conclusion

Screaming Architecture is more than just a catchy name; it’s a philosophy that advocates for making the core business logic the most prominent part of your codebase. By focusing on domain concepts rather than technical frameworks, developers can build systems that are more readable, maintainable, and scalable in the long run. Whether you’re working on a simple web application or a complex enterprise system, adopting Screaming Architecture can lead to cleaner, more focused code that clearly expresses its purpose.

To learn more about Screaming Architecture, you can check out some references and additional readings:

By embracing the principles of Screaming Architecture, you can create codebases that not only work but also "scream" their intent.

https://www.nilebits.com/blog/2024/09/what-is-screaming-architecture/

要查看或添加评论,请登录

Amr Saafan的更多文章

社区洞察

其他会员也浏览了