Software architecture is not just about writing code; it's about the strategic decisions that determine a system’s longevity, scalability, and maintainability. This guide covers the essential terminology and patterns every developer should master.
1. Fundamental Architectural Concepts
Before diving into patterns, we must understand the "physics" of software design.
Cohesion and Coupling
These two concepts define the health of your module boundaries.
- High Cohesion: A module does one thing and does it well. All its parts are closely related.
- Low Coupling: Modules are independent. Changing one should not break others.
Rule of Thumb: Aim for High Cohesion and Low Coupling to ensure your system is easy to refactor.
The CAP Theorem
In distributed systems, you can only guarantee two out of three:
- Consistency: Every read receives the most recent write.
- Availability: Every request receives a response (even if it's not the latest data).
- Partition Tolerance: The system continues to operate despite network failures.
2. Creational Patterns: How Objects are Born
Creational patterns abstract the instantiation process, making a system independent of how its objects are created.
Singleton
Ensures a class has only one instance and provides a global point of access.
- Use Case: Database connections or global configuration objects.
Factory Method
Defines an interface for creating an object but lets subclasses decide which class to instantiate.
- Use Case: A logistics app that creates "Trucks" for land and "Ships" for sea without the main logic knowing the difference.
Builder
Separates the construction of a complex object from its representation.
- Use Case: Creating a
Userobject with 20 optional fields without a "telescoping constructor."
3. Structural Patterns: Organizing Relationships
These patterns explain how to assemble objects and classes into larger structures while keeping them flexible.
Adapter
Allows incompatible interfaces to work together. It acts as a wrapper between two different systems.
- Use Case: Integrating a 3rd-party legacy payment API into your modern TypeScript application.
Decorator
Attaches new behaviors to objects dynamically by placing them inside special wrapper objects.
- Use Case: Adding "Extra Cheese" or "Extra Bacon" functionality to a base
Pizzaobject without creating 50 different classes.
4. Behavioral Patterns: Managing Communication
Behavioral patterns are concerned with algorithms and the assignment of responsibilities between objects.
Observer
Defines a subscription mechanism to notify multiple objects about any events that happen to the object they’re observing.
- Use Case: A "Price Alert" system where 1,000 users are notified when Bitcoin hits a certain price.
Strategy
Defines a family of algorithms and makes them interchangeable.
- Use Case: Switching between "Credit Card," "PayPal," and "Crypto" payment methods at checkout using the same interface.
5. Architectural Styles
While design patterns solve local problems, architectural styles solve global ones.
- Monolithic: A single, unified unit. Simple to start, hard to scale.
- Microservices: An application composed of small, independent services communicating over a network.
- Hexagonal (Ports & Adapters): Decouples the core logic from external tools like DBs or UIs.
Summary Table
| Pattern | Category | Main Intent |
|---|---|---|
| Singleton | Creational | Only one instance exists. |
| Builder | Creational | Step-by-step complex construction. |
| Adapter | Structural | Makes incompatible interfaces talk. |
| Decorator | Structural | Add behavior without inheritance. |
| Strategy | Behavioral | Swap algorithms at runtime. |
| Observer | Behavioral | One-to-many notification. |
Visualizing Architecture
Hexagonal Architecture (Ports and Adapters)

The Layered Pattern
-
Presentation Layer: UI and API Controllers.
-
Business Layer: Core logic and rules.
-
Persistence Layer: Database interactions.
-
Database Layer: The actual data store.
