# Clean Architecture Based on Robert C. Martin's *Clean Architecture*. Apply these principles when designing systems, services, and infrastructure — including Helm chart structure and Kubernetes deployments. --- ## The Dependency Rule **Source code dependencies point only inward.** Inner layers define interfaces; outer layers implement them. ``` [ Frameworks & Drivers ] ← outermost: UI, DB, APIs, Helm, K8s [ Interface Adapters ] ← controllers, presenters, gateways [ Use Cases ] ← application business rules [ Entities ] ← enterprise business rules (innermost) ``` - Inner layers know nothing about outer layers - Data crossing a boundary is always in the form the inner layer prefers — never a raw DB row or HTTP request object - If an outer layer changes (swap MySQL for Postgres, REST for gRPC), the inner layers are untouched ## Layers ### Entities — Core Business Rules - Enterprise-wide business objects with their validation and invariants - Pure domain models: no framework imports, no DB annotations, no HTTP concepts - Stable — change only if fundamental business rules change ### Use Cases — Application Business Rules - Orchestrate entities to fulfil one actor's goal: `TransferMoneyUseCase`, `ProvisionClusterUseCase` - Define input/output via interfaces owned by this layer — no knowledge of controllers or DB implementations - One use case = one reason to exist ### Interface Adapters - Convert data between use cases and the outside world - Controllers translate HTTP/CLI input → use case input models - Gateways implement repository interfaces defined by use cases - Presenters format use case output → UI/API response format ### Frameworks & Drivers - The outermost ring: web frameworks, ORMs, message brokers, Kubernetes, Helm - These are details — they plug into the system via the adapters; the core doesn't know they exist ## SOLID as the Foundation - **SRP** — one module, one actor, one reason to change - **OCP** — extend behaviour through new implementations, not modification of existing code - **LSP** — subtypes must honour the contracts of their interfaces - **ISP** — prefer narrow, focused interfaces over fat ones - **DIP** — high-level policy depends on abstractions; low-level detail implements them ## Boundaries - Boundaries are where the power lives — they isolate components so that one side can change without affecting the other - Define boundaries at the most volatile points: DB, UI, external services - Cross a boundary only via an interface; never pass a concrete type across ## What This Means in Practice - Business rules have no imports from frameworks, ORMs, or infrastructure libraries - Tests of use cases and entities need no running database, no HTTP server, no cluster - Swapping the database or the delivery mechanism (REST → gRPC, monolith → microservices) touches only the outer rings - "Screaming architecture" — the top-level structure should reflect the use cases, not the framework: `invoice/`, `user/`, `payment/` not `controllers/`, `models/`, `views/` --- ## In Helm and Kubernetes Clean Architecture applies to how infrastructure is organised, not just application code. **Helm charts are the outermost layer — they are the delivery mechanism, not the system.** - A chart should deploy exactly one service or one cohesive unit — not a bundle of unrelated things - Business rules belong in application config (`values.yaml` keys mapped to env vars); they must not be hardcoded in templates - Separate concerns across charts: one chart for the app, separate charts (or dependencies) for databases, queues, and shared infrastructure - A chart change (resource limits, replica count, ingress rules) must never require touching application business logic - Use `_helpers.tpl` as the adapter layer — it translates chart-level abstractions into Kubernetes primitives; templates themselves stay thin - Environments (`values-dev.yaml`, `values-prod.yaml`) are driver-layer configuration — they override defaults without touching templates - Test charts with `helm template` + schema validation; business logic is tested independently of the chart **Dependency Rule for Helm:** - App charts depend on library charts, not the reverse - Library charts define interfaces (helpers, common labels); app charts implement them - Avoid circular chart dependencies — they indicate a missing layer or a misplaced responsibility