ギークなエンジニアを目指す男

機械学習系の知識を蓄えようとするブログ

リーダブルコードを読了しました

f:id:taxa_program:20181201012041p:plain

おすすめ頂いたリーダブルコードを読了しました。 個人的に多くの知見を得ることができ、また、汎用的に利用できる知識が多くこれからのコーディングに少なからず影響を与えてくれる書籍でした。

今日はその中でも肝に命じておきたいこと、所感などまとめておきたいと思います。

名前に情報を詰め込む

プログラムに使用される変数名や関数名にはtmpなどハッキリしないものが多い。sizegetのように、一見問題なさそうな名前も、詳細な情報が含まれていないことがある。

本書では、名前を考える際に下記6点に注意することを推奨している。

  • 明確な単語を選ぶ
  • 汎用的な名前を避ける(あるいは、使う状況を選ぶ)
  • 抽象的な名前よりも、具体的な名前にする
  • 接尾辞や接頭辞を使って情報を追加する
  • 名前の長さを決める
  • 名前のフォーマットで情報を伝える

上記の中から、いくつか心当たりのある部分をピックアップしてみます。

汎用的な名前を避ける(あるいは、使う状況を選ぶ)

個人的に、関数の戻り値などにretなどの変数名をつけてしまう時があります。
この変数から読み取れる情報としては戻り値という当たり前の情報だけで、それ以外はないですよね。 例えば、2乗の合計を返す場合はsum_squaresなど、その変数(今回は戻り値)にどのような値が格納されているかを連想できるような名前を付けるべきですよね。 こうすれば変数の目的を事前に伝えることが可能となりますし、バグの発見確度もあがりそうです。

接尾辞や接頭辞を使って情報を追加する

例えば下記のようなコードがあった場合、変数startにはどのような値が格納されるか想像できますか?

var start = (new Date()).getTime()

時分?
秒?

正解はミリ秒です。

今回の場合は、下記のような変数名にするとわかりやすいですよね。

var start_ms = (new Date()).getTime()

このように、接尾辞や接頭辞に属性を追加するだけで、変数の意味の理解度が向上するはずです。

名前(変数名、引数名など)は短いコメントだと思い、命名することが大切なようです。

誤解されない名前

本書には、名前が「他の意味と間違えられることはないだろうか?」と何度も自問自答することが大切だと記載されています。

範囲を指定する場合はfirstlastを使う

よくコーディングしていて出くわすのが、範囲を絞ったコードですよね。 例えば、下記の例だとパッと見てどのように出力されるか分かり辛いと思いませんか?

print integer_range(start=3, stop=4) 

[2,3]?
あるいは[2,3,4]・・・?
コードを見ただけで判断するのはとても難しいと思います。

なので、範囲を指定する場合はfirstlastを使うと良いみたいです。
(この変数名が正しく聞こえるから)

包含/排他的範囲にはbeginendを使う

上記とは切り分けて、包含/排他的範囲を示す場合はbeginendを用いるのが良いみたい。

コメントすべきことを知る

コメントを書くことは良いことだと思いますが、何でもかんでもコメントとして残すべきではありませんよね。 コメントを読むとその分だけコードを読む時間も増えますし、画面を占領します。

よって、コメントには読むだけの、また、画面を占領させるだけの価値を持たせる必要があると思います。

本書では、この価値のあるコメントについても言及しています。

コードからすぐに分かることをコメントとして書かない

新しい情報を提供するわけでもなく、読み手がコードを理解しやすくなるわけでもないコメントは書かないべきです。

また、すぐに分かるという部分がとても重要です。
例えば下記のようなコードがあった場合、このコメントには価値があると思いますか?

# 2番目の`*`以降をすべて削除する
name = `*`.join(line.split('*')[:2])

上記コメントは「新しい情報」を提供できてはいませんよね。
また、コードを見ればどのように動くかは分かると思います。

しかし、コードを理解するよりも、コメントを読んだ方が早く理解できると感じたはずです。
よって、このコメントは価値のあるコメント(コメントとして記載した方が良いコメント)ということになりそうです。

