Refactoring Grid

The refactoring grid is a toy designed to give you a feel for what refactoring is like, by working in a simple, non-code domain.

[Michael Wainer has made game pieces available here: http://www.cs.siu.edu/~wainer/Pieces4RefGame/pieces4RefGame.html ]

The Domain

There is a grid of “windows,” like this:

Empty Grid

Each square in a window is known as a “pane.” Each pane can contain “tokens”; we’ll use two types, represented as “o” and “x.” A pane can contain any number of tokens. There are refactorings that define how tokens can be added, removed, or moved between panes.

Smells

To refactor, you need a sense of when your system needs improvement.

When there are problems that we can name, we call those “code smells.” A goal of refactoring is to eliminate (or at least minimize) the smells.

Here are four smells that can happen in this system:

  • Basement – there are any tokens in the lower row of windows.
  • Duplication – two of the same token occur in any pane.
  • Conflict – the grid contains both an “x” token and an “o” token (in any panes of any windows).
  • Sou’wester – any window has a token in the lower-left corner, and another token in either the upper-left or upper-right corner.

Here’s a grid that demonstrates each of these smells:

Empty Grid

Here’s a grid that is “smell-free”:

Smell-Free

Refactorings

It’s not enough to know smells; to do anything about them we need transformation rules (refactorings).

Vertical refactorings

V1x.

Rule V1x
Rule V1x

 This rule should be read: “If you see two windows stacked vertically, you can move an x from the pane in the lower right corner to the corresponding pane in the upper window, or vice versa.” (The shading is just to highlight the cells involved in the rule, and has no other significance.)

V2x.

Rule V2x
Rule V2x

V3x.

Rule V3x
Rule V3x

V4x.

Rule V4x
Rule V4x

There are corresponding rules V1o, V2o, V3o, and V4o to move “o” tokens.

Exercise 1.

Try your hand at this refactoring. One step at a time, convert this:

First exercise

to this:

First Exercise Goal

You’ve probably noticed that it’s pretty tedious to move things vertically one at a time. For repetitive refactorings, you may be comfortable taking shortcuts after you’ve done them a few times. (The same thing happens in code. For example, suppose you’re changing the name of something; you might change the first couple carefully, run tests, and then change all the others in one go, without running tests until the end.)

The vertical refactorings are tedious; give yourself permission to do them all at once. (You could call this shortcut rule Vx or Vo).

Exercise 2.

A unit test will be a rule that you can apply to the before and after states to reassure you that a grid has been refactored correctly. What unit test could reassure you that you’ve applied a group of vertical refactorings correctly? (Hint: there’s something true about the grid that is true before and after each of the vertical rules.)

One-pane refactorings

Pxo.

Exercise Starting Point

(There’s no order implied; “ox” = “xo”. The rule says that an “x” and “o” token in the same pane cancel each other out.)

Exercise 3.

A. Remove as many smells as you can with the refactorings you have so far.

Rule P1xx

B. What smells can you eliminate?

One-window refactorings

P1xx.

Rule P1xx
Rule P1xx

P2xx.

Rule P2xx

P3xx.

Rule P3xx
Rule P3xx

Rules P1oo, P2oo, and P3oo are the corresponding rules for “o” tokens. 

Horizontal refactoring

H24x.

Rule H24x
Rule H24x

 
 (This rule applies to any two horizontally adjacent windows.)

Rule H24o is the corresponding rule for “o” tokens.

Examples

Here are a couple examples:

 Example 1.

Example

Example 2.

Example

Exercises

Here are some more exercises for you to try. Eliminate all smells.

Exercise 4.

Exercise

Exercise 5.

Example

Exercise 6.

Exercise

Exercise 7.  Do it yourself.

Exercise

Debrief

Work through the exercises before you try these questions. 

  • Can you detect all the smells right away? Does fixing one smell make you aware of others? (How is this like programming?)
  • What is your strategy for addressing smells?
  • Can you design a strategy where once you’ve “fixed” a window, you don’t have to touch it again? Can you do this for code?
  • Some of the smells are very local; others are more diffuse. How can you detect smells that span several areas of a system?
  • Can any grid be transformed into one with no smells? What about any code?
  • The H24x and H24o refactorings only fix part of the “Sou’wester” smell; define  shortcut transformations that address the rest.
  • These refactorings don’t come with tests; can you devise a test that you can apply to the initial and final states to reassure you that a grid has been refactored correctly?
  • Just for fun, you could try one of these approaches to creating different sets of smells or rules:
    • Create an aesthetic that will clear every box except the lower right pane of the lower right window.
    • Stop worrying about the “Sou’Wester” smell. Drop rule H24x and add rule P4xx instead. Is the system as a whole simpler?
Rule P4xx
Rule P4xx

Rule P4xx. 

  • The “conflict” smell is global. Experiment with more local versions of the smell that still encourage you to apply rule Pxo but allow you to have both “x” and “o” tokens in the same grid.

[Written December 8, 2002. Thanks to Steve Wake for feedback. Correction from Shibukawa Yoshiki, 3-13-03. Updated images and added link to Michael Wainer’s work, Oct. ’09.]