# Architectural Styles

Comparison of major architectural patterns for structuring software systems. Each style manages dependencies differently and suits different contexts.

---

## Layered Architecture (Classic)

```
┌─────────────────────┐
│   Presentation      │  ← UI, controllers, API endpoints
├─────────────────────┤
│   Application       │  ← Use cases, orchestration, services
├─────────────────────┤
│   Domain            │  ← Business logic, entities, rules
├─────────────────────┤
│   Infrastructure    │  ← DB, external APIs, frameworks
└─────────────────────┘
```

**Rules**:
- Each layer depends only on layers *below* it
- Domain layer has no external dependencies
- Changes flow downward; domain is stable

**Pros**: Familiar, clear separation, easy to understand
**Cons**: Database changes ripple up to domain; infrastructure leaks into business logic; hard to test domain in isolation

**Best for**: Simple CRUD apps, small teams, low domain complexity

---

## Hexagonal Architecture (Ports & Adapters)

```
                    ┌──────────────────┐
                    │  Primary Adapters │  ← REST, CLI, UI, gRPC
                    │   (Driving)       │
                    └────────┬─────────┘
                             │ implements
                    ┌────────▼─────────┐
                    │   Inbound Ports   │  ← Use case interfaces
                    ├──────────────────┤
                    │   Domain Core     │  ← Entities, aggregates, domain services
                    │   (No deps out)   │
                    ├──────────────────┤
                    │  Outbound Ports   │  ← Repository, notification, external service interfaces
                    └────────┬─────────┘
                             │ implemented by
                    ┌────────▼─────────┐
                    │ Secondary Adapters │  ← DB, message queue, HTTP clients
                    │   (Driven)        │
                    └──────────────────┘
```

**Core rule**: All dependencies point **inward** toward the domain core. The domain defines interfaces (ports); infrastructure implements them (adapters).

**Key concepts**:
- **Primary adapters** (driving): Entry points — HTTP controllers, CLI, message consumers
- **Secondary adapters** (driven): Exit points — database repos, external API clients, email senders
- **Ports**: Interfaces owned by the domain, defining *what* it needs, not *how*

**Pros**:
- Domain fully testable without infrastructure
- Infrastructure swappable without touching domain
- Aligns perfectly with Domain-Driven Design
- Enables TDD — test domain via ports

**Cons**: More boilerplate; indirection can obscure flow; overkill for simple apps

**Best for**: Complex domains, long-lived systems, teams doing DDD, systems needing testability

---

## Clean Architecture (Robert Martin)

```
┌─────────────────────────────────────┐
│          Frameworks & Drivers       │  ← Web, DB, UI, Devices
├─────────────────────────────────────┤
│        Interface Adapters           │  ← Presenters, Controllers, Gateways
├─────────────────────────────────────┤
│         Application Business        │  ← Use Cases / Interactors
│            Rules                    │
├─────────────────────────────────────┤
│       Enterprise Business Rules     │  ← Entities
└─────────────────────────────────────┘
```

**Dependency Rule**: Inner circles know nothing of outer circles. Dependencies point inward.

**Differences from Hexagonal**:
- More prescriptive layer names
- Use cases (interactors) are explicit layer between domain and adapters
- Entities are innermost (enterprise-wide), use cases are application-specific

**Pros**: Very explicit boundaries; scream architecture (package by feature); good for large teams
**Cons**: More layers = more mapping/boilerplate; can feel rigid

**Best for**: Large enterprise apps, regulated environments, teams needing strict boundaries

---

## Onion Architecture (Jeffrey Palermo)

Similar to Clean but emphasizes:
- Domain model at center (entities + domain services)
- Application services orchestrate domain
- Infrastructure at outer edge
- Dependency inversion via interfaces in domain layer

**Key insight**: "The more you depend on things that change, the more you'll have to change."

---

## Domain-Driven Design (DDD) — Strategic Architecture

DDD is not an architecture style per se, but it produces architectural patterns:

