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?


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.

  • A good suggestion. But do you have a practical example? I think it would also be preferable to have the "inflate domain model objects" functionality built-in, not to have to write it. – duality_ May 26 '14 at 9:28
  • 1
    @duality_ Your domain object would have a method called e.g. "inflate" with an argument of the type of the equivalent orm model object. Inside the inflate() you have access to all the private variables you wish to set and you can just pump the data across. As to your suggestion about having that built in: I would caution against it. I have seen it happen time and time again that people try to generalize mapping stuff right up to the point that they paint themselves in a corner. Don't generalize prematurely. – Stefan Billiet May 26 '14 at 12:40

The problem with Django models (or rails active record its the same pattern) its that this is not a behavior model of your application, its a data model, with this architectures your application are tightly coupled to the database. Problems of this types of applications:

  • The design of the database dominates the design of your application. Normally you end up with one table -> one class.

  • As a consequence of the previous design, when the application grows the "model" classes tend to grow and grow, the typical "fat model" problem.

  • Your business logic and your persistence technology are totally coupled, you cannot change one thing without changing the another.

  • You view the database as a global data storage, you can access every table/model from every point of the application. When the application grows this type of systems are really difficult to maintain because of the highly coupling. Kent Beck wrote about this a long time ago: http://www.threeriversinstitute.org/blog/?p=338 , he call this type of systems "connected" vs a more moduler approach.

For easy database centric applications with not complex domain models Django ORM (or rails active record) can do a good job. The problem is when your system grows, a lot of people in the rails and django community are looking at things like hexagonal architecture or Domain Driven Design for finding ways to deal with complex domain.

For an intro, this is a great talk from matt wayne (cucumber author): http://www.youtube.com/watch?v=CGN4RFkhH2M, its about rails, but, its exactly the same problem.

  • I find the easiest way to ge round this is to put an API layer on your DB, stored procs for example, which allow you to de-couple what the ORM creates and the DB schema. Its not great as you push the API into the DB when really you want it in the DAL, but its good enough for practical purposes. – gbjbaanb Feb 14 '14 at 8:44
  • I prefer the repository pattern from DDD. I usually write a in memory repository (for testing purposes) and then i write a SQL implementation of this repository (or perhaps a no-sql implementation). Other good thing of repository pattern its that you can easily build application with a more polyglot persistence. – AlfredoCasado Feb 14 '14 at 8:47

Its a similar question to "should do you do validation in the presentation layer?"

And the answer is the same - generally business logic needs to go in the middle tier, but there are always exceptions where it is appropriate.

If you're putting a lot of logic in the data layer then you're doing it wrong, you're polluting the data access and retrieval code with a load of other stuff that doesn't belong there and you're writing a client-server style program.

In OO terms, your middle tier should be taking a "raw" Customer data object and a set of Product objects and combining them to produce an Invoice object that is sent downstream. Note that there is no Invoice data directly stored in the DB, just customers, products and their orders.

Its a little bit of a poor example, as apart from combining data into new object there's no business logic being applied (unless you have complicated tax rules maybe) and if all you're doing is jiggling data then its a great example of what should go into the Data layer. A rule of thumb could be "if you have to modify that data then it has to go in the middle tier"

  • I don't think you've properly demonstrated how the question "Should do you do validation in the presentation layer?" is similar to the question asked by the op. If you clarify, I'll vote it up. – Neil Feb 14 '14 at 8:39
  • @Neil - in that many times validation is something that should go in the middle tier too (to be clean) but too often its easier and faster for the user to put the validation code (and the validating data) in the presentation tier too. Its an example of logic being in the wrong place for a clean architecture. – gbjbaanb Feb 14 '14 at 8:42
  • I agree with this sentiment, but before you can use this analogy, you also have to demonstrate why this is bad. Is all I take from this only that you shouldn't do it because it is in the "wrong place" for a clean architecture? – Neil Feb 14 '14 at 8:49
  • Its ok, if its used sparingly - but if you overdo it and put all you validation code there, ytou see it becomes a right old mess of tightly coupled business logic mixed in the presentation layer; just like if you mix all your business logic in the data layer. – gbjbaanb Feb 14 '14 at 9:11
  • Fine, close enough. Edit your answer and I'll vote it up. – Neil Feb 14 '14 at 9:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.