- Writing generic code is hard
- Avoid premature generalisation
- Don't re-invent the wheel
- Do re-design the chariot
- Import hooks are the new command line arguments
Thus Spake Andy:
Writing generic code is hard. Really hard. I would say it's at least an order of magnitude harder than writing specific code. Avoid premature generalisation. Do something several times before even thinking about generalising it. Ideally do it a dozen similar, but slightly different ways over the course of 10 years and then look back and abstract out the bits that you always did the same (that's partly why TT is taking so long and has 3 different implementations - or is it 4? I forget). Of course, you can do it much quicker than this, but there really is no substitute for experience, and in particular, making a few mistakes. It's often the experiments that don't work as you expect that teach you more about the underlying science.
We all have "problem horizons" that are impossible to see beyond until you've walked around a bit and explored the surrounding area, ideally walking in someone else's shoes. Unless you can predict the future, it's very hard to anticipate what people might want to do with your software. It's better to put a few sticks in the ground and see what people build around it instead of trying to plan the whole town in advance. Whichever way you do it, you'll inevitably make mistakes, but that's the way it goes. As Matt Trout would say, this is the kind of stuff that you really Shouldn't Give a Fucking Shit About™. Quite right, too. JFDI.
Thus Rambled Andy Ever Onwards:
Try to avoid re-inventing the wheel. But remember that coder re-use is more important than code re-use. Algorithms are important, implementations less so. Find out how other people have done it before, and if that's not what you want, or if it can't be coerced or cajoled into doing what you want, then re-implement it using their ideas and experience. Figuring out what code to write is much harder than actually writing the code. So don't re-invent the wheel, but don't be afraid to build new wheels based on someone else's design, or to design and build new chariots based on other people's wheels (giving appropriate credit where due, of course)
Some people will inevitably get cross because they think everyone should be driving the same kind of car, but don't let them vex you. Software is like art and the only justification you need for creating it is "Because I felt like it". Just remember that you have to balance your artistic desire with the real world limitations that you might be up against. Sometimes you just have to get the job done using whatever you tools you have at hand because you or your boss/client haven't got several days/weeks/months/years to wait for you to craft the ultimately reusable and infinitely configurable solution. Put a stick in the ground today and move it tomorrow if it turns out that it wasn't in quite the right place.
He's Still Going:
And here's the painful truth - there rarely is a perfect solution. Or none that I've ever stumbled across, anyway, except perhaps for very simple problem domains. Software reuse through object orientation is a bit of a myth. Inheritance is fundamentally broken. Encapsulation has a few problem too (although that's less of a problem in Perl where there is no strict form of encapsulation unless you build it in yourself). Interestingly, polymorphism seems to be the one remaining aspect of OO programming that brings benefits without any immediately obvious drawbacks. It also features prominently in functional languages which is a clue that it's a sound fundamental principle. If it's good enough for Haskell then it must be good enough for us mere mortals!
Anyway, what that boils down to is that
Badger isn't going to solve all
your software engineering programs overnight. Or at all. However, it
hits the 80/20 sweet spot for me (and specifically, TT) in a reasonably
simple and efficient manner and that's good enough for what I want. It's
in keeping with the principle of "design it for yourself - that way you'll
have at least one happy customer" (which I thought was one of Kawasaki's
Rules for Revolutionaries, but perhaps not. It's certainly in keeping with
"eating your own dog food" which is). Badger doesn't claim to do anything
particularly remarkable, but it does a bunch of unremarkable things in a
reasonably sane and coherent fashion.
Actually He Didn't Say Most of That
By coincidence, Ovid posted a blog entry about his disillusionment with OO on the day I gave this talk. He references an essay dating back to 2000 on the subject. I came across it this morning, just as I was starting to write these footnotes. Both articles helped to clarify some of my thinking on the matter, allowing me to elaborate on some of the above points in the paragraphs above. It's probably a good thing I didn't read it before I gave the talk, or I might have subjected the audience to the extended ramble presented above. He also mentions Schwern's skimmable code talk which everyone should read. Matt Trout's "You're Not Worthy, and Neither Am I" lightning talk at LPW was also highly inspirational.
I'd like to finish by proposing the
Skimpy as the official, if intangible,
unit of how skimmable your code is. Skimpy++ is the way forward, even if
we're not quite sure where we're supposed to be going.
http://use.perl.org/~Ovid/journal/37975 (Ovid's blog on use.perl.org)
http://www.advogato.org/article/83.html (Encapsulation, Inheritance and the Platypus effect)
http://use.perl.org/~schwern/journal/36704 (Schwern's skimmable code talk)