Software architecture defines the structural boundaries and communication paths of a system. Choosing a pattern is a trade-off between developer velocity, system maintainability, and operational complexity.
The most common traditional pattern, where components are organized into horizontal layers. Each layer has a specific responsibility and typically only communicates with the layer immediately below it.
Key Characteristic: High coupling. The business logic depends directly on the database implementation. If you change the database, the Service layer often requires modification.
This pattern inverts the dependencies of the Layered architecture. The "Core" (Business Logic) sits at the center and defines Ports (interfaces) for everything external.
UserRepository).PostgreSQLAdapter) implements that port, performing the actual physical I/O.Key Characteristic: Dependency Inversion. The Core depends on nothing external. The Database depends on the Core's interface.
EDA moves away from synchronous method calls toward asynchronous message passing. Components communicate by emitting and consuming events.
UserRegistered event to an Event Broker (e.g., Kafka).Key Characteristic: Temporal and Spatial Decoupling. Producers and consumers do not need to exist at the same time or know each other's location.
| Pattern | Dependency Direction | Primary Benefit | Main Drawback |
|---|---|---|---|
| Layered | Top → Down | Simple to understand | Hard to test without DB |
| Hexagonal | Outside → Inside | Testable, Tech-agnostic | High boilerplate |
| Event-Driven | To/From Broker | Massive Scalability | Debugging/Tracing complexity |
Cluster Hub: Design Patterns Hub: Creational, Structural, and Behavioral Software Patterns (design-patterns)