Live data from Hacker News

Fat Models – A Django Code Organization Strategy

redbeacon.github.io

21–30 of 36 posts

Re: Fat Models – A Django Code Organization Strategy

#21

Fat models are slightly better than having that crud in your views, but they're still an antipattern. Models should describe the relationships between entities in your business, not be the junk drawer for stuff that doesn't go anywhere else. Fat models are already a code smell, but passing the request object to your model should really set off alarm bells. You've now made it extremely messy to use your models outside…

"the junk drawer for stuff that doesn't go anywhere else"

I really want to know where to put that stuff. Creating an object to put the "filterBlah" function that you only use once is overkill, so it sits there as a one-off method in your View or Controller or Model. I've worked with large enough code bases for long enough that I know there's always hacky junk there, and I'd just like to know more strategies for addressing it. Do large code bases have a strategy for putting the one-offs in a place where they are obvious and organizable?

I'm now working on a 5M line code base, and at that scale, you kind of have to put the code into acceptable, bad, worse and awful categories and come up with strategies to fix it. There IS no good code at this point. I've actually done refactoring with regexes, but I want better tools for reasoning about extremely large and weird code bases.

Re: Fat Models – A Django Code Organization Strategy

#22
post #18

Earlier quoted context omitted.

That doesn't make it any less of an antipattern. The "fat model" pattern is essentially "if you can't figure out where it goes, put it in the model." In the article's example, the credit card processing code is wrapped up into the quote model. I can't think of a single situation in which this is a good idea.

The "fat model" pattern is simply organising your logic and relationships into the model layer. How well you organise it is up to you. If you just dump things from the controllers into random parts of the model then that's your choice but there are plenty of ways to design it well.

I'm closely involved in a big system that uses Catalyst (perl's nearest equivalent to Django). We spend allmost all of our time in Model classes (MyDomain::Model::Whatever, not MyWebApp::Model::Whatever that's just a dumb connector). It works well and I get the shits every time I have to deal with code that doesn't separate this stuff out properly. Also works on the front end using modern javascript.

Re: Fat Models – A Django Code Organization Strategy

#23
post #21

Fat models are slightly better than having that crud in your views, but they're still an antipattern. Models should describe the relationships between entities in your business, not be the junk drawer for stuff that doesn't go anywhere else. Fat models are already a code smell, but passing the request object to your model should really set off alarm bells. You've now made it extremely messy to use your models outside…

"the junk drawer for stuff that doesn't go anywhere else" I really want to know where to put that stuff. Creating an object to put the "filterBlah" function that you only use once is overkill, so it sits there as a one-off method in your View or Controller or Model. I've worked with large enough code bases for long enough that I know there's always hacky junk there, and I'd just like to know more strategies for addre…

you could simply use unbound functions which you put into a Python module which fits the bill. For example you could create a file services.py - or something more related to your actual domain.

Re: Fat Models – A Django Code Organization Strategy

#24

Fat models are slightly better than having that crud in your views, but they're still an antipattern. Models should describe the relationships between entities in your business, not be the junk drawer for stuff that doesn't go anywhere else. Fat models are already a code smell, but passing the request object to your model should really set off alarm bells. You've now made it extremely messy to use your models outside…

If it's a complex query of some sort, create a query repository that returns model objects rather than a "fat" static method on the model itself.

I believe that the "Django way" of doing that is to have a custom "Manager" class;

https://docs.djangoproject.com/en/1.6/topics/db/managers/#cu... http://zmsmith.com/2010/04/using-custom-django-querysets/

Re: Fat Models – A Django Code Organization Strategy

#26
There is no "one right way", but when thinking about code organization and architecture I find inspiration from the "clean architecture"[1] and similar approaches. The dependency rule can really turn your world upside down!

[1] http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-arch...

Re: Fat Models – A Django Code Organization Strategy

#27
Maybe you guys can help me apply this to an actual Django project I'm working on.

So I made an "Order" model to track orders. But now I have to add a lot of logic regarding things such as what can be ordered together, and which users can order what.

Where you keep that logic? It seems to make sense to me to put it right in the model, no?

Re: Fat Models – A Django Code Organization Strategy

#28
post #21

Fat models are slightly better than having that crud in your views, but they're still an antipattern. Models should describe the relationships between entities in your business, not be the junk drawer for stuff that doesn't go anywhere else. Fat models are already a code smell, but passing the request object to your model should really set off alarm bells. You've now made it extremely messy to use your models outside…

"the junk drawer for stuff that doesn't go anywhere else" I really want to know where to put that stuff. Creating an object to put the "filterBlah" function that you only use once is overkill, so it sits there as a one-off method in your View or Controller or Model. I've worked with large enough code bases for long enough that I know there's always hacky junk there, and I'd just like to know more strategies for addre…

In rails filter functions like that are kept in the model. They're composable and lazily evaluated so you don't really end up with giant, one-off methods. In python I'd expect to find this sort of functionality in a service class (with each domain object having it's own service class).

Re: Fat Models – A Django Code Organization Strategy

#29
post #8
post #5

I would stick with no classes being "fat". Breaking up fat classes into many smaller classes leads to code being really easy to understand, test, and develop. I tend to stick with the Single-Responsibility-Principle and classes do not become unmanageable. Some people argue that many small classes leads to complex code, but I have not found that to be true in any case I have come across.

Ah, but there be monsters in that sea too. I used to subscribe to the many-focused-models camp, but depending on the relationships you're trying to model, that can become damn-near unmaintainable as well. I've actually begun building out more "wide" models, that is, models with a great many fields set to allow null/blank, because mixins and abstract base classes are very hard to maintain 3-4 years out. Don't misunder…

There's another option besides mixins and base classes, composition. You can break your fat model into lots of smaller classes that you aggregate into your original model. The big advantage over using mixins is that the scope is kept much smaller. Keeping scopes small in general is always a good way to scale up to a large codebase (functional languages get this pretty much for free).

Re: Fat Models – A Django Code Organization Strategy

#30
post #29
post #8

Earlier quoted context omitted.

Ah, but there be monsters in that sea too. I used to subscribe to the many-focused-models camp, but depending on the relationships you're trying to model, that can become damn-near unmaintainable as well. I've actually begun building out more "wide" models, that is, models with a great many fields set to allow null/blank, because mixins and abstract base classes are very hard to maintain 3-4 years out. Don't misunder…

There's another option besides mixins and base classes, composition. You can break your fat model into lots of smaller classes that you aggregate into your original model. The big advantage over using mixins is that the scope is kept much smaller. Keeping scopes small in general is always a good way to scale up to a large codebase (functional languages get this pretty much for free).

Yes, I generally stick to composition. "High level" classes end up using a bunch helper classes to perform specialized tasks. I find that I do not often find the need for an abstract base class or mixins, but I will use them if it makes sense.
Post reply on HN