Agile Code Refactoring Scenario


Reuse and refactoring are emergent processes. Under pressure to build more complex software in ever shorter cycles, developers craft code to fit the immediate needs of a given project. Developers tackle refactoring/reuse during subsequent iterations of a project, or under demand from a different project altogether, or perhaps never. While good SCM practices enable refactoring and reuse, inadequate SCM tools hinder or prevent refactoring/reuse altogether.

Consider the following example. Suppose your development team uses separate "branches" for development and for maintenance of individual releases. You then create a team branch (sw_mnt_team) from release 2.0, to enable maintenance developers (Ann and Jon) to work in their own private sandboxes/workspaces (sw_mnt_ann and sw_mnt_jon). Ann and Jon promote and integrate their changes in a maintenance team branch (sw_mnt_team).

Let's assume that Jon finishes a bugfix to sim/Display.java. He keeps the file to his workspace, effectively creating version 1.1. Meanwhile, Eric works on a long overdue refactoring, as part of Release 2.0.2. Eric still sees version 1.0 of sim/Display.java. Figure 1 depicts this environment.

figure 1

Figure 1: Before Refactoring

Eric finds that sim/Display.java can be forged into a reusable view component for use in other Model-View-Controller triads. He moves sim/Display.java to the common/ directory in his workspace (ref_eric) and eventually finishes one iteration of his refactoring work. Eric tests and promotes his changes; his refactoring work results in a leaner, faster executable. Meanwhile, Jon fixes another problem with sim/Display.java, creating version 1.2.

Some time later, management, under pressure from a large customer, Eric decides to create a special release for that customer, with the refactored, faster code. Jon then merges the refactored code from the 2.0.2 release into his workspace. Figure 2 depicts the sequence of Eric's and Jon's changes.

figure 2
Figure 2: After Refactoring

With legacy file-based SCM systems such as Subversion and Perforce, the changes that Jon made between version 1.1 and version 1.2 would be lost. Those systems can handle merging between Jon's version 1.2 file and Eric's version 1.0 file because the files have a common ancestor, namely the version that they both inherit from the parent sw stream.

Unfortunately, those systems can't handle the more difficult merge from common/display.java to sim/Display.java. In Subversion and Perforce's case, the file move essentially acts as a copy + rename, instead of being a true move with complete file history.

By contrast, AccuRev handles the above scenario in full, with no loss of changes.

Legacy file-based SCM products, unlike AccuRev, don't support streams, a first-class generalization of branches, which supports, among other features, stream inheritance. With AccuRev, each branch depicted in Figures 1 and 2 become a stream.

For simple code refactoring, there are workarounds in both Subversion and Perforce; however, for more comprehensive and common refactoring initiatives with many files, the workarounds become tedious in those products, and require a tool that supports streams.


¹Updates the version of a file in a workspace. Unlike most other SCM systems, AccuRev stores the version safely in the depot.