プログラマが知っておくべきネーミングの基本

Naming 101: Programmer’s Guide on How to Name Things

translated on

開発者の間で最も多い問題の一つはネーミングです。どのような名前にしようかと考えるのに何時間費やしたか、また、望ましくない名前を含むコードを理解するのに何時間費やしたか、数え切れません。オブジェクト名、メソッド名、クラス名、その他なんであろうが、そんなことは関係ありません。コードを書くよりも、コードを読む方に時間を費やしているということは証明されているので、良いネーミングをするということは、将来的に応えてくれるということなのです。

好ましい名前を使うことにより、あなたのコードはより良く、また、より簡潔なものとなります。良い名前をつけることで、コードのそれぞれの役割を直観的に識別しやすくなります。そして、将来、あなた自身が読むときと同様に、他の開発者があなたのアプリケーションを読むことを容易にしてくれます。

次の数分で、良いネーミングの重要性を説明し、良い名前を思いつくための有益なコツをシェアしたいと思います。

The Book of Names

抽象度

メソッド名と変数名は、それらが何を意味しているか、に基づいて命名しなければなりません。名前をつける前に、各コードの役割について考えましょう。

例えば、"The distance between Warsaw and Paris(パリとワルシャワ間の距離)" という文字列を返すメソッドについて考察してみましょう。

class DistancePresenter
  def to_s
    'The distance between Warsaw and Paris is 1591 km'
  end
end

シンプルで正しく動作するように見えますが、少し仕様を変えたとしたらどうでしょうか?ここで、距離の単位がキロメートル、マイルの両方ありえるようなケースを考えます。そのためには、クラスに変数を定義する必要があります。この変数は、"km" という文字列を to_s メソッドの中で置き換えるために使うものです。

変数には、変数に入る値よりも高い抽象度の名前をつけるべきです。 つまり、まず最初に変数の目的について考える必要がある、ということを意味します。そうすることにより、より汎用的な名前を付けることができるようになるのですが、かといって、曖昧になってしまってもいけません。以上のことをふまえると、変数名は、その変数の目的を表す必要があり、入りうる値を表すべきではない、ということです。

では、新しい変数の役割とは何でしょうか?オブジェクトにキロメートルやマイルという単語を導入するためのものですので、名前は kilometers_or_miles となるでしょうか。しかし、これでは変数に入る値とまったく同じ抽象度です。他の単位を使用する可能性を考慮するのであれば、kilometers_or_miles という名前はふさわしくないでしょう。もっと汎用的な名前を考えるべきです。キロメートルやマイルは長さの単位なので、望ましい名前は unit となります。変数の役割より一段階高い(より汎用性のある)抽象度になっています。従って、新しいクラスの実装は次のようになります:

class DistancePresenter
  def initialize(unit)
    @unit = unit
  end

  def to_s
    "The distance between Warsaw and Paris is 1591 #{unit}"
  end

  private
  attr_reader :unit
end

ワルシャワとパリ間の距離は、1591キロメートルですが、988マイルでもあります。そのため、単位に応じた正しい値を返すメソッドを定義する必要がでてきました。方法は unit 変数のときと同じです。まず、意味について考えてみましょう。新しいメソッドでは、ワルシャワとパリ間の距離を表す 1591988 という値を返すことが期待されます。メソッドがどのように動作するかは関係ありません。distance_warsaw_paris と命名することもできますが、それでは戻り値と同じ抽象度です。つまり、すべての戻り値をメソッド名に入れてしまっているということです。少し具体的すぎますね。

これらの都市は、将来他の都市(たとえば、ニューヨークとロンドン)に変わるかもしれません。そうなると、distance_warsaw_paris という名前は望ましくないものになり、その都度名前を変更する必要が生じ、結果としてコストが高くなってしまいます。最も良い解決方法は、distance と命名することです。まさに探していたもの(メソッドの内容よりも一段階高い抽象度)です。

以上より、メソッドは次のようになります。

class DistancePresenter
  def initialize(unit)
    @unit = unit
  end

  def to_s
    "The distance between Warsaw and Paris is #{distance} #{unit}"
  end

  private
  attr_reader :unit

  def distance
    if unit == 'km'
      1591
    else
      998
    end
  end
