chapter four

4 Thinking in Layers: Separating the 'How' from the 'Why' at Scale

 

This chapter covers

  • What layers are and how they work in architecture.
  • Applying the downward dependency rule to create loosely coupled layers.
  • Handling cross-cutting concerns like logging and authentication.
  • Recognizing common anti-patterns in layered architectures.
  • Visualizing layers with a simple diagramming technique and exploring parallels with network layering.

4.1 Introduction

In the first three chapters, we built our foundation. Chapter 1 gave us the Architectural Thinking Process; Chapter 2 filled our toolkit with tools such as ADRs and the “-ilities”; and Chapter 3 armed us with fundamental structural principles such as Separation of Concerns and SOLID. We learned how to make good decisions and how to build well-structured individual components.

Now, it’s time to zoom out. How do we organize all those well-built components into a cohesive, maintainable application? How do we structure the system as a whole?

One of the most powerful and time-tested techniques is thinking in layers. No, not your mother’s lasagna or seven-layer taco dip; we’re talking about architectural layers. This chapter explores how layering helps us apply Separation of Concerns on a grander scale, manage complexity, and build applications that are easier to understand, test, and evolve. We’ll look at the layered approach, the rules that make it work, and how it helps us avoid common pitfalls.

4.2 Layered Architecture

4.2.1 Command Flow vs. Data Flow

4.2.2 Classic Layered Architecture

4.2.3 The Evolution of Layers

4.2.4 Challenging the Layers: Newer Patterns

4.3 Downward Dependency

4.3.1 Why Is It So Important?

4.3.2 The Danger Zone: Violating the Rule

4.4 Physically Structuring Layers

4.4.1 Approach 1: Folders (common in Python/JavaScript)

4.4.2 Approach 2: Separate Projects (Common in Java/C#)

4.4.3 Fitness Functions: A Different Kind of Test

4.5 Cross-Cutting Concerns

4.5.1 The Problem: Tangling and Scattering

4.5.2 The Solution: Invert the Dependency!

4.5.3 The Payoff: Why This Matters Architecturally

4.6 The Four-Layer Diagram

4.6.1 Reading the Blueprint

4.7 Anti-Patterns: When Layers Go Wrong

4.7.1 Anti-Pattern 1: The Fat Controller (or Bloated Service)

4.7.2 Anti-Pattern 2: The Anemic Domain Model

4.7.3 “After”: The Defensible Decision (Rich Domain, Thin Controller)

4.7.4 The Architect’s Mandate: Decide and Enforce

4.8 The Dork Side: The 7-Layer Sandwich That Runs the Internet

4.8.1 The Problem: The Digital Tower of Babel