All posts
Interactive engineering notebook · Swift 6

Where does this
code live?

Most Clean Architecture tutorials hand you a diagram and hope. This one makes you build a ride-sharing app one file at a time and decide, for every piece, which layer it belongs in. Guess. Get it wrong. Watch the dependency arrows turn red. Then never forget.

01 · The map

Four layers, one rule

A pragmatic take, not the textbook five. Use cases fold into Domain; adapters and infrastructure merge into one Data layer. The rule: everything points at Domain, and Domain points at nothing. Organise by feature, not by type. Click any layer to open it up.

Dependencies point inward. Data and Presentation both depend on the Domain core, never on each other. Framework is the replaceable shell the outer layers plug into — and Domain never does.

Framework · replaceable edge
SwiftUIURLSessionMapKitFirebase
Data
RideDTORideAPIRideRepositoryImpl
Domain · the core
RideRideRepositoryRequestRideUseCase
imports nothing
Presentation
RideStoreRequestRideView
Domain
What a ride is, and what you can do with it. Pure Swift, no frameworks.
Data
Talks to the API and turns its messy JSON into clean Rides.
Presentation
The screen. A Store decides what to show; the View just draws it.
Framework
The plug-ins: SwiftUI, URLSession, Firebase. Swappable, and Domain never imports them.

02 · Where does it live?

Guess before you're told

Real problems from the ride-sharing app. Pick where each piece of code belongs. You'll get the reasoning either way — being wrong here is how it sticks.

03 · Build it, one file at a time

Ship “Request Ride,” file by file

Start from an empty project. Each step adds exactly one file, and shows the architect's thought process behind it — the reasoning that turns memorising layers into designing them.

RideShare.xcodeproj
Step 1 / 8 Ride.swift Domain
◆ Architect's thought process
Problem
Question
Answer
Decision
Consequence

04 · Follow the request

Watch a tap flow through every layer

The rider taps “Request.” Step through exactly where control goes, and where a raw JSON payload becomes a clean Ride your UI can trust.

Presentation

05 · Prove it

Place every piece

Drag each component into the layer where it belongs — or tap a piece, then tap a layer. Put URLSession in Domain, or a use case in Presentation, and you'll see exactly why the architecture won't allow it.

0 / 6 placed

06 · How we got here

From massive view controller to clean

Clean Architecture isn't dogma for its own sake. It's the endpoint of a decade of iOS teams feeling the same pain and factoring it out. Watch the coupling drop.

Senior insight · Composition Root Where do all these objects get wired together? Not inside the views. At one Composition Root — typically your App entry point or a per-feature factory — you construct the concrete RideAPI, inject it into RideRepositoryImpl, inject that into RequestRideUseCase, and hand the use case to the RideStore. Every arrow is resolved in exactly one place, so swapping Firebase for Supabase is a one-file change.
Senior insight · Dependency Inversion Why does the protocol live in Domain, not Data? Because the high-level policy (the use case) must not depend on a low-level detail (the API). Both depend on an abstraction — RideRepository — and that abstraction is owned by the inner layer. The concrete implementation in the Data layer conforms up to it. That inversion is the whole trick, and it's the one place a protocol earns its keep.
Senior insight · Actors & offline-first Production reach: make RideRepositoryImpl an actor to serialise cache access without locks, back it with an offline-first store (return cached rides instantly, revalidate in the background via an AsyncStream), and keep all of that invisible to the use case — it still just calls repository.requestRide(...).

Pin board

The rules, on sticky notes

The five things that, if you remember nothing else, keep any codebase clean.

Now design one yourself

You've seen why each layer exists. Want a senior to review your architecture, or run a mock system-design interview on exactly this? First session is free.

Book a free 1:1 Connect on LinkedIn