is a good idea, right?
- "The best defense is a good offense." -- Anonymous
Well, maybe. Quite often, DefensiveProgramming
has the effect of ExceptionHiding?
instead of making the bugs obvious. In a production system, this might
be a good thing, in a development system, it is hardly ever.
In "C++ in Action", Bartosz Milewski  suggests using the term OffensiveProgramming
instead. In addition to raising a few eyebrows, it has a different DevelopmentStance
. The Term was independently coined in a 1998 Usenet post: http://groups.google.com/groups?selm=u1g1j4sh5v.fsf%40noisy.vggas.com&output=gplain
This is also referred to as FailFast.
The idea behind DefensiveProgramming
is that you should expect erroneous input to your functions. In languages like CeeLanguage
, where an invalid pointer can wreak havoc, this is very important. DefensiveCoders?
often silently ignore these erroneous situations, or try to compensate for them.
That is pretty much the opposite of what the DefensiveProgramming page actually says. There may be a problem with misapplication of the term "defensive programming", but there's nothing wrong with the idea, which is essentially the same as - or at least consistent with - FailFast, ShipWithAssertionsOn, KeepErrorInformation, etc.
Actually, to the extent that OffensiveProgramming is different from DefensiveProgramming, I think it is simply wrong. Bugs should
not be reported loudly; ReportBugsSilently is better. Also, programs should
not crash, they should fail in a well-defined way that allows a supervisor process to clean up, similar to the error-handling philosophy used in ErlangLanguage. -- DavidSarahHopwood
When you code offensively, you still expect erroneous input, but your treatment of it is quite different. You complain as loudly as you possibly can, to as many channels as you can. Even crashing the program is permitted, as long as you provide a good stack trace. This way, someone must deal with the deep problem, not just patch over the cosmetics. -- JohannesBrodwall
This is the essential premise of exception handling in languages that support it, such as C++ and Java. Instead of merely reporting a problem to its immediate caller via a returned value, a procedure throws an exception that can propagate up outside of the buggy code.
An advantage of exception handling over shutting down upon recognition of an error is that failure can be constrained to the buggy part of the program. (e.g. In a word processor, if an exception is thrown from deep within a printing procedure, that printout can fail without losing the user's hard work.)
Crashing a program on erroneous procedure input is an extreme case of exception handling in which the operator catches the exception. :-)
- Don't silently ignore errors, HidingBugs?
- Don't accept dealing with bugs. Force bugs to be detected and fixed as close to home as possible (or at least closer than with DefensiveProgramming)
- Usually gives simpler code than DefensiveProgramming, as the error checking weeds out the bad situations, instead of compensating for them.
- Errors shipped to the customers will be blatantly obvious, which can make it easier to get management buy-in to fix them.
- Errors shipped to the customers will be blatantly obvious, so the customer will get no results rather than wrong results. It is often better for the customer to be empty-handed than armed with falsehoods. Example: Medical database.
- Errors shipped to the customers will be blatantly obvious: Low quality will be on the surface, visible to everyone.
- May cause production code bugs to crash the system more than what is necessary. (But remember that a crashing program is preferable to a program that corrupts your data)
- In real-time LifeCritical applications, a broken limping program may be better than a crashed one. Example: fly-by-wire software.
is all about choosing where to put your checks, and resilience even has its place. The Usenet post mentioned above was by me and talks bout how OffensiveProgramming
arose at a shop which does indeed write safety-critical systems (the distinction from life-critical is that the system can only kill someone by failing to save their life, if you see what I mean). One benefit of OP there was that there was a monitoring layer which was designed to breathe life back into the crashed system. However, for this to work, the ailing module actually had to die. DefensiveProgramming
would just have concealed the evidence, allowing a duff module to limp along in some unknown half-functional state. Allowing the monitor to kill it off and restart was actually better - so for the affected module to fall on its sword in that case actually *improved* overall reliability. With the added benefit of smoking out the bugs faster, OP was a win both ways. -- JamesYoungman
- You must have control over the code that generates the error. If it is your library that caused your offensively-coded program to barf, you can fix the library. If it is someone else's library, you may be forced to code defensively after all.
I've been using OffensiveProgramming
with my automated test projects. Many testware projects allow any number of tests to fail. They report the passed and failed tests at the end of the test run.
In my experience, sometimes a user forgets to check if a test failed. Sometimes the testware framework fails to report a failed test properly. Sometimes individual tests fail to report a test failure when they detect it.
When I write automated tests, I want the world to stop spinning as soon as any test fails. I want alarm bells to go off, I want the whole project to screech to a halt. Tests written in C++ use assert() to report the error. In VbScript
, and VisualBasic
, I raise/throw an exception. I've seen a few cases where VbScript
has lost a raised exception, so I created a C++ Exitter component so I can stop the program reliably from any component. Exitter calls the C exit() function to terminate the process.
of automated tests gaurantees that I'm never losing ground with respect to the program's functionality. This falls in line with ExtremeProgramming
, although the XP test frameworks I've seen do not stop when the first error occurs. -- EricRunquist
In one project I started to use a more offensive programming style. When an exception occurs, the user will get notified something failed (no details), but at the same time I take a snapshot of the state of the affected object.
I have special objects which I call exception decorators. These will create, when applied to an object, a multiple layers of try/catch blocks.
If the exception is the right type of exception, the decorator will run its code, which can handle it. And if it don't it will send it down, until some exception decorator can. The bottom decorator catches all exceptions. -eg: StockExceptionDecorator?
After this it pulls out the state out of the controller where the exception occured and then stores the state in the database.
Now I can examine the state and design a test, which will trigger the bug. Most of the times.
See also: UseAssertions
 C++ In Action: Industrial-Strength Programming Techniques -
Bartosz Milewski - 2001 - http://www.aw.com/product/0,2627,0201699486,00.html