By Peter Bell

Moving Business Logic to the Database

Should you move more of your business logic out into your db? After some recent comments on a very old posting I wanted to revisit the benefits and downsides of such an approach.

Firstly, if you're likely to be changing db vendors (data sets are getting large and you're considering Oracle, or licensing costs are an issue so you're considering moving from MSSQL to MySQL, for example), keep the db dumb. However, on the other hand if you are considering changing scripting language (or using multiple), having more logic in the db might allow you to make such changes more easily.

Also, if you work in a larger shop where you don't have permission to deploy stored procedures and UDFs without review by a DBA, that might make coding in the db impractical (depending on how responsive the DBAs are).

If you're looking for optimal performance, putting the code in the db may make sense, but for most applications, trading off maintainability for performance is almost always a bad choice, so unless you know you're going to have a performance problem, don't move code to the db just to try to speed up your app. It just isn't worth it.

In general I like to keep my code in a 3GL like ColdFusion. It means I can write OO code which gives me lots of tools for writing maintainable code. I get decent code completion and it's easy to set up unit testing. It's easy to put the code into subversion, and I have a wide range of encapsulation and reuse mechanisms for keeping my code readable and DRY.

Of course, you can get some of that in T-SQL (or your dialect of choice). There is no reason why you can't write UDFs, I'm hoping IDE support for SQL is improving, you can (and should) put all of your SQL scripts into source control and automate the running of them as part of your build process. I still don't feel like putting substantial code into SQL is as easy or maintainable as keeping it in (say) ColdFusion, but I'd love to hear below if anyone has managed to create a setup that allows them to write equally maintainable code in SQL as in CF.

In my use case (being able to generate thousands of web applications quickly and cost effectively), I tend to value consistency and development efficiency over optimization of other criteria. If I only built five or ten projects a year, I might decide on a case by case basis what to implement in SQL and what to put in ColdFusion (and I might move away from a 1:1:1 relationship between business objects, service classes and DAOs). In my use case there just isn't a justifiable business ROI on the effort required to think about the trade offs every time. I use a heuristic that I'll put all code in the 3GL and for the kind of projects I build it works quite well. Why didn't I decide to move things like getter and setter logic to the db? Here's why . . .

At first it seems like a no brainer to move some code into the db. Want User.FullName? Just create a view with a field that concatenates first name and last name and you're done. Returning User.Age based on the tbl_User.DateofBirth column is a little more work - but not much.

However, what happens for a getPrice() method for a product where the price depends on the total orders by that user over the last rolling 12 month period and those of all of the other users within their buying group - requiring complex joins between multiple order item and order user, user group and various discount group tables? From a performance perspective you could argue that it will probably be more performant in SQL, but if there is a lot of conditional logic in addition to the set based operations, you might want to be able to break down the code into component parts and while UDFs and SP's calling SPs can be used, I'd rather keep such complex business logic in my 3GL programming/scripting languages.

