Saturday, January 26, 2013

Taking Out A Contract

Earlier this week, I was involved in a discussion about the relative merits of Design By Contract vs Defensive Programming.  While both are good, I was struck by the thought that in my experience, it's hard to get other developers to keep up their end of the bargain for DBC.

For example, one protocol I programmed to had a field in one message that specified the maximum time it would take for a file to be transferred across a link,  When we wrote the code, the client received that message, took that time value, added a small fudge-factor to account for some specific conditions on their end, and all was well.  However, at some later point, a new group of programmers for that project decided that "No file will ever take longer than 30 seconds to be transferred", so they would wait a maximum of 30 seconds before timing out, even though we routinely had files that took 2 minutes to transfer.

Basically, any program that is built in a work environment where the original programmers will be replaced at some point is almost guaranteed to have one or more of the new programmers ignore the constraints at some point, rendering the contract useless.  And unless you're programming in Eiffel, you get bad results.

Defensive programming, however, differs in that the receiving side will check the inputs and can complain when its expectations are violated.  The big problem with Defensive programming is that it tends to clutter up the code, and foster paranoia.  The compromise I have come up with is to but string defensive checks on things that cross object boundaries - the public methods, API calls, etc.  It's generally easy to at least document the expectations within a class so that later developers will see them and follow them, but once you have to call something defined in another file/directory/subsystem, you risk not being able to find the details.

No comments: