I’m collecting some posts here that have been lost in the history of the internet. I’ve collected them from the Wayback Maching (archive.org) Here, Here, and Here.
As many of you know, I’ve leveraged and extended “The Eight Fallacies of Distributed Computing” originally created by Peter Deutsch (and extended by James Gosling) to add two more and call them “The Ten Fallacies of Enterprise Computing” for the Effective Enterprise Java book. At the Reston, VA No Fluff Just Stuff Symposium, though, an attendee suggested, in response to an answer I gave, that perhaps I was missing one more, the 11th Fallacy:
11. Business logic can and should be centralized.
The reason this is a fallacy is because the term “business logic” is way too nebulous to nail down correctly, and because business logic tends to stretch out across client-, middle- and server- tiers, as well as across the presentation and data access/storage layers.
This is a hard one to swallow, I’ll grant. Consider, for a moment, a simple business rule: a given person’s name can be no longer than 40 characters. It’s a fairly simple rule, and as such should have a fairly simple answer to the question: Where do we enforce this particular rule? Obviously we have a database schema behind the scenes where the data will be stored, and while we could use tables with every column set to be variable-length strings of up to 2000 characters or so (to allow for maximum flexibility in our storage), most developers choose not to. They’ll cite a whole number of different reasons, but the most obvious one is also the most important–by using relational database constraints, the database can act as an automatic enforcer of business rules, such as the one that requires that names be no longer than 40 characters. Any violation of that rule will result in an error from the database.
Right here, right now, we have a violation of the “centralized business logic” rule. Even if the length of a person’s name isn’t what you consider a business rule, what about the rule stating that a person can have zero to one spouses as part of a family unit? That’s obviously a more complicated rule, and usually results in a foreign key constraint on the database in turn. Another business rule enforced within the database.
Perhaps the rules simply need to stay out of the presentation layer, then. But even here we run into problems–how many of you have used a website application where all validation of form data entry happens on the server (instead of in the browser using script), usually one field at a time? This is the main drawback of enforcing presentation-related business rules at the middle- or server-tiers, in that it requires round trips back and forth to carry out. This hurts both performance and scalability of the system over time, yielding a poorer system as a result.
So where, exactly, did we get this fallacy in the first place? We get it from the old-style client/server applications and systems, where all the rules were sort of jumbled together, typically in the code that ran on the client tier. Then, when business logic code needed to change, it required a complete redeploy of the client-side application that ended up costing a fortune in both time and energy, assuming the change could even be done at all–the worst part was when certain elements of code were replicated multiple times all over the system. Changing one meant having to hunt down every place else a particular rule was–or worse, wasn’t–being implemented.
This isn’t to say that trying to make business logic maintainable over time isn’t a good idea–far from it. But much of the driving force behind “centralize your business logic” was really a shrouded cry for “The Once and Only Once Rule” or the “Don’t Repeat Yourself” principle. The problem is that we just lost sight of the forest for the trees, and ended up trying to obey the letter of the law, rather than its spirit and intentions.
Now, the question remains, is this a fallacy of all enterprise systems, worthy of inclusion in the fallacies list? Or is this just a fragment of something more? Much as I hate to admit it, I’m leaning towards the idea that it’s worthy of inclusion (which means Addison-Wesley is going to kill me for trying to make a change this late in the game).
A couple people have commented on the 11th Fallacy, so I figured I’d respond with further thoughts.
First, Andres Aguiar wrote:
The only way to centralize it is to have the business logic in metadata, or at least the business logic that needs to be defined in multiple layers. You can then interpret the metadata (hard) or do code-generation with it (easy).
Not necessarily, although certainly metadata helps with the sample situation I spun out (that of field lengths and such). What do you do for rules along the lines of “Person.spouse must be in the database and must have Person.gender != this.gender” (that’s a required rule, if our current administration has its way, anyway….)? And this only brings up the simple rules–the more complicated ones simply defy OCL (or any equivalent) or any other imperative language’s ability to centrally define. A declarative language (like OCL) definitely helps here, but it’s still not the silver bullet.
Then, LCS wrote:
Your problem is mixing up logic definition and interpretation. There is no reason why you can’t have a central defintion of business logic, but have it interpreted on different tiers.
Remember to differentiate tiers from layers–depending on what you’re saying here, LCS, I’m either agreeing with you or disagreeing with you, depending on the details of your suggestion. 🙂 Unfortunately, however, I don’t think we’re anywhere close to an ability to define the business rules in one place and have those rules “scatter” throughout the system in a meaningful way–even if the tools existed, they’re pretty easily defeated as soon as you have to interoperate with somebody else’s code and/or programs and/or schemas.
Finally, Giorgio Valoti wrote:
Exactly. The “Once and only once” rule should be valid for the business rules definition, but not for their execution. Indeed, the 40 char max length rule will be probably checked at least twice: from a browser script and from the relational database.
Actually, three times–remember, you can’t always trust that the browser actually did what it was supposed to, so you’ll have to check it when the input comes through the HTTP pipe on the web server tier, as well. (Attackers are always able to fudge up an HTTP packet with Telnet.) But you’re effectively violating the OAOO or DRY rule by validating in three places–or else you’ve somehow managed to create something like what LCS is referring to above, somehow centralizing the rules definition yet somehow spreading it out into the code (and into at least three different forms, too: script, servlet/ASP.NET code, and database schema). I’ve not yet seen the tool that could do that.
Frankly, though, even if said tool did exist, again, we’re defeated by the interop scenarios that are going to become more prevalent as time goes on. More importantly, I’ve never yet run across a situation where all business rules were (or even could be) centralized across the enterprise; across a single stovepipe system, yes, but not across the enterprise or even any meaningful number of systems, for that matter. I’m becoming more and more firmly convinced that this is a legitimate fallacy.
Craig responds to the 11th Fallacy
Craig McClanahan responds:
I believe that it is too strong to call this issue a “fallacy” … but that is mainly because it illustrates a very common trend today of thinking in black and white terms, when the real world has an infinite number of shades of grey :-). The argument to centralize business rules is based in a pragmatic reality — the cost of changing a rule is directly dependent on how many places it is enforced. If a metadata type solution helps you centralize even 50% of your business rules, it is VERY worthwhile, even if it doesn’t deal with the obvious exceptions (“is this credit card number valid” cannot be easily checked by JavaScript running in a client browser). The fact that you can’t centralize *all* business rules is simply reality; it does not invalidate the idea that centralizing where you can reduces maintenance costs, and is therefore useful on its own merits. One of the most popular features of Struts, for example, is the Validator Framework … precisely *because* it allows you to centralize the maintenance of a certain class of business rules (the “40 character name” rule, for example) in one place instead of two. The fact that you need server side validation of this rule (either in the application or the database or both) is obvious. The fact that enforcing the constraint on the client side improves the usability of your application (because the user doesn’t have to wait for the round trip to the server to find out they violated a rule) makes it well worth using metadata to enforce the rule in two different tiers is very much worthwhile, even if it doesn’t cover all possible use cases. Calling this a fallacy, simply because you can’t use it 100% of the time, is somewhere between idealistic and naive.
I disagree, Craig–if you look at the other fallacies on the list (including the original 8), they all basically point out that we can’t make the assumption that something will be true 100% of the time: “The network is reliable”, “The network is secure”, and so on. Frankly, the network IS reliable, most of the time, and frequently there IS just one administrator, and so on. It’s a fallacy to assume that these truths will ALWAYS hold, though, and so we need to code defensively around the idea that they won’t be there. Remember “Deutsch’s Rule” regarding the fallacies: “Essentially everyone, when they first build a distributed application, makes the following N assumptions. All prove to be false in the long run and all cause big trouble and painful learning experiences” (My italics). Such is the same for this one: how many developers haven’t tried to centralize ALL business rules/logic, and discovered that the system proves to be too painful to use and/or maintain as a result? Because we can’t centralize all business logic, we need to design and code around the idea that it won’t be centralized. Or, loosely translated, we shouldn’t try to force-fit logic into the central slot of the system (I hate to use either “tier” or “layer” here, since either or both could very well apply) when it doesn’t make sense to do so.
Does the fallacy imply that we shouldn’t look for ways to beat it? Absolutely. Does that mean we’ll find that way? Probably not–there’s just too much stuff that would need to be done to make it doable.