Thursday, January 31, 2008

peeve no. 255 is an API call changing global state

Ooooo, there's nothing quite like spending most of the workday trying to track down the root cause of a single problem.

Except for when the root cause turns out to be an API call changing global state.

It's like the spammy counterpart to the inversion of control technique. "You know how convenient it can be to define an application's callbacks/delegates/listeners, and just let library code handle the Big Picture as much as it can? What if the library code also manipulated the application code's variables and resources on its behalf, without even being asked!" It's an idea so innovative it'll prompt you to smack your forehead in response. Or smack your forehead against a desk. Repeatedly.

It's like the code equivalent of Yzma's frustration with Kronk. "...why did I think you could do this? This one simple thing. It's like I'm talking to a monkey..." I ask my API for help with one task, the task the API call is clearly named for. I provide the API call with what it needs to carry out the task. And at execution time, the API call then proceeds to surgically cut a piece of data, which sends the entire program crashing down like a chandelier.

Testing it is like repeatedly stepping on rakes lying on the ground. Each time the code runs (stepping on the rake), failure seemingly comes out of nowhere (the handle) to bash you. So you try changing some of the application code, merely to see if the change might make a difference. Thwack. Grab your stress-relief squeeze ball ("that little sucker just saved your life, monitor!") for a moment, adjust a different section of the application code, try again. Thwack.

The Wheel of Morality for today contains the following tips, any of which the spin could land on: 1) minimize global state by whatever options are available, 2) minimize the number of incidental side-effects per procedure and document the side-effects that remain, 3) minimize the general "action-at-a-distance" quality of all code, 4) minimize the assumptions a reusable library makes about the application, 5) minimize surprise without introducing inconvenience by somehow providing multiple library code paths--for instance, by including an optional DoMyWorkForMe parameter, a separate super-deluxe FunctionWithStateMunging, or an OptimizedForYourConvenience fa├žade object.

As for my situation, in which the offending API is written and maintained by a vendor and distributed only in bytecode form (say hello to my little friend, the .Net Reflector), 6) frakking minimize the frelling respect and tolerance and money for that kriffing vendor.

No comments:

Post a Comment