Offensive Programming

DefensiveProgramming 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 [1] 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. :-)


Pros

Cons


OffensiveProgramming 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


Requirements


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, JavaScript, 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.

OffensiveProgramming 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? handles StockExceptions?- 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, OffensiveDefensiveProgramming

References: [1] C++ In Action: Industrial-Strength Programming Techniques - Bartosz Milewski - 2001 - http://www.aw.com/product/0,2627,0201699486,00.html


CategoryDefensiveProgramming

EditText of this page (last edited March 25, 2011) or FindPage with title or text search