The Eleventh Fallacy of Enterprise Computing

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) HereHere, and Here.

 

 

MONDAY 17 MAY 2004
The 11th Fallacy of Enterprise Computing 

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).

TUESDAY 18 MAY 2004
More on the 11th Fallacy 

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.

 

LogMeIn Ignition for iOS version 3.0.714

I have previously written a review or two for LogMeIn Ignition, discussing some weaknesses of the software, but also talking about the issues there are reporting issues and requesting features from the company.

The recent version of Ignition has added fantastic new features, and fixed some of the defects I’ve talked about in the past. Blogging and tweeting about the issues I’ve found has also gotten me a much better response from the company than I ever received by going through their help desk or forums. It’s good to find that there are people who care about their products at the company.

The new video and audio features are a wonder. The quality isn’t quite as good as Splashtop, but Ignition is a much nicer remote control solution to use. Audio and video quality are high on a WiFi network, but only marginally useful over 3G. Also, I really wish there was an audio-only feature for use on cellular networks where the video was stopped or muted so the audio could use all the bandwidth.

I’m also very happy that the constant failures that occurred during WiFi <-> 3G network changes, which locked the application and required you to force-quit it, have been resolved. Good work guys!

I’m still seeing another couple of bugs that haven’t been resolved in quite some time. The application still blames your phone for connection losses that happen due to normal iOS memory management and multitasking. The errors still constantly ask you to turn off application features (resolution, HD video) even though there is nothing wrong.

You also will likely see some errors that blame the date/time settings on your phone for a bug that occurs on network connections. I’ve reported this one to their help desk a number of times, but they are apparently ‘working on it’. In case anyone is listening, here’s the debug log for the problem, and a screenshot of the error.

The other new feature that has come with the new version is a changed pricing model. Ignition is now completely free. All of the best-in-class remote control functionality I’ve raved about in the past is now completely free. The newer functionality is available for a per-computer subscription cost. You now get a lot more functionality for the same price or less than it came at before. The full Ignition app costs more now (although I’m a happy camper because I bought it at the old price), but you also get the video features without having to pay the subscription costs. If you don’t need all of the features the subscriptions offer, Ignition is still a value at $99.99.

I know there will be lots and lots of complaining about the cost here, but we’re talking about a fantastic product, not a flash-in-the-pan single-feature hit app. You don’t mind paying for a high-quality Apple product that Just Works. This product Works. And we should pay developers for that, or at least respect their right to ask us to pay for their best work. Especially when so much of the good stuff is free.

Custom Tools

I get a big kick out of watching the show How It’s Made. I enjoy learning about the physical engineering concepts used in creating many of the things we take for granted in our lives. Contact lenses. Aluminum foil. Pencils.

The other thing I get enthralled in is the mind-boggling use of specialized equipment for creating these objects. I don’t know if I ever really thought about how a big bakery made bread, but I’m sure I thought that I’d see something that resembled an oven in the process somewhere. And maybe a guy with a spatula on a pole, like at the pizza parlor. A real bakery looks nothing like that. It’s all custom-built equipment that is designed for nothing but mixing, balling, raising, cooking, cooling, cutting, and bagging bread. Very few human hands are involved, and somebody has clearly been thinking about ways to make it faster and cheaper for quite a long time.

So, why is it that we approach our development and IT tasks as if each one is a heirloom chest of drawers that needs to be chiseled out from the hewn oak with our bare, expert hands?

LogMeIn Ignition 2.1.321 for iPhone and iPad

I have gotten in the habit of writing scathing reviews of LogMeIn Ignition. It’s been a little while, and I missed a version, so I thought I’d spend a little time raking them over the coals again. What I discovered surprised me. I can no longer reproduce the problems I was seeing in the last couple of versions. Maybe they fixed it! Or possibly upgrading to an iPhone 4s is how you avoid the bugs.

After my last review (and a tweet mentioning it) I got a flurry of response from LogMeIn support and customer relations. Unfortunately, after a few conversations, and providing detailed notes as well as client logs of the failures, I fell off their radar again. I am going to raise my App Store rating a star, since I can’t find the bugs for now….but I’m still terribly disappointed by the responsiveness of their support team.

  • Talking to their help desk is like arguing with pigeons. Each new one wants to start the conversation over. Usually with a form-letter FAQ.
  • Talking on their forums is simply a waste of keyboard life. They rarely even come and read or respond in their forums. Let alone fix things that are mentioned there.

I really want to see LogMeIn be the best product on the market. They have the programmers and technology to do it. It just looks like those people are surrounded by people who don’t care about the product or customers.

I see a number of quality reviews in the App Store that echo these sentiments.

I’ve said it before, and I’ll say it again:

LogMeIn is the best…But their support is very poor. And this version of the app is buggy as hell.

