Building Software

Engineering Fundamentals for the Agent Era

Contents Section 6, Design

Components and Architecture

Mistakes to catch in review

  1. Business rules written directly inside HTTP handlers or UI components, where they can't be reused or tested alone.

  2. A small application split into many services, adding network failures and deployment overhead for no benefit.

  3. Code in every module reaching straight into the database instead of going through the component that owns that data.

How a system is divided into modules and services, which way dependencies point, and how the parts communicate.

Topics

Layers and Dependency Direction
Keeping core logic independent of frameworks, databases and delivery mechanisms.
Modular Monoliths and Services
When one deployable with strong internal boundaries beats many services, and when splitting pays for itself.
Ports and Adapters
Isolating external systems behind interfaces so they can be swapped, faked in tests or replaced.
Synchronous and Asynchronous Communication
Direct calls, queues and events, and the coupling and failure modes each one creates.
Enforcing Boundaries
Module rules, dependency checks and architecture tests that keep boundaries intact across many hands and many agents.

You understand it when you can

  • Describe the components of an application you know, which way each dependency points, and why it points that way.
  • Decide whether a new capability belongs in an existing module, a new module or a separate service, and defend the choice.
  • Explain what changes when a synchronous call between two components becomes a queued message.

Drill

An agent split a small internal tool into four services (users, projects, notifications and billing) that call each other over HTTP, and put the billing rules inside the web request handler. Find the failure modes the split introduced and say where the billing rules should live instead.

Start here

Watch

Modular Monoliths • Simon Brown • GOTO 2018

Simon Brown, 2018. 47-minute talk.

Brown shows how to package one deployable by component instead of by layer, so boundaries are enforced in code instead of by a network hop, and why a messy monolith turns into messy microservices.

Hexagonal Architecture (Alistair Cockburn)

Alistair Cockburn, 2024. 56-minute lecture.

The pattern's creator explains ports and adapters: why core logic must not depend on UI, database or framework, and the real costs of the extra indirection.

Read

Fundamentals of Software Architecture: A Modern Engineering Approach

Mark Richards and Neal Ford, 2025, 2nd edition.

Covers component identification, the layered, modular-monolith, event-driven and microservices styles with explicit trade-off ratings, and architectural governance to keep boundaries intact.

Balancing Coupling in Software Design

Vlad Khononov, 2024.

Gives a model for judging coupling by the knowledge shared between components, their distance and how often they change, which explains when splitting a component into services lowers coupling and when it only makes it more distributed.

Building Microservices: Designing Fine-Grained Systems

Sam Newman, 2021, 2nd edition.

The chapters on modelling service boundaries, synchronous versus event-driven communication, and data ownership explain what changes, and what can fail, once a call crosses a network.

Primary sources

  • Reference

    Hexagonal Architecture (Alistair Cockburn)

    Cockburn's original write-up of ports and adapters, with the rule that the application talks to databases, UIs and tests only through ports it defines.

  • Reference

    MonolithFirst (Martin Fowler)

    Fowler reports that successful microservice systems almost always started as monoliths, and explains why service boundaries drawn before the domain is understood tend to be wrong.