views:

219

answers:

6

I periodically ponder how to best design an application whose every business rule exists in just a single location. (While I know there is no proverbial “best way” and that designs are situational, people must have a leaning toward one practice or another.) I work for a shop where they prefer to house as much of the business rules as possible in the database. This requires developers in many cases to perform identical front-end validations to avoid sending data to the database that will result in an exception—not very DRY. It grates me anytime I find myself duplicating any kind of logic—even lowly validation logic. I am a single-point-of-truth purist to an anal degree.

On the other end of the spectrum, I know of shops that create dumb databases (the Rails community leans in this direction) and handle all of the business logic in a separate tier (in Rails the models would house “most” of this). Note the word “most” which implies that some business logic does end up spilling into other places (in Rails it might spill over into the controllers). In way, a clean separation of concerns where all business logic exists in a single core location is a Utopian fantasy that’s hard to uphold (n-tiered architecture or not).

Furthermore, I see the “Database as a fortress” and would agree that it should be built on constraints that cause it to reject bad data. As such, I hold principles that cause a degree of angst as I attempt to balance them.

How do you balance the database-as-a-fortress view with the desire to have a single-point-of-truth?

+6  A: 

Anyone who doesn't enforce the required business rules in the database where they belong is going to have bad data, simple as that. Data integrity is the job of the database. Databases are affected by many more sources than the application and to put required rules in the application only is short-sighted. If you do this you will get bad data from imports, from other applications when they connect, from ad hoc queries to fix large amounts of data (think increasing all the prices by 10%), etc. It is foolish in the extreme to enforce rules only through an application. But then again, I'm the person who has to fix the bad data that gets into poorly designed databases where application developers think they should do stuff only in the application.

The data will live on long past the application in many cases. You lose the rules when this happens as well.

HLGEM
The easy way to have **all** these problems is to break the architecture, bypassing the business rule layer that was put outside the database. The easy way to prevent these problems is to make "direct" access to the database grounds for dismissal.
S.Lott
Strongly disagree. I'm not importing a million targets one record at a time using the application. Nor should I do a major data update that way.
HLGEM
Are you proposing importing a million records with complete data validation done in the database? How does that work? Stored procedures? Isn't that terribly slow? Or does some validation step have to get run first before loading? I don't understand what you're proposing.
S.Lott
A: 

The Model-View-Controller framework is one way to solve this issue. The rails community uses a similar concept...

The basic idea is that all business logic is handled in the controller, and where rules need to be applied in the view or model they are passed into it by the controller.

chills42
+3  A: 

In way, a clean separation of concerns where all business logic exists in a single core location is a Utopian fantasy that’s hard to uphold

Can't see why.

handle all of the business logic in a separate tier (in Rails the models would house “most” of this)

Correct. Django does this also.

some business logic does end up spilling into other places (in Rails it might spill over into the controllers

Not really. The business logic can -- and should -- be in the model tier. Some of it will be encoded as methods of classes, libraries, and other bundles of logic that can be used elsewhere. Django does this with Form objects that validate input. These come from the model, but are used as part of the front-end HTML as well as any bulk loads.

There's no reason for business logic to be defined elsewhere. It can be used in other tiers, but it should be defined in the model.

Use an ORM layer to generate the SQL from the model. Everything in one place.

[database] built on constraints that cause it to reject bad data

I think that's a misreading the Database As A Fortress post. It says "A solid data model", "reject data that does not belong, and to prevent relationships that do not make sense". These are simple declarative referential integrity.

An ORM layer can generate this from the model.

S.Lott
A: 

Well, in general, business rules are much more than sets of constraints, so it's obvious not all business rules can be placed in the database. On the other hand, HLGEM pointed out that it's naive to expect the application to handle all data validation: I can confirm this from experience.

I don't think there's a nice way to put all of the business rules in one place and have them applied on the client, the server side and the database. I live with business rules at the entity level (as hibernate recreates them at the database level) and the remaining rules at the service level.

Tomislav Nakic-Alfirevic
+2  A: 

The concerns of database-as-a-fortress and single-point-of-truth are one and the same thing. They are not mutually exclusive. And so there is no need what so ever to "balance them".

What you call "database-as-a-fortress" really is the only possible way to implement single-point-of-truth.

"database-as-a-fortress" is a good thing. It means that the database forces anyone to stay away who does not want to comply (to the truth that the database is supposed to adhere to). That so many people find that a problem (rather than the solution that it really is), says everything about how the majority of database users thinks about the importance of "truth" (as opposed to "I have this shit load of objects I need to persist, and I just want the database to do that despite any business rule what so ever.").

Erwin Smout
A: 

Database-as-a-fortress is nonsense for relational databases. You need an OODB for that.

Stephan Eggermont