Olivier Lowe

Dieser technische Artikel ist auf Englisch verfügbar.

We Said Django Was an Adapter. Prove It.

Calling Django an adapter was an architectural claim. Replacing its HTTP role with Flask was the experiment.

For much of the project, I had been making an architectural claim:

Django was an adapter. It did not own the business.

The structure appeared to support that claim.

HTTP
 ↓
Django / DRF
 ↓
Application
 ↓
Domain

Business rules lived in the Domain. Application operations were expressed through commands and handlers. Django REST Framework translated HTTP requests at the edge.

It looked right. But an architecture diagram is not proof. Neither is putting Django inside a directory named adapters.

So I decided to challenge the claim.

Change One Thing

Instead of rewriting the application with another stack, I changed one variable.

Django / DRF
     ↓
Application
     ↓
Domain
Flask
  ↓
Application
  ↓
Domain

Before implementing the Flask path, I defined the success criterion:

Domain changes      = 0
Application changes = 0

If another HTTP framework forced changes into the business core, then the architecture was telling me something important.

Flask Was Allowed to Be Flask

I did not try to hide Flask behind a universal web-framework abstraction. Flask used Flask concepts:

Blueprint
routes
error handlers
test_client()

Django continued using Django and DRF concepts. The interesting question was not whether framework-specific code existed.

Where did that code stop?

Both HTTP paths eventually had to converge on the same existing Application behavior.

Django ─┐
        ├─→ PlaceOrderCommand
Flask ──┘
              ↓
       existing Application
              ↓
             Domain

No FlaskPlaceOrderCommand. No Flask-specific business rules. No second Domain model.

Then I Tested the Real Path

An adapter test alone was not enough. A mock could prove that Flask called the right handler while still hiding coupling deeper inside the system.

So the stronger experiment used the real path:

Flask
 ↓
real Application
 ↓
real Domain
 ↓
existing persistence
 ↓
Redis

I ran the system test.

1 passed in 0.90s

GREEN. Immediately.

And the success criteria remained:

Domain changes      = 0
Application changes = 0

That immediate GREEN was the interesting result. There was no business-core implementation to fix. The HTTP framework changed without forcing the center to follow it.

What It Proved — and What It Didn't

The result did not mean that Django had disappeared from the system.

Django ORM still participated in persistence. That was a different architectural role and therefore a different experiment.

For the place-order operation, the inbound HTTP framework could change without requiring changes to the Domain or Application.

That is a much more useful claim than saying that the entire application is framework-independent.

Architecture becomes more credible when the conclusion is no larger than the experiment supporting it.

The Lesson

Calling something an adapter is easy. Drawing the arrow is easy. Creating an interface is easy.

Can you replace the thing you claim is replaceable without the business core changing with it?

That experiment changed the way I think about architectural boundaries.

No architectural claim without proof.

CONTINUE THE ARCHITECTURE JOURNEY

The experiment is only part of the story.

This is one experiment from my book Building Software Around the Business — Not Around the Framework — Backend Architecture with Python, Django, and Flask.

In the book, I walk through the complete development path: the first Flask RED, the boundary decisions, error translation, the system-level proof, why Django remained in persistence, and what the experiment still could not prove.

Explore the backend architecture book →