I should start off by saying I'm not very friendly towards computer methodology purists; those folks that see the world one way and only one way and any deviation from that is a sin against their god and you therefore kill babies in blenders, eat puppies, etc. I usually take the viewpoint of "code has to be written somewhere, might as well write in the location where it is most efficient and where it will get the most use." Unfortunately, throughout history (long), that viewpoint seems to get me into arguments with the purists because some of the time doing so will break one of the rules of their methodology. I guess the best way to explain this would be to look at a strict, multi-tier object oriented structure.
- data service object
- provides standardized properties and methods to data objects to isolate them from the physical RDBMS.
- data object
- creates and uses data service object to
- delete a stored object by unique ID
- create or update a stored object by unique ID
- read a collection of records by unique ID or other searchable field
- map columns to/from business entity properties
- requires a business entity to create, read, update or delete
- creates and returns a collection of business entities for read requests
- business entity
- contains only properties, overriden methods and constructors
- business object
- creates and uses data objects to
- save and delete business entities
- read business entities
- search for business entities by searchable field(s)
- evaluation of business rules
- presentation objects
- create (or not?) and use a business object to
- fetch data that needs to be presented
- evaluate and store data in business entities
Of course, this structure is just one of a couple dozen "standard" ways of implementing this kind of methodology and there are hundreds of books that would support and/or refute line-by-line everything mentioned above but I'll just go with it but keep my points to a minimum so you don't get bored, teary-eyed, listless and then run off to surf porn.
Why must all business logic be in the business object?
Example #1: in a table containing 14.5 million rows you need to update 1 million rows that meet specific criteria. Do you:
- Run a process that creates a business object that creates a data object that retrieves 1 million rows creating a business entity object for each row then returns that collection of objects to the business object which loops through the collection one record at a time making updates to the business entity and using the data object to save the changed business entity (with the data object creating, using then destroying a data service object 1 million and 1 times)?
- Run a process that creates a business object that creates a data object that creates a data service object that tells the database to do the whole damn update?
Of course the answer is "depends, does somebody want a report?" because if that "Coke-bottle glasses wearing paper-hoarding genetic mutation that can find a report from March 4, 1982 in a nine foot stack of green bar" wants a report you really can't just pass the whole event to the database – might as well do the whole object tossing process. However, if you want it done in the most efficient manner possible you go to the database, which is already optimized to do such a thing.
Example #2: you need a collection of objects where the selection criteria are not only in the object but in associated objects with 1-1 and 1-many relationships between the two. Do you:
- Run a process that creates a business object that creates data objects for each type of object then uses the driving data object to retrieve the initial set of data creating a business entity object for each row then returns that collection of objects to the business object which loops through each of them using the associated data objects to create business entities for each associated record evaluating all criteria adding the business entity to another collection of selected records?
- Run a process that creates a business object that creates a data object to fetch a collection of records using pre-defined criteria in both objects to call a database procedure to fetch the result set creating business entities for each row then returning them in a collection to the business object?
If you are the object oriented guru you say the second option, of course.
But I thought rules for valuation and evaluation had to be in the business layer because the database shouldn't know how to calculate a balance or determine how old someone is (it should only know how to handle CRUD). Apparently the duplication of logic and relocation of code is acceptable in this case because it provides a more practical and efficient view of "read only" data (I forget what the actual word for this was but it made me just want to say "why don't you simply it read-only instead of something obscure like neojurassient"). Well why not move update logic to the database as well? "No, no, no that violates the rules of separation of business from persistence" they would say as I cocked my head like a dog trying to equate his owner's noises to "am I going to get fed" or "can I go pee on something".
Example #3: you have your three tier framework as solid as a rock then along comes department X (with the blessing of the CEO behind them) with a completely different architecture written in a completely different language. They need minimal read and update integration with your RDBMS. Do you:
- Count your blessings because you moved such logic to your RDBMS so everybody who needs to use it can use it?
- Create an entirely new layer to interface the two languages?
Of course, you silly fool, the answer is the second one. You write a service and let the foreign system interface with yours using the service. I try to comprehend where the "service" component fits in and my best guess is that it is between the presentation and business logic. I seem to remember Enterprise Java Beans having a similar construct with the "stubs" on the presentation and application tiers talking to each other via RMI (?). Or would the service be a business object? To me the only standard thing between all of these languages and tiers is all of them can talk to a database right out of the box but need a service, web service, RMI, etc. to talk to each other. Seems stupid, doesn't it? I'm not advocating opening up a database to the Internet at all (no way). But it seems like, again, that the higher up the tier the code goes, the more beneficial it is to multiple tiers beneath it and more beneficial to the database in terms of efficiency.
Quote from "Java Enterprise Best Practices"; In spite of my recommendations to avoid stored procedures, there are valid reasons for using them. Specifically, stored procedures can significantly speed up some very complex database operations and encapsulate complex transaction logic. The rule of thumb in these situations is to write the application using prepared statements first and identify the bottlenecks and complexities. Once you have identified them, manage them by moving special cases to the database in the form of stored procedures. If the changes are designed to improve performance and are successful, keep the changes just in those bottlenecks. Also, stored procedures allow the DBA to handle the database logic and allow the programmer to use just the exposed hooks. But, no matter what, never resort to placing business logic into stored procedures!
Okay, just how the hell does this work, add separate code for these cases? Business entities (entity beans in this case) use a persistence manager to load and save themselves. Properties are mapped to/from columns via your code, a meta-data based framework, or by the container. But you still have a one-to-one relationship between "types" of business objects. The "more efficient in this case" stored procedure is going to be doing most if not all of the complex transaction. I assume this involves a number of tables and records at the simplest level (persist all of these records) or some business logic (if this situation exists, do this, etc. in addition to persisting data). Does the business object (session bean) bypass the business entity and perform a direct action through the data service (through a special business entity)?
Does anybody understand why I get frustrated sometimes? It just seems to me that through all of this decoupling, separation and redundancy this whole ideology is adding a lot more physical code, more hardware requirements and the need for more resources to manage the latter with the same amount of direct one-to-one coupling? A lot of the time I think it is the responsibility factor kicking in when I start asking questions about why this framework is better than the other one or why this RDBMS is better than this one or why should we throw money and time into something that is probably replacing something that works but isn't current?