Refactoring in Small Steps

advertisement
Test Driven
Lasse Koskela
Chapter 3: Refactoring in Small Steps
Paul Ammann
http://cs.gmu.edu/~pammann/
Overview
• Exploring a Potential Solution
• Changing Design in a Controlled Manner
• Taking the New Design Further
The Most Powerful Designs Are Always the Result of a
Continuous Process of Simplification and Refinement.
7/1/2016
2
Recalling the Problem
• Existing Design Replaced Variables Via Simple Matching
– For all variables v, replace ${v} with its value:
result = result.replaceAll(regex, entry.getValue())
• Failing test: @Before sets template value to “${one}, ${two}, ${three}”
@Test
public void variablesGetProcessedJustOnce() throws Exception {
template.set(“one”, “${one}”);
template.set(“two”, “${three}”);
template.set(“three”, “${two}”);
assertTemplateEvaluatesTo(“${one}, ${three}”, ${two});
}
Tweaking the Current Design Won’t Make This Test Pass.
7/1/2016
3
Exploring A Potential Solution
• Exploring a “Segment” Solution for Templates
• Prototyping with Spikes
– A Spike is A Detour to Learn
– In Template Example, Learning is About regex
• Learning by Writing Tests
– Need to Figure Out An API?
• Write Some Test Code That Uses The API
• RegexlearningTest
• Example Spike for Learning an API
– Note Koskela’s Misunderstanding of the Role of Parentheses
• Simple Here: We’re Finding Variables in a Template
– Compiling Regex Patterns, Matching Expressions
Get Smarter On The Side, Then Apply
7/1/2016
4
Changing Design in Controlled Manner
• Creating an Alternative Implementation
– Starting With the Low Hanging Fruit
• TDD Development of a Template Parser
– Removing Duplication From Tests
• Refactoring Is Always Important
– Applying Learning From the Spike
• Final Code Version (note Segment class, originally String)
private void append(String segment, StringBuilder result) {
if (isVariable(segment) { evaluateVariable(segment, result); } // dispatching 
else { result.append(segment);}
}
• Koskela Refactors Substantially
– TemplateParse.java
Now We Can Parse; Next Step Is To Use Parser
7/1/2016
5
Changing Design in a Controlled
Manner - Continued
• Switching Over Safely
– Adopting the New Implementation
• Recoding the evaluate() method
– Cleaning Up By Extracting Methods
• Pull Out The Old Stuff That ‘s No Longer Relevant
• Result is new Template Class
– Template.java
No New Functionality, But Definitely Refactored
7/1/2016
6
Taking the New Design Further
• Keeping Things Compatible
– Building on Existing Functionality
• Note equals(), hashCode() treatment in Segment classes
– Any Worries About This?
• Segment, PlainText , Variable
– Refactoring Logic into Objects
• Tell, Don’t Ask!
• Motivation for Segment class
– Making the Switchover
– Getting Caught By the Safety Net
• Adding Exceptional Behavior!
– Deleting Dead Code and Further Clean Up
Test Set Makes Requirements Concrete
7/1/2016
7
Download