## Code Along

A *code-along* is a story about coding in which you are encouraged to “code up” all the examples in the story. In a code-along you should **not** cut-and-paste.

In this code along, we will explore *code refactoring* which, when the context is understood, is simply referred to as *refactoring*.

Code can be refactored in a variety of different ways. The following list summarizes the refactorings used in this code along.

- Converting a sequence of function calls into a nullary function.
- Converting a nullary function declaration into a parameterized function declaration.
- Introducing a wrapper function.
- Factoring a constant out of the body of a function declaration.

## Code to be refactored

Below is a simple program that creates the blue, yellow, red, green square (shown below the code). It contains function declarations.

```
open Level_3;
build2D (32,32);
put2D (1,1) BLUE (0,0);
put2D (1,1) YELLOW (1,0);
put2D (1,1) RED (1,1);
put2D (1,1) GREEN (0,1);
show2D "4 colored square";
```

## Step 1: Move top-level function calls to function declaration.

In this first refactoring step, the Bricklayer function calls that create the square are moved to the body of a nullary function declaration called *fourColoredSquare*. The square is then created by the function call *fourColoredSquare().*

open Level_3; fun fourColoredSquare () = ( put2D (1,1) BLUE (0,0); put2D (1,1) YELLOW (1,0); put2D (1,1) RED (1,1); put2D (1,1) GREEN (0,1) ); build2D (32,32); fourColoredSquare (); show2D "4 colored square";

## Step 2: Introduce (x,z) coordinate parameter.

The next refactoring introduces the (x,z) coordinate parameter to the function *fourColoredSquare*. This change requires: (1) the creation of the formal parameter (x,z), (2) conversion of all absolute coordinates (e.g., (1,0)) to relative coordinates (e.g., (x+1,z)) in the body of the function, and (3) removal of the actual parameter () and addition of the actual parameter (0,0) to the *fourColoredSquare *function call.

open Level_3; fun fourColoredSquare (x,z) = ( put2D (1,1) BLUE (x , z ); put2D (1,1) YELLOW (x+1, z ); put2D (1,1) RED (x+1, z+1); put2D (1,1) GREEN (x , z+1) ); build2D (32,32); fourColoredSquare (0,0); show2D "4 colored square";

## Step 3: Introduce 4x scalable put as a wrapper function.

This next refactoring actually changes the artifact from a 2×2 four colored square to an 8×8 four colored square. This is accomplished by introducing a wrapper function, called *myPut*, whose purpose is to modify all calls to the function *put2D*. To facilitate the introduction of *myPut* into the code, the *myPut* function is declared in such a way that its signature (i.e., the arguments it takes, and order in which it takes them) is identical to Bricklayer’s *put2D* function. Aligning the function signatures in this way enables the conversion from *put2D* to *myPut* to be accomplished by simply replacing all occurrences of *put2D* with *myPut* – a change that be easily accomplished using the find/replace function of a text editor.

open Level_3; fun myPut (xSide,zSide) brick (x,z) = put2D (4*xSide,4*zSide) brick (4*x,4*z); fun fourColoredSquare (x,z) = ( myPut (1,1) BLUE (x , z ); myPut (1,1) YELLOW (x+1, z ); myPut (1,1) RED (x+1, z+1); myPut (1,1) GREEN (x , z+1) ); build2D (32,32); fourColoredSquare (0,0); show2D "4 colored square";

## Step 4: Factor out the scale constant from myPut.

The *myPut* function declaration contains four occurences of the scale factor 4. An important goal when writing code is to express every idea in your program only once. For example, suppose we wanted to use our program to create a (large) set of four colored squares having different sizes. To create a 10×10 four colored square the scale factor 4 would need to be changed to the scale factor 5. In particular, each occurence of the scale factor would need to be changed. We would like to redesign our program so that there is only one occurrence that needs to be changed. We will accomplish this through two refactoring steps. The first refactoring is shown here and lifts the scale factor 4 (a constant) out of the body of the *myPut* function declaration. This is accomlished by adding the formal parameter *scale* (any identifier will do) and then replacing all occurrences of the the scale factor 4 in the body of the *myPut* function with the formal parameter *scale*. In addition, all calls to the function *myPut* must contain the scale factor 4.

open Level_3; fun myPut scale (xSide,zSide) brick (x,z) = put2D (scale*xSide,scale*zSide) brick (scale*x,scale*z); fun fourColoredSquare (x,z) = ( myPut 4 (1,1) BLUE (x , z ); myPut 4 (1,1) YELLOW (x+1, z ); myPut 4 (1,1) RED (x+1, z+1); myPut 4 (1,1) GREEN (x , z+1) ); build2D (32,32); fourColoredSquare (0,0); show2D "4 colored square";

## Step 5: Factor out the scale constant from fourColoredSquare.

The previous refactoring moved the scale factor 4 out of the body of the *myPut* function and into the body of the *fourColoredSquare* function. Since the constant 4 occurs multiple times in the body of the fourColoredSquare the goal of expressing this scale value exactly once in the program has not been reached. So we apply the same refactoring described in the previous step to the funtion *fourColoredSquare*. We introduce a formal parameter named *scale* (keeping the name consistent with our previous refactoring step – since this represents the same idea) and replace all occurences of the scale factor 4 in the body of the function *fourColoredSquare* with the formal parameter *scale*. We then need to add the scale factor 4 to every call to the the function *fourColoredSquare*. There is only one such call so we have reached the goal of having exactly one occurence of the scale factor 4 in the program.

open Level_3; fun myPut scale (xSide,zSide) brick (x,z) = put2D (scale*xSide,scale*zSide) brick (scale*x,scale*z); fun fourColoredSquare scale (x,z) = ( myPut scale (1,1) BLUE (x , z ); myPut scale (1,1) YELLOW (x+1, z ); myPut scale (1,1) RED (x+1, z+1); myPut scale (1,1) GREEN (x , z+1) ); build2D (32,32); fourColoredSquare 4 (0,0); show2D "4 colored square";

## Step 6: Add brick parameters to fourColoredSquare.

This last coding example shows an artifact that is created using four calls to the function *fourColoredSquare*. Care needs to be taken when scaling – especially when creating an artifact using different scaling factors. A interesting question for the code below is: “If the fourColoredSquare function call sequence is extended, will the squares always be touching each other?” What about if we change the size of our initial square from 2×2 to 3×3? Is there a theory that underlies the creation of such artifacts using the algorithm shown in this code?

open Level_3; fun myPut scale (xSide,zSide) brick (x,z) = put2D (scale*xSide,scale*zSide) brick (scale*x,scale*z); fun fourColoredSquare scale b1 b2 b3 b4 (x,z) = ( myPut scale (1,1) b1 (x , z ); myPut scale (1,1) b2 (x+1, z ); myPut scale (1,1) b3 (x+1, z+1); myPut scale (1,1) b4 (x , z+1) ); build2D (32,32); fourColoredSquare 1 BLUE YELLOW RED GREEN (0,0); fourColoredSquare 2 BLUE YELLOW RED GREEN (1,1); fourColoredSquare 3 BLUE YELLOW RED GREEN (2,2); fourColoredSquare 4 BLUE YELLOW RED GREEN (3,3); show2D "4 colored square";