July/August issue of acmqueue


The July/August issue of acmqueue is out now


Kode Vicious

Quality Assurance

  Download PDF version of this article PDF

The Meaning of Maintenance

Software maintenance is more than just bug fixes.

Dear KV,

Isn't software maintenance a misnomer? I've never heard of anyone reviewing a piece of code every year, just to make sure it was still in good shape. It seems like software maintenance is really just a cover for bug fixing. When I think of maintenance I think of taking my car in for an oil change, not fixing a piece of code. Are there any people who actually review code after it has been running in a production environment?

Still Under Warranty

Dear Still,

The short answer is that, yes, the term software maintenance is yet another computer industry bit of Newspeak, probably invented so that people wouldn't have to put bug fixer on their resumes. Since there is strength in ignorance, I should probably not answer your question any further, but I find it impossible now to follow the party line.

Although the term software maintenance has little meaning other than bug fixing, the question you ask has some deeper implications. The reason to do maintenance on a car, or any other machine, is that it has moving parts that wear out over time. Parts wear out because they are subjected to physical stresses, such as two gears, one of which drives the other in order to transfer energy from a motor to a wheel. Software isn't subjected to physical stresses, though there are pieces of code I've read, only just recently, that rightly deserve to be put under physical stress—or, at least, their authors do. Even though software itself does not wear out after it is executed repeatedly, there is a place for maintenance in the software industry.

The more modern term for what really is software maintenance is another bit of Newspeak: refactoring. It is unfortunate that every term we come up with to describe something simple and direct in our industry is almost instantly debased so that it loses all meaning. While I'm not generally against debasement, in this case it does make our lives a bit more difficult. Many people wrongly use the term refactoring to stand in for: "Oh, we really screwed up the entire system we were writing over the past six months, so we're going to have to write it again from scratch, but we'll keep the name of the program the same, as well as the names of many of the classes. We will, of course, have to change all the insides of the classes, their method signatures, and about 90 percent of the rest of the text that was the program, but from the outside it will look the same, except for all the features; those will change too." When you replace most of your API, the innards of the code, and the features, that is not refactoring; nor is it maintenance. That's a rewrite.

Refactoring actually means that you have some functions or classes that, with a small number of changes, can be used in another program. It is this more honest type of refactoring that begins to look like software maintenance. The reason that refactoring is more like maintenance is because you're looking at several moving parts that no longer mesh well with each other. In the previous program or system in which they were used, they meshed well—otherwise, that program would not have worked correctly—but they do not mesh correctly with the new design; therefore, you're required to add a metaphorical bit of grease, or break off a few teeth from the gears to make them work well in their new application.

When you're refactoring a piece of code is also the perfect time to think about the original design: if it made sense originally, if it makes sense now, and if you want to be stuck with this same design in the future. I am NOT saying that you should rework every single piece of code you see just to make it a bit cleaner, nicer, more generic, etc. You can't actually even imagine that I would give people license just to diddle with all the code in a system. That kind of navel-gazing really ought to result in whippings, but I hear that those are not allowed in most workplaces at this point.

While you're maintaining—oh, I mean refactoring—please remember that whatever you change must be tested. Just because you "changed the API only a little bit by adding one teensy-weensy little bit field" does not excuse you from testing your change. If you don't, I can guarantee that you'll be back doing the old kind of software maintenance (i.e., bug fixing).

KV

Dear KV,

A co-worker recently chewed me out for including one C file within another C file. Though this may not be the way many people build software, it doesn't seem wrong to do so, and the compiler doesn't complain. Is this really wrong, or just unorthodox?

All in One and One in All

Dear All in One,

There are many things that a compiler will not complain about. Compilers, unlike people, have no moral sense and therefore have only a very limited idea of right and wrong. Most people have a better sense of right and wrong than a compiler—most, but not all. Clearly, you are one of those people who does not have a highly developed moral sense, for if you did, you would have realized, even before e-mailing me, that what you were doing was wrong. Why was it wrong?

The simplest reason not to include one C file within another is that it obfuscates the relationships between pieces of code. The few times I've seen this kind of thing in practice, it has been done at the end of a C file—sort of like tacking on one file at the end of another. If, for example, you don't wind up reading the very end of the file, you'll never know that there is one file (or more) built when the code you're looking at is compiled. Such surprises are an unwelcome part of a programmer's day. It's like grabbing a bag that you thought contained a few loaves of bread only to find out that there is an anvil at the bottom.

