| Programmer's Corner: Code Re-use | Entry id: code-reuse |
|
By The Famous Brett Watson On Wed, 16 May 2001 14:49:00 +1000 |
One of the advantages of Object Oriented code is supposed to be a high degree of reusability in the code. That is to say, you can write software components which can be reused in other projects, rather than reinventing the wheel again and again. I could ramble at length about how Object Oriented languages succeed and fail in this goal of creating reusable code (I like programming language theory a lot), but for today I will touch on the much smaller subject of typical industry practice with regards to code re-use.
To be frank, I don't know whether my place of employment is typical of anything, but one of the most popular log entries I've written to date, Protestant Laziness Ethic, describes some of the Dilbertesque goings on there, so I seem to have struck something of a chord. Take it as given that my view of "typical industry practice" in this case is based squarely on this one (somewhat dysfunctional) workplace rather than a rigorous industry survey.
Where I work, Object Oriented languages have not caught on in a big way. There is a little Java, although it's fairly unloved, and although there's quite a lot of Perl, I'm the only one who has any substantial understanding of how to write Object Oriented code in Perl; most people aren't even familiar with Perl5 syntax, having learned Perl4. There's no C++ — and all things considered, I'm very grateful for that fact. There's some interest in Python, but not a lot written in it. 90% of everything is written in C.
Code re-use is still possible in a structured language like C by the use of shared libraries, for example. These aren't quite as powerful a re-use mechanism as objects, because there's less data-hiding, insulation from change, and so on. Even so, most of our code re-use does not happen via shared libraries: those shared libraries which do exist tend to be poorly documented and unloved. I've had bizarre bugs arise in my code after the most trivial of changes which I've then traced back to shared library problems totally unrelated to my code change, so it's important to do shared libraries properly if you do them at all.
The vast majority of our code re-use happens at a more fundamental level. Say, for example, that we have a program that keeps two data repositories in sync, exporting data from the authoritative database into some other system for final use. Say also that we decide that we have a need for another, similar program. We can leverage (if you'll pardon my verbing of nouns) our existing code base against this problem by cloning the existing program and then modifying it to suit the new problem. Thus, a kind of rapid prototyping is possible.
If that isn't enough, the same technique can be used internally within a program. Say you have a function that does 90% of what you want, needing only slight modification to suit your needs. You can reuse the existing code by making a complete copy of the existing function, give the copy a slightly different name, and then modify it to suit your new need. Once again, the development time required to do this is very small relative to alternatives such as "code refactoring".
Alas, the approach is not without its drawbacks. This kind of re-use results in a proliferation of code. Every modification and new requirement causes your code base to mushroom to new sizes. Bugs which are copied along with the good code then exist in many places rather than one, and the intended structure of any given program or set of programs is obscured when functionality is duplicated. Code which is repeatedly copied and modified without due care and attention to tidyness becomes increasingly crufty (containing dead code, unused variables, mixed coding style) with each iteration.
In a nutshell, the process facilitates rapid prototyping and deployment at the direct expense of future maintainability. Today's quick hack is tomorrow's maintenance nightmare. As is often the case, the main culprits with regards to this coding style have long since left our company or moved to other positions. It's left to me (and others) to cope with the aftermath and explain why every change is harder than you'd expect.
All in all it's a technique I don't recommend, but to which many programmers gravitate nonetheless. Many programmers like reinventing the wheel again and again, or at least taking existing wheels and customising them a bit. They are too lazy to expend the effort necessary to make a truly universal wheel which will fit all their existing applications. I, on the other hand, am too lazy to not try to make the universal wheel. I've written Perl components for university projects which I've then reused (without modification) later in life because they really did solve a generic and recurring problem.
As is often the case, however, the technique of re-use by duplication tends to have better short-term results, and so it is more successful in the typical Dilbertesque business environment.