I took my first real programming class in high school. Someone up in the higher echelons of the Indian education system decided that we should all start learning Java even though it’s a perfectly terrible language for beginners. Anyways, here we are, some twenty-odd high school kids being indoctrinated in the many wonderful benefits of object-oriented programming despite Java not really being an honest-to-goodness OO language. One the things we memorized (and later spilled onto our exam papers) is that OO enables this really good, absolutely awesome thing called ‘code reuse’. I don’t remember anyone actually defining what code reuse is. I can’t really blame them because it seems rather self-explanatory, doesn’t it? You use old code instead of rewriting stuff over again. Until recently, I didn’t realize all the nuances that came with the idea of code reuse.
I had always thought that code reuse meant being able to lift code unchanged from one project and drop it into another. And I couldn’t think of any case over the last few years where I’d actually done something like that. With what experience I had with OO programming, it didn’t seem to me that reuse in that manner fell out naturally from using OO. In fact, it seemed quite the opposite. In each project, my classes were fairly specialized to the task at hand and I’d only be reusing them if I was doing a rewrite of the project along the same basic lines. It struck me that code reuse might just be yet another one of the myths that software engineering has picked up in its short, but interesting lifetime. Or as tycho garen tweeted to me : “cake is a lie. code reuse? just a little fib”.
However I didn’t want to base any broad generalizations like this on only my limited personal experience. I first tried to see if there were any published statistics regarding code reuse across large corporate projects. I found some academic papers regarding how code reuse could be encouraged, but nothing by the way of real hard data. I next turned to Arch Linux community contains a fair number of programmers. This turned out to be a really good as the resulting discussion brought up a number of points I hadn’t thought about regarding the different forms of code reuse.
1. Code Reuse between projects
This was the type of reuse that I had in mind. It seems that this sort of reuse is mostly a myth and understandably so. In most cases you want to get a project as simply as you can (though simplicity can be measured in different ways). That in turn means that your code will most likely be designed to solve the problem at hand as opposed to being suited for reuse. At the same time I think that if you have a group of similar projects, you can be careful to make sure you can use code between them. However the cance you’re going to be working on suffiiciently similar projects at the same time is pretty slim
2. Code reuse through libraries
Even though copy-and-paste reuse between projects may be a myth, there’s still a lot of code being resued out there. If it weren’t our field wouldn’t get very far. A lot of this reuse is done via libraries: collections of code that solve a particular problem and are designed to be used as part of larger programs. No matter what sort of programming, it’s almost inevitable that you’ve used some sort of third party library. This sort of reuse has been around a lot longer than object-orientation and I personally think that the appearance of OO hasn’t made library use more common or even easier. The ease with which code can be distributed and reused is very dependent on the support a particular language has for it which is orthogonal to how much it supports object-orientation (or any other paradigm for that matter).
3. Code reuse through class hierarchies
I’ve come to realize that this is probably what is actually meant by code reuse in OO languages. You don’t reuse classes between projects, but rather structure your class hierarchy so that you minimize the amount of code you have to write and try to eliminate copy-paste code duplication (which can be a nightmare to maintain). A proper design means that you can isolate common functionality and place them in superclasses leaving subclasses to deal with the variation. The code in the superclass gets reused without having been actually placed in the subclasses. Trent Josephsen gave a more detalied answer in the Arch Linux thread:
Imagine three classes A, B, C that share an interface. The status() method is the same for all three, but the serialize() method is different in each class. Without code reuse, you would copy identical code from A.status to B.status and C.status, which could be a problem if the code in A has a bug in it which becomes a serious problem in B or C. With OOP-style code reuse, you derive A, B, and C from an abstract class Z which contains an implementation of status() and a declaration of serialize(). Then each child “re-uses” the code in Z without having to write it in each class.
Furthermore, imagine that you derive class AA from A, and you need to modify the serialize() method ever so slightly. If most of the code is identical, you may be able to call A.serialize() from AA.serialize(), hence “re-using” the code in A.serialize() without copying it into AA. You might argue this is a redefinition of “reuse”, but I think it is the generally accepted definition in OOP.
It’s possible to take this view on code reuse and implement it even if you’re not working in an object oriented languages. Functional languages with higher order functions allow just this. If you have a bunch of functions which do almost the same thing with a small amount of variation you can isolate the common part into its own higher-order function and pass in smaller functions as arguments (which each implement the different behavior).
So it turns that code reuse isn’t a lie after all, but it didn’t mean what I thought it did. Another comment that came out of the discussion was “Code reuse is a choice” which I think is a very appropriate way of putting it. You can have code reuse in a number of different ways: Using libraries, proper class or function organization or even writing your code as a set of reusable libraries tied together with some application specific code. There really is more than one way to do it and it’s up to the programmer to decide which path to take.