online shoes store xkshoes,here check the latest yeezy shoes click here.

know more about 2020 nike and adidas soccer cleats news,check shopcleat and wpsoccer.

Refactoring By Example

Kent Beck, Three Rivers Institute
September 2007

 

I noticed a curious-but-effective twist on refactoring the other day—refactoring by example. It uses two of the principles of test-driven development—dividing tasks into more-approachable sub-tasks and working by example.

In Short

To change a method’s signature, change one of the uses of the method and use Quick Fix to change the method itself and its uses instead of using the Change Method Signature refactoring.

Explanation

Working by example has proven to be a powerful metaphor for programming. Query By Example allowed people to search databases. Various schemes allowed people to program by example. Test-driven Development: By Example[1], showed how to re-structure the workflow of development by introducing examples-as-tests one at a time and modify the system to match. Working by example appeals to concrete thinkers who best digest theory with a large dose of reality.

Test-driven development uses another principle that can help programming: breaking big steps into smaller steps. Reducing programming to small, bite-sized tasks improves the flow of activity and reduces the risk of the paralyzing fear of a seemingly-impossible next step. Designing a programming interface, implementing logic, and verifying behavior can be too much to tackle at once. However, sequencing these activities as:

  1. Verifying behavior
  2. Designing the programming interface
  3. Implementing the logic

offers programmers more-manageable tasks at every stage. I may not be able to figure out a whole program at once, but I can almost always figure out what the next answer is I want it to compute (if I can’t, I have no business programming anyway).

The middle task in this modified workflow, designing the programming interface, is done by example. Once I’ve decided that the area of a 5 x 6 rectangle should be 30:

@Test public void area() {

     

      assertEquals(30, area);

}

I need to figure out how to represents the inputs and the operation. For purposes of this test, I can represent a rectangle as a Rectangle object with a width and a height, the creation of a rectangle I can represent as a constructor, and the area calculation I can represent as a method on Rectangle:

@Test public void area() {

      Rectangle input= new Rectangle(5, 6);

      int area= input.getArea();

      assertEquals(30, area);

}

In doing so, I have just designed the programming interface by example. I typed in the interface I wished existed. Then it is my job to grant my own wish, implement the interface, and produce the desired result.

This “by example” style of design has advantages over designing in the abstract. A programming interface designed by example is likely to include all the data needed to complete an operation, since I just calculated the expected answer by hand. A programming interface designed by example is likely to be easy to use, as the use is written before the implementation. A programming interface written by example is not likely to include extra features that aren’t necessary or helpful. In short, designing by example helps rein in some over-engineering by providing immediate feedback.

Once the example of a programming interface is written, Eclipse and similar modern programming environments help the programmer create stub implementations of classes and operations:

This facility allows the programmer to type in class names once, in the example, and have the programming environment use those class names in the generated class.

One challenge of designing by example is that subsequent examples are likely to require changes to the existing design. Eclipse also supports changing the design. The Change Method Signature operation, for example, helps the programmer add, remove, or reorder method parameters. Here is an example of adding x and y parameters to the Rectangle constructor:

Combining a good set of tests serving as examples with incremental refinement of the design of the programming interface can be a very effective way of arriving at a usable, minimal, and yet complete interface.

I recently noticed an application of the “for example” style of design to refactorings that extend a programming interface. Instead of changing all callers and implementors of an operation at once, as in the Change Method Signature operation illustrated above, the idea is that you change the one call you are looking at right now to use the interface you’d like, then use Eclipse to generalize your example to all callers and implementors. This breaks the refactoring into smaller steps, in much the way that satisfying tests one-at-a-time breaks programming up into smaller steps.

For example, suppose I want to generalize my simple Rectangle to also represent rectangles with a non-zero origin. I could pop up the Change Method Signature dialog above, but then I lose the benefits of working by example and I have to make the whole design change at once. Refactoring by example, I change the code in the tests to include x and y parameters to the constructor. Eclipse quite correctly complains that the code will no longer compile:

 

Eclipse generates a list of ways to reconcile this use of Rectangle with the existing class. One option Eclipse suggests is that I could change the design of Rectangle. This is the refactoring by example, because the result of selecting the “Change constructor” option is the same as applying the Change Method Signature refactoring.

 

The arguments are simply appended to the argument list, so I will have to go re-arrange them if I want them in a different order (and in this case I do), but that is a smaller job than figuring out what the arguments should by and what type they should have in the first place.

The principle behind working by example to to encourage activity by starting concretely. Faced with the need to write a program that works in a wide variety of situations, it’s possible to be paralyzed by all the options. Working by example lets you write the program a little at a time. Once you get a program to work for some input you can focus on getting it to work on more input.

Refactoring by example works similarly. Rather than think about all the declarations and implementations of an operation, get the design of this one invocation right and figure out the rest later. Sometimes a programming interface that works in one situation won’t work in others, but that is a rare problem usually diagnosed and fixed quickly. Most of the time, refactoring by example provides a quick route to necessary design changes.

 

Acknowledgements

Thanks to Matthias Kempka of Innoopract Informationssysteme GmbH who first showed me this trick.


[1] Kent Beck, Test-Driven Development: By Example, Addison-Wesley, 2002. Winner of the Jolt Productivity Award and still a source of royalties.