Show Intent with Better Naming

I had an interesting experience at a code retreat with the creator, Corey Haines. I created some code that I felt was really perfect. I didn’t think there was room for much improvement, but it only took Corey a few seconds in passing to find a flaw. It starts with this list of rules for simple design:

  1. Passes tests – the code should be test-driven, and the tests should all pass.
  2. No duplication – often known as DRY – don’t repeat yourself. Every distinct piece of information in the system should have one (and only one) representation in the code.
  3. Expresses intent – the code should be self-explanatory.
  4. Small – methods, classes, indeed the entire application shouldn’t be any bigger than absolutely necessary.

My Original Version

I won’t explain what this code is supposed to do. That might defeat the point. See if you can figure out which principal I violated with this code. I’ll say it’s not Rule #1, but showing the tests would take up too much room.

def new_status current_status, neighbor_count
  return :alive if neighbor_count == 3
  return current_status if neighbor_count == 2

The Problem

Corey asked me one question: what if one of the requirements changes? And there it was. In an attempt to do the most in the fewest lines, I’d over-refactored the method. Not only had I made the method brittle if business requirements should change in the future, I’d factored out the intent of the method itself.

As usual, one good software practice begets another. Test-driven development results in smaller, simpler methods for instance. And in this case, showing intent in your code reduces brittleness. So how do you accomplish this?

The Solution

Express the problem domain in the code itself. Here’s my example, reworked:

def new_status current_status, neighbor_count
  return :dead if overpopulated?(neighbor_count)
      || underpopulated?(neighbor_count)

  return :alive if population_perfect?(neighbor_count)
def overpopulated? neighbor_count
  neighbor_count > 3
def underpopulated? neighbor_count
  neighbor_count < 2
def population_perfect? neighbor_count
  neighbor_count == 3

This code is longer, but it shows intent much more clearly. You don’t even need to know what “overpopulated” is to understand what the method is doing. But if you want to know, or need to change it, it’s easy. In fact, we’re passing neighbor_count around a lot, so it looks like it’s time to abstract this into a class:

class Cell
  def initialize current_status, neighbor_count
    @current_status = current_status
    @neighbor_count = neighbor_count
  def next_status
    return :dead if overpopulated? || underpopulated?
    return :alive if population_perfect?
  def overpopulated?
    @neighbor_count > 3  
  def underpopulated?
    @neighbor_count < 2
  def population_perfect?
    @neighbor_count == 3

Now the code is much more readable, and understandable. We’re now clearly showing intent. And now, just for fun, the tests:

class CellTest << Test::Unit::TestCase
  def test_should_die_when_alive_and_overpopulated
    cell = :alive, 4
    assert_equal :dead, cell.next_status
  def test_should_die_when_alive_and_underpopulated
    cell = :alive, 1
    assert_equal :dead, cell.next_status
  def test_should_live_when_alive_and_perfect_population
    cell = :alive, 3
    assert_equal :alive, cell.next_status
  def test_should_stay_alive_by_default_when_alive
    cell = :alive, 2
    assert_equal :alive, cell.next_status
  def test_should_die_when_dead_and_overpopulated
    cell = :dead, 4
    assert_equal :dead, cell.next_status
  def test_should_die_when_dead_and_underpopulated
    cell = :dead, 1
    assert_equal :dead, cell.next_status
  def test_should_live_when_dead_and_perfect_population
    cell = :dead, 3
    assert_equal :alive, cell.next_status
  def test_should_stay_dead_by_default
    cell = :dead, 2
    assert_equal :dead, cell.next_status

Tags: , , , , ,

5 Responses to “Show Intent with Better Naming”

  1. Chris Whamond Says:

    This is great, Jaime. I’m glad to see someone talk about the importance of naming to reveal intent. I find this is one of the easiest ways to improve my productivity anywhere in the stack. One of my takeaways from reading “Rails Anti-patterns” recently is that really long (and almost verbose) method names which clearly reveal intent trump short, concise method names almost every time. Good naming is even more critical when building rich, Ajax-laden apps. Might be a good meetup topic: naming. Thanks for the post.

  2. Dan Carper Says:

    I had the very same experience. Was at a code retreat hosted by Corey. Thought I had written some great code.. Took Corey 2 seconds to break my code but not my tests..

    Good stuff!


  3. jim Says:

    Cool post, I like the idea of showing intent in method names. This can help reduce comments and use self-documenting code instead. I’ve seen so many out-of-date misleading comments in old code that I rarely trust comments anymore.

Leave a Reply

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

You are commenting using your 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

%d bloggers like this: