本「リーダブルコード」の要約

## 命名規則
### 明確な単語を選ぶ

**「GetPage」だと何も分からない** 

- このメソッドはページをどこから取ってくる？
- ローカルキャッシュから？データベースから？
- インターネットから取ってくるなら、FetchPage()やDownloadPage()のほうが明確


**Size()メソッドは何を返すか分からない**

- ツリーの高さ？ノードの数？メモリ消費量？
- それぞれ、Height(), NumNodes(), MemoryBytes()になる


**Stop()でもいいけど、もっと明確な名前をつけれる**

- 取り消しができない重い操作ならKill()
- あとからResume()できるなら、Pause()

### tmp や retvalなどの汎用的な名前を避ける

- ２乗の合計を返すなら、sum_squaresなど
- 一時的に保管する目的であればtempを使ってもいい

### ループイテレータも明確な単語に

- i・j・k・iterなどの名前は、イテレータが複数ある時に複雑になる
- club_i, members_i, users_i または ci, mi, uiなどする

### 名前に情報を追加する

- `string id: // af84ef845cd8` → IDのフォーマットが大事なら、hex_idが適切

### 値の単位

- 変数名に単位を入れる
- start → start_ms
- delay → delay_secs
- limit → max_kbps
- angle → degrees_cw

### その他の重要な属性を追加する

- セキュリティ問題の多くは、プログラムの受診するデータが安全でないことが原因で発生している
    - untrustedUrl や unsafeMessageBody などの命名をする
    - データを安全にしたら、 trustedUrl や safeMessageBodyにするといい
- 具体
    - password → plaintext_password
    - comment → unescaped_comment
    - html → html_utf8
    - data → data_urlenc

### 名前の長さの決め方

- スコープが小さければ短い名前でもいい
- 単語保管機能を使えば、長い命名でも大丈夫
- プロジェクト固有の省略形の名前にしない
- 後から入った人が理解できる省略形なら大丈夫
- 不要な単語を投げ捨てる
    - ConvertToString → ToString
    - DoServerLoop → ServerLoop

### 曖昧な名前をつけない

**fileter()はどんな値が返ってくるか曖昧すぎる**
    - 選択する → select()
    - 除外する → filter()

**Clip(text,length) も最後からlength文字を削除するのか、最大length文字まで切り詰めるのかわからない**
    - Truncate(text,length)に変えるほうがいい
    - そしてlengthもmax_length、さらに言えば、単位をつけてmax_charsにするといい

### 限界値を含めるときはminとmaxを使う

- 未満なのか以下なのかわからないため、max_、min_を使う

### 範囲を指定するときはfirstとlastを使う

- stopは複数の意味に解釈できる
    - lastをつかあえば、抱合していることが明確になる

### 包含/排他的範囲にはbeginとendを使う

- endは包括的を意味する

### ブール値の名前

- **read_passwordだと二つの意味がありえる**
    - パスワードをこれから読み取る必要がある
    - パスワードをすでに読み取っている
    - → need_password, user_is_autheticatedを使う
- **頭にis・has・can・shouldをつける**
- - **名前を否定的にするのは避ける**
    - disabled_ssl = false → use_ssl = true
    - 肯定形にしたほうが声にだして読みやすい

### 説明変数を使う

- 式を表す変数を使う

```jsx
username = line.split(":")[0].strip();
```

### コードを「段落」に分割する

```jsx
def suggest new_friends(user, email_password);
 # ユーザーの友達のメールアドレスを取得
 friends = user.friend();
 friend_emails = set(c.email for in friends);

 # ユーザーのメールアカウントからすべてのメールアドレスをインポートする
 contacts - import_contacts(user.email, email_password)
 contact_emails
```

## コメント
## 自分の考えを記録する

```jsx
// このデータだとハッシュテーブルよりもバイナリツリーのほうが40%早かった
```

- コメントから情報を得ることができるので、下手に最適化しようとして無駄に時間を使う必要がなくなる

## コードの欠陥にコメントをいれる

- 改善が必要なときは以下のように書いておく

```jsx
// TODO: もっと高速なアルゴリズムをつかう
```

- コードが未完成のときは以下のように書いておこう

```jsx
TODO(グラ): JPEG以外のフォーマットに対応する
```

- よく使う記法
    - TODO : あとで手を付ける
    - FIXME : 既知の不具合があるコード
    - HACK : あまりキレイじゃない解決策
    - XXX : 危険！大きな問題がある

### 定数にコメントをつける

- その定数が何をするのか、なぜその値を持っているのか「背景」が存在する場合が多い

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

image_quality = 0,72; // 0.72ならユーザーはファイルサイズと品質の面で妥協できる
```

### ハマりそうな罠を告知する

```
// 実行時間は0(タグの数 * タグの深さの平均)なので、ネストの深さに気を付ける
```

### 要約コメントをつける

```
def GenerateUserReport():
  #  このユーザのロックを獲得する
  ...
  # ユーザの情報をDBから読み込む
  ...
