読みやすいコードを書く

僕はエンジニアを志している大学4年生（2020年6月現在）です。
内定先の会社の先輩に、誕生日プレゼントとして「リーダブルコード」を買っていただきました。
メモを取りながら3回くらい読んだので、それをまとめて記事にしてみます。

## 名前に情報を詰め込む

- 明確な意味を示す単語を選ぶ
- 汎用的で、誤解を招くような意味の単語を避ける

### 明確な意味を示す単語を選ぶ

- `get` ではなく `fetch` や `download` を選ぶ
- `size` ではなく `height` や `num` を選ぶ

### 汎用的で、誤解を招くような意味の単語を避ける

- `tmp`
    - 一時的な保持が大切な変数にだけ使う
    - このような名前を使うときは、それ相応の理由を用意する
- ループイテレータ（`i`, `j`, `k`）は基本的には問題ない
    - ただし、例えばクラブに所属しているユーザを調べるループなら、以下のような変数名が良い
        - `club_i`
        - `member_i`
        - `user_i`

## 誤解されない名前をつける

その名前が「**他の意味と間違えられることはないだろうか？**」と何度も自問自答する。

- `filter` ではなく `select` や `exclude` を使う
- 限界値を含めるときは `min` と `max` を使う
- 範囲を指定するときは `first` と `last` を使う
- ブール値の変数名は、頭に次のような単語を付けると分かりやすい
    - `is`
    - `has`
    - `can`
    - `should`

## 美しさを意識する

- 一貫性のあるレイアウトを使う
    - 一貫性のある改行位置にする
    - 並び方、順番に意味を持たせる
        - 対応するHTMLフォームの<input>フィールドと同じ並び順
        - 「最重要」なものから重要度順
        - アルファベット順
- 似ているコードは、似ているように見せる
    - 空白文字を使って、縦の線を真っ直ぐにする（引数の位置を揃える、など）
- 関連するコードをまとめてブロックにする
    - 空行を使うことで、論理的な「段落」に分ける
    - 段落ごとに要約コメントを追加するのも有効

## コメント

### 原則

- コメントの目的は、**書き手の意図を読み手に知らせる**こと。
    - なぜ他のやり方ではなく、こうなっているのか
    - 懸念や欠陥と思われるもの
    - それにまつわる背景など
- コードを見てすぐに分かることを、わざわざコメントに書かない
- 優れたコード > ひどいコード + 優れたコメント
- 読み手の立場になって考える
    - 質問されそうなこと、その答え
    - 間違える可能性のあること
    - 全体像についての簡単な解説
    - 関数やクラスなどについての要約
    - その他コードを理解するのに役立つあらゆる情報

### 正確で簡潔に

- 曖昧な代名詞を避ける
    - `その` や `それ` を具体的な表現に変える
- 関数の説明に、実際の具体例を使うのは有効
    - 例）この引数に対して、この値を返す
- 引数にコメントをつける（と分かりやすいこともある）

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

- 条件式の引数の並び順
    - 左：調査対象、変化するもの
    - 右：比較対処、あまり変化しないもの
- if / else ブロックの並び順
    - 条件は否定形よりも肯定形を使う
    - 単純な条件を先に書く。if と else が同じ画面に表示されて見やすい
    - 関心を引く、目立つ条件を先に書く
        - 具体的な値を使うときなど
- 三項演算子はなるべく使わない
    - ただし、簡潔になるときは使っても問題ない
- do / while ループを避ける
    - while ループで書き直せることが多い
- ネストを浅くする
    - 早めに返してネストを削除する
        - 関数で複数のreturn文を使っても問題ない
    - `continue` でループ内部のネストを削除する

## 巨大な式を分割する

- 式を表す変数を使う（説明変数）
- 式を変数に代入しておく（要約変数）
- ド・モルガンの法則を使う
    - `not (A or B or C) = (not A) and (not B) and (not C)`
    - `not (A and B and C) = (not A) or (not B) or (not C)`
