Hacker News new | ask | show | jobs
by samwillis 1653 days ago
I'm unconvinced by the "skinny models" and "service layer" arguments. Django's ORM is an active record style ORM, its at its best if you use it that way. If you want to have a service layer type architecture, use SqlAlchemy with implements the data mapper scheme.

I follow this general rule of thumb, in order:

If it's a complicated business logic touching multiple models or external apis, put in in a `utils` module (keeping this sensibly organised by model/role/activity depending on what you are building, i.e. utils.{model_name}.{methods} or utils.{e.g. order_processing/email/accounts}.{methods}). You can add a shortcut to it as a method on the model if this makes sence. (some may argue this is a service layer)

If I'm only doing something once in one place (in one view), then keep the logic there.

If it's a custom create method, stick it on the models manager class.

If it's something you want to do to a set of objects (from a query set), put it on the manager class or a QuerySet subclass (to make it chain-able).

If you haven't put it elsewhere put it on the model class, as a method or a property if it seems cleaner (don't do get_... and set_... use a property)

1 comments

The argument is that Active Record is itself a bad pattern that you should not use. And it may be. But it might be a long way down the runway before you run into the bad effects.
Yes, exactly, I agree there are valid arguments against active record, partially at scale. However, I believe, certainly when starting out on a new project/startup, sticking with the standard recommendations and patterns provided in the docs for Django and DRF you make life much easer for on boarding new people to the project later on - they will have seen it all before.

If you get big enough where the standard patterns don't work anymore, YAY! you got big, celebrate! Then start looking at how to refactor for easer maintainability for your specific use case and scale.

The problem I tend to see is that the refactoring never happens. Instead the system becomes the legacy mess nobody wants to work on and eventually it gets replaced. If you get lucky, it'll be replaced by the people who wrote the first version, but it's more likely to be replaced by a team who weren't there when the first one was built, who will build it in this-year's-shiny, without learning the fundamental lessons of why the first version ended up that way so doom the next version to a similar fate.