Friday, February 5, 2010

APIs are more important than code

I have spent a lot of time in my career worried about clean code. Using patterns and good naming conventions (naming things is still one of the two hard things) to produce the simplest, most elegant code possible. But in the last six months or so I've learned that it doesn't matter.

Well, it does matter but clean code's importance is dwarfed by a few things. Two of those things are API design and scope of responsibility.

No matter how beautiful your code is, if it does too much stuff it's still bad. And no matter how bad the code is, if the API is well thought out, easy to use and doesn't try to have too much responsibility ... you're OK. You can always refactor bad code.

You would think that this would have been obvious to me after I started doing TDD seriously. It wasn't. I mean, I knew API design was important and that code shouldn't do too much, but for me to really grok that API design and scope of responsibility was more important than clean code, I had to see the mistakes being made.

I had to see the far reaching problems caused by modules that did too much or projects that dipped too deeply into the responsibilities of others. The effect of unreadable, bad code is immediately visible. The effect of bad API design or creeping outside the realm of your true responsibility is much, much more insidious and can poison projects and waste a lot of time. Many of the mistakes I've seen over my career could have been prevented by asking these questions, or questions like them:

  • "What does this feature I'm adding have to do with this module I'm adding it to? Does it belong here or is it orthogonal?"
  • "Does this module I'm reimplementing/moving really have responsibility for this feature?"
  • "What information will the caller have when they need my API to do stuff?"
  • "How will the caller want to use my API?" (This should be easy to answer if you're using TDD)
Very simple, obvious questions, but for the longest time I put less emphasis on them than I did on questions like "Should I refactor this decision logic to command pattern?" or "Is this more suited to builder or factory?"

Clean code is important, I still believe. Patterns can certainly make code more elegant. Naming methods and modules is still very hard and very important. But I have re-assigned the weight I'm going to give them. This is the kind of "mental shift" that has happened several times now in my career. They usually occur when I'm transitioning in or out of a job: you readjust what you know based on new evidence or use cases. It's humbling and exciting. It's also usually obvious. (This probably happens to me more than most other programmers since I have little formal training in computer science and I'm just not very good at it.)

So, my new adventure is going to be going back to Python (and using Django this time around) as as kind of a "clean up" consultant for the non-profit my brother works for. This will be an excellent area for flexing/building API design skills since Django has really neat ways to make pluggable, reusable apps. Hopefully, my bitbucket account will fill up with little, tiny, reusable pieces of Python or Django goodness. Wish me luck.