Saturday, June 16, 2007 3:11 PM Olaf Conijn

Paranoid Programmers

Most people should be familiar with the term “defensive programming”. It’s a way of writing code, in which the default mode is to explicitly check all assumptions you have in mind while writing logic (most of the time throwing exceptions to the caller).Though, when does this make sense?

Assume you are developing a framework, application host or plug-in to an application host. How sure are you all the assumptions you have in mind hold, once having released whatever you are working on “out in the wild”?

What if a “friendly hacker” wants to exploit some unforeseen extensibility point in your framework, making it do cool stuff beyond something you thought was possible… would that be gain or loss in value for your framework?
Think of all the mash-ups people made against google maps, flicker, whatever web 2.0 stuff is out there. Or extensions made to “application hosts” such as the Visual Studio Shell (soon to be released and positioned as a true application host!).

My default mode is different: I won’t check assumptions I have when coding, “unless …”:

- I am exposing some surface of an application to whomever (for instance a public service boundary, user input, whatever “unfriendly hackers” could exploit to do bad things).

- I am shielding from conditions that simply cannot be handled gracefully (and will throw an exception anyways). Most of which can be done through basic parameter guarding.

-Etc

When exposing a public API I’d love to have people do whatever they think makes sense.
In return, whatever I expose meets some basic assumptions, around stuff like thread-safety, security and in general its behaviour (implied through convention or somehow more explicit).
If something is not thread-safe or possibly unsecure it should not be part of the public API.

Example would be a pattern such as:
FooBar foo = bar.GetContextualSomething() as FooBar;
if (foo != null) // whatever ContextualSomething I get back, my logic only applies on a FooBar
{
foo.DoStuff();
}

I agree that having an API that works regardless of how it is called wouldn't make sense either, though the consumers of a framework know the problem they are trying to solve best. So why not give them the benefit of doubt?

Filed under:

# » Paranoid Programmers

Saturday, June 16, 2007 8:35 PM by » Paranoid Programmers

Pingback from  » Paranoid Programmers

# re: Paranoid Programmers

Sunday, June 17, 2007 6:52 PM by Jezz Santos

Hi Olaf,

Frameworks are tailored to certain specific domains of use. The whole idea with a framework, like any abstration is that they are built upon a collection of assumtpiopns about their use. This is a key differentiator between frameworks and class libraries, where class libraries can make little, if any, assumptions about their use.

Frameworks positively depend on a certain set of assumptions so they can provide this simplification or abstraction.

Not sure what your pain is, but as a framework programmer you simply have to relax all this excessive checking to see if the context of its use is correct. The use of the framework itself assumes the context in which is used. This is part of its value.

Is this anything of what you are getting at?

# re: Paranoid Programmers

Monday, June 18, 2007 12:01 AM by Olaf Conijn

Jezz, my thoughts exactly :-)

Call it a framework (or something else) but when you design for reuse there is no sense in being a defensive programmer.

Still, every once in a while you are after using a framework and you bump into silly exceptions, just for the sake of.... what? ;-)

# re: Paranoid Programmers

Monday, June 18, 2007 11:37 PM by Gael Fraiteur

PostSharp is programmed defensively. I do it for two reasons:

1. I like exceptions to be thrown as soon as the defect is detected. This avoids many situations where the exception is a side effect of the defect. Finding the root cause of a side effect can be very difficult, what is more when the application is deployed and you can't run it in a debugger.

2. Forward compatibility. When you build a framework, you want the version 2.0 to be compatible with version 1.0. It is difficult to design the version 1.0 for forward compatibility. But this is possible only when you know that your framework is used as intended. However, you would have to maintain the compatibility of side behaviors...