プログラマーのバイブル!「リーダブルコード」の内容をまとめてみた
この記事の概要
初めて自分が共同開発や実務案件に入った時、コードが読みづらかったり、
PRがいい加減で何度も指摘を受けてきました。
実務案件に入った今しっかり読み返そうと思って書いています。
実際に実践をやってから読んだ方が理解が共感すると思うので何かしら
チームでの開発をしてから読むのがおすすめです。
書いている人間の現在地
・Laravelで共同開発を経験した
・LaravelとRailsで実務経験あり
・これからReactの開発に挑戦
・自社開発と受託開発の実務案件に入って4ヶ月目
まだ経験が浅い人間目線で書いていきます。
この記事の対象者
・リーダブルコードの要点を知りたい人
・現場に入りたての人
・コードレビューをもらった経験がある人
・個人開発中の学習者
1.理解しやすいコード
優れたコードとは何か
コードは他人が最短で理解できるコードである必要があります。
コードは短く書いたほうがよいが理解するまでの時間が短くなるのでいかにこれができるかですね。
2.名前に情報を埋め込む
例えばメソッドでgetだけだとわかりづらいし、GetPageだと何のページとなってしまいます。
commitとかでも「修正」だけだと何を修正したの?ってなりますよね。
def DownloadPage(url)
end
だと圧倒的にわかりやすくなりますね。
ここの章をまとめると
・明確な単語を選ぶ(ex Getではなく状況によってFetchやDownloadなど)
・tmpやretvalなどの汎用的な名前は避ける(明確な理由があれば別)
・具体的な名前を使って、物事を詳細に説明
・変数名に大切な情報を追加
・スコープの長い変数名には長い名前をつける
・大文字やアンダースコアなどに意味を含める
3.誤解されない名前
誤解されるような名前をつけてしまうと他人がコードを読み間違えてしまうことがあります。
ex) Clip(text,lenght),filter()
そのような事態にならないためにはどうすればいいでしょうか。
①限界値はmaxとminを使う
$start = 5;
$end = 15;
$upperBound = max($start, $end);
$lowerBound = min($start, $end);
echo "上限値: " . $upperBound . "\n";
echo "下限値: " . $lowerBound . "\n";
②範囲指定はfirstlaとstを使う
あくまで具体例なのでご了承ください。
// テスト用の配列と範囲
$array = ["a", "b", "c", "d", "e"];
$start = 0;
$stop = 4;
// integerRange 関数を呼び出して範囲内の値を取得
$result = integerRange($array, $start, $stop);
// 結果を表示
print_r($result);
③範囲指定をfitstとlastで命名する
<?php
#省略
return array_slice($array, $first, $last - $first + 1);
}
$first = 0;
$last = 4;
$result = integerRange($first, $last);
print_r($result);
④ブール値の名前
ブーリアン型の命名ではis、has、canやshouldなどを使うといいみたいです。
ex) isActive, hasPermission, canEdit, shouldDisplay
4.美しさ
美しさが大事なのは見た目が美しいコードの方が使いやすいからです。
美しくっ買う方法は以下の通りです。整形ツールも出てきていますが、知っておいた方がいいです。
1.コードの列を整理する
2.意味のある順番を選んで、常にその順番を守る
3.空行を使って大きなブロックを論理的な「段落」に分ける
5.コメントすべきことを知る
コメントの目的は書き手の意図を読み手に知らせることです。
コメントすべきではないこと
①コードからすぐにわかることはコメントに書かないことが大切です。
例えば
#ユーザー情報保存
user.save
みたいなコードですね。
②コメントのためのコメントをしない
# 以下コメントアウト
# ユーザー情報を更新
user.save
これだと見ればわかるよーってなりますよね。
①コメントすべきこと
自分の考えを記録することに使います。
#このクラスは汚くなってきている
#サブクラス'ResourceNode'を作って整理したほうがいいかもしれない
こんな感じですね。
②コードの欠落にコメントをつける
こんな感じですね。
#{
# TODO: もっと早いアルゴリズムを使う
# }
コードが未完成の時は以下のように書いておくといいみたいです。
# TODO(ダスティン): JPEG以外のフォーマットに対応
プログラマーがよく使う記法です。
| 記法 | 典型的な意味合い |
|---|---|
| TODO | あとで手をつける |
| FIXME | 既知の不具合があるコード |
| HACK: | あまり綺麗じゃない解決策 |
| XXX: | 危険!大きな問題がある |
③読み手の立場になって考える
処理が長いoか複雑な場合は処理の要約のコメントを残しておくと良さそうです。
またはブロック単位で要約コメントを残すのが良さそうです。
6.コメントは正確で簡潔に
①コメントを簡潔にしておくべきです。
1行で書けるとこを3行とかにすると読む手間がかかってしまう。1行でシンプルに書くようにしましょう。
②あいまいな指示語は避ける
例えば
// データをキャッシュに入れる。ただし、先のそのサイズをチェックする
これだとそのって何だってなりますよね。こうすればわかりやすいはずです。
# データをキャッシュに入れる。ただし、先のデータサイズをチェックする
これなら何のサイズかわかりますよね。
③コードの意図を書く
このように書くとわかりやすいですよね。
#値段が高い順に並び替える
@products = Product.order(price: :desc)
7.制御フローを読みやすくする
①にします。
コードの読み手が立ち止まったり読み返したりしないようにします。
if($count <= 100){} // 調査対象countが左側
if(100 > $count){} // 調査対象countが右側
調査対象($count)が左側の方が読みやすいですよね。
②if/else文は否定文ではなくて肯定文を使う
③三項演算子を使う
④do/whileループは避ける
⑤関数から早く返す(関数で複数のreturnは使っていい)
⑥ネストを浅くする
8.巨大な式を分割
1.説明変数を使う
式を分割するには式を表す変数(説明変数)を使うといいみたいです。
// ソースコードの意図を明確にするための説明変数
$length = count($array); // 配列の長さ
// 説明変数を使用したコード
if ($length > 0) {
// 配列に要素が存在する場合の処理
echo "配列に要素があります。";
} else {
// 配列が空の場合の処理
echo "配列は空です。";
}
$lengthという説明変数を使って配列の長さを表し、コードの意図がわかりやすくなります。
2.要約変数
式を変数に代入しておくと便利です。大きなコードの塊を小さな名前に置き換えて
簡単な変数にすることを要約変数と言います。
// 要約変数を使用したコード
$subtotal = $price * $quantity; // 小計
$tax = $subtotal * 0.1; // 税額
$total = $subtotal + $tax; // 合計
// 要約変数を使用した結果の表示
echo "小計: $subtotal" . PHP_EOL;
echo "税額: $tax" . PHP_EOL;
echo "合計: $total" . PHP_EOL;
$subtotal、$tax、$total という要約変数を使用して、価格と数量に基づく小計、税額、合計を計算し、
複雑な処理でも簡単になります。
説明変数と要約変数を使って分割し、読んで理解しやすいコードにすることができます。
9.変数と読みやすさ
①邪魔な変数を削除
不要な変数を策書することでコードは綺麗になり読みやすくなります。
$now = new DateTime();
$root_message['last_view_time'] = $now;
上のコードだと複雑な式を分割せず、new Date()のままでも意味は通じますが、
重複コードの削除になっていません。修正すると
$root_message['last_view_time'] = new DateTime();
になります。
②変数のスコープを縮める
グローバル変数は避けて変数のことが見えるコードをできるだけ減らすことが大切です。
グローバル変数はどこでどのように使われているのかが追いにくいので、
全ての変数のスコープを縮めることを考える必要があります。
10.無関係の下位問題を抽出
この章で言いたいことは固有のコードを分離することです。
こちらの都合でここでは一旦この記述だけにしておきます。
11.一度に1つのことを
一度に複数のことをするコードは理解しづらいので、コードは1つずつタスクを行うようにしなければいけません。
そして一度に1つのタスクをする必要があります。
1.コードが行っている「タスク」全てを列挙する
2.タスクをできるだけ異なる関数に分割する
タスクは小さくできる
本の例を出すとブログに設置する投票機能を例に出してある。
具体的な機能としては、
①ユーザーが「賛成」か「反対」のどちらかを投票できる
②投票スコアの合計を取得
③賛成がクリックされた時、賛成を+1、反対なら-1
この処理を1つの関数内で行うと、やるべき処理が複数になってしまい理解がしづらいです。
そのため以下の2つの関数を作成して処理を分割するといいみたいです。
①ユーザーが賛成を押したら+1、反対を押したら-1を返す関数
②現時点でのスコアを取得し1で返ってきた値を計算
読みにくいコードがあれば、そこで行われているタスクを全て列挙して
そこには別の関数に分割できるタスクがあります。
まとめ
12章以降は今回は省略します。正直自分は共同開発をやり、実務案件やり始めたばかりの段階で
読みました。正直難しかったので定期的に読み返して、記事を更新していこうと思います。
資料
Discussion