I have spent literally thousands of dollars on LogMeIn services. They have the best remote control platform in the world. That said, I’m a small customer for them, and it is very clear that their support for small customers is in the “ignore them until they go away” category.

I wish things were different.

LogMeIn Inition 2.1.299 for iPhone and iPad Review

LogMeIn is the best…But their support is very poor. And this version of the app is buggy as hell.

I have spent literally thousands of dollars on LogMeIn services. They have the best remote control platform in the world. That said, I’m a small customer for them, and it is very clear that their support for small customers is in the “ignore them until they go away” category.

I have spent extensive time documenting and reporting the memory management and connectivity problems with this version (other people are reporting these issues here in the reviews). I get a new person on each email, and most of them let me know that problems can be temporarily fixed by rebooting my iPad. Great.

Issue 1: Try Closing the LogMeIn application in your app tray. Then connect to LMI _using 3g only_. Hit the home button. Connect to WiFi. Try using LMI again. That’s right. It’s hung until you re-kill the app, or restart your iPad.

Issue 2: Try connecting to a computer on LMI. Then go to a couple other memory-intensive applications, like games or opening a lot of pages in Safari. Go back to LMI. You’ll find it disconnected. That’s fine…it would be nice if it automatically reconnected, but not everything needs to be perfect. However, when you log back into LMI, it will inform you that your screen resolution was too high. In fact, it reports that your screen resolution is too high _for any type of crash at all_! Bad memory handling and failure to respond to iOS termination events is not a good reason to blame your user for ‘doing it wrong’.

Issue 3: It is possible to follow a repeatable set of steps that hangs the app until you force-quit it in the app tray.

Their forums are completely ignored by employees as well.

I recently downgraded my Ignition App to the october and now it is fast again, and it doesnt crash constantly either.

If you are stuck with the new version, reboot or kill the app every crash and you can use it.

Ignition is worth every penny when it works, and they clearly have some software guys who know their business.

Too bad they are saddled with a sales and support organization that doesn’t have the time or inclination to talk to users.

Two Way Bindings in JavaScript

jQuery Templates are fantastic! They provide an easy way to render your data from JavaScript to HTML.

I’ve written a simple jQuery.tmpl() implementation on JSFIDDLE to show the basics.

It is also easy to use nested templates to simplify rendering and to repeat the template over the contents of an array. Another example displays a nested template using an array of objects.

jQuery Templates also provides a mechanism for updating the data that is rendered out.

However, this feature has a problem. In this sample, I have made the “update” button dynamic using jQuery. But go ahead and click it and see what happens. It loses the cool styling and hover events. Why? Because jQuery.tmpl re-renders it’s templates and REPLACES the version on the page with a new one when you call .update();

So, jQuery.tmpl doesn’t keep the connections to your cool UI Widgets. That’s a hassle, but not too bad.

It does get bad when the user starts interacting with your template-rendered HTML. Imagine a page where there is a list of items, that can be expanded when the user wants to see details. Imagine also that the user can enter information into fields for each item. Then the user hits the sort button.

BAM! The template gets re-rendered. All the user’s expansions are lost. All the user’s entries are lost. AND you still have to reconnect all your widgets. Nasty.

Now, here’s my advice. When you have a programming problem that’s all nasty and thorny…don’t write code! Programming is easy because there are people much smarter than us that have already written the solutions for most problems.

Templates have a problem. jQuery doesn’t fix it. I’m sure somebody else has solved this problem. Let’s find them.

Today the answer is knockout.js by Steve Sanderson.

Our problem is that while jQuery.tmpl makes it easy to go from JavaScript to HTML, it does nothing for going from HTML to JavaScript. Knockout encapsulates jQuery.tmpl and extends it to provide the full round trip.

Read the excellent documentation, check out the live samples, and listen to Steve’s interview with Scott Hanselman

I’ve made the ‘Hello World‘ sample from the Knockout.js site available on JSFIDDLE, go and play with it a bit, and see what you can make it do.

A Survey of Javascript Thought

Frameworks

Knowledge

People, Podasts, and News

Tools

Careers

Interface Segregation Principle

Before the Kurukshetra War, Lord Krishna had a conversation with Arjuna, one of the things he said:

Therefore I tell you: be humble, be harmless, have no pretension, be upright, forbearing, serve your teacher in true obedience, keeping the mind and the body in cleanness, tranquil, steadfast, Master of ego, standing apart from the things of the senses, free from self; aware of the weakness in mortal nature, its bondage to birth, age, suffering, dying;

One of the wonderful results of writing about right coding and better code philosophy is the oportunities it provides to be humble. I frequently write bad code and don’t follow the principles I know to be correct.

First, let’s define the Interface Segregation Principle (see the excellent Uncle Bob Article)

Clients should not be forced to depend upon interfaces that they do not use.

