Skip to content

Instantly share code, notes, and snippets.

@hjwp
Last active January 9, 2021 15:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hjwp/70e89d04e9e16d44dd9756ac4c29c6b9 to your computer and use it in GitHub Desktop.
Save hjwp/70e89d04e9e16d44dd9756ac4c29c6b9 to your computer and use it in GitHub Desktop.

How to do clean architecture in Django - some options

Assumptions & Context

Assumes an existing Django app with substantial complexity, and the intuition that "clean architecture" might solve some problems.

Django's sweet spot is rapid application development, CRUD, low to moderate domain complexity / application size.

What problem you are trying to solve?

Usual disclaimer, clean arch isn't a goal in itself.

Slow tests?

Is it slow tests? If that's the only problem, then other solutions could work. Someone wrote a whole book about it

Spaghetti code / big ball of mud?

Does everything depend on everything else, and you don't know where to find stuff, or where to put things?

Option 1: Fat Models & DDD, keep the Django ORM.

As long as you keep the Django ORM your tests will still be slow, but you could get many of the benefits of DDD by just moving as much of the business logic as possible into your models.

Try and sort your models into Value Objects, Entities and Aggregates. You might also be able to identify multiple bounded contexts within your app.

You may also find that you want to split out some sort of layer or abstraction for "use cases", a service layer, in between your views.py and models.py files. Probably not much point in this unless you still find a lot of duplication in your different views, after you've already done the fat models thing. Service layers should be doing "orchestration" not business logic.

Option 2: split out a domain model with no dependencies

This is going to get you the most benefit in terms of getting fast unit tests and being able ot do "proper" DDD, but it's going to cost a lot in terms of boilerplate.

I'm assuming you'll use some sort of repository pattern that ends up doing a lot of work translating from dependency-free domain model objects to django orm models, like the example in the django appendix of the book

Probably you'd want to do this incrementally, start with a small and unimportant model, for practice, and then move onto one where you think you'll get more bang for your buck in terms of managing complexity and speeding up tests. then review and decide if the effor was worth it

Option 3: service-layer first, figure out your use cases

Bob had a lot of success with this in the past. Where there's a lot of complexity in your views, and they seem to be reusing logic from each other a lot, it might be a good way to go... see the separating entangled responsibilities section in the book

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment