Where Does the Business Logic Belong?
logic-Dilemma queries: "I'm currently working in a big project that involves creating tons of reports. These reports require extensively data operation and manipulation in order to be build, and most of that can be handled directly by the DBMS (which would greatly increase performance and implementation time). However, letting all business logic sit in the database implies that we will be extremely attached to one vendor, which kills any attempt at portability. What would you do to tackle this dilemma? Have you ever faced a situation in which the choice between clean design/portability versus performance would change dramatically the whole system design? What have you chosen?"
Follow the priority list and go from there.
If the priority is minimize development time, that might tell you one thing, if it is to maximize portability that might suggest another.
For example if you are a pure Oracle shop, have been for 10 years, would never port off of it - why should you care that your logic is implemented inside Oracle. If you are prototyping on a new database, and have no history with it (or any other product) you had better come up with a different answer
I have mod points and I am not afraid to use them
I should clarify my above point, definitely don't put business logic into the presentation layer of the application.
Couple of things. First off, if you're a publicly traded company go score points with your managers by suggesting that you should talk to the Risk Management and Comp Sec guys at your accounting firm. They'll give you criteria that the project should meet (usually very low impact to implement early but nightmarish to implement later) if you want the data to meet financial disclosure and Sorbains Oxley (SOX) criteria. If you're publicly traded and you don't meet SOX criteria at (or by) the end of this fiscal year then you stand to pay HUGE fines and possibly get de-listed. (Trust me, not meeting SOX criteria by the end of this year would be BAD.)
Business Intelligence and many widespread corporate reporting tools are often subject to SOX regulations. The Risk Management guys will usually have an opinion about the portability vs performance issue for you. (Also, these guys are way way way too busy this year to artificially create more work for themselves. Every publically traded company in the US is trying to get these guys to sign off before the year end.)
Second, look into some of the XML data portability ideas and solutions out there... I can't name anything off the top of my head, but there are companies out there with enterprise and off the shelf data portability options. Also, if you're a flexible development team you probably have someone who can cobble together something good using XML. Google XML Data Portability and you'll get started on pointers.
I think the best place for business logic is the database server.
The COM middle tier business logic MS was promoting in the 90's was a joke. I found it to just be another layer of abstration with no benifit.
If you place everything in stored procedures you get a very centralized app that any client application can connect to (web, java, etc...)
If you're worried about being locked into one DBMS platform, try to write all your queries and stored procs with standard sql. Avoid database specific features, then future migration is easier.
Remember, when you are running a stored procedure, you are ceding control of your application to the database. It may or may not be appropriate to do this. Often this is an issue that doesn't get enough consideration.
It's simple: I demand prosecution for torture.
the answer depends: is your app a product? if so, it should probably support whatever rdbmses that your potential clients use. if it's a custom app for a client, do they use more than one rdbms? these are the only two cases in which it makes sense to spend substantial effort on isolating your database layer. otherwise, take the stored procedures and run -- this is exactly what they were designed for. there are a couple other advantages (other than performance) which may not have been mentioned:
1) abstraction. yes, abstracting the data layer at the database means accepting that you're tied to that database, which isn't a bad thing: i grew up with oracle and still swear by it. as a result, you only write one db layer api, not one per supported dbms per target business logic language.
2) depending on which rdbms and how you set up the user access, you can also probably push a large chunk of the connection pooling onto the db engine rather than having to manage it yourself.
3) access control. microsoft mentioned this several times at their devdays convention. i was surprised that it was news to them (hint: fewer doors means fewer ways in). regardless, it's a good idea: i've always seen allowing execution of arbitrary sql statements by joe random as an invitation for bad things.
4) one place to go to for developer support requests.
hope this helps.
Not only that, the only guarantee is that the business logic will change. In my experience the changes will be somewhere between "modest updates" to "complete rewrite". That means you put them where you can get at them easiest, have the easiest time implementing (i.e. more like Perl or SQL and less like assembly language), will be able to understand/verify/explain what you've coded, where it will look the best if you have to show it to someone else (again, SQL over assembly), etc etc.
In some cases it will be easier to maintain in an application than on the database, in other cases vice versa. Also consider which spot gets you the easiest access to version control. The only other guarantee besides change seems to be the reversed decision.
I do not have a signature
I don't see how putting business rules into the database limits accessability to them. Enterprise applications have database connectors/adapters.
How is a business rule in an application cleaner and "API-like"? Do you mean creating a library (e.g. perl module) of routines that implement policy? How is that "cleaner" than calling a stored procedure in a package? Have you used stored procedures and databases as back ends to applications?
Regarding your last paragraph, that's the whole reason why this topic is here. Everyone knows not to build business rules into the interface. The question is where to put them instead. That's what we are discussing here.
If I can boil down your post, I think you are saying that you prefer coding business logic in a library of a particular language. What language?
So what you're saying is: I don't know about any other databases and have never ported anything from Postgres to anything else, but Postgres supports several languages so it must be portable.
I LOVE Postgres, but the stored procedure portability is not its strong point.
To the best of my knowledge, Oracle and MS-SQL server do not support Perl, TCL, etc. I know Oracle supports Java, but I haven't ventured into that territory.
Oracle uses PL/SQL, MS-SQL server uses T-SQL, and Postgres uses PL/PG-SQL. All of these are different enough that you would have no hope in hell of being able to do a straight recompile. Esepcially when it comes to date handling and things like that each database does it differently.
You will have to decide what's more important: speed or portability. If it's speed, choose the native stored procedures in PL/SQL or whatever your database uses. If portability is your main concern, stick as close as possible to the subset of ANSI SQL that most databases support. Check and see if the SQL constructs you're using work in other commonly used databases.
Finally, keep in mind that Oracle does not have the notion of "databases" the way that MySQL, Postgres, and MS-SQL server do. The closest thing is to have a seperate instance of Oracle running in its own memory space with its own "SID" identifier (Oracle is a wonderful but complex beast!) The reason this may be important is because you might find down the road (as we did) that when you try to mix your 8 unique databases into one Oracle instance that you have conflicting table names. We solved this by putting a three-letter prefix and underscore on each table name to describe what logical application it belongs to. Also, Oracle table names can't be longer than 32 characters, so keep that in mind as well.
My recommendation for portability is to use one database with prefixes on the table names, then have a Perl (Java, whatever you're using) API that returns / accepts the appropriate data structures.
Good luck!
Procedural sql is reasonably portable.
I don't know about other RDBMs, but postgres supports perl, tcl, and others.
That portable enough for ya?
Stupidity is mis-underestimated.
Ahh, there's your problem right there. Now, the reports are static, meaning they are standards, run at specific intervals.
When a business asks for "some reports", it's an indicator that they only have an implicit, at best, understanding of their own business process. They treat the computer as a big bin in which to dump "facts" and generate some output in standard formats which they use to do manual analysis and processing. If your application consists primarily of reports, this is a smell because:
One of the things to realize about reporting is that the type of queries made to a database for reports is very different from the queries made during use of the application.
A solution to your performance problem probably lies in creating some views into your database that represent the data in a less transactional way - create the views such that they are not normalized for transactions but rather for the queries you expect, and the report generation speed problems will take care of itself, and you can leave the business logic code portable.
For example, somebody might want a report like "sales by state", and this report takes age to run against your transactional database because it's normalized for inserting a sale across many tables, and a select to retrieve this data might take a bunch of joins across all tables. If you create views, or replicate the data to another database with a different scheme, your select might be "select * from sales where state=''" and return very quickly.