Martin Pool's blog

Plumbing the depths of poor interface design

I hit a particularly precise example of Rusty's API quality spectrum today in some WBEM code.

What's wrong with this code?

member_kb.append(CIMKeyBinding("CreationClassName", "HP_Processor"));

Not much, on first glance. Looks pretty reasonable. But it turns out for some reason that CreationClassName is getting recorded as True, because the second argument gets coerced to a boolean (being non-null). The fix is

member_kb.append(CIMKeyBinding("CreationClassName", String("HP_Processor")));

Yes, this code has its own C++ String class, which is perhaps forgiveable in old code. What is less forgiveable is that C-style char* will almost, but not quite always get coerced into a String object; sometimes into something else. I could even cope if it gave an error and made me go back and check it ("compiler won't let you get it wrong"), but this is just bizarre.

This achieves a pretty high score's on Rusty's scale: The obvious use is wrong.

[This is not a reflection on OpenPegasus as a whole, which is actually pretty clean aside from being non-STL. That's just where I happened to find the example.]

Rusty on Interface Simplicity

Rusty's OLS 2003 keynote looks at the problem of designing and defining interfaces between software modules. For large programs, this tends to be a more important issue than the design of any one module, for a few reasons. Modules can be rewritten, but changing an interface can destabilize the whole system. You can get away with only one or a few programmers understanding the internals of a module, but almost by definition interfaces need to be understood by more people:

Once the code gets too big for one person, it's all about damage control. Interfaces make damage control possible... except when the interfaces themselves are the problem.

Rusty says the key criteria for an interface is how easy it is to use correctly or (by Murphy's Law) how hard it is to misuse. He delineates a spectrum from best to worst, which is so good I am going to shamelessly reproduce it here:

1. Compiler/linker won't let you get it wrong.

2. Compiler will warn if you get it wrong.

3. The simplest use is the correct one.

4. The name tells you how to use it.

5. Do it right or it will break at runtime.

6. Follow common convention and you'll get it right.

7. Read the documentation and you'll get it right.

8. Read the implementation and you'll get it right.

9. Read the correct mailing list thread and you'll get it right.

10. Read the documentation and you'll get it wrong.

11. Follow common convention and you'll get it wrong.

12. Do it right and it will break at runtime.

13. The name tells you how not to use it.

14. The obvious use is wrong.

15. Compiler will warn if you get it right.

16. Compiler won't let you get it right.

17. It's impossible to get right.

When you're inventing an interface, see if you can shift it up this list one or more steps. In particular, think about whether bugs are caused by interfaces that are too far down the list.

A favourite example of perverse interface design is bogofilter inverting the meaning of two flags from one release to the next.

Linus's law should have prevented that: if you change the meaning of an interface, change the name as well. In this case, if you feel the you assigned the wrong action to the -n option in the first release, then don't just change it. Make that option deprecated or invalid, and assign the new action to some other action. Years later you might reuse that option, once you're sure everyone has forgotten the original meaning, but even that is risky.

OOP considered horrible

LWN links to an essay by Kimbro Staken about excessive use of OOP.

Kimbro is replying to a truly awful article by Bergin and Winder on "Understanding Object Oriented Programming". Go and read it yourself, and see if you agree that an interacting system of seven files and fifteen methods is really clearer than a single procedure. Poop indeed. (Or perhaps it's a really subtle spoof? If so, it deserves a prize, though they should have dated it 1 April to give us a bit of a clue.)

Simon Willison and Jarno Virtanen have more to say about it.

All programmers are optimists...

All programmers are optimists. Perhaps this modern sorcery especially attracts those who believe in happy endings and fairy godmothers. Perhaps the hundreds of nitty frustrations drive away all but those who habitually focus on the end goal. Perhaps it is merely that computers are young, programmers are younger, and the young are always optimists. But however the selection process works, the result is indisputable: "This time it will surely run," or "I just found the last bug."

— Frederick Brooks, "The Mythical Man Month"

Redefining Professionalism for Software Engineers

old post by Philip Greenspun

Ian Lance Taylor

Good essays by Ian Lance Taylor on debugging, stock prices and atheism.

Archives 2008: Apr Feb 2007: Jul May Feb Jan 2006: Dec Nov Oct Sep Aug Jul Jun Jan 2005: Sep Aug Jul Jun May Apr Mar Feb Jan 2004: Dec Nov Oct Sep Aug Jul Jun May Apr Mar Feb Jan 2003: Dec Nov Oct Sep Aug Jul Jun May