Chapter 3 Refactorings

3.1 Composing Methods

Much of refactoring is devoted to correctly composing methods. In most cases, excessively long methods are the root of all evil. The vagaries of code inside these methods conceal the execution logic and make the method extremely hard to understand – and even harder to change.

The refactoring techniques in this group streamline methods, remove code duplication, and pave the way for future improvements.

3.1.1 Extract Function

used

3.1.2 Inline Function

used

3.1.3 Extract Variable

3.1.4 Inline Temp

3.1.5 Replace Temp with Function

used

3.1.6 Split Temporary Variable

3.1.7 Remove Assignments to Parameters

3.1.8 Replace Method with Method Object

3.1.9 Substitute Algorithm

3.2 Moving Features between Objects

Even if you have distributed functionality among different classes in a less-than-perfect way, there is still hope.

These refactoring techniques show how to safely move functionality between classes, create new classes, and hide implementation details from public access.

3.2.1 Move Method

3.2.2 Move Field

3.2.3 Extract Class

Used

3.2.4 Inline Class

Used

3.2.5 Hide Delegate

3.2.6 Remove Middle Man

3.2.7 Introduce Foreign Method

3.2.8 Introduce Local Extension

3.3 Organizing Data

These refactoring techniques help with data handling, replacing primitives with rich class functionality. Another important result is untangling of class associations, which makes classes more portable and reusable.

3.3.1 Change Value to Reference

3.3.2 Change Reference to Value

3.3.3 Duplicate Observed Data

3.3.4 Self Encapsulate Field

3.3.5 Replace Data Value with Object

3.3.6 Replace Array with Object

3.3.7 Change Unidirectional Association to Bidirectional

3.3.8 Change Bidirectional Association to Unidirectional

3.3.9 Encapsulate Field

3.3.10 Encapsulate Collection

3.3.11 Replace Magic Number with Symbolic Constant

3.3.12 Replace Type Code with Class

3.3.13 Replace Type Code with Subclasses

3.3.14 Replace Type Code with State/Strategy

3.3.15 Replace Subclass with Fields

3.3.16 Replace Atomic with S3 Class

3.4 Simplifying Conditional Expressions

used

Conditionals tend to get more and more complicated in their logic over time, and there are yet more techniques to combat this as well.

3.4.1 Consolidate Conditional Expression

3.4.2 Consolidate Duplicate Conditional Fragments

3.4.3 Decompose Conditional

3.4.4 Replace Conditional with Polymorphism

3.4.5 Remove Control Flag

used

3.4.6 Replace Nested Conditional with Guard Clauses

3.4.7 Introduce Null Object

3.4.8 Introduce Assertion

3.5 Simplifying Method Calls

These techniques make method calls simpler and easier to understand. This, in turn, simplifies the interfaces for interaction between classes.

3.5.1 Add Parameter

3.5.2 Remove Parameter

3.5.3 Rename Method

3.5.4 Separate Query from Modifier

3.5.5 Parameterize Method

3.5.6 Introduce Parameter Object

used

3.5.7 Preserve Whole Object

used

3.5.8 Remove Setting Method

3.5.9 Replace Parameter with Explicit Methods

3.5.10 Replace Parameter with Method Call

3.5.11 Replace Parameter with Query

used

Before:

simple_mean <- function(x, length) {
  sum(x) / length
}

After:

simple_mean <- function(x) {
  length <- length(x)
  sum(x) / length
}

3.5.12 Hide Method

3.5.13 Replace Constructor with Factory Method

3.5.14 Replace Error Code with Exception

3.5.15 Replace Exception with Test

3.6 Dealing with Generalization

Abstraction has its own group of refactoring techniques, primarily associated with moving functionality along the class inheritance hierarchy, creating new classes and interfaces, and replacing inheritance with delegation and vice versa.

3.6.1 Pull Up Field

3.6.2 Pull Up Method

3.6.3 Pull Up Constructor Body

3.6.4 Push Down Field

3.6.5 Push Down Method

3.6.6 Extract Subclass

3.6.7 Extract Superclass

3.6.8 Extract Interface

3.6.9 Collapse Hierarchy

3.6.10 Form Template Method

3.6.11 Replace Inheritance with Delegation

3.6.12 Replace Delegation with Inheritance

3.7 Other

3.7.1 Remove Dead Code

used

3.7.2 Change Function Declaration

Used

3.7.3 Replace Loop With Apply

Used

3.7.4 Rename Function

See also: rename variable

Before:

ss <- function(x) {
  sum(x ^ 2)
}

After:

sum_of_squares <- function(x) {
  sum(x ^ 2)
}

“Find in files…” command

3.7.5 Rename Argument

See also: rename function

Having informative variable names in your is important for your readability. One of the main culprits are single letter variable such as w when the fully spelled out word weight isn’t that much longer. This becomes increasingly important once you have many variables and you come back after a break not remembering what pisg means.

Before:

weighted_sum_of_squares <- function(x, w) {
  sum(x ^ 2 * w)
}

After:

weighted_sum_of_squares <- function(x, weight) {
  sum(x ^ 2 * weight)
}

Renaming a variable inside a function can be easily done in RStudio using the “Rename in Scope” shortcut Ctrl/Cmd + Shift + Alt/Option + M.

3.7.6 Rename Variable

used