Wellfire Interactive // Expertise for established Django SaaS applications

The module hierarchy and your Django project (This Old Pony #30)

In previous publications I’ve alluded to an app hierarchy in your Django project. Today I want to expand on that a little in the context of a more general module hierarchy, including what it is, and why it matters to your project.

Whenever we started on a new problem in my high school calculus class, our teacher Mr. Brunner would ask, “What do you think we should do?” And he reliably replied to every single suggestion with, “That’s right, draw a picture!

So let’s start with a fancy diagram[0].
 

Diagramming a simple module hierarchy

Super hi-tech enterprise architecture inspired diagram of a Django project's module hierarchy

Keep in mind this is a gross simplification.

It’s divided into three sections. At the top we have Python modules without dependence in any way, shape, or form on Django. Below this section, we have Django, which for our purposes here includes third-party Django modules, i.e. standalone apps. And then lastly we have our own project, including the various locally defined apps (these could also be modules which are _not _apps, but that distinction isn’t critical here).

There are dependencies within each section diagrammed to varying degrees. We’re ignoring Python module dependencies not because they don’t matter but because they’re not the focus. Similarly the dependencies within third-party Django app are important but not something over which you have direct control. 

If we were to represent this as a graph we would not see edges between every node. There may be local Django apps which depend on some third-party Django app which has no dependency on any of our Django-free Python modules, and there may be local Django apps with dependencies on Django-free Python modules but none on any of our third-party Django apps (this, by the way, is important to note).
 

Why it matters: a kitchen experiment

If you don’t cook, assume for a few brief minutes that you do. Summon whatever experience you have of watching Anthony Bourdain and just pretend.

You’re cooking a multi course meal with several dishes going into the main course alone. Your kitchen is limited - one oven, one range, and a more-or-less set dinner time. You may even want to be free before dinner to have a drink and mingle with your guests.

So the question is this: do you prepare and cook everything in exactly the order you intend to serve it, dish by dish? Or do you break steps out based on common ingredients and preparation methods, special clean up[1], cooking and rest times, etc?

If its not your first rodeo you’ll choose the former. You might combine dry spice mixes early on, prep some vegetables and then include the trimmings in the soup that can cook for the duration of prep time…

In short, respecting the hierarchy of tasks in meal prep allows you to parallelize tasks, make use of scarce resources, and in general contract the time otherwise needed to prepare and cook a potentially complicated meal.
 

A mountain still exists even if you don’t have a map

It is so much easier to read the task hierarchy in a single dinner than to identify a clear module hierarchy in a non-trivial Django project.

And as a result many real Django projects powering real applications and real businesses suffer from mixed up hierarchies. It can look like unnecessarily complicated testing or plain old cyclic dependencies, and the result is usually slower development, riskier changes, and an increase in costly complexity.

This is the equivalent of trudging up and down a mountain because your map shows a direct line between points A and B. You can tell yourself its more direct because the mountain isn’t on your map, but you’re still climbing it every day. Once you put the mountain on your map you can decide if it’s better to walk around it, or even tunnel directly under it.

But you need to have it on your map first.
 

Breaking up is hard to do

The upshot is that you probably need to break up monolithic Django apps in your project.

Breaking up Django apps is an excellent way of making them easier to understand, to test, to reuse, and in totality to maintain. It’s much easier to break them up when you understand what the hierarchy should look like in your app.

Separated functionality can become another Django app, a Django-free Python module, or a separately published standalone Django app.

But only once you know that something can be lifted up (e.g. into ‘utils’ in the diagram) or moved laterally can you start executing.

What’s been your biggest challenge digging functionality out of your code? Hit reply, I’d love to hear your perspective.

Laterally yours,
Ben

[0] Yes, this is a photograph of a whiteboard. Somethings are just easier that way.
[1] Getting everything ready ahead of time so you need to touch as little as possible and bleach, bleach, bleach everything after. Trust me.

Learn from more articles like this how to make the most out of your existing Django site.