Software crash on LandingGear->Deploy()
Referencing and de-referencing objects in an Object Oriented Environment can be a challenge.
These are real life examples; the names of the objects have been changed to preserve the identity of the victims. Please fasten your seat belt.
When I take an airplane, I cannot help but think of all the poor programming practices I have witnessed -some committed by myself- over the years. I often wonder if the on-board computers have been programmed by my earlier engineering peers.
1. A short Object Oriented Programming Refresher
1.1 Object Inheritance
Say you have three classes. An airplane, a commercial airliner and a private jet. We can all agree that both the jet and the airliner are kinds of airplanes.
This is the basis of object-oriented development. You model abstract objects after entities in the real world.
1.2. Object Properties
Say that an airplane has landing gear, I reckon all airplanes have landing gear. Assuming we are not discussing here the very specific case of hydroplanes, the gear (at least a generic one) should probably belong to the airplane object.
1.3. Inherited Properties
So in the real world, having landing gear is not particularly specific to the private jet or the commercial airliner. Being fitted with landing gear, retractable or not, is general to all airplanes.
1.4. Class Members
The landing gear, in itself, can be a pretty complex device.
-
Member variables
It has members that remember states, such as stowed away vs. ready for landing.
Example: isReady -
Member methods
It also has functions, which generally, but not always, will change its state. Such functions can be deploy vs. stow.
Example: Deploy()
This is where encapsulating functionality into an object starts to make a lot of sense. You need not to know the specifics of how a mechanism (or an algorithm) is implemented. You only need to know how to invoke it: in this example, it’s Deploy().
1.5. Delegate Behavior
In this simplified model, it matters not which kind of airplane you fly. All you need to do is to flip a switch to initiate the landing procedure, and the airplane object just “knows” what to do.
1.6. Larger Picture
![]()
2. A Programming Error Crash Course: Dont’ fly with those!
I have gathered below a few errors I have seen in the past. Do not try this at home!
![]()
2.1. public static
BAD:
// Whenever needed
if( nil == Airplane.staticLandingGear) {
Airplane.staticLandingGear = create an instance of LandingGear
}
... followed somewhere upon destruction of the object:
// Upon desctruction of the creator
if( nil != Airplane.staticLandingGear) {
delete Airplane.staticLandingGear;
Airplane.staticLandingGear = nil;
}
While this may look proper at first glance, and possibly even work depending on the situation, I have seen this code create havoc when placed in the “Private Jet” or “Commercial Airliner” sub-class. Create more than one plane and you have a disaster.
BETTER:
// Whenever needed
aLandingGear = Airplane.getLandingGear();
... and the LandingGear instance in turn created and maintained by a singleton
getLandingGear()
{
// Ensures only one LandingGear instance exists
if( nil == staticLandingGear) {
staticLandingGear = create a unique instance of LandingGear
}
return staticLandingGear;
}
- Problem:
More than one object may destroy the public static variable
- Suggestion:
Use a singleton and a private static.
![]()
2.2. silent error
BAD:
if( nil != aLandingGear) {
aLandingGear.Deploy();
}
Defensive programming has it’s price. In this case, the software will not crash if the LandingGear object does not exist. Good.
Conversely, the plane will crash because no landing gear has been deployed. Bad.
This situation could have been detected early on if the software had not failed silently during the development phase, before it was deployed.
BETTER:
assert( aLandingGear); // Will alert QA that something went terribly wrong
if( nil != aLandingGear) {
aLandingGear.Deploy();
} else {
// Something is terribly wrong and we should not be there
startEmergencyProcedure();
}
- Problem:
Failure goes undetected and unreported during development
- Suggestion:
Use assert() and error_log() to report unexpected conditions
![]()
2.3. uninitialized object
For this example, assume that the landing gear needs to be connected to an airplane.
BAD:
if( ! aLandingGear) {
aLandingGear = new LandingGear();
}
// The app will not crash, because aLandingGear exists
aLandingGear->Deploy(); // Will do nothing. Plane will crash!
If an object MUST be initialized, one possibility is to make the default constructor private
BETTER:
if( ! aLandingGear) {
aLandingGear = new LandingGear( anAirplane);
}
- Problem:
Failure to initialize an object
- Suggestion:
Make constructor private to force the use of proper initializer, otherwise source code will not compile in the first place.
![]()
2.4. A bug? Which bug? I didn’t see a bug.
I will conclude with my favorite quote from an engineer with whom I do not share the view. I can see the benefits and even possibly some logic behind it, but this is why I hate to fly.
If a bug cannot occur, it is not a bug.
W.W.
I guess that I am not inclined to take the risk; a condition could have been overlooked, or simply created at a later maintenance stage. New situations will arise as the software evolves, and code that was once safe may be misunderstood and misused. From the same engineer, I’ve also heard this:
W.W.
No comment.
![]()
