リーダブルコードの要点をまとめてみた


## はじめに
職業訓練を経て未経験エンジニアとして案件に取り掛かっている者です。
初学者が読むべき本としてよく上がる[リーダブルコード](https://www.amazon.co.jp/dp/4873115655/ref=as_sl_pc_as_ss_li_til?tag=sutabaopen-22&linkCode=w00&linkId=a36e0d8d544fc6c1ef5fa162e2f7ad4a&creativeASIN=4873115655)を読みながら、要点をまとめてみました。

## この記事の主な対象者
- リーダブルコードを読んだが振り返りたい人(未来の自分)
- そもそも要点だけ知りたい人
- プログラミング初学者

## この記事について
全１５章あるので、１章ずつが長くなりすぎないようにしたいと思います。
個人的に「なるほど」と思ったところだけを要約して記述していますので、もちろん書籍内の全ては網羅していません。
ご注意ください。
<br><br>

## 1章　理解しやすいコード
#### 鍵となる答え
コードは他の人(未来の自分を含む)が短期間で理解できるように書かなければならない。
下記にコード例を記述↓
```:書籍例(1)
return  exponent > 0 ? mantissa * ( 1 << exponent) : mantissa / (1 << -exponnent)
```

```:書籍例(2)
if (exponent > 0) {
    return mantissa * ( 1 << exponent)
} else {
    return mantissa / (1 << -exponnent)
}
```

どちらも処理内容は同じだが、**例(2)のほうが直感的に理解しやすい**と感じる人は多いのではないだろうか。  
本書では、「**行数が少ないことよりも、読みやすさを優先すべき**」というメッセージが書かれている。

<br><br>
## ２章　名前に情報を詰め込む
#### 鍵となる答え
名前に情報を詰め込む。
1. 明確な単語を選ぶ
    - メソッドの命名の例として『size()』を挙げるとすれば、size()だけでは何のサイズに関してのメソッドか分かりにくい、Height()・NumHeight()等目的に応じた命名をすべき
1. 値の単位を設定する
    - ``` const start = (new Data()).getTime(); ```を例とした場合、取得するのはミリ秒なので命名はstart_msとしたほうが分かりやすい
1. 重要な属性を追加する
    - 命名の例として『password』をあげると、暗号化したパスワードは『plaintext_password』と命名に属性を付けたほうがよい
1. スコープが小さければ短い名前でもいい
    - 小さいスコープ内で使用する変数などの命名については短くても良い(コードを理解するための情報がすぐそばにあるため)、メンバ変数やグローバル変数などでは短い名前ではいけない

<br><br>
## ３章　誤解されない名前
#### 鍵となる答え
他の意味と間違えられることはないだろうか？と自問自答する


1. 限界値を設定するときはminとmaxを使う
    - カートに商品が１０個までしか入らないシステムを作成する想定で`CORT_TOO_BIG_LIMIT = 10`としたとする、この場合『１０未満』なのか『１０以下』であるかが分かりずらい、この場合`MAX_ITEMS_IN_CART`とすれば、カートに１０個までしか入らないことが明確になる
1. 暗黙的な命名は誤解の元
    - filter()というメソッドを命名した場合、オブジェクトから選択するのか、一部除外するのか分かりにくい、選択するなら`select()`、除外するなら`exclube()`にしたほうがよい(length・limit等も同じ)
1. ユーザーの期待に注意した命名
    - get()やsize()は軽量なメソッドであると期待される、重い処理を行うメソッド尾の場合、命名を変更するか軽量な処理に変更すべきである
1. ブール値の名前
    - 頭に『is・has・can・should』などを付けると分かりやすくなる
    - 例として`spaceleft()`は数値を返すように聞こえるがbool値を返すのであれば、`hasspaceleft()`のほうがよい
    - また、否定形より肯定系のほうが短く、読みやすい
``` :否定形と肯定形の比較
bool disable_ssl = false  // 否定形

bool use_ssl = true　// 肯定形
```

<br><br>
## ４章　美しさ
#### 鍵となる答え
見た目が美しいコードのほうが使いやすい、プログラミングの時間のほとんどはコードを読む時間である、さっと流し読みできるコードであればだれにとっても使いやすいコードになるだろう

- 美しいコードの心得
    - 一貫性のあるレイアウト
        - 一貫性のある改行位置
        - {}の改行の位置を統一する
        - ある場所で「A-B-C」と並べているものを別の場所で「B-A-C」等順番を変えて並べると分かりにくいコードになる
    - 似ているコードは似ているように見せる
        - 引数ごとで縦に同じラインで整列させる　※１
    - 関連するコードをまとめてブロックにする
        - 似たような処理はメソッドでまとめて処理を行う
        - 宣言を多数記述するときはコメントでブロックごとに区切り宣言をする、空行を活用して段落も付けることでより分かりやすくなる　※２

<br>

```:※１
空欄を入れる事で引数のラインを整える
  Checkprofile("Doug", "man"  , 26)
　Checkprofile("Doug", ""     , 28)
　Checkprofile(""    , "woman", 26)
```

```:※2
多数の宣言をコメントや空行で分けて分かりやすく

    // ユーザー関連の情報
    private String userName;
    private String email;
    private int age;
    
    // ユーザー処理
    public void updateUserName(String newName) {
        this.userName = newName;
    }

    // 住所関連の情報
    private String postalCode;
    private String addressLine;
    private String city;
    
    // 住所関連処理
    public void updateAddress(String postalCode, String addressLine, String city) {
        this.postalCode = postalCode;
        this.addressLine = addressLine;
        this.city = city;
    }
```

<br><br>
## 5章　コメントすべきことを知る
#### 鍵となる答え
コメントは書き手の意図を読み手に知らせる為に記述する。
コードから**すぐ**分かることをコメントに書かない

下記コードはコメントが新しい情報を提供していないが、コードを理解するよりコメントを見たほうが早く理解できる。
```
# ２番目の'*'以降をすべて削除する
name = '*'.join(line.split('*')[:2])
```
<br>
また価値のない(必要ない)コメントもある、下記に例を挙げる

#### 価値のないコメントの例
- 関数の名前と引数をそのまま文章形式で書きだしているコメント
    - 例) `addUser(name, age) // nameとageをもとにuserを新たに加える`
    - コメントを付けるのであれば関数の役割や条件分岐を明記したほうがよい
