Complete Guide | Lesson 11: Polymorphism → Lesson 12: Architecture → Lesson 13: Hidden Knowledge (Jun 18)
You can design a building from the penthouse down or from the foundation up. Great architects do both simultaneously.
Every lesson in this series has been building toward this one. Pseudocode taught you to think (Lesson 1). Objects taught you to see (Lesson 2). Types gave you atoms (Lesson 3). Classes gave you blueprints (Lesson 4). Inheritance and composition gave you relationships (Lesson 5). Interfaces gave you contracts (Lesson 6). SOLID gave you discipline (Lesson 7). Patterns gave you vocabulary (Lesson 8). Generics gave you reusability (Lesson 9). Normalization gave you data integrity (Lesson 10). Polymorphism gave you the runtime mechanism (Lesson 11).
Now, in Lesson 12, all of it materializes into a working system.
This lesson maps to Malkuth on the Tree of Life. Malkuth means "The Kingdom." It's the final sephira, where all the abstract spiritual forces above condense into physical reality. The idea becomes a thing. The design becomes a building. The architecture becomes running software.
Top-Down vs Bottom-Up: Two Ways to Build
Top-Down: Start With the Vision
Top-down design begins with the big picture and decomposes into smaller pieces. This is the Lesson 1 decomposition skill applied at the system level.
"We need an e-commerce platform" becomes:
- We need a product catalog
- We need a shopping cart
- We need a checkout and payment system
- We need user accounts
- We need order tracking
- We need an admin panel
Each of those decomposes further. "Product catalog" becomes: product listing, search, filtering, categories, product detail pages, image management, inventory tracking.
Strength: You always have a clear vision of where you're going. Risk: Analysis paralysis. You spend six months designing and zero months building. The design is beautiful. The codebase is empty.
Bottom-Up: Start With the Bricks
Bottom-up design starts with small, tested, working components and composes them into larger systems. Build a brick. Then a wall. Then a room. Then a building.
You build a Product class that works perfectly. You build a Cart that holds products. You build a PaymentService interface with a Stripe implementation. Each piece works in isolation. Then you connect them.
Strength: You have working code from day one. Each component is tested in isolation. Risk: Components that don't fit together. You built a beautiful engine, transmission, and body, but they don't connect because nobody drew the full car first.
The Pragmatic Approach
Real architects do both: sketch top-down, build bottom-up, iterate.
- Sketch the high-level modules and their interactions (top-down, 1 hour)
- Build the smallest module that delivers value (bottom-up, 1 day)
- Connect it to the next module, discover what the sketch missed
- Revise the sketch based on what you learned
- Repeat until the system works
Layered Architecture: The Foundation Pattern
The most fundamental architectural pattern is layers. Every system you've ever used is built in layers, whether the developers intended it or not.
1┌─────────────────────────────┐
2│ Presentation Layer │ ← What the user sees (UI, API endpoints)
3├─────────────────────────────┤
4│ Business Logic Layer │ ← Rules and decisions (calculate tax, validate order)
5├─────────────────────────────┤
6│ Data Access Layer │ ← Talk to the database (Repository pattern, Lesson 9)
7├─────────────────────────────┤
8│ Database / Storage │ ← Where data lives (normalized tables, Lesson 10)
9└─────────────────────────────┘The rule: Each layer talks only to the layer directly below it. The Presentation layer never touches the database. The Business Logic layer never renders HTML. The Data Access layer never validates business rules.
Why? Because when you swap PostgreSQL for MongoDB (Data Access change), the Business Logic and Presentation layers don't know and don't care. When you add a mobile app (new Presentation layer), the Business Logic stays identical. Layers are SOLID's Dependency Inversion (Lesson 7) applied at the system level.
MVC: Model-View-Controller
The most widely used architectural pattern in web development. Every web framework you've heard of (Rails, Django, Spring, ASP.NET MVC, Laravel) implements some version of MVC.
Model: The data and business rules. Your classes, your domain objects, your normalized database (Lessons 3, 4, 10).
View: What the user sees. HTML, CSS, templates, mobile UI. No business logic here.
Controller: The traffic cop. Receives a user request, asks the Model for data, passes it to the View, returns the response.
1User clicks "Buy" → Controller receives request
2Controller → Model: "Process this order"
3Model → Controller: "Order #1234 confirmed"
4Controller → View: "Show confirmation page"
5View → User: "Thank you for your purchase!"MVC Flow
User → Controller (handles the request) → Model (applies business rules, accesses data) → Controller (receives result) → View (renders output) → User (sees the result). The Controller never generates HTML. The Model never talks to the user. The View never queries the database. Separation of concerns at the architectural level.
MVVM (Model-View-ViewModel) is MVC's evolution for reactive UI frameworks. The ViewModel acts as a data-binding layer: when the Model changes, the View updates automatically. Used in WPF, SwiftUI, Vue.js, Angular.
Clean Architecture: Dependencies Point Inward
Robert C. Martin's Clean Architecture takes layering to its logical conclusion: the innermost layer (your business rules) has zero dependencies on anything external. No framework imports. No database drivers. No HTTP libraries. Pure domain logic.
1┌─────────────────────────────────┐
2│ Frameworks & Drivers │ ← Web, DB, UI (outermost)
3│ ┌───────────────────────────┐ │
4│ │ Interface Adapters │ │ ← Controllers, Presenters, Gateways
5│ │ ┌─────────────────────┐ │ │
6│ │ │ Use Cases │ │ │ ← Application-specific business rules
7│ │ │ ┌───────────────┐ │ │ │
8│ │ │ │ Entities │ │ │ │ ← Core business rules (innermost)
9│ │ │ └───────────────┘ │ │ │
10│ │ └─────────────────────┘ │ │
11│ └───────────────────────────┘ │
12└─────────────────────────────────┘Dependencies ALWAYS point inward. Entities know nothing about Use Cases. Use Cases know nothing about Controllers. Controllers know nothing about which web framework serves them.
Why this matters: your core business logic (the valuable stuff) is completely portable. Switch from Express to Fastify? Only the outer ring changes. Move from MySQL to DynamoDB? Only the gateway adapter changes. Your business rules never know the difference.
Microservices vs Monoliths: The Great Debate
The Monolith (Start Here)
A monolith is a single deployable unit containing your entire application. One codebase, one build, one deployment.
Pros: Simple to develop, simple to deploy, simple to debug. One database, one log file, one process. Refactoring is a find-and-replace away.
Cons: As it grows, modules become entangled. Deployment means redeploying everything. Scaling means scaling everything, even if only one feature is under load.
Microservices (Graduate to Here When You Must)
Microservices split each bounded context into its own independently deployable service. Catalog Service. Order Service. Payment Service. User Service. Each has its own database, its own API, its own deployment pipeline.
Pros: Independent scaling, independent deployment, independent technology choices. The Catalog team uses Python. The Payment team uses Go. Neither needs to coordinate deployments.
Cons: Network latency between services. Distributed transactions are exponentially harder. Debugging requires tracing requests across multiple services. Deployment requires container orchestration (Kubernetes). Observability requires distributed tracing (Jaeger, Zipkin).
The Monolith-First Rule
Martin Fowler and Sam Newman (the microservices advocates themselves) recommend starting with a monolith. Build your domain. Discover your boundaries. When a specific module needs independent scaling or team ownership, extract it. Premature microservices cause more pain than premature optimization.
API Design: Contracts Between Systems
Whether your system is a monolith with internal modules or microservices talking over the network, the interfaces between them are APIs. Good API design mirrors good interface design from Lesson 6: clear, consistent, and hard to misuse.
REST (The Standard)
REST uses HTTP verbs and resource URLs:
1GET /api/products → List all products
2GET /api/products/42 → Get product #42
3POST /api/products → Create a new product
4PUT /api/products/42 → Update product #42
5DELETE /api/products/42 → Delete product #42The verbs tell you the action. The URL tells you the resource. Status codes tell you the result (200 OK, 201 Created, 404 Not Found, 500 Server Error).
Putting It All Together: E-Commerce Architecture
Let's design a system using everything from the series:
Bounded contexts (decomposition from Lesson 1):
- Catalog (products, categories, search)
- Cart (items, quantities, pricing)
- Orders (checkout, confirmation, history)
- Payments (charge, refund, balance)
- Users (auth, profiles, preferences)
Each context uses:
- Types and classes (Lessons 3-4) for domain models
- Interfaces (Lesson 6) between layers
- SOLID principles (Lesson 7) for module boundaries
- Patterns (Lesson 8): Repository for data access, Factory for object creation, Observer for events
- Generics (Lesson 9): Repository
, Repository - Normalized data (Lesson 10): 3NF for core tables
- Polymorphism (Lesson 11): IPaymentService with Stripe/PayPal/Crypto implementations
Architecture: Layered monolith with clear module boundaries. REST API for the frontend. Each module follows Clean Architecture internally.
"The goal of software architecture is to minimize the human resources required to build and maintain the required system." Robert C. Martin, Clean Architecture. Everything in this lesson serves that goal: minimize the cost of change.