Local variables - the new global variables?

The topic of tonight’s Melbourne Ruby meetup was “things I wish I’d known earlier”.
This was my contribution.

presentation slide

Last year I read the Refactoring book and it gave me some surprising new insights into local variables.

presentation slide

If you look through the contents of the book you’ll quickly find the refactoring “Introduce explaining variable”.

Imagine you have a method that does some processing that is not particularly obvious. Here’s an example that selects a certain number of evenly spaced elements from an array:

presentation slide

You can make it more readable by assigning an intermediate value to a well-named local variable, like so:

presentation slide

There are times when that will be a great help, and you should definitely perform such refactorings.

Tonight, however, I want to focus on the more general case, which is that local variables stink.

presentation slide

Local variables are bad because they are often introduced as a premature optimisation.

Take this Library class for example, which can prepare a report on overdue books for the library detective. It uses the total number of overdue books twice, but it manages to only calculate it once, by storing the value in a local variable. The same is done with the total count of all books.

presentation slide

These are premature optimisations that don’t aid readability or have any perceptible influence on performance, yet they do add additional lines of code.

They should be removed by repeating the calculation call wherever its result is required.

presentation slide

The example of counting elements in an array is perhaps trivial. The mistake is easier to make with other kinds of calculations. Data on disk or across a network may require further consideration, but when it is in memory you should assume that the results of sorting, arithmetic, string manipulation and most other processing can be instantly recalculated as required.

Our #detective_report method still uses the explaining variable percent_overdue. The problem with this is that the logic that went into calculating that value is not ready for reuse. When we add a method to tell us whether late fees need to be reviewed (which they obviously should be if more than 50% of our books are overdue), we end up with duplication.

presentation slide

If we replace that explaining local variable with a method, we significantly improve readability as well as reducing duplication.

presentation slide

Local variables are bad because they hide Law of Demeter violations and other complexity.

The #can_borrow? method says a borrower can borrow a book if they don’t already have a book out and their membership record shows no fees are due.

It’s a fairly short and clear method. We just make a couple of simple method calls, and we don’t have the long method chains that Law of Demeter violations are often recognised by.

presentation slide

However, if we remove our local variables, the equivalent code reveals itself as ridiculously inappropriate. It is reaching deep into the record object - coupling itself to fee structures and introducing duplication of fee handling logic.

ActiveSupport’s #try method would shorten this, but it’s still a clear candidate for refactoring.

We can fully resolve these issues by introducing a new method, good?, which shows whether a borrower’s record finds them in good standing.

presentation slide

Local variables are bad because they go together with big methods.

presentation slide

Big methods usually do several things, and local methods help them store the intermediate values that appear in their multi-part processing.

As well as being involved in the work of methods that are already big, local variables make methods even bigger because they usually add at least one line of code each as they come into existence.

So, are they the new global variables?

presentation slide

Yes!

Local variables are the new global variables because as you write better code, you will use them less, and because when they appear in existing code, it is usually a sign that you should refactor.

presentation slide

The next time you discover or create a local variable, consider extracting a method instead. You’ll find yourself with cleaner code and a clearer mind in no time flat.