Architecture Patterns

Master architectural patterns that separate concerns, enforce dependency rules, and build maintainable Python applications that scale from prototype to production

Part of the free Python course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

What You'll Learn

What Is Architecture?

Architecture is how you organize code and responsibilities in an application. It determines where business rules live, how modules depend on each other, and how easy it is to change, test, and extend your system.

❌ Bad Architecture Symptoms

✅ Good Architecture Signs

"God files" with 1000+ lines

Small, focused modules

Business logic mixed with SQL/HTTP

Clear layer boundaries

Can't test without starting servers

Each component testable in isolation

Changing DB breaks half the app

Can swap DB without major rewrites

New features cause ripple effects

Features added without breaking others

MVC Pattern Basics

Model-View-Controller separates an application into three interconnected components:

Model

View

Views should be thin: format and present data, don't implement business rules

Controller

Clean Architecture Core Principle

"Dependencies point inward toward business rules, never outward."

This single rule prevents most long-term maintainability problems. Business logic should never depend on frameworks, databases, or UI code.

The Four Layers

1. Domain / Entities (Core)

Pure business objects and rules. Zero framework or database imports. Contains entities, value objects, and domain services.

2. Application / Use Cases

Orchestrates domain actions. Implements "what happens when..." logic. Defines interfaces (ports) for external dependencies.

3. Infrastructure / Adapters

Implements interfaces defined by inner layers. Contains DB, HTTP clients, file storage, external API wrappers, caching, queues.

4. Interface / Presentation

Entry points: web routes, CLI commands, event handlers, cron jobs. Thin layer that delegates to use cases.

Dependency Inversion Principle

Key Principle: High-level modules should not depend on low-level modules. Both should depend on abstractions (interfaces).

✗ Bad: Direct Dependency

Problem: Use case knows about PostgreSQL. Can't test without DB. Can't switch to MongoDB.

✓ Good: Depend on Abstraction

Benefit: Use case depends on interface. Can test with fakes. Infrastructure is swappable.

Ports and Adapters (Hexagonal)

Hexagonal Architecture formalizes Clean Architecture with two key concepts:

Ports

Abstract interfaces defining what the application needs:

Adapters

Key Benefits

Production Project Structure

A professional Python application typically follows this structure:

Testing Different Layers

Test Type

What It Tests

Speed

Unit

Domain entities, value objects

⚡ Milliseconds

Integration

Use cases with fake repositories

Infrastructure

Adapters with real DB/APIs

🐢 Seconds

E2E

Full system, HTTP → DB

🐌 Minutes

Common Anti-Patterns

Anti-Pattern

The Problem

The Fix

Fat Controller

Route handler does EVERYTHING

Extract logic to use cases

Anemic Domain

Entities are just data bags

Put behavior where data is

DB-Driven Design

Models mirror DB tables

Design domain first, map later

Framework-First

Logic coupled to Django/Flask

Core logic is framework-agnostic

God Object

One class knows everything

Break into focused modules

Refactoring Toward Clean Architecture

When to Use Clean Architecture

✓ Use Clean Architecture When:

⚠ Simple Structure Is Better For:

Choose architecture proportional to your project's expected lifespan and complexity.

Validating Your Architecture

Ask yourself these questions to evaluate your architecture:

Can I change the database without rewriting core logic?

✓ Good architecture isolates DB behind interfaces

Can I test workflows without starting servers or databases?

✓ Use cases should work with fake implementations

Does business logic import framework modules?

✗ Red flag - domain should be framework-agnostic

Is complexity growing linearly or exponentially?

✓ Good architecture scales linearly as features are added

Can I add a CLI interface without touching existing code?

✓ Multiple interfaces should share the same core logic

Key Takeaways

📋 Quick Reference — Architecture Patterns

Pattern

What it achieves

MVC

Separates data, display, and logic

Clean Architecture

Domain core independent of frameworks

Repository Pattern

Abstract data access behind an interface

Dependency Injection

Decouple components for testability

Event-Driven Architecture

Decouple services via events/messages

You can now apply Clean Architecture, MVC, and the Repository Pattern to structure Python apps that scale across teams and years.

Up next: Final Project — bring everything together and build a portfolio-worthy Python project.

Practice quiz

What is the single core rule of Clean Architecture?

  • Dependencies point outward toward the database
  • Every layer can import every other layer
  • Dependencies point inward toward business rules, never outward
  • The UI controls the domain

Answer: Dependencies point inward toward business rules, never outward. Clean Architecture's central rule is that dependencies point inward; business logic never depends on frameworks, DBs, or UI.

In MVC, which component holds the business rules and domain entities?

  • Model
  • View
  • Controller
  • Router

Answer: Model. The Model represents data, validation, and business operations; Views present data and Controllers coordinate.

What should a View do in MVC?

  • Implement business rules
  • Talk directly to the database
  • Validate domain invariants
  • Stay thin — just format and present data

Answer: Stay thin — just format and present data. Views should be thin: they format and present data and leave business rules to the Model.

What does the Dependency Inversion Principle state?

  • High-level modules should import low-level modules directly
  • Both high- and low-level modules should depend on abstractions (interfaces)
  • Interfaces should depend on implementations
  • Avoid all abstractions

Answer: Both high- and low-level modules should depend on abstractions (interfaces). High-level and low-level modules both depend on abstractions, so concrete details become swappable.

In Hexagonal (Ports and Adapters) architecture, what is a 'port'?

  • An abstract interface defining what the application needs
  • A concrete database class
  • A network socket
  • A UI component

Answer: An abstract interface defining what the application needs. Ports are abstract interfaces (e.g. UserRepository, EmailSender) describing required capabilities; adapters implement them.

Which is an example of an 'adapter' for the EmailSender port?

  • EmailSender itself
  • The use case
  • SMTPEmailSender
  • The domain entity

Answer: SMTPEmailSender. Adapters are concrete implementations of ports, such as SMTPEmailSender implementing the EmailSender interface.

What is the recommended order of the four Clean Architecture layers from core outward?

  • Interface → Infrastructure → Application → Domain
  • Domain → Application → Infrastructure → Interface
  • Infrastructure → Domain → Interface → Application
  • Application → Domain → Interface → Infrastructure

Answer: Domain → Application → Infrastructure → Interface. The lesson orders them Domain (core) → Application (use cases) → Infrastructure (adapters) → Interface (entry points).

Why are fake repositories useful when testing use cases?

  • They run faster than real code but break easily
  • They are required for production
  • They replace the domain layer
  • They let you test workflows in milliseconds without a real database or network

Answer: They let you test workflows in milliseconds without a real database or network. Because use cases depend on interfaces, you can inject in-memory fakes and test logic without servers or DBs.

Which is described as an anti-pattern in the lesson?

  • Thin controllers that delegate to use cases
  • An 'anemic domain' where entities are just data bags with no behavior
  • Framework-agnostic core logic
  • Small, focused modules

Answer: An 'anemic domain' where entities are just data bags with no behavior. An anemic domain (entities as mere data bags) is an anti-pattern; behavior should live with the data.

When is a simple structure preferred over full Clean Architecture?

  • Large production apps with many developers
  • Apps needing multiple interfaces
  • Small personal projects, one-off scripts, and short-lived prototypes
  • Compliance-heavy systems

Answer: Small personal projects, one-off scripts, and short-lived prototypes. Clean Architecture adds complexity; for small scripts, MVPs, and prototypes a simple structure is the better fit.

Continue this course