Section 3.4. Is It Refactoring or Rework?


3.4. Is It Refactoring or Rework?

Plan-driven methods were specifically designed to prevent rework and were based on the philosophy that if we planned carefully enough, we could ensure that the first time we developed the code it would be correct. Another way of looking at this was that the cost of a change to the system was thought to increase as the project progressed. Clearly, if we develop the system in iterations and specifically do not plan for subsequent functionality during those iterations, we will have to modify and possibly completely replace our code later in the project. This is something agile methods must address.

The first strategy for addressing rework is to modify the process so that the cost of a change is relatively constant throughout the development process. Much of the increase in cost that plan-driven methods experienced came from two sources: updating the documentation and the risk of increased defects resulting from undetected side effects of the change. Both of these costs increase as the system grows. Agile methods such as automated unit and acceptance tests and generation of documentation from the code are designed to reduce the costs and risk of rework so that they stay relatively constant throughout the project.

At the beginning of the transition to agility, you will have a design document, and as with the beginning of the implementation phase of plan-driven development, the code you develop should be driven by that design. This gives your code the longer-term perspective that most agile organizations require. As a result, the amount of rework that you need in early iterations will be low. However, as the system grows, the design of the code will deviate from the planned design. By that time, your team will need to develop skills and you will need to optimize your process further to maintain the quality of the design into the future.

The consistency of the cost of rework opens opportunities for improving the quality of the system. In all projects, plan-driven or agile, the quality of the code degrades if changes are introduced without considering the effect those changes have on the overall design of the system. Each change only increases the complexity by a small amount (an extra parameter here, slightly tighter coupling there). As we make more of those changes, however, the overall design of the system becomes increasingly complex and convoluted. This is known as software rot. Essentially, as we continue to add functionality to the code, it becomes increasingly fragile. This is a symptom of design debt, which is much like regular debtit accrues interest over time. Eventually, design debt must be paid back. Many projects have declared design bankruptcy and redeveloped their system from scratch. (Kerievsky[1] offers an excellent discussion of design debt.) Particularly in agile projects, it is critical that the team keep an eye on the overall design of the system; they must clean up (refactor) the code and pay back that design debt as they progress. The tests that we have developed in this and previous iterations[4] can provide a safety net so that we can make changes with minimal risk.

[4] The assumption here is that there was some existing unit/system test capability, and you must maintain that. The refactoring "Automated Unit Tests" will help you improve the robustness of those capabilities to support your refactoring activities.

Reeves[2] gives an alternative view of the development process. He compares developing software to building a bridge. When engineers design a bridge, they build many prototypes and refine the design until it specifies every bolt in the bridge. As the design increases in detail and prototypes are built, the engineers learn things that make them revise the design. When that process is complete, they pass the plans (the design document) to the bridge builders.

Reeves parallels this to software development where we can build prototypes and revise the design of the system to the same level of detail as the bridge builders (essentially to the point where building it is deterministic). The only specification Reeves could find that met that level of detail was the source code itself. Therefore, he postulates that the design process continues throughout the development of the source code. Essentially, the intermediate coding steps are prototypes from which we learn and improve the system. The only difference between this and bridge building is that we can build our systems many times a day because it only requires running the compiler, whereas bridges can only be built once. This difference means that our prototypes and our resulting product are built from the same specifications taking on the same form. We just need to remember that prototypes may require redesign before they can be products.

Reeves' argument holds whether the process is agile or plan-driven. He is arguing that the design thought process does not end with the traditional design document but goes on throughout the coding activity. Techniques like source code refactoring help us efficiently execute the redesigns and lower their risk.




Refactoring to Agility
Refactoring to Agility
ISBN: B000P28WK8
EAN: N/A
Year: 2006
Pages: 58

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net