Linguistically motivated refactoring

Posted by Piers Cawley on Aug 8, 2006

When naming a variable, method, parameter or class, give it a name that fits well with the language and concerns of the scope in which you are using it.

Here’s some Ruby code:

def test_can_load_unique_articles
number_of_iterations = 8

articles = create_articles(number_of_iterations) do create_valid_article end

assert_equal number_of_iterations - 1, articles.first.related_articles.size end

def create_articles(number_of_iterations) … end

What do you notice about number_of_iterations in the definition of test_can_load_unique_articles? I notice that it’s wrongly named. The name has been chosen to make sense in the context of the loop in the middle of the method, rather than in the assertion at the end - the clue is in the name of create_articles’s parameter. In a test method, it seems to me, one of the most important things to do is to ensure that the assertions read as clearly as possible.

Consider:

def test_can_load_unique_articles
family_size = 8

articles = create_valid_article_family(family_size)

assert_equal family_size - 1, articles.first.related_articles.size end

def create_valid_article_family(size) create_articles(size) {create_valid_article} end

def create_articles(number_of_iterations) … end

Look at how the assertion becomes clearer. In a family with n members then obviously any member of that family will have n - 1 relations. I’ve also interposed a helper method between the test and create_articles. The idea is to make the language used within the test method internally consistent so the test can be read quickly to understand its intent, before chasing down any method definitions whose behaviour isn’t immediately apparent.

I’ve found this sort of linguistically motivated refactoring to be a very handy practice for increasing code clarity. I should do it more often.

With apologies to Paul Ingles - who must be getting sick of me bashing on this particular chunk of code by now. The article I took this code from makes a good point about striving to keep the language within your code relevant to the problem domain, and how different programming languages make that easier or harder.

And now I really am gone fishing.