![]() |
Development Lifecycle »
Design and Architecture »
General
Beginner
The Art of Maintenance ProgrammingBy Nemanja TrifunovicSome tips to make maintenance programming more enjoyable. |
All Topics, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
I have seen and read numerous books and articles that cover new development, including design and architecture, coding, and project planning and management. Not so for humble and overlooked maintenance programming. Maintenance is often mentioned in studies on software life cycle, but actual design and coding techniques are usually taught with active development in mind, rather than maintenance.
Here, I am not going even to try to define maintenance programming, or to quote someone else’s definition. Instead, I’ll just list some characteristics of a maintained software as opposed to an actively developed one:
The tips I offer here are the result of my own experience. You may find they don’t apply well in your situation, or even more likely, that some of them apply and some of them don’t. If you have any additional advices, please post them at the article’s forum.
How can anyone like maintenance programming? Developers dream of being chief architects in their teams, and when they end up maintaining existing software, it feels almost like punishment. It doesn’t have to be: maintenance programming has its own set of challenges, and requires a lot of creativity, adaptability, patience, discipline, and good communication. It can be good for your career as well: having bombastic entries like “Architected n-tier 24/7 enterprise application” in your resume looks nice, but employers actually value people who solve problems; and maintenance programming can be a good chance to demonstrate your problem-solving skills.
It is crucial to know the functionality of the software you maintain. Read the existing documentation, and make sure to try it for yourself. If you have a QA department, try to dig out the test plan, and go through it. Find out how the software is being used in practice and make sure you know the most common scenarios of use. There will be cases when users come to you requesting features that already exist, they just don’t know about them. In other cases, there will be handy workarounds. If you are a power user of the software you maintain, chances are you will spend less time in the debugger.
You would expect to inherit detailed and up-to date design documentation, including requirements, functional specifications, high-level and low-level design, as well as well-commented code, right? In reality, chances of that happening are close to zero. It is much more likely you get a little, if any, documentation, and even that will probably be outdated. Code, or some parts of it, may be commented, but you can’t be sure even the comments are up to date; sometimes they can actually be deceptive if the code was changed in the meantime.
Look at the code; try to understand the roles of classes, modules and components. Use the debugger: step through different scenarios of use, and see what happens when different parts of code are executed. Be sure to write down your findings and organize them in some form; it can be some formal method like UML diagrams, or something informal but easy to understand. Think of getting familiar with the architecture as of an ongoing process, rather than one time thing. You will have the opportunity to know the system even better when you start to fix bugs and add features; be sure to document your findings in this stage as well.
I can’t stress enough the importance of this. Many software developers are introvert persons who prefer to deal with technology rather than with people. However, the software is written for people to use it, and in the case of maintained software, we already have users. It is crucial to find out how they use the software, why they use it, what problems are they trying to solve, what functionality they need. To find that out, don’t wait for them to come to you; be proactive and go to them. Try to establish simple and effective procedures for submitting bug reports and enhancement requests. When they report a problem, get back to them immediately, even if you don’t have a solution at that moment – just let them know you are looking into it and not ignoring them. Keep them updated about the status of their problem. Finally, be honest; if you can’t meet their request for any reason, tell them.
If you are lucky, some of the original developers are still with the company. Sure, they have moved forward and want to forget about this old crappy software you are maintaining, but they can be a tremendous help and save a lot of your time. Don’t expect them to do the actual coding for you, but they can throw you an idea how to accomplish something, explain you why something works the way it works, and provide you with lots of helpful hints. Again, dealing with them requires “people skills” that many developers lack, but it is not something we can’t learn.
There are different and not mutually exclusive ways to keep the history of changes. The most obvious thing to do is to comment each and every check-in to your source control system (I am not even going to consider the possibility you don’t use a source control system). Some people prefer to put the list of changes at the top of each file. It may be convenient to have a centralized list of changes in a spreadsheet as well. Whatever approach you take, be serious about it. An accurate history of changes is invaluable for successful maintenance, even if nobody else before you took care of it, and you get only a partial list of changes.
Many times during the maintenance work, you are going to get frustrated with the existing code in some module, and just want to toss it away and rewrite it from scratch. Before you actually do that, ask yourself some questions:
The fact is that whenever we make a change to existing code, no matter how trivial the change is, there is a risk of introducing bugs. Therefore, we want to be as conservative as possible given the circumstances. When a new feature is requested, we would want to implement it in a separate module if possible and keep the old code unchanged. Don’t fix it if it isn’t broken. If it is broken, fix it rather than rewrite it from scratch. Keep the changes as local as possible – you don’t want to find out that you improved one part of the system and broke another.
Refrain from refactoring. While it can be a useful technique during active development, in maintenance phase, it will probably bring you only troubles. Even if you don’t break anything through refactoring, you will complicate your history of changes and screw up the differences between versions in your source control system (you do have a source control system, right?).
Also, when you do change the code or add new features, try to do it the right way immediately. Too many times I’ve seen people say “let’s just make a quick hack now to meet the deadline, and we can rewrite it properly later”. Well, “later” usually never comes, for various reasons. If you can, do it properly; if not, be honest with yourself and don’t mention “later” as an excuse.
Probably the first coding task you need to do after taking some software to maintain is to write a comprehensive regression-test suite for it; that is unless you inherited one already, but in general, you are not going to be that lucky. It is true that automated tests cannot guarantee the code is bug-free, but it is a poor excuse to avoid them; they will not uncover all bugs, but they will help you find many and bring you confidence that the core functionality of the software you maintain is not broken after you do a change. A good practice is that for each defect report you get, write a test-case to reproduce it. That way, you will know if you reintroduce a bug when fixing something else.
Sometimes, depending on the maintained software, it may take too long to run the whole regression-test suite after every little change you want to check-in to your source control system (which you do have, right?). In that case, it may be useful to take a subset of regression tests and make a “smoke-test” that would cover only a subset of test cases from the regression-test suite. You would run this smoke-test after every change you make, and the regression-test overnight or during weekends.
Code conventions are something people get religious about, and in general, it is hard to make someone change his mind about which coding conventions to use. Even with languages that come with suggested coding conventions from the authors (like Java, Visual Basic and C#), developers still argue about them. With languages where authors leave the conventions to developers (C, C++, Perl), the matter of choosing a convention quickly becomes a war.
I know I am not going to convince anybody, but try to stick to whatever conventions exist in the code you maintain. Even if there is no uniform convention all over the system, chances are that the conventions are uniform at least on module level, since in most cases, one person develops one module. In the worst case scenario, someone other than the original developer already altered the code and used other conventions, so you have a horrible mix of conventions to deal with. Even in that case, adopt one of the existing conventions, and don’t introduce yet another one.
Maintenance programming has its own set of challenges, and these challenges need to be addressed in a disciplined manner, just as with active development. In this article, I present some practices that I found useful in my work; this is by no means an attempt to write the definite guide to the art of maintenance programming.
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 14 Dec 2004 Editor: Smitha Vijayan |
Copyright 2004 by Nemanja Trifunovic Everything else Copyright © CodeProject, 1999-2009 Web19 | Advertise on the Code Project |