The Mythical Business Layer: This is an exceptionally well-written article from an unlikely source discussing the classic “N-Tier” application structure.
[…] what it really is, however, is a bad design that leads to bad software. Or at the very least, dangerously poor semantics.
Now, multi-tiered applications aren’t bad, but some really stupid code sometimes goes into trying to strictly separate the three tiers — usually defined as (1) presentation, (2) business logic, (3) and persistence. The bottom line is that some code will “drift” between tiers. It may even get duplicated.
[…] it’s completely infeasible to encapsulate an application’s business logic into a single layer. It’s also logically impossible.
One of the example he gives is a company that was determined to keep any logic out the presentation layer at all costs, including form validation and formatting. This excerpt is long, but well-worth reading for the horror factor alone.
While coding the validation rules in the HTML form’s onsubmit() method would most certainly do the trick, the ERE team found that to be completely unacceptable. After all, business logic had no place in the presentation layer.
The answer to that was surprisingly simple. They built a two-way data-binding utility that would save to and load from fields on the business entity with controls on the page. It got pretty tricky when it came to dropdown lists, file uploads, and the like, but they coded around that as well.
As the ERE developers continued on their quest of freeing the presentation layer from business logic, they came across another “problem.” In order to display and constrain certain fields in the user interface, they had to implement business logic. Thing like, the “years old” field should only be two characters big. So they coded around that, too. In addition to a validation rules, the business entity classes returned field lengths so that the presentation layer knew how to size the controls.
And this happens all the time. I’ve even caught myself doing some ridiculous architectural stuff in order to avoid doing anything “improper” in the code.
Using input forms as an example is easy. They’re tedious, similar, repetitive, and they seem to be the first thing that people try to automate.
Data validation, for example, really needs to happen in all three layers.
- The presentation layer should validate the code coming in from the form post.
- The business logic likely has objects with strongly typed variables which again ensure the cleanliness of the data.
- The persistence layer has database fields which also require data to be a particular format.
Is this duplication of effort? Maybe, but what’s the alternative? Someone might try to avoid #1 by moving validation to the business layer — assign the raw form post to some method in the object which passes back an “Error Group” showing all the validation errors, etc.
This might not be so bad, but when do you stop? Just like the example given, soon you feel like having the form input types in the presentation layer is bad, so you move that backwards and generate the form from the object definition, etc.
Soon you realize you’ve removed your presentation layer entirely, and now are deriving everything from the business layer…and by this point you’re sliding so fast down the slope there’s no stopping you.
The value of this is directly proportional to how big your app is. If you have eight hundred different entities, so you’re juggling eight hundred different input forms, perhaps there’s some value in automatically generating as much of the presentation layer as possible. But this is an edge case. Usually you just have a dozen or so entities, so bite the bullet and hand-massage you input forms for the sake of sanity and usability.
The bottom line is that, sometimes, rules and conceptual perfection needs to be broken. And, yes, sometimes an If-Then statement in your HTML is a quick and easy way to solve a problem. Sure, too many of them can be an issue, but the solution isn’t to replace them with a “semantically correct” method that requires capturing an event and casting seven variables in order to duplicate it.