Frequently, when you look at C# code, you’ll see interfaces defined that have a lot of members defined (Try implementing a Forms Authentication Provider and you’ll see what I mean!). The downside of this is that it’s confusing for the client to know which methods to use. It also forces each alternate implementation of the interface to implement a bunch of methods that maybe are not relevant (in the example of forms authentication, you have to handle email addresses even if you only want to implement a username/password).

The Interface Segregation Principle suggest sthat our interfaces should be simpler and more focused, supplying only the members needed for a specific use. If one object implements more than one interface, that’s fine, but an object that supports multiple uses should provide targeted interfaces for each of those uses.

Let’s look at how I violated this principle in the my UI code:

Each endpoint on the Login Controller has a corresponding method on the interface. It’s impossible to change our just one implementation. You have to provide a replacement for the whole login service in order to implement any changes.

The fix is easy:

And suddenly, each individual service can be swapped out separately. It’s also much easier for me to refactor my LoginService implementation to comply with the Open-Closed Principle and Single Responsibility Principle.

There is always room for better code, and the SOLID principles are wonderful tools in learning to write better patterns.

Dependency Injection Principle

Remote controls are fantastic. The ability to stand over here and control something over there is like magic. Since the first remote controls, which only controlled a single device, were made we’ve extended the idea of the remote control quite a bit. Your remote for your TV can control your Blu-Ray player. You can buy a remote control from Logitech that can be programmed to turn on your TV, set the sound on your stereo, and dim the lights in your TV room….all at the press of one button. You can buy a keychain remote control that turns off all the TVs in a restaurant or bar. In the movies, Adam Sandler made a movie where he found a remote control that controls the whole universe.

The magic of remote controls is in the gap between the controller and the thing controlled. There isn’t a wire. They are not wired together. They are loosely coupled.

We have a good habit of loosely coupling the top side of our code. Anybody can call one of our methods. They aren’t hard wired for only one consumer.

However, on the underside of our code, we fail to couple loosely. We create new instances of database connections and proxy classes. We use Static methods to get resources and get information from the server context. Each time we do this, we break the magic of the remote control. These tight couplings prevent us from changing the implementation of our dependencies (the database connections, proxy classes, and resource systems).

The Dependency Injection Principle protects us from our urges to tightly couple to our dependencies. It states:

1. High Level Modules Should Not Depend Upon Low Level Modules. Both Should Depend Upon Abstractions.

2. Abstractions Should Not Depend Upon Details. Details Should Depend Upon Abstractions.

Frequently, Dependency Injection is implemented by using the constructor. In our classes constructor, we pass in references to the database connection or service proxy. This provides the loose coupling in one easy step. Using a IOC container, like Autofac or StructureMap then automates constructing the object by providing a central point where we can define all those dependencies and compose them into objects.

If you’d like to know more, read the excellent Uncle Bob article.

Liskov Substitution Principle

If you were an infantryman in the 14th century, charging up a hill with your rifle (they weren’t really called rifles yet, but let’s not quibble), you’d not only have to deal with the mud and the thunder of the battlefield, but the difficult task of reloading your rifle. Powder. Padding. Bullet. Wadding. Priming. Worst of all, eventually you’d put your hand into your bullet pouch, and find it empty.

Once that happened, you were done shooting for the day. You couldn’t borrow a bullet from the guy next to you. It either wouldn’t fit, or it would cause your gun to explode. You see, each and every rifle in use by your army had been made by hand, and no two barrels were the same. You had to find a bullet that would fit, and that took some time. Eventually with bore width for gun barrels was standardized, even centuries before Honore Blanc demonstrated the first true interchangeable parts to Thomas Jefferson. Today, we take it as a given that we can use similar parts interchangeably without risk, but that’s due to centuries of effort to make sure that our common assumptions are followed by everyone.

In software, the Liskov Substitution Principle is meant to bring the same benefits to our code. It states that Methods that use references to base classes must be able to use objects of derived classes without knowing it. This is a simple concept, but it is easy to accidentally violate the principle if you don’t give sufficient thought to your derived classes.

An obvious failing is to not use virtual/override keywords on your methods. This would mean your subclass code never gets called when someone is using a reference to the base class. A more significant issue is when the subclass changes behavior in a way that violates the assumptions of the base class. “Square” could be a subclass of “Rectangle”, but when you change the height of a square, the width changes automatically. This is not true of a rectangle. Unintended side effects can break your code at runtime, often unpredictably. Following the Liskov Substitution Principle means you can avoid some problems. (If you want to research more, the Uncle Bob article is great, and “Design By Contract” is a similar concept with a lot of coverage.)

Commonly we use the language feature of inheritance for things that it was not designed for. If you need to re-use code, there are other ways of including it than putting it in a base class, composition is frequently better than inheritance. Similarly, polymorphism can be made more granular by implementing interfaces, rather than having a over-broad base class that may or may not be fully implemented by its inheritors.