If you need to use a piece of code in two places, you don't #include it in both; you build it as a separate module and use the linker to put the pieces together at the end when you build the final executable.

We are no longer programming in the 1950s, and we are not building programs out of paper-tape libraries where you splice together a program out of smaller segments of paper tape. In an environment with linkers, loaders, and compilers capable of generating and working with separate modules, there is no excuse for #including one compilable file within another.

KV

KODE VICIOUS, known to mere mortals as George V. Neville-Neil, works on networking and operating system code for fun and profit. He also teaches courses on various subjects related to programming. His areas of interest are code spelunking, operating systems, and rewriting your bad code (OK, maybe not that last one). He earned his bachelor's degree in computer science at Northeastern University in Boston, Massachusetts, and is a member of ACM, the Usenix Association, and IEEE. He is an avid bicyclist and traveler who currently lives in New York City.

© 2009 ACM 1542-7730/09/0800 $10.00

acmqueue

Originally published in Queue vol. 7, no. 7
see this item in the ACM Digital Library


Tweet



Follow Kode Vicious on Twitter
and Facebook


Have a question for Kode Vicious? E-mail him at kv@acmqueue.com. If your question appears in his column, we'll send you a rare piece of authentic Queue memorabilia. We edit e-mails for style, length, and clarity.


Related:

Robert Guo - MongoDB's JavaScript Fuzzer
The fuzzer is for those edge cases that your testing didn't catch.


Robert V. Binder, Bruno Legeard, Anne Kramer - Model-based Testing: Where Does It Stand?
MBT has positive effects on efficiency and effectiveness, even if it only partially fulfills high expectations.


Terry Coatta, Michael Donat, Jafar Husain - Automated QA Testing at EA: Driven by Events
A discussion with Michael Donat, Jafar Husain, and Terry Coatta


James Roche - Adopting DevOps Practices in Quality Assurance
Merging the art and science of software development



Comments

(newest first)

Volkan TUNALI | Mon, 30 Nov 2009 01:30:46 UTC

In the the article it looks maintenance is almost equal to refactoring. However, refactoring is not only part of maintenance; refactoring is a continuous effort through the development process. Thus, I think refactoring should not be taken as the equivalent of maintenance, or vice versa. Maintenance is the process of changing the system (software) after it is delivered and it is in use. Of course the process of maintenance includes bug-fixes in the code, fixes of errors in design, porting of software to different platforms (h/w or s/w), and adding new features. All those jobs cannot be regarded as only refactoring, and cannot be done just by refactoring.


Robert Taylor | Tue, 17 Nov 2009 16:15:53 UTC

Re:Maintenance

I'm not sure why anyone would have issues with being a bug fixer. I do it for mine and other staff's code. It's part of the process. The process is that of removing flaws and improving the system or adding needed function to an existing system. It is a different effort related to the original task. Maintenance is just a different form of problem solving but requires a slightly different outlook.


Andrew Dalke | Wed, 04 Nov 2009 12:32:11 UTC

The Python re module(s) has one case where #include:ing a C file makes sense. The _sre.c code implements the re engine for 8-bit byte strings then sets up an #define and #include:s itself. The #define changes a few settings and does some conditional code to support 16-bit Unicode strings. Because most of the code between those two instances is identical, having one C file means there's less code and less code duplication, at the cost of this recursive #include.

I've also used #include to bring in a section of code which was machine-generated, in my case a set of precomputed data tables. As you write, this can be replaced with a linker, but I figured I didn't want another global symbol and by using #include I can keep it in the same compilation unit.


John Ahlstrom | Mon, 31 Aug 2009 22:17:08 UTC

Software engineers (or their bosses) are the only ones who would call adding an upper deck to the Golden Gate Bridge "maintenance". -- unknown


Samuel Bronson | Fri, 28 Aug 2009 02:53:36 UTC

Well, that's a bit different -- for one thing, you're hardly going to miss the #includes when the file contains nothing else except comments and whitespace ...


Paul Lalonde | Sat, 22 Aug 2009 22:27:08 UTC

There is a situation where #include of a C file is valuable. Some (many? most?) build systems can't aggregate multiple source files to pass to the compiler at once, leading to compiler invocation overhead for each C file - this can slow your build dramatically. One work-around is to include all the C source files for one library into one C file; I've seen build times go up an order of magnitude using this technique. Yes, it's better to have your build system do this, and you only want to do it when your build times have been crawling up towards unacceptable. And you had better document why you did it. Caveat emptor.


Leave this field empty

Post a Comment:







© 2017 ACM, Inc. All Rights Reserved.