Murga

個人的に言いたいコト・主張・気持ち。

data とか info とか list とか item とかいう変数名止めろ

  • currentData
  • itemInfo
  • dataList

とかなんとかいうダッサイ変数名マジで止めろ。

ただ単に「ネーミングセンスがダサい」という話では留まらず、実際に悪影響を及ぼすネーミングだから、止めるべき理由と、止め方・改善方法を教える。

何が悪いの?

→ 「どんな data なの?」「どういう意味を持つ list なの?」という情報がコードの読み手に一切伝わらないから悪。

意味や意図が伝わりにくい・伝わらないコードは、挙動や仕様を読み手に誤解させ、それによって改修時の影響調査漏れや、バグの埋め込みを誘発する。それを実装した時点でバグっていなくても、悪いコード、迷惑なコードなのだ。

コード例

例えば Java の例。「発注書」の内容を保持する PurchaseOrder というクラスがあって、それを配列やリストで複数保持する場合。

// 悪い例 1

List<PurchaseOrder> dataList = new ArrayList<PurchaseOrderList>();

…うん、お前何回 list 言うてんねんと。

配列使ってて dataArray とか書いてるのも同じやで。

次に、例えば「テレビ番組」を TvProgram クラスで管理していたとして。

// 悪い例 2
List<TvProgram> dataList = new ArrayList<TvProgram>();

// …中略…

TvProgram newData = new TvProgram('新番組名称');
dataList.add(newData);

newData とか dataList とか、それはどういうデータなんや?何が新しくて (new)、何を表すリスト (list) なんや?

前後を読めば。メソッド名や利用される機能の箇所を予め分かっていれば、理解できるかもしれない。だがそれは読み手に推測させただけであって、コードが宣言しているワケではないのだ。

どう直したらいいの?

考え方を教えてやる。

list は書かず、単語の複数形にする

「何回 list 言うてんねん」というのは、list なのは型定義を見たら分かるからもう言わんでいい」という意味だ。だから、以下のように書くのがマシ。

// マシな例
List<PurchaseOrder> purchaseOrders = new ArrayList<PurchaseOrderList>();

PurchaseOrder のインスタンスが配列やリストになって、複数個格納される (されうる) から、複数形で purchaseOrders と書くワケだ。

Java のような静的型付け言語はもちろんだが、動的型付け言語だろうと list とか array とか書く必要はない。単数形・複数形という英語の基礎文法を理解していれば分かることだ。

なお、datainfo は不可算名詞なので、datasinfosinformations とは書けない。というか datainfo といった単語はそれ自体の使用が悪なので、次に説明する。

どんな datainfo なのかを考えて名前を付け直す

data はデータ。info は情報。

プログラムにおいて扱うモノって、全て「データ」だよね?「情報」だよね?

ということは、この単語を変数名に使ったところで、何の意味も成していないのである。

何の意味も成していない単語が混じっている文章 (コード) は、それをどう解釈すれば良いか読み手に迷わせるから悪、存在してはならないのである。

じゃあ data とか info とか名付けたくなった時にどう回避すれば良いか。先程の TvProgram クラスを例にしてみる。

// 悪い例
List<TvProgram> dataList = new ArrayList<TvProgram>();

// …中略…

TvProgram newData = new TvProgram('新番組名称');
dataList.add(newData);

上のコードは、「こういう変数名が登場する」ということを表したくて、空の Value Object (DTO) をいじっているが、実際はこんなメソッドだったとする。

// 現在の「予約番組一覧」に、引数で指定した「新たに予約するテレビ番組」を追加して、一覧全体を返す
private List<TvProgram> setToRecord(TvProgram newData) {
  // 現在の「予約番組一覧」を取得する
  List<TvProgram> dataList = this.getCurrentReservationList();
  // 「新たに予約するテレビ番組」を追加する
  dataList.add(newData);
  
  return dataList;
}

「この処理自体がまずどうなの…?」というツッコミも大切なことで、「一覧を返しているコイツは誰なんだ?」というオブジェクト指向的な違和感が持てれば、まずこんな命名にならなくて済むのだ。だがこの話は一旦置いておいて、「おかしな変数名」にだけフォーカスしてみる。

変数 newData は、何が新しいデータなのかと思えば、「新たに予約したいテレビ番組」という意味だった。dataList はどういうリストなのかと思えば、「既に予約一覧に含まれているテレビ番組のリスト」だった。

data とか info とかいう安直なネーミングをする連中は、「考えること」と「タイピングすること」を面倒臭がっているだけで、「コレって何なの?どういう意味なの?」としつこく掘り下げていけば、本当の意図をちゃんと言語化できるはずなのだ。ひとたび言語化できたら、変数名が長くなっていいから、そのまま書く。

  • newData → 「新たに予約したいテレビ番組」 → 「(このメソッドでこれから) 予約するテレビ番組」 → tvProgramToReserve
  • dataList → 「既に予約一覧に含まれているテレビ番組のリスト」 → 「予約番組一覧」 → reservedTvPrograms

toReserve という単語は実際のところ、いささか冗長かもしれないが、意味はより限定的に、狭まっていくので、悪いとは思わない。

予約番組一覧は、同じ変数に add() した上で return しているので、「current = 現在の一覧」という時制を与えようとするとおかしくなるので、current とかいう単語は含めない。それでも「どんなリストなんですか?」という質問には「予約番組のリストです」と答えられているのが、reserved という単語と、複数形の s だ。


そもそもこのメソッドがやってることがワケ分かんなくね?という指摘がまっとうで、「テレビ番組を予約する」というメソッドを、誰が持っているのか、ということを考えると、プログラムで考える場合は「ユーザ」でも「テレビ本体」でも微妙だ。ユーザは命令を与える側であって、番組一覧を保持する係ではない。「テレビ本体」が番組を予約したり一覧を保持したりするのは、現実を表面的に見ればそう言えるが、「テレビ本体」クラスの責務が大きすぎる気がする。そこで、「テレビ本体」の中に「番組予約するマン」を擬人化して考えるのが、昨日分割という視点でも良いだろう。

class TvProgramReserver {
  // 予約番組リスト
  private List<TvProgram> reservedTvPrograms = new ArrayList<TvProgram>();
  
  // 番組を予約する
  public void setToRecord(TvProgram tvProgramToReserve) {
    this.reservedTvPrograms.add(tvProgram);
  }
}

例えばこんな感じ。

予約番組リストは Reserver クラスが保持しているので、current とかいう時制は登場しなくて良い。setToRecord() で「予約録画する」だが、ショッピングカートなんかで言えば addToCart() なんて書いてやれば、productItemToPurchase なんていう変数名にしなくても、cartadd する productItem なんだな、ということはメソッド名で伝わったりする。

横着すんな

「コレってどういうデータなんだっけ?」「ココで何するんだっけ?」「この処理を行うのはコイツで正しいか?」

そういうことを考えるのを面倒臭がると、infoList とか言い始めるので、横着すんな頭使え、ってこった。

「配列だから Array」「リストだから List」、うんそれ型で分かるから書かなくていいよ。「書かないと分かんなくなる」っていうのは、1メソッドがデカ過ぎるから。

オブジェクト指向とかドメイン駆動設計とか何とかほざきながら data とか list とか書いたらもう許さねえからな。

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

  • 作者:Dustin Boswell,Trevor Foucher
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2012/06/23
  • メディア: 単行本(ソフトカバー)