```

## 制御フローを読みやすくする
### 条件式の引数の並び順

- 左側
    - 調査対象の式。変化する
- 右側
    - 比較対象の式。あまり変化しない

```jsx
if(age >= 10){}
while(bytes_expected < bytes_expected) {}
```

- 「もし君が18歳以上ならば」という順番が自然
    - 「もし君の年齢が年齢以下ならば」というのは不自然

### if / elseブロックの並び順

- 条件は否定形よりも肯定形を使う。例えばif(!debug)ではなく、if(debug)を使う。
- 単純な条件を先に書く。ifとelseが同じ画面に表示されるので見やすい
- 関心を引く条件や目立つ条件を先に書く

```jsx
if(a == b) {
	// 第一のケース
} else {
	// 第二のケース
}
```

以下のように書くのは同じ

```jsx
if(a != b) {
	// 第二のケース
} else {
	// 第一のケース
}
```

### 関数から早く返す

- 関数で複数のreturn文を使ってもいい

### ネストを浅くする

- ネストの深いコードは理解しにくい

### 早めに返してネストを削除する

- ネストを削除にするには「失敗ケース」をできるだけ早めに関数から返せばいい

### ループ内部のネストを削除する

- 早めに返す技法はいつでも使えるわけではない。
- 早めに返すのと同じようなことをループ内部で行うには、continueを使う

```jsx
for (int i = 0; i < result.size(); i++) {
	if(result[i] == NULL) continue;
	non_null_count++;
	if(result[i]->name == "") continue;
	count << : "Text" << endl;
}
```

## 変数の取り扱い
### 不要な変数の切り出しを削除する

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

### 役に立たない一時変数

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

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

### 中間結果を削除する

- 変数 **index_to_remove** は、中間結果を保持するためだけに使っている

```jsx
var remove_one = function(array, value_to_remove) {
	var index_to_remove = null;
	for (var i = 0; i < array.length; i += 1) {
		if(array[i] === value_to_remove) {
			index_to_remove = i;
			break;
		}
	}
	if(index_to_remove !== null) {
		array.splice(index_to_remove, 1);
	}
}
```

- 結果をそのまま使えば、このような変数は削除できる

```jsx
var remove_one = function(array, value_to_remove) {
	for (var i = 0; i < array.length; i += 1) {
		if(array[i] === value_to_remove) {
			array.splice(i,1);
			return;
		}
	}
}
```

- 関数から早く返すことで、index_to_removeをすべて削除できた。
- **タスクはできるだけ早く完了するほうがいい**

### 制御フロー変数を削除する

```jsx
boolean **done** = false;
while(/* 条件 */ && !**done**) {
	...
	if(...) {
		done = true;
		continue;
	}
}
```

- 制御フロー変数は削除できる

```jsx
while(/* 条件 */) {
	...
	if(...) {
		break;
	}
}
```

### 変数のスコープを縮める

- クラスのメンバ変数を減らす
    - メソッドをできるだけ static にするといい
    - staticを使えば、メンバ変数とは関係ないことがよくわかる

### 変数は一度だけ書き込む
- const使うべき
- 変数が絶えず変更されると、値を追跡する難易度が高い

### 汎用コードをたくさんつくる

- ReadFileToString() や format_pretty()など、広く適用可能な関数を、複数のプロジェクトで再利用する
- 特別なディレクトリ(例: util)を用意する


## 一度に複数のタスクを行わない
```jsx
var vote_changed = function (old_vote, new_vote) {
	var score = get_score();
	
	if(new_vote !== old_vote) {
		...
	}

	if(new_vote === "Up") {
		score += (old_vote === "Down" ? 2 : 1);
	} else if (new_vote === "Down") {
		score -= (old_vote === "Up" ? 2 : 1);
	} else if (new_vote === "") {
		score -= (old_vote === "Up" ? -1 : 1);
	}
	set_score(score);
}
```

- たった１つのこと(スコアを更新すること)をしているように見えて、実際には一度に２つのタスクを行っている

1. old_vote と new_voteを数値に「パース」する
2. score を更新する

２つのタスクを別々に解決すれば、読みやすいコードになる

```jsx
// 最初のタスク(投票を数値にパースする)を解決したもの
var vote_changed = function (old_vote, new_vote) {
	if(vote === "Up") {
		return +1;
	}

	if(vote === "Down") {
		return -1;
	}

	return 0;
}

// ２つめのタスク(スコアの更新)を解決している
var vote_changed = function (old_vote, new_vote) {
	var score = get_score();
	score -= vote_value(old_vote); // 古い値を削除する
	score += vote_value(new_vote); // 新しい値を追加する
}
```