There are different opinions about whether we should use defensive programming or not.
I want to give you my point of view about it, but first, I will explain what defensive programing is all about.

According to Wikipedia:
“Defensive programming is a form of defensive design intended to ensure the continuing function of a piece of software in spite of unforeseeable usage of said software.”

I personally think that developers should focus on realizing a defensive programming just in case that they create middleware or code to be used by other people.
In some way, defensive programming is nice to control errors and crashes, that is true, but also is “nice” to hide possible errors.

So, depending whether you are programming an online game where you can receive intruder data because a hack game, or you are writing a piece of code to use within your team (or for an external team) who doesn’t know the implementations details, you should apply techniques of defensive programming or not.

I will show you one example. Imagine that you have an array with several items, or you have references to your items in a map using a item identifier, or whatever.
We could write a piece of code to retrieve the pointer to one item by using defensive programming in the following way:

typedef uint32 TItemId;

Item* getItem( TItemId itemId )
{
Item* ret = 0;

TItemMap::iterator match = mItemInstances.find( itemId );
if( match != mItemInstances.end() )
ret = match->second;

 

 

return ret;
}

What will we achieve with this? In case that we request one item that doesn’t exist, the application will not crash.
But, do you really want this to happen during the development? I mean, why don’t you try to design the program in order to avoid wrong entries in your functions?
Why should you overprotect your code against this kind of “wrong” data?

I would prefer to write something like this:

Item* getItem( TItemId itemId )
{
Item* ret = 0;

TItemMap::iterator match = mItemInstances.find( itemId );
ret = match->second;

 

return ret;
}

We missed the checking about if we reach the end of the iterator.
If we can write our client code in this way, probably our program flow is correct.

We could think about the bad things in defensive programming if we think in some kind of “chain of events”. Imagine that you introduce some input data and to obtain the result of the processing of that data the program takes 5 steps. Well, if in the second step you apply defensive programming, the output data of that step could be something like a “default” value as 0, so, the third step will be executed correctly with that default value and also the fourth and the fifth steps. The result at the end, is a correct flow of our program that “hides” the mistake.

This can be valid when the input data is introduced by the user, but not when the input data comes from other subsystem or from the system itself, that data must be correct inside of the application. You can think in that data as a flow in your system, and the wrong data like a poison in your flow.

A different case appears when we are playing an online game. In that case, you have to take into account that you could receive wrong data from other players because they can hack the game or inject data with sniffers applications into the network. That is a different case and should be studied carefully.

Other different case is when you are preparing a version for testing purposes. This version usually is not executed in a debug enviroment. In that case I highly recommend to include asserts and dump logs to know exactly where the crash was.

If you don’t use defensive programming during the development, when you try to get an item which doesn’t exist, you will obtain a crash. But that is nice, because you can know whether there is some assets missed, or you can know that the input data in that function is wrong for some reason.

Other different cases are related to libraries and middleware. When you design any library or code to be used by other people, you have no idea how they will use it.

In that case, you should control the errors but not hiding them, you should track and trace that kind of errors and provide the user with the information explaining why that entry was wrong.

Finally I have to say that during my career I have found people who think completely different from me. They prefer to use programming defensive during the development. Either way or another, I think that it is an interesting issue to think about. Maybe we should think more about designing before coding in order to avoid using this kind of techniques so frequently :)

Kind Regards