- ひどい名前の埋め合わせの為に付けたコメント
    - 優れたコード　＞　ひどいコード　＋　優れたコメント　であることを意識してコメントの有無や命名を考える
    - ひどいコードをコメントで補足するのではなく、コード自体を優れたものにする必要がある

<br>

また、価値のあるコメントを行う為の心得についても記述があったので下記に記述する

#### 価値のあるコメントの例
- コメントには自分の考えを記述する
    - AパターンとBパータンで比較をしてAパターンのほうが軽量な処理である場合はコメントで「Aパターンのほうが軽量であった」と記述すると読み手はBパターンについて考えなくて良くなる
- 質問されそうなことを想像する
- ハマりそうな罠を告知する
    - 書籍の例としてはメソッドが外部のサービスを使っていることを挙げている
    - 外部のサービスの接続に時間がかかる場合はコメントで接続に時間がかかる旨を記述したほうが親切である
- コードの欠陥をTODO:やXXX：で記述する
- ファイルやクラスの全体像についてのコメント

<br><br>
## 6章　コメントは正確で簡潔に
#### 鍵となる答え
コメントは領域に対する情報の比率が高くなければならない
良いコメントの例がいくつか挙がっているので下記に記述する

1. コメントを簡潔にしておく
    1. １行で済むコメントを複数行にすることはナンセンスである
1. あいまいな代名詞を避けたコメント
    1. 『それ』や『この』等、何を指しているのか分からないコメントを残さない
1. 歯切れの悪い文章を磨く
1. 関数の動作を正確に記述する
    1. その関数が何を処理し、どのような結果を返すのかを、はっきりと書く
