Refactoring Models

Learn about refactoring models, refactoring importance, and break up complexity.

In a TDD process, much of the design takes place during the refactoring step. Much of this design happens under the guise of cleanup: looking at parts of the code that seem overly complicated or poorly structured and figuring out how best to rearrange them.

Refactoring importance

Just because the refactoring step includes cleanup doesn’t mean we can skip this step when we’re in a hurry. Don’t do that. Refactoring is not a luxury. Refactoring is where we think about our code and how best to structure it. Skipping refactoring will slowly start to hurt, and by the time we notice the problem, it’ll be much harder to clean up than if we had addressed it early.

Note: Refactoring is where a lot of design happens in TDD, and it’s easiest to do in small steps. Skip it at your own peril.

At the most abstract level, we’re looking for the following three things:

  1. Complexity to break up
  2. Duplication to combine
  3. Abstractions waiting to be born

Break up complexity

Complexity will often initially manifest itself as long methods or long lines of code. If we’re doing a “quick to green” first pass of the code to make the tests pass, there will often be a line of code with lots of method chaining or the like. It’s almost always a good idea to break up long methods or long lines by extracting part of the code into its own method. In addition to simplifying the original method, we have the opportunity to give the method we’re creating a name that is meaningful in the domain and that can make our code self-documenting.

Local variables

Booleans, local variables, and inline comments are almost always candidates for extraction:

  • Any compound boolean logic expression goes in its method. It’s much harder than we might think for people to understand what a compound expression does. We should give people reading our code a fighting chance by hiding the expression behind a name that expresses the code’s intent, such as valid_name? or has_purchased_before?.

  • Local variables are relatively easy to break out into methods with the same name as the variable. In Ruby, code that uses the variable doesn’t need to change if the variable becomes a method with no arguments. Having several local variables is a huge drag on complex refactorings. We’ll be surprised at how much more flexible our code feels if we minimize the number of local variables in methods.

  • In long methods, sometimes a single-line comment breaks up the method by describing what the next part does. This nearly always is better extracted to a separate method with a name based on the comment’s contents. Instead of one twenty-five-line method, we wind up with a five-line method that calls five other five-line methods, each of which does one thing and each of which has a meaningful name in the context of the application domain.

Note: Try to extract methods when we see compound booleans, local variables, or inline comments.

Get hands-on with 1200+ tech skills courses.