You just have to have the guidance to lead you in the direction until you can do it yourself.
It is the neglect of timely repair that makes rebuilding necessary.

—Richard Whately

Refactoring

Refactoring is the activity of improving the internal structure or operation of a code or component without changing its external behavior.

The goal of software development is the continuous delivery of business value to users and stakeholders. Constantly changing technology, coupled with the evolution of business objectives and changing user paradigms, makes it difficult to maintain and constantly increase business value. Two paths to the future exist:

Keep adding new functionality to an existing code base toward an eventually unmaintainable “throw-away” state

Continuously modify the system to provide a foundation for efficiently delivering not just the current business value but future business value as well

The second choice, refactoring, is better. With continuous refactoring, the useful life of an Enterprise’s investment in software assets can be extended as long as possible, and users can continue to experience a flow of value for years to come. Refactors are a special type of Enabler story in SAFe and, like any other Story, they must be estimable, demonstrable, and evaluable, as well as accepted by the Product Owner.

Details

Figure 1 illustrates the essence of Refactoring, which is the modification of any software entity—a module, method, or program—to improve its structure or viability, without changing the external functionality.

Figure 1. Refactoring in an isolated environment for change within a larger entity

For example, refactors may accomplish such things as increases in processing speed, sourcing different internal data, or improving security concerns. Another type of refactoring involves streamlining some aspect of the code to make it more efficient, more maintainable, or more readable.

Refactoring mandates that each change is tested immediately to verify the accomplishment of the desired goal. A refactor may be broken into a series of sequential micro-refactors in order to accomplish a larger goal; each small refactor must be tested to ensure correctness. This iterative process preserves the integrity of the software at any stage.

SAFe emphasizes the importance of keeping all work visible, including refactoring. Like user value work, it must be planned for, estimated, and prioritized at all levels of the Solution.

Sources of Refactors

Refactors arise from various sources, as illustrated in Figure 2.

Figure 2. Possible sources of refactors

A refactor can be instigated by a business Feature or can be a part of larger refactoring initiative required by some new architectural Enabler. New user Stories may also require some refactoring of code. Accumulated technical debt may drive the team to refactor certain components. Some refactors may be necessitated by new Nonfunctional Requirements.

It is important to emphasize that not all the team’s refactoring effort comes in the form of specific story refactoring. Much of it should be “in-line” clean-up work, done while implementing user stories. Such work should be factored into the estimate of the corresponding Story (see continuous refactoring techniques described in [1], [2], [3]). Specific refactors, however, represent larger pieces of redesign that need to be planned and tracked as separate backlog items.

Specifying Refactors

It is important to understand what value will be achieved once the refactor is completed. Teams may wish to use the “ . . . so that . . . ” portion of the user story voice form to foster shared understanding of purpose and value, as Figure 3 illustrates:

Figure 3. Refactor example

Splitting Refactors

As with user stories, splitting refactors is important, as it helps sustain better development flow. Table 1 provides some useful methods for splitting refactors, and examples for each.

1. By User Scenario or User Story Refactor incrementally in a story-by-story or scenario-by-scenario mode, or otherwise identify the functional areas as a basis for incrementing.

Improve DB queries and introduce data caching so that the system will run faster

Establishing Acceptance Criteria

As with user stories, defining acceptance criteria for refactors helps resolve ambiguities. Figure 4 illustrates the additional specificity that comes with an established acceptance criteria.

Figure 4. Example of acceptance criteria for a refactor story

Acceptance criteria can often be used as a natural basis for splitting. For example, the first step in Figure 4 might be to “ . . . make synchronous non-configurable batch processing with a single query to dictionary, but without the debug logging.” Then “ . . . add capability to read batch size from the file.” Step 3 would be “ . . . process items asynchronously,” and finally “ . . . add debug logging functionality.”

Demonstrating Refactors

Even though refactoring is focused on the internal working of the code, as with any other story, teams demonstrate the results. From the example above, the teams might demonstrate the following:

Reduced processing time on a few web pages, compared to the previous benchmark

Dependency of processing time on the size of the batch, which can be configured from the file

A code snippet for asynchronous processing

The debug log file that captures all the operations

The number of queries to dictionaries per batch (from the log file)

Adopting the Culture

Refactoring is a mandatory skill for Agile Teams. Refactors should routinely appear on the Team Backlog and be included—along with in-line refactoring—in story estimates. A Design Community of Practice (CoP) can foster awareness and attention to refactoring techniques. Scrum Masters can help their teams learn efficient approaches to specifying, estimating, and splitting refactors. Product Owners should embrace refactoring by prioritizing the work and by helping to define acceptance criteria.