
Fat Models – A Django Code Organization Strategy - bit2pixel
http://redbeacon.github.io/2014/01/28/Fat-Models-a-Django-Code-Organization-Strategy
======
caseydurfee
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 of a web context, making it impossible to unit test
them, and pretty much wiped out the purpose of the controller as an
encapsulation layer.

Domain-driven design (DDD) provides a lot of patterns that help to keep from
either having model code in your views, or these types of junk drawer models.

Basically, DDD as it applies to MVC webapps is: 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. If it's a business transaction,
create logic objects that encapsulate the biz logic, and service objects that
applies the logic to the models. The controller serves as the broker between
requests, services, and entities. You end up with much more testable and
reusable code this way.

~~~
gasull
The article precisely says you should not pass the request to the models.

~~~
karmajunkie
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.

~~~
ollysb
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.

~~~
singingfish
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.

~~~
collyw
I have most of my logic in the views (because I didn't now any better when
starting my project). I know the Django way suggests fat models (well I know
that now). But is it honestly that big of a deal? I know in my app that any
complex logic will be in the views. What will I gain by following these best
practices?

~~~
singingfish
Yeah, try having a fat controller or view, on a rapidly developing codebase
with poor specs which change mid-project regularly while avoiding getting
fired.

~~~
collyw
Sounds very like my work.

Yeah, schema changes are a pain in the arse, but I don't see that moving my
code from views to models would have a great deal of impact (though I am
gradually moving the code that way when it does need changed).

~~~
singingfish
A better answer is, that you get to decouple the functionality of your
application's business logic from the web portion. This is achieved trivially
purely by applying disciplined coding standards. Removing the web dependency
makes the code much much easier to write automated tests for, and it gives a
sane development path when making minor or major changes to feature sets.

------
unoti
I write my code as if there will be multiple user interfaces. Usually there
are not multiple user interfaces, but thinking as if there will be has a
positive impact on the code. Thinking as if there will be multiple user
interfaces means putting as little code as possible into the views, since
there will be more than one. Some of those user interfaces might not even have
Django views and templates, such as a service exposed via Zero MQ. This
naturally leads me to putting as much logic as I can either into the models,
or sometimes into other modules which in turn use the models. About the only
code that goes into views then is the glue that looks things up and gets
things ready to be passed into a model.

------
edwinnathaniel
I can only shake my head in disbelief when I heard Rails or Django developers
touting their framework and saw their actual codebase (ever see FatCRM
codebase back in the days? it has been improved significantly these days, but
it used to be ... hard to read).

I even shake my head faster when I read the split in opinions in Rails world:
the Rails DHH and the DCI/Service Rails.

Moreover, I keep shaking my head when the Django and Rails community voiced
their complain over their so-called bloated framework just because they want
an API service.

Last but not least, I shake my head again whenever I heard that Django and
Rails is not like NodeJS.

C'mon guys... you guys speak a lot of bad things about JAVA yet you've become
Java Enterprise Edition.

I suppose JavaEE (especially 6 and 7) does work better in terms of writing
maintainable code.

Stuff like Service pattern, Repository pattern, Data mapping pattern, DTO,
Value Objects, Mocking are pretty much "common" in most Java projects I've
seen or worked on.

I felt that no matter how cool Rails and Django are, when it comes to medium-
to-large codebase, Rails/Django are definitely either following the patterns
that pretty much common in JavaEE or may not be so comfortable to use anymore.

------
Daishiman
I honestly think this guy doesn't get it.

The proper way to separate concerns in Django is through applications, which
have their own URL routes, models, and views (although they can invoke any
other thing in another app).

Through Class-based views you can define base views for common behavior for
templates and basic logic, and the built-in views are usually good enough to
contain most patterns and easy enough to customize for any other use case you
might think of.

A good rule of thumb is that an application should generally have less than a
dozen views (I'd say 5 or 6 is enough already). Since each app has its own
forms and models file, adding utility methods in an extra file contained
within an app is reasonable.

I've used this to manage Django apps with over 50.000 lines of custome code
(not counting several dozen extra apps and admin sites with their own
customization) and it has never been a problem.

Fat models are just a massive problem. If Python supported extension methods
then perhaps you could load your own extensions when performing an action, but
a proper design of forms and views that aims for maximum simplity has never
failed me.

------
lgunsch
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.

~~~
secstate
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 misunderstand me,
there's a place for those, but it's easy to get lost on road to abstraction.

Of course, the lesson is that if you're representing complex relationships in
code, the implementation is going to wind up complex to some extent.

~~~
ollysb
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).

~~~
lgunsch
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.

------
salsakran
Not sure I agree with fat models being a "rarely seen, alternative code
organization strategy".

It's a natural state which most django codebases tend towards. There's a
natural Views use ModelForms use Models data flow which leads to bloat
somewhere in that chain as you add code. Fat models are easiest to test and
the natural place to put most things, but eventually massive models get
unwieldly and you start putting things into helpers. The core thing the author
seems to have conflate util functions that have access to a request and
helpers that have no connection to the request/response cycle.

~~~
jscn
In my experience, fat models are the most common approach to organising code
in Django projects. As another comment stated, it's better than having fat
views, but it's not ideal.

------
Demiurge
"Fat" abstract models is the way to go if you have logic that operates on the
data. It's not even fat. There were fields assigned values in the example.
That is exactly what model methods should do.

"Fat" abstract forms is the way to go if your forms have crispy layouts,
placeholder initializers, or other stuff that that directly has to do with
forms.

Views can be easily split into categorical files and shouldn't contain much
logic other than bringing models and presentation together.

Sounds like thinking about what you're doing is the way to go to not have code
get out of hand.

------
mrfusion
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?

~~~
jhh
Personally I would make models a package rather than just a module (since you
sy you have a lot of order related logic). I would create one or more modules
in this package, presumably one of those for orders.

Then I would actually create the base logic which clearly belongs to one Order
instance as methods on the Order class.

If you have something like "can x and y and (...)" be ordered together I would
make an unbound function in your orders module which takes an iterable (Lists
etc.) of Orders and works on it.

Note that I am by no means a Django guru or something like that.

------
davvid
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...](http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-
architecture.html)

------
rartichoke
Does anyone else feel weird knowing that when you call that model method it
may or may not call out to a background worker task?

Why not just throw all of your celery tasks that are related to an app inside
of a worker.py file or something else?

If you import from service.py or worker.py then it becomes obvious the thing
you're doing is happening in the background.

------
mariocesar
Is this article pointing out the most common way of organizing code in Django
as an advice?

I'm such a failure at marketing ... sigh

