Re: Changing Organizations
Posted: Apr 18, 2006 5:15 PM
> The constraints should be as close to the data as
> possible. Where we can we put it right on the data and let
> the DBMS take care of making sure bad data doesn't get
> into the database. However, there is a lot that we want to
> do with the data besides shuttle it into and out of the
> database. There seems to be a never ending debate about
> whether you should use the DBMS tools (stored procedures
> and triggers, mainly) to apply business logic to the data
> or whether this logic should be in some middle layer. I'm
> firmly in the camp that says this logic should be
> somewhere else. You'll need more than pithy quotes to
> convince me otherwise.
I don't have a requirement to support lots of databases, though I do keep in mind we may want to upgrade from Postgres to Oracle or some other commercial database someday. Nevertheless, enforcing constraints on data is one area where I believe in violating the DRY (Don't Repeat Yourself) principle.
One of the things I thought was hacky from the Pragmatic Programmers' Agile Programming with Rails book was how they, in the name of the DRY principle, check for valid data (such as non-null, etc.) in the entity layer of the application. If there's a problem, they throw an exception with a message that gets shown on the UI to the user. So the entity layer is providing (non-localized in this case) user interface messages.
I think that error messages that show up in the user interface should really originate in the user interface layer. In our case these will be localizable. I think working with the user to get valid input is a conversation, a potentially different process than simply checking data for correctness before persisting. So we do checking in the user interface layer.
But I also think the entity layer should be checking too. Because it shouldn't let anything pass. Here I just throw exceptions, because a pre-condition of calling into these APIs is that the passed data is valid.
But I also really think it is useful to have those constraints checked again by the DBMS itself, both as an extra check in case there's a bug in a higher layer, and because that one application isn't the only way to get data into the database. The database may outlive that application. Other applications may be added that also access the same data. Admins may tweak things with an SQL interpreter, and so on. Right now in Artima's new architecture I'm only doing things like non-null, foreign key, or unique, easy things that don't require writing any stored procedures. But I'm tempted to use stored procedures for certain simple cases that we can declare in our entity DSLs, such as a positive number, or a valid user name, or valid email address. Bad data, when it slips into the database, can cause application failures and cost money to clean up.
These constraints are, in my mind, part of the business logic. So I believe it is useful to have some business logic there in the database, even if the vast majority of business logic is in the application itself. Certainly things like unique, non-null, and foriegn keys, which are very easy to use declaratively, cost little and help a lot.