- 「頭が良い」コードに気をつける
    - 「頭が良い」＝「一見だと分かりづらい」
    - あとで他の人が読むときに分かりにくくなる

### 式を表す変数を使う（説明変数）

例えば、以下の左辺は何を指しているか分かりづらい。

```
if line.split(':')[0].strip() == "root":
```

これをあらかじめ、説明された変数に代入しておく。

```
username = line.split(':')[0].strip()
if username == "root":
```

### 式を変数に代入しておく（要約変数）

以下の例では式は長くないが、もっと良くできる。

```
if (request.user.id == document.owner_id) {
    // ユーザはこの文書を編集できる
}

...

if (request.user.id != document.owner_id) {
    // 文書は読み取り専用
}
```

この式が言いたいことは「**ユーザは文書を所持しているか？**」である。
そこで、要約した変数を追加して、もっと明確なコードにすることができる。

```
final boolean user_owns_document = (request.user.id == document.owner_id);
if (user_owns_document) {
    // ユーザはこの文書を編集できる
}

...

if (!user_owns_document) {
    // 読み取り専用
}
```

## 変数と読みやすさ

- 変数の数を減らす
    - 数が多いと追跡するのが難しくなる
- 変数のスコープを小さくする
    - 変数のスコープが大きいと、把握する時間が長くなる
    - できるものは、ローカル変数に「格下げ」する
    - 大きなクラスを、小さなクラスに分割する
    - クロージャを使う
        - 変数を関数内に入れて、アクセスできる範囲を縮める
    - 使う直前で、変数を定義する
- あまり変数を頻繁に変更しないようにする
    - 頻繁に変更されると、現在の値を把握するのが難しくなる
    - 一度だけ書き込むようにする
        - `const` や `final` を使う
        - 「永続的に変更されない」変数は扱いやすい

## 一度に1つのことを

コードは**1つずつ**タスクを行うようにしなければならない。

1. コードが行っているタスクを全て列挙する
2. それぞれのタスクをできるだけ異なる関数に分割する
3. 分割できないものは、異なる領域に分割する

## コードに思いを込める

「**おばあちゃんに分かるように説明できなければ、本当に理解したとは言えない**」
by アルバート・アインシュタイン

1. コードの動作を簡単な言葉で同僚にも分かるように説明する
2. その説明の中で使っているキーワードやフレーズに注目する
3. その説明に合わせてコードを書く

## 短いコードを書く

- 必要になりそうな機能の実装について悩まないようにする
    - YAGNI原則
        - 今の時点で必要のない機能は実装しない
        - 必要になったら実装する
- 要求の分割
    - 最も簡単に問題を解決できるような要求を考える
    - 問題を解決できるのであれば、多少の厳密さは失われても問題ない
- コードを小さく保つ
    - 重複コードを削除する
    - 未使用のコードや無用の機能を削除する

## テストと読みやすさ

- テストを読みやすくて保守しやすいものにする
    - 他のプログラマが安心してテストの追加や変更ができるように
- エラーメッセージを読みやすくする
    - もし使えるのであれば、便利なアサーションメソッドを使うべき
    - 手作りのエラーメッセージを作る
- テストの適切な入力値を選択する
    - 入力値を単純化する
    - 1つの機能に複数のテスト
        - 完璧な入力値を1つ作るよりも簡単で効果的で読みやすい
- テストの機能に名前をつける
    - `Test1()` ではなく `Test_SortAndFilterDocs()` のようにする
- テストに優しい開発をする
    - テストしやすいようにコードを設計する
        - 振る舞いごとに上手く分割される
        - 自然に良いコードが書けるようになる

## おわりに

この「リーダブルコード」という本は、とても勉強になりました。
読みやすいコードを書くためのヒントが盛りだくさんでした。

ただ1つ思ったのは、知識があるだけでは良いコードは書けないだろうということです。
大切なことは、やはり多くのコードを書くこと、すなわち経験値だと思いました。
この本から学んだことを意識しながら、これから経験を積んでいきたいと思います。