12

In the perfect application every business rule would exist only once.

I work for a shop that enforces business rules in as much as possible in the database. In many cases to achieve a better user experience we're performing identical validations on the client side. Not very DRY. Being a SPOT purist, I hate this.

On the other end of the spectrum, some shops create dumb databases (the Rails community leans in this direction) and relegate the business logic to a separate tier. But even with this tack, some validation logic ends up repeated client side.

To further complicate the matter, I understand why the database should be treated as a fortress and so I agree that validations be enforced/repeated at the database.

Trying to enforce validations in one spot isn't easy in light of conflicting concerns -- stay DRY, keep the database a fortress, and provide a good user experience. I have some idea for overcoming this issue, but I imagine there are better.

Can we balance these conflicting concerns in a DRY manner?

Community
  • 1
  • 1
Mario
  • 6,572
  • 3
  • 42
  • 74

6 Answers6

7

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
  • 94,695
  • 15
  • 113
  • 186
  • 3
    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 Mar 31 '10 at 20:14
  • 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 Mar 31 '10 at 21:55
  • 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 Apr 05 '10 at 14:17
  • "Databases are affected by many more sources than the application" All of the other "sources" that are affecting your database need to be going through the business layer of the application. If you have multiple applications (with different business layers) accessing the same database, you are doing it wrong. – RepDetec Jan 13 '11 at 19:39
6

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
  • 384,516
  • 81
  • 508
  • 779
4

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
  • 18,113
  • 4
  • 33
  • 52
0

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
  • 14,201
  • 3
  • 42
  • 77
0

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
  • 10,017
  • 5
  • 38
  • 51
0

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

Stephan Eggermont
  • 15,847
  • 1
  • 38
  • 65