I was talking with a friend over the holidays. He was telling me how they are always in panic mode at work. They never get time to do anything properly, and they end up being surrounded by one off hacks that never quite get the job done. He asked if I had any input to maybe mitigate this.. One word, Interfaces.
What I mean by interfaces is simply this… compartmentalize the hacks. Take five minutes and look at all the different hacks that surround you. Find two that do similar things and look closely at them. They probably have some pieces that need to do identical things (perhaps they do them in an identical way, perhaps not, doesn’t matter) If you see a common step there, then break it out into it’s own script/class/function and give it a general interface that allows both hacks to use it.
Another way to create interfaces is to create them while you’re writing your hack. Look at the task… Break the task up into it’s discreet steps. Put a facade (also known as a wrapper) around any of those steps that can be used elsewhere.
Interfaces allow you to go back and fix a portion of an application without having to go back and rewrite the entire thing. It’s an integral part of the incremental development process. Nobody has time to throw away all of their code (nor should they, but that’s a different discussion.) However any project should be in some state of rewrite continually. This is only possible when you have a general interface to compartmentalize some of the functionality.
So how do you write the general interface? Well, that comes with practice. I would start with making an interface anywhere that you think it makes sense. You will most likely create too many interfaces. It’s not hard to remove an interface, so this is of little concern. As you reuse some interfaces, but not others, you can get a feel for the interfaces that fit your problem set.
Interfaces can allow you to compartmentalize your hacks, so it is less effort to go back and clean them up. If you’re finding yourself wishing you had time to rewrite something, perhaps breaking it up into it’s parts, and putting interfaces in there will allow you to take bite-sized pieces on. You can then go back and remove any excess interfaces you had. Eventually a rewrite is just an ongoing process.
An example of this is my current project. We’ve got three people working on a KDE application that is roughly 60,000 lines long. It has been 400,000 lines before. We’ve managed to refactor it down to that level. We’re progressing to our sixth generation now. This rewrite isn’t changing too many of the internals of the app. It is, however, changing it from a monolithic multi-threaded app that used plugins to extend functionality, into several small singlethreaded apps that work together to achieve the same goal. This rewrite has taken us a little over 1 man month so far, and it’s roughly 70% complete. We’ve been doing this in between tasks for the existing system, so it’s been very sporadic as well. The codebase looks like it will end up being roughly 30,000 lines when we’re done, and it will be far simpler to debug and maintain.
We’ve gotten away with 6 rewrites (actually more like major architecture changes) because we can reuse so much of the code we’ve previously written. Our interfaces allow us to swap pieces out as needed, and when we make a bug-fix, it doesn’t affect the entire system, but just what’s behind the interface. If that component is outputting bad information that affects something outside of the interface, then it’s pretty obvious and easy to track down.
Interfaces really can allow you to isolate problem areas. You can better respond to changing needs. It allows more agile development. And best of all, you can start reusing what works, and rewriting what doesn’t!
So Here’s to interfaces!