Urban Legends and Error Handling
We have all heard those stories that begin with "I know somebody" or "I have heard of somebody" before. You can never tell whether the story being told is true or just an urban legend. But then again, I guess that's the whole point of an urban legend.
I could swear that I know somebody who knows somebody who has travelled the USA in an RV a few years back. Horror movie fans might already be predicting a gruesome end to this story, but don't worry – nobody is going to get hurt in this column. You can continue reading this story to your children (as always, right?).
The tourists in their RV were on their way to Las Vegas, starting out from south of the Grand Canyon. If you're not familiar with the area, you may not realise that it is not possible to cross the Grand Canyon by car, a hard limit that is non-negotiable.
So when it comes to planning your route, you are somewhat limited in the choice of roads that you can take. Now the big mistake that the tourists made was that they did not take into account that, due to the size of their car, they might not be able to use every available road.
In due course, they ended up in front of an underpass which their vehicle could not fit through. They had to back up for several hours to find an alternative route and basically lost a whole day. Given the fact that they were heading for Las Vegas, "the adults playground", this might have saved them a fortune, or have cost them a fortune if they had thrown a quarter into the slot machine and won the jackpot. You never know.
Ending up in such a situation is not the fault of the underpass: the error, made somewhere upstream, merely shows up right when approaching the underpass, and is usually difficult (or at least tedious) to handle.
PHP as a programming language, just like any dynamic language, may at first appear to not need overly strict validations of data. Validation of data, however, is directly related to error handling: If data is invalid, this should be an error or an exception (if you write OOP code, which you should be doing). This error needs to be handled somewhere.
In most cases a failed validation, at least from the viewpoint of the business or domain logic, means that the application programmer has allowed the code to pass on an invalid value. Since the application code should not have done this, the application is probably missing validation code. The main difference between application code and domain logic in performing validations is that application code will usually validate all data fields, and collect multiple "error messages", while domain logic will throw an exception immediately on the first failed validation.
So when did the error occur in the scenario described above? The error showed up at runtime when a user entered invalid data. However, the mistake was in fact made far earlier, when the developer wrote the application's validation code. And, as with all errors that are discovered late in the process, error handling is tedious: The only way to deal with the described problem at runtime would be to translate the exception to some kind of "please correct this form field" message.
This way of looking at a runtime error might not feel natural to you. Maybe this is because in real life it is such a common pattern to deal with errors long after they occurred. Let’s create a brand new urban legend of our own to illustrate this.
Imagine you are a truck driver on a German Autobahn, proudly driving a gigantic 50-ton plus super-truck. You will soon reach your final destination (on time, as usual). Not too far ahead you can see a beautiful suspension bridge spanning across a wide river valley. You are just about to make dinner plans when you pass a sign informing you that on the bridge, there is a weight limit of 18 tons for individual vehicles. Wait, 18 tons? Your super truck weighs over 50 tons. Before you hit the brakes, let us freeze the scene and think for a moment.
A problem has just arisen, a consequence of an error that occurred much earlier when you were planning the trip. What options are there to handle that error right now?
You can drive on and hope that the bridge withholds the weight of your truck. If the bridge collapses as you drive over it, you will most certainly die, and probably leave it up to your family to buy a new bridge. This does not sound like a good option. The bridge might hold, but since urban legends traditionally never have happy endings ... well. Let’s just assume that you have already spotted a police inspection right after the bridge, even if you manage to cross the bridge, you will lose your license forever, so driving on is absolutely out of question.
Your only option right now is to hit the brakes and stop. But what next? You are on a highway, so you cannot just turn and go back. Driving in reverse on an Autobahn is forbidden by law, for very good reasons. So are you going to unload your truck, right on the Autobahn, or even dismantle it? You might ask the police to stop all traffic and block a whole section of the highway so that you can go back. While this might be the only viable option, you are most certainly not going to make a whole lot of new friends on the way. And you will probably leave your boss with an enormous bill when the police charge you for their expenses. Guess which salary that bill is going to be deducted from!
In real life, the only way to avoid situations like this is to be very, very careful when planning a trip (or not to drive anywhere, which is somehow problematic if you make a living from driving). In software development, it is crucial that you handle any errors as soon as they occur. This requires you to actually realize that an error has occurred. In the above example, at some point in the planning process, the business rule "the road has to support the vehicle" is violated. If that business rule does not exist, you are very likely to run into serious trouble at some point in the future. One could argue whether a violated business rule is in fact an error – I would say it is not. The actual error occurs if there is no rule in the first place.
To sum it up, knowing and documenting all requirements and restrictions is the key to success. And the best documentation I can imagine is working code, because this does not only make your specification executable, but also guarantees that your documentation is in sync with the code and thus never lies.
This article originally appeared in Web & PHP magazine.