「誰にもできる」より良いコードを書くためのテクニック

# はじめに
こんにちは、愛知でWEBエンジニアをしているkokuboと申します。

ここ最近の業務でコードレビューをすることが多くなり、人によって読みやすさの違いがあることや過去に自分で書いたコードが読みにくかったことから、**良いコードとは何か**を調べて見ました。
今回は「リーダブルコード」を元に良いコードとは何かを簡単紹介させていただきます。

この記事では難しい技術がいらないため、初心者や私と同じようにレビューを始めた方達の参考になれば幸いです。

# 概要
【この本での「良いコード」とは】
　他の人(過去の自分も含む)が最短時間で理解ができるコードのこと

【メリット】
- 理解しやすい
  - コードを読んだだけで、そのコードが何をしようとしているのかがすぐに理解できる
- メンテナンスしやすい
  - バグの修正や機能の追加など、コードを変更する際に、その意図を把握しやすくなる
- チームで開発しやすい
  - 複数の開発者が同じコードに関わる場合、お互いのコードを読み解きやすくなり連携が容易になる

# １：分かりやすい名前とは
**【より具体的な名前を選択する】**
- 例えば「getData」だけでは何のデータをどこから取得してきているのかが具体的ではない
```diff_php
// NG例：具体的ではない名前
function getData() // 名前から推測することができない

// 具体的な名前
function readSessionUsers() // セッションからユーザー情報を取得
function fetchUsers()       // Usersデータベースから取得(fetchはDB関連でよく使用する)
function downLoadUsers()    // ユーザー情報をダウンロード

// 短いネスト(返り値を変えすだけ等)では短い名前でもOK
if ($check_user) {
    $sl_cnt = $shoppingListData['count'];
    return $sl_cnt;
}
```
- シソーラス(類語辞典)でより具体的な名前を探そう
 「[weblio](https://ejje.weblio.jp/english-thesaurus/)」では単語を検索することで類語を検索することで、状況に応じた類語を確認できるので便利です。

 <img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033765/867c096f-5dab-08bd-3294-9aa25c9dbd19.png">

 　
**【名前だけではなく、情報も追加する】**
　重要な情報を持つようなものであれば、情報を追加して間違いを起きにくいようにしましょう
 | 状況 | 変数名| 改善後 |
|:-:|:-:|:-:|
| スタートした時間(ミリ秒)  |  start | start_ms  |
| 暗号化されてないプレインテキストのパスワード  | password  | plaintext_password  |
| UTF-8に変更したhtml  | html  | html_utf8  |
| dataをURLエンコードした  | data  | data_urlenc  |

**【分かりにくい名前をつける時のデメリット】**
**誰かが理解しやすい名前を考えるのは時間がかかる？？**
　普段英語を使用しない日本人には特に面倒なのが、「適切な英語を考える」ことです。私は特に苦手なため、以下のサイトや記事を使用してなるべく簡単に作成しています。
 1.関数名の命名規則の参考
 　https://qiita.com/YutaManaka/items/62dda256bb7ba6c08399
2.入力した日本語を関数や変数名に自動変換する(スネーク・キャメルにも変換可)
　https://codic.jp/engine
3.類義語の検索
　https://ejje.weblio.jp/english-thesaurus/#google_vignette


# ２：美しさ
**【美しさとは】**
　雑誌のレイアウトは多くの考えが詰められており、段落の長さ・横幅・記事の順番などを工夫することでページを飛ばしても順序よく読めるようになっています。

 **【プログラミングではどこで工夫できるか？】**
 ソースコードでは以下の点で美しさを工夫することができます。
　- 余白
　- 配置
　- 順序 

**【改行での工夫】**
```diff_php
// NG例：全て横並び
public function fetchShoppingData($userId)
{
    $shoppingData = ShoppingLists::selected('id','name','price')->leftJoin('users','users.id','=','user_id')->where('user_id',$userId)->get();
}

// 改行によってORマッパーが確認しやすい
public function fetchShoppingData($userId)
{
    $shoppingData = ShoppingLists::selected('id', 'name', 'price')
                                　->leftJoin('users', 'users.id', '=', 'user_id')
                                 ->where('user_id', $userId)
                                 ->get();
}
```
**【余白での工夫】**
```diff_php
// NG例：代入値、コメントが分かりづらい
$mail_checks = new MailChecks;
$mail_checks->limit_month = $mailLimitMonth; //確認月
$mail_checks->send_flg = 1; //送信フラグ
$mail_checks->created_at = date('Y-m-d H:i:s'); //作成日時
$mail_checks->created_user_id = $userId; //ユーザーID

// それぞれを縦並びにして分かりやすくする
$mail_checks = new MailChecks;
$mail_checks->limit_month     = $mailLimitMonth;      // 確認月
$mail_checks->send_flg        = 1;                    // 送信フラグ
$mail_checks->created_at      = date('Y-m-d H:i:s');  // 作成日時
$mail_checks->created_user_id = $userId;              // ユーザーID
$mail_checks->save();
```

# 3：コメントすべきことを知る
　コメントの目的は書き手の意図を読み手に伝えること

**【コメントすべきではなきこと】**
コードから分かることをコメントにしない
```diff_php
// NG例：　コメントに書いてあることは関数名と同じ
// profileに値を設定する
$this->setProfile($user)
```
**【自分の考えを記載する】**
　以下のようなコメントがあれば、失敗するテストケースに無駄な時間を費やすことがなくなる。
```diff_php
// ヒューリスティックだと単語が漏れることがあるのは仕方ない。100%解消するのは難しい
```
**【コードに欠陥があった時】**
「アノテーションコメント」を使用する
- コメントにメタデータを付加することができる
- コードの欠陥が分かりやすくなる
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033765/fe2e6f99-6555-73fb-52ae-b99ae860fb7e.png">

**【読み手の立場になったコメント】**
- 質問されそうなこと
- 機能をグループ化した時の要約
- 指示語を使用しない（あれ、これ、それ）
- 罠にかかりやすいコード
- コードの意図（なんのためにこのコードがあるか）
```diff_php
//　コードの意図の例

// listをイテレートして逆順に変えるためにforする
for (let i=0; i<list.length; i++){ 処理 }

// 値段が高い順に並び替えるためにforする
for (let i=0; i<list.length; i++){ 処理 }
```

# 4：終わりに
いかがでしたでしょうか？

今回はリーダブルコードの中でも割と簡単に活用できる部分を紹介させていただきました、この記事は経験年数やプログラミング言語に関わらず活用できると思います。

皆さんの良いコードを書くために役立てられれば幸いです。
最後まで読んでいただきありがとうございました。