Software Refactoring

Michael L. Collard, Ph.D.

Department of Computer Science, The University of Akron

Source-Code Activities

  • Fix a bug (Debugging)
  • Add a new feature (Development)
  • Understand what some part of the code is doing (Comprehension)
  • Change for a new API (Adaptive Maintenance)

Levels of Software Changes

  • High-Level Software Changes
    • Add features to a system
    • e.g., Support new output format by adding a class
  • Intermediate-Level Software Changes
    • Change design
    • e.g., Move a method from one class to another
  • Low-Level Software Changes
    • Change individual statements
    • e.g., Change code in a method

Mathematics: Factor

  • fac.tor
    • One of two or more quantities that divides a given quantity without a remainder, e.g., 2 and 3 are factors of 6; a and b are factors of ab
    • Multiple equivalent forms: 2 × 3 = 6 and 1 × 6 = 6, x^2 - 4 = (x - 2)(x + 2)
    • Best form depends on the problem being solved
  • fac.tor.ing
    • “To determine or indicate explicitly the factors of”

SE: Factoring

  • fac.tor
    • The individual items that combined together form a complete software system:
      • identifiers
      • contents of methods
      • contents of classes
      • relationship of a class to other classes
    • Many different ways to factor a software system
  • fac.tor.ing
    • Determining the items, at design time, that make up a software system

Refactoring

Process of changing a software system in such a way that it does not alter the external behavior of the code, yet improves its internal structure [Fowler’99]

A program restructuring operation to support the design, evolution, and reuse of object oriented frameworks that preserve the behavioural aspects of the program [Opdyke’92]

Specifics

  • Does not change the behavior of the program
  • Type of software transformation
  • Source-to-source, remain inside the same language, e.g., Java to Java, C++ to C++
  • Originally designed for object-oriented languages, but can also apply to other programming paradigms, e.g., functions

Testing Requirements

  • Testing must be in place to make sure that behavior of the software is not changed
  • At a minimum: unit testing
  • No refactoring (or changes of any kind) should be done before unit testing is in place
  • Current, expected behavior of the software must be preserved

Legacy Code

  • Often applied to old systems with “old” technology (e.g., COBOL, which has a surprising amount of code still being used
  • There is a great deal of software behavior that is:
    • Not stated (or clearly stated) in written policies
    • No code documentation
    • And even no testsuite
  • Any code that does not have a unit-testing suite can be considered legacy code

Relationship to Process

  • Not the same as “cleaning up code” (which may cause changes to the behavior of the program)
    • Cleaning up code is not an effective strategy
  • Changes can be made in a small context (e.g., individual method), or to entire program
  • Key element of most workflows and processes in agile
  • Viewpoint is that design is part of an iterative process

Ref: Rename Method

Ref: Rename Method Timeline

  1. Copy the declaration/definition of the old method to the new method
  2. Compile. Can also commit at this point.
  3. Change the body of the old method to call the new method
  4. Compile and be sure to commit
  5. Find all calls to the old method, and replace with calls to the new method
  6. Compile after each change. Commit at least once.
  7. Remove the old method declaration and definition (if not a public interface)
  8. Compile and commit

Some Examples

  • Introduce Explaining Variable
  • Rename Method
  • Move Method
  • Pull Up Method
  • Change Value to Reference
  • Remove Parameter
  • Extract Hierarchy

Ref: Split Temporary Variable

Ref: Pull-Up Method

  • Methods with identical results in subclasses
  • Move them to the superclass

Ref: Replace Inheritance with Delegation (UML)

Ref: Replace Inheritance with Delegation (Code)

Ref: Replace Inheritance with Delegation

  • A subclass uses only part of a superclasses interface or does not want to inherit data.
  • Create a field for the superclass, adjust methods to delegate to the superclass, and remove the subclassing

Catalog

  • Collected by Fowler
  • Refactoring entry composed of:
    • Name
    • Summary
    • Motivation
    • Mechanics
    • Examples
  • Recent edition examples are in Javascript

Categories

  • Composing Methods
  • Organizing Data
  • Moving Features Between Objects
  • Simplifying Conditional Expressions
  • Simplifying Method Calls
  • Dealing with Generalization
  • Big Refactorings

Composing Methods: Extract Method

Composing Methods: Inline Method

Replace Nested Conditional with Guard Clauses A:

Replace Nested Conditional with Guard Clauses B:

Inline Temp

Replace Temp with Query

Why: Design Preservation

  • Code changes often lead to a loss of the original design
  • Loss of design is cumulative:
  • Difficulties in design comprehension -> Difficulties in preserving design -> More rapid decay of design

  • Refactoring improves the design of existing code

Why: Comprehension

  • Developers are most concerned with getting the program to work, not about future developers
  • Refactoring makes existing code more readable
  • Increases comprehension of existing code, leading to higher levels of code comprehension
  • Often applied in stages

Why: Debugging

  • Greater program comprehension leads to easier debugging
  • Increased readability leads to the discovery of possible errors
  • Understanding gained during debugging can be put back into the code

Why: Faster Programming

  • Counterintuitive argument made by Fowler
  • Good design is essential for rapid development
  • Poor design allows for quick progress, but soon slows the process down
  • Spend time debugging
  • Changes take longer as you understand the system and find duplicate code
  • Supported by Lehman’s laws

When?

  • Adding Functionality
  • Comprehension of existing program
  • Preparation for addition
  • Debugging
  • Code Review
  • Preparation for suggestions to other programmers
  • Stimulates other ideas