### Bounded Contexts
Explicit boundaries within which a domain model is consistent and valid.
- Different parts of a system can model "Customer" differently
- Contexts communicate via **Context Maps** (conformist, anticorruption layer, shared kernel, etc.)

### Context Map Patterns
| Pattern | Description |
|---|---|
| **Shared Kernel** | Subset of model shared explicitly; requires coordination |
| **Customer/Supplier** | Upstream/downstream relationship; downstream defines needs |
| **Conformist** | Downstream conforms to upstream model (no negotiation) |
| **Anticorruption Layer** | Translation layer protects downstream from upstream model |
| **Open Host Service** | Published protocol for multiple consumers |
| **Published Language** | Well-documented shared language (e.g., OpenAPI, Protobuf) |

---

## Microservices Architecture

**Not a style** — an organizational/deployment pattern that *uses* architectural styles internally.

Each service typically uses:
- Hexagonal/Clean internally
- Own database (database per service)
- Communicates via async messaging or synchronous API

**Challenges**: Distributed system complexity, data consistency, operational overhead, network latency

**Best for**: Large organizations, independent deployability needs, polyglot teams

---

## Modular Monolith

A single deployable unit with **internal modular boundaries** (bounded contexts as modules).

```
┌────────────────────────────────────┐
│            Application             │
├─────────┬─────────┬────────────────┤
│ Module A│ Module B│ Module C       │  ← Bounded contexts as packages
│ (DDD)   │ (DDD)   │ (DDD)          │
├─────────┴─────────┴────────────────┤
│         Shared Kernel              │  ← Minimal shared code
└────────────────────────────────────┘
```

**Pros**: Simpler operations, easier refactoring, transactions across modules, no network latency
**Cons**: Requires discipline to maintain boundaries; single failure domain

**Best for**: Most applications! Start here. Extract services only when organizational/scale demands it.

---

## Comparison Matrix

| Concern | Layered | Hexagonal | Clean | Modular Monolith | Microservices |
|---|---|---|---|---|---|
| **Testability (domain)** | Low | High | High | High | High |
| **Infrastructure swap** | Hard | Easy | Easy | Medium | Easy |
| **Boilerplate** | Low | Medium | High | Low | High |
| **Learning curve** | Low | Medium | Medium | Low | High |
| **Deploy simplicity** | High | High | High | High | Low |
| **Team scaling** | Low | Medium | Medium | Medium | High |
| **DDD alignment** | Low | High | High | High | High |

---

## Decision Guidance

| Situation | Recommended |
|---|---|
| Simple CRUD, small team, short timeline | Layered or Modular Monolith |
| Complex domain, long-lived, needs testability | Hexagonal / Clean |
| Multiple teams, independent deployment needs | Modular Monolith → Microservices |
| Regulated, audit-heavy, strict boundaries | Clean Architecture |
| Greenfield, uncertain domain | Modular Monolith (extract later) |

---

## Key Principles Across All Styles

1. **Dependency inversion** — Domain defines interfaces; infrastructure implements
2. **Separation of concerns** — Business logic separate from infrastructure
3. **Boundaries align with change** — Modules/bounded contexts = deployment/change units
4. **Explicit contracts** — Ports, interfaces, APIs define integration points
5. **Testability as a design driver** — If it's hard to test, the architecture is wrong

---

## Related Notes

- [[Architecture/Design-Principles]] — Principles that inform these styles
- [[Architecture/Domain-Driven-Design]] — DDD tactical/strategic patterns
- [[Architecture/CQRS-Event-Sourcing]] — Advanced patterns for complex domains
- [[Architecture/Architecture-Decision-Records]] — Document your architectural choices
- [[Patterns/Integration-Patterns]] — How services/modules communicate
- [[Methodologies/Team-Topologies]] — Team structure should match architecture

---

*Sources: AWS Prescriptive Guidance (Hexagonal), Clean Architecture (Robert Martin), Onion Architecture (Palermo), Domain-Driven Design (Evans), Software Engineering Guide, Martin Fowler, Microsoft Clean Architecture*