---
title: Name It
teaser:
tags: web,ruby,good code
author: Mike Burns
published_on: 2012-07-24
---

There will be Ruby in the middle of this blog post. But first, a
  tangent in which we explore the lambda calculus. Don't worry too much
about being lost in this next section; we'll fix that immediately
afterward.

## A Simple Language

There is a programming language named the lambda calculus. It's rather minimal: an expression, `E`, is one of three things:

* a variable, `V`, like `a`, `b`, or `c`
* a function of one parameter, written <code>&lambda;V.E</code>
* two expressions applied to each other, written `E E`

For example, the identity function is written:

<pre><code>&lambda;x.x</code></pre>

And a function that takes two arguments and produces the first is written:

<pre><code>&lambda;x.&lambda;y.x</code></pre>

You might want to [try it out interactively](https://trylambda.com/).

We can encode numbers using this programming language, with some creativity. For example, this is the number zero:

<pre><code>&lambda;f.&lambda;x.x</code></pre>

And this is one:

<pre><code>&lambda;f.&lambda;x.f x</code></pre>

And this is two:

<pre><code>&lambda;f.&lambda;x.f f x</code></pre>

And so on. We can even add them, using this addition expression:

<pre><code>&lambda;m.&lambda;n.&lambda;f.&lambda;x.m f (n f x)</code></pre>

(This is far too tangental, but this definition of numbers and addition is an early example of object-oriented programming.)

For example, to add the number one and the number two, we'd write this:

<pre><code>(&lambda;m.&lambda;n.&lambda;f.&lambda;x.m f (n f x)) (&lambda;f.&lambda;x.f x) (&lambda;f.&lambda;x.f f x)</code></pre>

## Name It

There is an oft-included "extension" to the lambda calculus that might help: naming. Let's add this expression to our language:

* a name definition, written <code>VALUE &equiv; E</code>

So now we can write:

<pre><code>
ONE &equiv; &lambda;f.&lambda;x.f x
TWO &equiv; &lambda;f.&lambda;x.f f x
ADD &equiv; &lambda;m.&lambda;n.&lambda;f.&lambda;x.m f (n f x)

THREE &equiv; ADD ONE TWO
</code></pre>

## Law Of Demeter

Here is another case, in another programming language, where naming is useful:

    User.where('admin').each do |user|
      user.articles.where('published_at IS NULL').each do |article|
        article.update_attributes(published_at: Time.now)
      end
    end

Here it is after introducing some names:

    User.admins.each(&:publish_articles)

And here it is after a further simplification:

    User.publish_admin_articles

## Take It Further

In the first naming section, we named concrete nouns; in the second, we named verbs.  Let us now name a concept:

    class SignUp
      def initialize(params)
        @account_params = params[:account]
        @user_params = params[:user]
        @credit_card_params = params[:credit_card]
      end

      def run
        account = Account.new(@account_params)
        if account.save
          user = User.new(@user_params.merge(account: account))
          if user.save
            credit_card = CreditCard.new(@credit_card_params.merge(user: user))
            if credit_card.charge
              user.charged
            end
          end
        end
      end
    end

Above we have named the concept of signing up, and given it behavior. We can name even more concepts: merging two users, generating flash messages, processing image files, building a model of a couch.

## Taking It Too Far

![Mulva? Gipple? Dolores!](http://media.tumblr.com/tumblr_m7m9jk8dds1qztl3j.jpg)

The average human vocabulary is around 10000 words. While the jury is still out on what the maximum number is, we can all agree that keeping the number of names low is useful for keeping all of an app in your head at once.

There is another trick for more easily understanding an app: a common vocabulary.  When you see a `User` model, you know what it means; when you see an `Enrichment` class, that's puzzling. By naming more things uniquely, you have reduced the vocabulary overhead.

Or is this a red herring? Another way to keep the vocabulary low is to name everything, but have very few things to name. Push stuff into frameworks, libraries, and <abbr title="Application Programming Interface">API</abbr>s when possible, and out of scope otherwise. You ain't gonna need that `Bracelet` class.

## Not Taking It Far Enough

The idea of a common vocabulary is enticing. User, article, comment, controller, singleton, and enumeration are all names we Rails developers understand. [Monad](http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#t:Monad), [cut](http://en.wikibooks.org/wiki/Prolog/Cuts_and_Negation), [disjunction](http://hyperphysics.phy-astr.gsu.edu/hbase/electronic/or.html), [pointer](http://boredzo.org/pointers/)&mdash;those are other people's vocabularies. But what if &hellip;

What if we outgrew our vocabulary and started poaching theirs? And not like how we poached "functional test" and "closure"&mdash;I mean actually use their words the way they are defined.

What if instead of this &hellip;

    def map(&f = lambda {|x| x})
      accumulation = []
      each do |element|
        accumulation << f.call(element)
      end
      accumulation
    end

&hellip; we wrote this:

    def map(&f = id)
      inject([]) do |accumulation, element|
        accumulation + [f.call(element)]
      end
    end

Heck, what if we went further and wrote this:

    def map(&f = id)
      inject(empty) do |accumulation, element|
        accumulation + wrap(f.call(element))
      end
    end

This uses a method `Kernel#id` to name the common `lambda {|x| x}` abstraction; a method `empty` that produces the empty version of whatever object this `Enumerable` is mixed into; and a similarly-defined method, `wrap`, that projects the given object into the `Enumerable`. Now it produces arrays, linked lists, sets, tries, [maybes](https://thoughtbot.com/blog/post/20907555103/rails-refactoring-example-introduce-null-object), and so on, as needed.

And now we can use the names identity function, functor, and monoid, too.

## Readability and Conceptualization

Just as our lambda calculus example was greatly simplified by naming our functions, our way-too-long methods can be improved by naming our methods. As with anything, though, there is a trade-off that you must carefully consider.

Here's an example of some code with very few names:

    def acquire_access_token_for(c)
      res = Net::HTTP.start('github.com', 443, use_ssl: true) do |http|
        r = Net::HTTP::Post.new('/login/oauth/access_token')
        r.set_form_data('client_id' => '1234123',
                        'client_secret' => 'basdu9as',
                        'code' => c)
        http.request(req)
      end

      case res
      when Net::HTTPsuccess
        b = res.body
        if b['access_token'].any?
          b['access_token'].first
        else
          raise b['error'].first
        end
      else
        raise res.inspect
      end
    end

Here's the same example, with more names:

    def acquire_access_token_for(code)
      access_token_response = access_token_post(code)

      case access_token_response
      when Net::HTTPsuccess
        extract_access_token_from(access_token_response)
      else
        handle_access_token_failure(access_token_response.message)
      end
    end

    private

    GITHUB_CLIENT_ID = '1234123'
    GITHUB_SECRET = 'basdu9as'

    def access_token_post(code)
      Net::HTTP.start(*http_connection) do |http|
        request = Net::HTTP::Post.new(github_access_token_path)
        request.set_form_data('client_id' => GITHUB_CLIENT_ID,
                              'client_secret' => GITHUB_SECRET,
                              'code' => code)
        http.request(request)
      end
    end

    def http_connection
      [
        github_access_token_uri.host,
        github_access_token_uri.port,
        use_ssl: true
      ]
    end

    def github_access_token_path
      github_access_token_uri.path
    end

    def github_access_token_uri
      URI.parse(github_access_token_url)
    end

    def github_access_token_url
      'https://github.com/login/oauth/access_token'
    end

    def extract_access_token_from(successful_http_response)
      body = CGI.parse(successful_http_response.body)
      if body['access_token'].any?
        body['access_token']
      else
        handle_access_token_failure(body['error'].first)
      end
    end

    def handle_access_token_failure(error_message)
      raise error_message
    end

As you can see, there's a trade-off: on the one hand, you can now read it with ease, debug more easily, and have a vocabulary with which to discuss it with others. On the other hand, it takes more vertical space.

## Naming As a Building Block

Naming is the most powerful abstraction possible. By naming something, you give other people the ability to build atop it. By re-using a name you build a common vocabulary, encouraging more people to build. Naming turns a blob of code into a sequence of patterns. Giving a name to something develops it into a concept with analogies.

So, name it.
