ExtremeMaintenance is what happens when a system is so well-built that nobody has touched it for 5 years, and anyone who knew anything about it is long gone. But now, something needs to be changed. Fortunately, you originally built the system using ExtremeProgramming. This is a hypothetical situation, obviously, but one that will eventually happen.
I believe a more realistic scenario would be that management stopped funding development on the system for 5 years and finally is being forced to make improvements. I have yet to see software that is being used that does not have a backlog of user requests for changes and improvements.
We think having used XP will shorten the maintenance effort and provide the necessary foundation for making the change. Just because you used XP, doesn't mean everything becomes easy. If you have a complex system, no matter what methodology you used, there will be significant effort in learning how to make the change in the system. One good thing is that you don't have reams and reams of obsolete documentation which could be: a) misleading (which is bad), b) just plain wrong (which is worse), or c) almost correct (which is worst of all). What you do have are UnitTests and AcceptanceTests which by definition must be correct and up-to-date, and you have the code itself which was crafted to communicate without external props.
XP gives us the ability to see how the requirements are reflected into the code itself, because the AcceptanceTests and UnitTests directly interact with the classes which compose the system. The browsers allow you to jump directly from requirements (AcceptanceTests) to functionality (classes/code). Other methodologies use one set of tools for diagrams and documentation and another set for the actual classes and code. Often, the correlation between the two is not obvious. Which leads one to ask, does anyone ever bother to read the vast wasteland of documentation or just jump in with both feet (JangIt)?
Our approach to this hypothetical situation would be the following.
The first step in any kind of ExtremeMaintenance would be to analyze the AcceptanceTests, because they tell you what the system does from an external black box perspective. Since you have only been given the requirement for what the system needs to do differently (i.e. from an end-user perspective), and you have no knowledge of the system internals, you decide to look at the AcceptanceTests. Either the tests which exist need to be changed to reflect the new requirements or new tests need to be created to test the new functionality.
The second step would be to start looking at where the new functionality needs to be applied. To do this, you go backwards from the AcceptanceTests. You find out what classes and behavior are involved. Prudent browsing will yield how the classes interact, and from there you should easily be able to find the UnitTests to give you robust examples of correct use. Now you can change/add the UnitTests for the new functionality.
Thirdly, you change the code. Run the UnitTests; at 100% you are almost done. Then you run the AcceptanceTests; at 100% you are done. Release and let the system run smoothly for another 5 years.
-- VcapsProject
Coming at it from another angle, in tackling a system that has been evolving for the last 4+ years, I'm writing the UnitTests before I dare change anything. In the course of 3 days, the CppUnit tests managed to identify the source of several interesting features that had survived conventional developer testing for quite a while. -- PeteMcBreen
I experienced something very similar while extending a persistence framework that builds the foundation of a large business application. Before I applied any change, I created a comprehensive test suite that allows me to make sure that i do not break existing code. While building and running the test suite I uncovered some very subtle bugs in the system for which there were bug reports pending for several months. -- PeterMaier
As you work on a project, your coding conventions and standards will tend to improve as the team becomes more proficient. How do you deal with older code that does not incorporate some of the more recent lessons learned?
There are two opposing forces at work. On one hand, you want to minimize the changes to the code, because each change introduces a risk of causing a defect and requires testing. On the other hand, you want to bring the old code into conformance with the current practice.
Is there a pattern that balances these forces?
-- KentSchnaith
If you need to change it, fix it first (tests then refactoring).
"to bring the old code into conformance with the current practice" The practical way to do this may present sizeable tasks, and may not be appropriately classified as "maintenance".
Projects produced using ExtremeProgramming do not present such a severe requirement, because of the nature of the deliverables, the quality and existence of source, AcceptanceTests and UnitTests, and manner and quality of documentation.