A Catalog of Smells

Posted by Ian Whitney on January 29, 2015

A Catalog of Smells

Early on in Refactoring is a chapter by Fowler and Kent Beck about code smells. Beck apparently coined the phrase earlier, but I think Refactoring is what brought it to prominence. But while Fowler & Beck do a good job of cataloging the smells, they didn’t illustrate them with code samples. I thought it would be useful to discuss the Fowler & Beck smells and alongside samples. So, consider this the first in a series.

Duplicated Code (Refactoring, p.76) is the first smell Fowler & Beck list, which only makes sense as it’s also one of the smells programmers see most often. It’s also one of the most misunderstood. And Fowler & Beck don’t help clarify things with their 2nd sentence:

If you see the same code structure in more than one place you can be sure that your program will be better if you find a way to unify them.

Removing code duplication is also one of the 4 Rules of Simple Design (also partly authored by Kent Beck). In his book The 4 Rules of Simple Design, Corey Haines phrases the rule differently:

Every piece of knowledge should have one and only one representation.

The emphasis is those quotes is mine, to highlight the very different type of duplication they highlight: structure versus knowledge. Let’s get to that example and hopefully show off what I mean.

class Person
  def change_password
    if email.any?
      send_email && log_change
    else
      ask_for_email && send_email
    end
  end

  def add_friend
    if email.any?
      send_email
    else
      ask_for_email && send_email
    end
  end
end

There’s some clear duplication in this code. Let’s combine those two if statements into one with Extract Method.

class Person
  def change_password
    notify(change_password, true)
  end

  def add_friend
    notify(new_friend)
  end

  private

  def notify(type, log = false )
    if email.any?
      send_email(type) 
      log_change if log
    else
      ask_for_email && send_email(type)
    end
  end
end

I’ve extracted the structural duplication, but I don’t know that I’ve made the code better. I have a notify method that takes an unexplained boolean in one call, but not the other. And if I ever want to change add_friend so that it emails 2 people, then I run into a problem of accidentally stepping on the behavior of change_password.

What I missed in my rush to remove a duplicate structure was a chance to clarify and refine the knowledge in my system. I clearly need a class (or more) responsible for managing and sending emails.

class Person
  def change_password
    MailBuilder.new({type: change_password, log_sending: true}).send
  end

  def add_friend
    MailBuilder.new({type: new_friend, log_sending: false}).send
  end
end

And if you now use Extract Method on those duplicate MailBuilder calls?

class Person
  def change_password
    send_mail({type: change_password, log_sending: true})
  end

  def add_friend
    send_mail({type: new_friend, log_sending: false})
  end

  private

  def send_mail(options)
    MailBuilder.new(options).send
  end
end

You get the benefit of isolating the knowledge of MailBuilder and its send method to just one place, which isn’t a bad thing. But it might be a little bit of overkill. Depends on how many different mail-sending methods, I think.

Link-o-rama.

A double-dose of Pull Request links. GitHub offers “How to Write the Perfect Pull Request” and Atlassian countered one day later with “A Better Pull Request”. Sticking with the false duplication theme, the titles sound almost identical, but the posts are actually totally different. GitHub’s is about the social act of making a pull request. How to write one, how to handle feedback, why you should use emoji, etc. Atlassian’s is a more technical discussion of how to best merge branches. The difference between the two companies seems perfectly illustrated by these two posts.

On the 8th Light blog, Elizabeth Engelman offers a great illustration of the Single Responsibility Principle, which is a topic I’m sure I’ll get into on Design Is Refactoring. Eventually.

Non-code link of the weeks is to the Velo Orange blog. VO is a small maker of gorgeous bikes, and they also make a variety of excellent bike parts, should you not be able to afford one of their full bikes. When I get a chance to update my current bike I have my eyes on these sweet fenders, probably with some leather mud flaps.

Next week’s post on Design is Refactoring will hopefully be the polymorphism post that I promised a few weeks back. Or maybe it won’t. I’ve been puzzling over my Exercism problem for the week and I’m not yet sure what principle it will best illustrate. Once I see what kind of terrible code I write I’ll have a better idea.