How does accumulating large amounts of business logic on the model objects make building strong service contracts harder

encapsulationmodelmodelingorm

I heard a couple of times that putting business logic in database models is bad down the road.

I just read this in blog of a Rackspace employee:
The Django ORM also tended to have us accumulate large amounts of business logic on the model objects, which made building strong service contracts even harder.

But it seems logical to me that if you have an Invoice model to encapsulate a lot of invoicing logic there. Seems very similar to what we've been taught in OOP. Could you show me how this is wrong? Please include a practical example if possible.

Benefit of "put logic in models"

What I see as a big benefit of putting logic in models is that users of the models don't have to worry about how they can use stuff, they just use it and it works, can't break anything.

Let me elaborate with an example:
So if you don't put logic in models, then you probably have this code elsewhere, let's say it's in api. If you want to change a state of an Invoice, what do you do? Do you do invoice.state = new_state or do you read the api code to see if there's some method there that changes the state?

This is confusing and error prone. How do you fix this issue then?

Best Answer

Wrong is a big word.
The reason why you shouldn't put it in the DB, is because the vocabulary of (most) DB systems is incredibly limited. There is nothing about "SELECT", "INSERT", "UPDATE", "DELETE" that allows you to fluently express why something is happening and to what it is a reaction, in domain language terms.

As to the second part of your question: the problem with ORMs is that they usually force you to organize your domain objects in ways contrary to what you want.
A simple and common example is that you generally want to encapsulate a lot of stuff inside domain classes, but ORMs need access to the fields and properties of classes to be able to persist them, so you wind up exposing everything, potentially breaking encapsulation.

What I generally tend to find a good idea is to separate your ORM model from your domain model and create a way to inflate domain model objects from ORM model objects.