However, some would look at that and think it was a perfect example of the benefits of putting business logic within SQL as it will be more performant and available independent of the programming language you choose to use. The final nail in the coffin (for me) was when I asked, what if the smart getter needs to access third party web services? For example, I want to be able to getShippingPrice() for an order and that is going to require either finding a way to write a SP that can call a web service (which even if possible is something most supporters of SQL would probably agree isn't exactly what it was designed for).

I decided for my use case to go for a consistency of having all of my business logic (including smart getters and setters and data validation) within my business objects. If performance was a concern or consistency wasn't such a big thing for my specific use case I can understand why someone would decide to put some of that logic in SQL and why it could be a valid choice, but I think it's important to think through all of the implications.

What do you think? Do you put business logic in the db? If so what (and if not, why not?). What are the rules of thumb you use for deciding what goes in the db?

Comments
I look at it from a separation of concerns view point. The primary "concern" of the database is data persistence. It serves no other purpose. In a "perfect" world, we wouldn't even need databases - applications would just boot up and every object would be loaded into RAM and no database layer would ever even be needed.

The database serves only to allow the user to move from one application/page load to another without losing information. By putting business logic into the database, you are now making it more than just an area of persistence - you are making it an integral part of the application functioning.
# Posted By Ben Nadel | 3/21/08 9:42 AM
Personally the only time business logic should be in the database is when you can put it in a view. My reason for this is simple with 99% of the database out there, you can move your views between them since views are just SQL. It's when you start to create stored procedures and udfs within your database that I draw the line. Stored procedures and UDFs written for MSSQL will not work on Oracle without porting them.

Using views for your application's business logic has the benefits that you mentioned, performance being the main one. This is why my next release of ICEGen will include the ability to link views to your objects. I'm surprises that other ORMs never thought of this since a mature ORM would benefit greatly from it.
# Posted By tony petruzzi | 3/21/08 10:26 AM
I rely on my database to enforce core datatypes as well as foreign key restraints.

As data is commonly an organization's most valuable asset, I'd have a hard time recommending that those be moved into a higher tier.

I would put as much business logic in my database which was easily importable/exportable to every other mainstream database platform. The trick is defining what one consider's "easy".
# Posted By Scott Fitchet | 3/21/08 12:19 PM
I side on keeping business logic out of the database, if for no other reason than for lack of unit testing. Most languages now days have some kind of unit testing framework, but I have never heard of one for SQL.
# Posted By Mike Lowry | 3/21/08 2:25 PM
I let the db do what it does best, store and aggregate data and that is about it. Yes we do some procs to maintain the data integrity but I tend to side on the application tier for business logic also.

I can scale my application tier a lot easier and cheaper than my db tier.
# Posted By RyanTJ | 3/21/08 2:45 PM
In general I agree with the position of using the DB more like just a container of data and also, as mentioned before, like a "last line of defense" for ensuring data integrity (via foreign keys, constraints, etc), this way you can be 100% sure that all data that is stored is "good data".

However, one aspect in which databases still hold an upper hand over application code is when it comes to reporting. Sometimes reports can be really complex in the sense that they aggregate tens of tables in complex joins and aggregations involving hundreds or thousands of rows. This is something for which database systems (especially the big ones Oracle, MySQL, MSSQL) have been completely optimized for, and will provide a performance orders of magnitude greater than what can be achieved through ColdFusion.
# Posted By Oscar Arevalo | 3/21/08 5:43 PM
One problem with treating your database as a dumb container of data that I've discovered is that it makes it difficult to paginate over data. Using your example with price calculation above, how do you get records 11-20 from the database, ordered by price, if you're doing the calculation in ColdFusion?

I wish I had an elegant solution for that one as it would probably make me switch over entirely to the "database is dumb" camp :)
# Posted By Per Djurner | 3/23/08 9:50 AM
@Per, As with everything. there's a degree of pragmatism. In MS SQL server I have a generalized paging stored procedure which I use for returning paginated lists. Another approach for some use cases is to cache the data set in application scope, and of course, with some database query languages you can just use built in SQL commands so you can handle paginated lists (I'm pretty sure MySQL and Postgres - not sure about Oracle).
# Posted By Peter Bell | 3/23/08 10:50 AM
@Per,

You can still do pagination in SQL but keep the business logic in your "application" by doing pagination in your data retrieval queries. For example, I consider the code I write in a CFQuery tag to still be inside the app, not the DB since I am dynamically generating it with ColdFusion.
# Posted By Ben Nadel | 3/24/08 7:44 AM
I've tried it both ways. My preference for new development is in the 3GL, while when I've got to maintain code, I don't mind it being in stored procs in the DB, as it gives me less to look at when tracing through the 3GL side of the app.

I sure could use some better tool support on the SQL side though.
# Posted By Sammy Larbi | 3/26/08 9:41 AM
So, what if you have multiple applications pointed at your database, or batch jobs running against it (written in your db's language), or if you want to maintain your data with something like SQL*Plus/SQL Advantage/SQL Analyzer? Putting your business logic in the database, esp table triggers, allows you to build once, and then every application can experience the benefit.
# Posted By Starsky | 3/26/08 10:59 AM
BlogCFC was created by Raymond Camden. This blog is running version 5.005.