また、通常は「補助的なコメント」(コードの読みにくさを補うコメント)が必要になるケースはあまりないようです。

このことを巷では「優れたコード > (ひどいコード + 優れたコメント)」と呼ぶそうです。

自分も業務の中で、「ここは補足的なコメントが必要だよな」と思い、良心からコメントを残していますが、そもそものコードがヒドいからコメントが必要だったんですね・・・。
こういった点も意識しながらコーディングすると、同じ量のコードを書いてもスキルの上達具合が全然違うんだろうと感じました。

本章の最後にとても簡潔なまとめが載っていたので、転記させていただきます。

「コメントはWHATではなく(あるいはHOWではなく)WHYを書こう」とうアドバイスを耳にしたことがあるかもしれない。 確かにキャッチーな言葉だけど、少し単純化しすぎていて、人によっては取り方が違うかもしれない。 ぼくたちからのアドバイスはこうだ。「コードを理解するのに役立つものなら何でもいいから書こう」 これなら、WHATでもHOWでもWHYでも(あるいは3つ全部でも)書ける。

制御フローを読みやすくする

条件やループなどの制御フローはできるだけ「自然」にする。コードの読み手が立ち止まって読み返したりしないように書く。

条件式の引数の並び順

例えばif文などの引数の並び順は、下記のような指針で決定すると良い。

左側 右側
「調査対象」の式。変化する。 「比較対象」の式。あまり変化しない。
if (10 <= length)

よりも

if (length >= 10)

の方が読みやすいですよね。
これは英語の用法と合っているようで、「もし君が18歳以上ならば」というのは自然ですが、「もし18年が君の年齢以下ならば」というのは少し不自然ですよね。
これと同じ原理なので覚えやすいです。

if/elseブロックの並び順

if/elseブロックは、下記を意識してコーディングする方が良い。

  • 条件は否定形よりも肯定系を使う。
  • 単純な条件を先に書く。ifとelseが同じ画面に表示されるので見やすい。
  • 関心を引く条件や目立つ条件を先に書く。

また、プログラムを書いていると、
より少ない行数でコーディングできた方が優れている

1行で書けたぜドヤ
という一種の俺すごいだろ錯覚に陥ることが少なくない。

行数を短くするより、他の人が理解するのにかかる時間を短くするのが一番大切だということを、改めて肝に銘じたい。

無関係の開問題を抽出する

エンジニアリングとは、大きな問題を小さな問題に分割して、それぞれの解決策を組み立てることに他ならない。 この原則をコードに当てはめれば、堅牢で読みやすいコードになる。 ここで大事なのは、無関係の下位問題を積極的に見つけて抽出することだと本書では述べている。

具体的には下記を念頭に置いてコーディングを行うと良い。

  1. 関数やコードブロックを見て、「このコードの高レベルの目標は何か?」と自問する。
  2. コードの各行に対して「高レベルの目標に直接的に効果があるのか?あるいは、無関係の下位問題を解決しているのか?」と自問する。
  3. 無関係の下位問題を解決しているコードが相当量あれば、それらの抽出して別の関数にする。

コードに思いを込める

コーディングする際に、プログラムのことを簡単な言葉で説明することで、コードがより自然になっていく。 この技法は思っているよりも簡単だが、非常に強力である。 説明で使う単語やフレーズをよく見れば、分割する下位問題がどこにあるかが分かる。

問題や設計をうまく言葉で説明できないのであれば、何かを見落としているか、詳細が明確になっていないということだ。 プログラム(あるいは自分の考え)を言葉にすることで明確な形にすることができる。

まとめ

  • 今後は1行ドヤコードは避ける。(いわゆる「頭の良い」コードには気をつける)
  • 他の誰か(数ヶ月後の自分を含め)に読みやすいコードを心がける。
  • コードだけで会話できることを目標とし、本書のタイトル通り読めるコードを書けるよう研鑽する。

冒頭でも述べましたが、コーディングに関わる方々は一読の価値ありです。
普遍的かつ不変的な内容なため、30歳になる手前の比較的若い年齢で本書と出会えたことは、とても幸せなことであり、今後のスキルアップ/キャリアアップに役立ってくれると感じました。