リーダブルコード 個人的まとめ


名前に情報を詰め込む

明確な単語をつかう

dataやinformationなど単語から何も伝わってこない命名は避けるべき。
→ 迷ったら類似辞典を使う。

名前に情報を追加する

前提として「名前は短いコメントのようなもの」と考える。
絶対に知らせなくてはならない大切な情報があれば「単語」を変数名に追加する。

名前の長さ

長すぎたり短すぎる命名は避けるべきだが、それをどこまで真に受けるべきか。
例えば、識別子のスコープ(その名前が見えるコードの行数)が小さければ短い命名でも良い
→ コードを理解するのに必要な情報がすぐそばにあるため。

不要な単語を捨てる

例えば

ConvertToInteger()
# これを
ToInteger()
# こうしても問題はない

誤解されない名前

最善の名前とは、誤解されない名前。
つまり自分のコードを読んでいる人が、自分の意図を正しく理解できるということ。
名前を決める前に、反対意見を考えるなどして「誤解されない名前かどうか」を想像してみる。

命名リファクタリングの例

length
→ max_length

これもバイト数なのか、文字数なのか、単語数なのか分かりにくい。
そのため、文字数を意味している場合は

length
→ max_length
→ max_chars

とする。

限界値を決めるときはmaxやminを使う

例えばショッピングカートに10点までしか商品が入らないとき

CART_TOO_BIG_LIMIT = 10

このとき、限界値を明確にするためには

MAX_ITEMS_IN_CART = 10

とするべき。

複数の名前を検討する

「この機能を知らない人が見たらどうなるか」を常に想像しなければならない。

例: copy

experiment_id: 101
copy: 100
# これを下のようにすると分かりやすい
# copy_element: 100

copyだけだと「この実験を100回コピーする」なのか「これは100回目のコピーだ」なのかが分からない。
他の実験を参照している言葉だと明確にするにはcopy_elementとすると良い。

美しさ

優れたコードは「目に優しいもの」でなくてはならない。
見た目が優れているコードのほうが使いやすいのは明らか。考えてみれば、プログラミングの時間のほとんどは「コードを読む時間」といえる。

  • 一貫性のある改行
    複数のコードブロックで同じようなことをしていたら、シルエットも同じようなものにする。

  • 縦の線を真っ直ぐにする
    コードの列を整列すれば、概要が把握しやすくなる。

  • 一貫性と意味のある並び
    ある場所でABCDのように並んでいたものを、他の場所でBCDAのように並べてはいけない。意味のある順番を選んで、常にその順番を守る。

コメント

コメントの目的は「書き手の意図を読み手に知らせること」である。
自分がコードを書いているときに、自分の頭の中にある大切な情報は、誰かがコードを読むときには失われてしまう。

コメントすべきでないこと

  • コードからすぐに分かることをコメントに書かない。(価値のないコメント)

  • ひどい名前の埋め合わせにコメントを書いてはならない。
    優れたコード > ひどいコード + 優れたコメント

自分の考えを記録する

良いコメントの例

# このクラスは汚くなってきている
# サブクラス'○○'を作って整理した方がよいかもしれない

# TODO: もっと高速なアルゴリズムを使う

# 合理的な限界値。人間はこんなに読めない。
const int MAX_RSS_SUBSCRIPTIONS = 1000;

# このファイルには、ファイルシステムに関する便利なインターフェースを提供
# するヘルパー関数が含まれている。ファイルのパーミッションなどを扱う。

# 注意: このコードはリストの重複を処理できない(実装が難しいので)。

# 所在地を正規化する (例: "Avenue" -> "Ave.")。

よく使うコメントの記法

# TODO:  あとで手をつける
# FIXME: 既知の不具合があることを知らせる
# HACK:  あまりキレイじゃない解決策
# XXX:   大きな問題あり

大切なのは「これからこのコードをどうしたいのかを自由にコメントに書く」こと。そういったコメントを書くことで、コードの品質は情報を知らせたり、改善の方向を示したりできる。

読み手の立場になって考える

読み手 = プロジェクトを自分のように熟知していない人のこと。

  • 質問されそうなこと想像する。
  • 「このコードを見てビックリすることは何だろう?どんな風に間違えて使う可能性があるだろう?」と自分に問いかける。

制御フロー

条件やループなどの制御フローがないコードは読みやすい。他の場所に飛んだり枝分かれしたりするのは複雑なので、コードがすぐに分かりにくくなってしまう。

比較を書くとき

if (length >= 10)
# 上の方が見やすい
if (10 <= length)

上記のどっちが読みやすいかという指針は
左側: 「調査対象の式」変化する。
右側: 「比較対象の式」あまり変化しない。

ネストを浅くする

ネストが深いコードは、読み手が「精神的スタック」に条件をプッシュしなければならず、理解しにくくなってしまう。
コードを変更するときは、自分が初めてそのコードを見たような新鮮な気持ちで全体を見る。

変数と読みやすさ

  • 変数が多いと変数を追跡するのが難しくなる
  • 変数のスコープが大きいと、スコープを把握する時間が長くなる
  • 変数が頻繁に変更されると、現在の値を把握するのが難しくなる

役に立たない一時変数

now = datetime.datetime.now()
root_message.last_view_time = now

このnowを使う意味はない。

  • 複雑な式を分解していない
  • より明確になっていない。datetime.datetime.now()のままでも十分に明確といえる。
  • 一度しか使っていないので、重複コードの削除になっていない。

変数のスコープを縮める

グローバル変数に限らずすべての変数の「スコープを縮める」のはよい考えといえる。
→ 変数のことが見えるコードの行数をできるだけ減らす。
→ 一度に考えなければならない変数を減らせるから。

変数は一度だけ書き込む

「生きている」変数が多いとコードが理解しづらい。変数が絶えず変更され続けるコードはもっと理解しづらい。
→ 変数は一度だけ書き込む。
→ 「永続的に変更されない変数」は扱いやすい。

無関係の下位問題を抽出する

簡単にいうとプロジェクト固有のコードから汎用コードを分離するということ。
一般的な問題を解決するライブラリやヘルパー関数を作っていけば、プログラムに固有の小さな核だけが残る。

一度に一つのことを

読みにくいコードがあれば、そこで行われているタスクをすべて列挙する。
そこには別の関数(やクラス)に分割できるタスクがあるはず。
それ以外は、関数の論理的な「段落」となる。
タスクをどのように分割するかよりも、分割するということが大切。

さいごに

名著「リーダブルコード」の個人的まとめを作成しました。
あくまで自習用まとめなので、詳細なコード例や説明は、直接書籍を購入し読んでみてください。