1. コードの意図が記述されたコメント
    1. この時コードの動作を書いているだけで情報を追加していないコードは良くない
    1. 商品を並び替える処理において``// listを逆順にイテレートする``とコメントをしても動作の説明をしているだけになる``// 商品を高い順に表示する``とコメントすることで意図が伝わりやすい

<br><br>
## 7章　制御フローを読みやすくする
#### 鍵となる答え
条件やループなどの制御フローは出来るだけ『自然』にする。コードの読み手が立ち止まったり読み返したりしないように書く

1. 条件式の引数の並び順
    1. ```if(length >= 10)```と``if(10 <= length)``であれば前者が読みやすいと感じる、これは左側に調査対象の式を配置しているからである(言葉で「もし君が１８歳以上なら」いうと自然であるが、「もし１８歳が君の年齢以下ならば」とすると不自然であると考えると分かりやすい)
1. ifの条件には否定形より肯定形のほうがよい。また単純な条件や関心を引く条件を先に書くことも良い(状況によって自己判断も必要になることもあるので注意)
1. 三項演算子よりif/elseのほうが分かりやすい、三項演算子は簡潔になるときだけ使用
1. do/whileはコードブロックを２回読むことになる可能であればwhileだけに書き換えての使用が良い
1. ネストの深いコードは理解しにくいのでなるべく浅く記述する
    1. 　書籍例を『※３』に記述します

```:※3
// ネストがある処理
    if(user_result == success){
        if(permission_result != success){
            // 処理A
            return
        }
        // 処理B
    }else{
        // 処理C
        return
    }

// ネストを削除した処理
    if(user_result != success){
        // 処理C
        return 
    }

    if(permission_result != success){
        // 処理A
        return
    }else{
        // 処理B
    }
```

<br><br>
## 8章　巨大な式を分割する
#### 鍵となる答え
巨大な式は飲み込みやすい大きさに分割する

1. 説明変数
    1. 複雑になった式を簡単見る為、式の一部を変数に格納する
    1. ``if line.split(":")[0].strip() == root``よりも``username = line.split(":")[0].strip()``と``if username == root``で分けたほうが分かりやすい場合もある
1. 要約変数
    1. ifの条件内で冗長に変数を並べて比較をすると見にくくなる為、比較式自体を変数に格納して使用すると読みやすくなる
    1. 例として``request.user.id == document.owner_id``を条件としたifが複数ある場合、変数が５つも入っているため考えるのに時間がかかるが``final boolean user_owns_docment = (request.user.id == document.owner_id)``として変数にすると考えやすくなる
1. ド・モルガンの法則を使用してロジックを操作して読みやすいコードに変換するとよい場合がある
    1. 例)  ``if(!(a && !b))--->if(!a || b)``

<br><br>
## 9章　変数と読みやすさ

この章では課題を３つに分けている
1. 変数が多いと編集を追跡するのが難しくなる
1. 編集のスコープが大きいとスコープを把握することが難しくなる
1. 変数が頻繁に変更されると現在の値を把握することが難しくなる

####　課題解決に向けて以下のことが挙げられる
1. 変数を削除する
    1. ``now = datetime.datetime.now()``のように、一度しか使わない変数でかつ、意味が明確な式は、わざわざ変数に格納せずそのまま使ったほうが、コードが短くなり、読みやすくなる（課題1の解決）
1. 変数のスコープを縮める
    1. グローバル変数は追跡が難しく、ローカル変数と間違えて変更してします恐れもある為、スコープを縮めてる考えは良い（課題2の解決）
1. メンバ変数もミニグローバルといった考え方が出来る為、大きなクラスでは追跡や変更の把握が大変である。ミニグローバルを減らし可能であればローカル変数に変更したほうがよい（課題2の解決）
1. JavaScriptにおいてconstやletで定義されていない変数はグローバル変数になる。また変数をifやforの中で定義するとコードが読みにくくなるほかエラーにつながることもある（課題2の解決）
1. constやfinalを使用してイミュータブルにすれば、コードが理解しやすくなる