end

抽象度とクラス名

メソッド名と変数名は、その内容よりも一段階高い抽象度で命名されるべきですが、クラスの命名に関してはまた別の話です。クラスの生成時に未来を気にする必要はありません。クラス名は、そのときどきの想定に基づいているべきです。自動車にボートの特徴を持つことを望みません。そのため、現在のアプリの要求が「自動車」であれば、クラス名は Vehicle ではなく Car であるべきです。

サブクラスも同様に命名されるべきです。Car クラスを持つことにより、より具体的なバージョンを定義することができます。たとえば、CarPickup という、より大きな積載スペースを持つ特殊なタイプのCar などです。

これは、一段階高い抽象度での命名は、メソッド名や変数名には適用できますが、クラス名には適用できないということを意味しています。

単一責任の原則

SOLID の原則の一つに、すべてのモジュールおよびクラスは、一つの役割のみを持つべきである、というものがあります。たった一つしか機能がない要素に命名することはより簡単です。

たとえば、ボトル(瓶)について考えてみましょう。ボトルの唯一の役割は、液体を入れる、ということだけです。ボトルモジュールに対し、動き回ったり、ボトルが本来行わないようなことをさせるべきではありません。移動できる液体容器に、一体どのような名前を付けますか?

これはかなり難しい話ですし、ボトルは単なる一例にすぎません。歩く(そしておそらく踊ったり走ったり話したりもする)ボトルについて考えるよりも、単一責任の原則を使ったほうがよいでしょう。液体容器のためにクラスを一つ生成して Bottle と名付け、移動するボトルには他のクラスを生成し、BottleCarrier と名付けます。

単一責任の原則は、変数にも関係しています。メソッドやクラスの変数、もしくはその他の種類の変数だとしても、すべての変数は役割を一つのみ持つべきです。クラスの命名と同様に、役割を一つしか持たない変数の名前を付ける方がよっぽど簡単です。

ドメインを小さく分割する

良いアーキテクチャは、良いネーミングと対になっています。問題を理解しているときには名付けるのは簡単です。良いアーキテクチャを構築するのに役立つテクニックの一つとして、タスクを小さく分割するという方法があります。これは、ネーミングをより素早く、より簡単にしてくれることでしょう。

それについて少し考えてみてください。モジュールやオブジェクトの目的が明確であるときに、それらに名前を付けた方が良くないでしょうか?たとえば、「自動車」を設計するとします。一つのクラスの中ですべての機能に名前をつけることは困難ですが、たくさんの小さな部品に分解すれば、WheelTiresteeringWheel 等があることがわかります。このように、小さくなった構成要素は命名しやすく、また、目的も明確になるでしょう。もし、要素に名前を付けるのが難しいのであれば、それはひょっとしたら、アプリのアーキテクチャに何らかの問題があることを意味しているのかもしれません。

まとめ

変数、メソッド、オブジェクト、クラスに良い名前を付けることにより、遅かれ早かれ報われることになるでしょう。この記事では、良い名前を付けるのに役立つシンプルなテクニックをいくつかご紹介しました。

  • 変数の値やメソッドの内容よりも一段階高い抽象度にすること(クラス名は除く)
  • そしてその名前はクラスの責務を言い表していること
  • 単一責任の原則を尊重すること(SOLID の原則の一つ)
  • 問題部分を小さな要素に分割すること

良いネーミングは、なにも難しくある必要はありません。正しく命名することに時間をかけることには確実に価値があります。上記のコツを用いることにより、その手続きも早くなることでしょう。

この記事は、Sandi Metz と Katrina Owen によって書かれた 99 Bottles of OOP という本に影響を受けました。ぜひ読んでみてください。ネーミング方法だけでなく、リファクタリングに関するベストプラクティスについても学ぶことができます。

著者について

Czarek は、EL Passion の Ruby デベロッパーです。

EL Passion を、 FacebookTwitterInstagram で検索してみてください。

Rafal Lisowski、Ula Kowalska、Karol Sarnacki、Agnieszka Dunin に感謝します。