Project Ramon

A learning journey from a Ruby noob perspective

Ruby Refactoring: Introduce an Explaining Variable

Hello!

Over the past few posts, we’ve seen a few refactoring patterns where we are improving the cleanliness of our code by removing local variables.

There are times when temporary variables can be used to make code more readable. The author suggests that we shouldn’t make light of adding refactorings of this sort however.

Introduce Explaining Variable

This is a technique based around the premise of renaming.

Conditionals with complex expressions can be thought of as good candidates for issuing such a refactor, as they can help to break down these expressions into something more manageable.

Lets look at an example that somwhat resembles the one in the book.

if (meal_plan.meal.breakfast.calories[2] && meal_plan.meal.lunch.calories[2] && meal_plan.meal.dinner.calories[2]) > meal_plan.goals.daily.calories
 "You went over your daily allotment by #{ (meal_plan.meal.breakfast.calories[2] + meal_plan.meal.lunch.calories[2] + meal_plan.meal.dinner.calories[2]) - meal_plan.goals.daily.calories } calories."
elsif (meal_plan.meal.breakfast.calories[2] + meal_plan.meal.lunch.calories[2] + meal_plan.meal.dinner.calories[2]) < 1200
 " 
 "Careful, by eating this little you may be placing your body in storage mode."
else
 "Congratulations! You stayed within your caloric allotment."
end

Now that we have a conditional with reasonably long-winded expressions, lets take a look at the mechanics of this refactoring pattern.

  • Step1: Assign a temporary variable to the result of the complex portion of the expression
  • Step2: Replace the result part of the expression with the value of the temporary variable
  • Step3: Test
  • Step4: Repeat as necessary

The Refactor

The first step instructs us to assign temporary variables to the result portions of the wordy expressions. I’m not certain if I’m deviating from this pattern, but I’m of a mind that all of the meal_plan.meal.breakfast.calories[2] expressions are what needs to be assigned to temporary variables, I’ll also create variables for the return statements.

breakfast = meal_plan.meal.breakfast.calories[2]
lunch = meal_plan.meal.lunch.calories[2]
dinner = meal_plan.meal.dinner.calories[2]
daily_caloric_allotment = meal_plan.goals.daily.calories
total_daily_calories = breakfast + lunch + dinner
LOW_CALORIC_FLOOR = 1200 

# Response strings assigned to variables
too_many_calories_msg = "You went over your daily allotment by #{}"
successful_caloric_msg = "Congratulations! YOu stayed within your allotment."
too_few_calories_msg = "Careful, by eating this little you may be placing your body in storage mode."

The second step guides us towards replacing the long expressions with our newly created temporary variables above.

if total_daily_calories > daily_caloric_allotment
  too_many_calories_msg
elsif total_daily_calories > LOW_CALORIC_FLOOR && total_daily_calories < daily_caloric_allotment 
  successful_caloric_msg
else
  too_few_calories_msg
end

I’ve just repeated step 4 as necessary and the above code snippet is the result! A much simpler read in my opinion.

Conclusion

This refactoring pattern seems to be one that is considered best used in thoughtful moderation. The main benefits of this seems to me to be that it allows for easier reading for yourself and any future maintainers. The author also mentions that before using this pattern, he asks himself if he would be better served with another refactoring option, namely extract method. In the case(s) where Extract Method won’t work, this pattern is then a good way to improve readability.

Stay tuned…

Advertisements

Categories: Uncategorized

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s