<br><br>
## 10章　無関係の下位問題を抽出する

- 大きな問題は小さな問題に分割してそれぞれの解決策を組み立てることで堅牢で読みやすいコードになる
    - 書籍内では『与えられた地点から最も近い地点を見つける』ことを例にしており、メソッド内で『２つの地点の球面距離を算出する』ロジックが書かれていたが、全体で見るとかなり見にくいコードであった
    - そこで『２つの地点の球面距離を算出する』ロジックは別でメソッドとしてまとめる事でコードが見やすくなる
    - 小さい問題に分けた独立した関数は改善も比較的簡単である

<br><br>
## 11章　一度に１つのことを
- 関数は一度に１つのことを行うべき
    - メソッドを分ける際はロジック内のタスクを分けて、別々の領域に分割するとよい
    - 読みにくいコードがあれば、そこで行われているタスクを列挙して別の関数に分割できるものがあれば分割する
    - 例として、ディクショナリから国名と町名を抽出して連結させるメソッドがあったが、名前の抽出は町名との結合とは別のタスクと考え、別のメソッドに記述を行ったことでコード全体が見やすくなった

<br><br>
## 12章　コードに思いを込める
この章ではコードの条件(やりたいこと)を人間の言葉に書き出して、条件を整理している
```:例
// 権限があるのは、以下三つ
// 1: 管理者
// 2: 文書の所有者
その他は権限はない

    if (is_admin_request()){
        //権限あり
    elseif ($document && ($document["username"] ==　$_SESSION["username"])){
        // 権限あり
    } else {
        return not_authorized();
    }
```

言葉に書き出す以外でも問題ややりたいことを声に出して説明するだけでも効果はある

<br><br>
## 13章　短いコードを書く
プロジェクトが進んでくるとファイルが増えていき把握が大変になってくるそこで下記のことを気にする必要が出てくる
1. 重複コードを削除する
1. 未使用のコードや無用なコードを削除する
1. プロジェクトをサブプロジェクトに分割する
1. コードの『重量』を意識する。軽量で機敏にしておく

また身近なライブラリに目を通しておき、どういったときにどのようなライブラリが使用できるか把握しておくと、より簡潔にコードを記述することが出来る。

<br><br>
## 14章　テストと読みやすさ
テストコードが恐ろしく大きいものであると以下のことが考えられる
- 本物のコードを修正するのを恐れる
- 新しいコードを書いたときにテストを追加しなくなる


#### 読みやすいテストコードは・・・
1. 大切ではない詳細はユーザーから離して、大切な詳細は目立つようにする
    1. ヘルパー関数を使い、大切でないコードは目立たないようにする
1. またテストコードを作成するときは『12章　コードに思いを込める』を参考にテストが何をしようとしているか言語化すると分かりやすい
1. テストに失敗したらバグの発見や修正がしやすいようなエラーメッセージを付ける

#### やりすぎ
場合によってはテストに集中しすぎてしまう可能性もある、例として下記があげられる
1. テストの為に本物のコードの読みや憂さを犠牲にしてしまう
1. テストのカバレッジ(対象範囲に対してどれくらい網羅しているかを示す指標)が100%でないと気が済まない。
1. テストがプロダクト開発の邪魔になる(テストがプロジェクト全体を支配しているような状態)

<br><br>
## 15章　分/時間カウンタを設計実装する
14章までの内容を総括して、コードを記述している章です。

命名やコメントアウトについて話がされています。
その他１つの問題の解決法が３つに分かれて説明されていますがここでは割愛します。(まだ理解しきれていない為・・・)

## 最後に
初めてリーダブルコードを最後まで読み、確かに素晴らしいことが書かれていると思ったが、すべてを把握して吸収できたとは感じなかった。(自分の出来の悪さが出ています)
なんとなくニュアンスでだけでもこういった感じにすればいいのかなと掴めれば、読みやすいコードに近づくことが出来るのではないかと思う。
今後も何度も読み返し、日々のコードで意識し続けたいと思います。