I spent yesterday morning practicing a refactoring in Kotlin I wanted to potentially demonstrate for a workshop, and after half a dozen unsuccessful attempts, I found a way that seems relatively safe. I thought it might be useful to document it here, both for myself for the future and anyone else who might be interested.
My goal here is to encapsulate the data used in this function for calculating quotes for fitted carpets. The solution I’m thinking of is closures.
How do I get from this to closures being injected into quote() safely? Here’s how I did it in IntelliJ.
- Use the Function to Scope… refactoring to extract the body of, say, the roomArea() function into an internal function.
2. As a single step, change the return type of roomArea() to a function signature that matches area(), return a reference to ::area instead of the return value from area(), and change quote() to invoke the returned area() function. (Phew!)
3. Rename roomArea() to room() so it makes more sense.
4. In quote(), highlight the expression room(width, length) and use the Extract Parameter refactoring to have that passed into quote() from the tests.
5. Now we’re going to do something similar for carpetPrice(), with one small difference. Next, as with roomArea(), use the Function to Scope refactoring to extract the body of carpetPrice() into an internal function.
6. Then swap the return value with a reference to the ::price function.
7. Now, this time we want the area to be passed in as a parameter to the price() function. Extract Parameter area from price(), change the signature of the returned function and update quote() to pass it in using the area() function. Again, this must be a single step.
8. Change the Signature of carpetPrice() to remove the redundant area parameter.
9. Rename carpetPrice() to carpet() so it makes more sense.
10. Extract Parameter for the expression carpet(pricePerSqrMtr, roundUp) in quote() called price()
If you want to have a crack at this yourself, the source code is at https://github.com/jasongorman/kotlin_simple_design/tree/master/fp_modular_design , along with two more examples (an OO/Java version of this, plus another example that breaks all the rules of both Simple Design and modular design in Kotlin.