リーダブルコード 3章、4章 まとめ

# 3章 **誤解されやすい名前**

---

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

**→**　積極的に「誤解」を探して、**あいまいな名前**、**間違った名前**を減らす

---

## **例: filter()**

filter()という言葉では、選択するのか、除外するのかがわからない。(つまり、あいまい)

```java
resultls = Database.all_objects.filter("year <= 2011");
```

選択するのであれば、 select() にした方が良い。
除外するのであれば、 exclude() にした方が良い。

---

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

ショッピングカートには商品が10点までしか入らないとする。

**✗** `CART_TOO_BIG_LIMIT = 10`
**◯** `MAX_ITEMS_IN_CART= 10`

アドバイス: 限界値を明確にするには、名前の前に max_ や min_ を付けよう。

---

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

包含の意味を含むのであれば、範囲を指定するときはfirstとlastを使用した方が良い。

`set.PrintKeys(first="Bart", last="Maggie");`

---

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

包含・排他的範囲 (最初を含むが、最後の要素は含まない)の場合は beginとendを使うのが良い。

---

## **ブール値の名前**

**✗** `read_password`
**◯** `need_password, user_is_authenticated`

**is, has, can, should** をつけておけばOK

---

## **ブール値の名前**

否定形は避けよう

**✗** `disable_ssl`
**◯** `use_ssl`

肯定形にしたほうがわかりやすい(Swiftのguardとかにも言えることかもね)

---

## **ユーザ(使用者)の期待に合わせる**

```
get〇〇()、〇〇.list()、〇〇.size()
```

は軽量なメソッドであると大抵のプログラマーは思う(らしい)

なので、重い場合は

```
generate〇〇()、〇〇.countSize()、〇〇.countElement()
```

とかにすべし

---

## **複数の名前を検討する**

類義語調べて比較して適切なものを選べ

---

## **まとめ**

- 最善の名前は**誤解されない名前**
- **✗** filter, limit, length
- **◯** max, min, first, last, begin, end
- **Bool値**が返るなら **is** や **has** をつける
- **disable_ssl** のような**否定形**は避ける
- **get()** や **size()** のようなメソッド名なら**軽量**を期待される
- 名前は大事だからよく検討しろ

---

# 4章 **美しさ**

---

## **鍵となる考え**

**一貫性のあるスタイルは「正しい」スタイルよりも大切だ**

**→**　どちらの書き方が正しいのかなんてのは**一貫性の前ではゴミ同然**

---

## **鍵となる考え**

**優れたソースコードは「目に優しい」ものでなければならない**

**→**　余白、配置、順序に気を使おう!

---

## **なぜ美しさが大切なのか**

プログラミングの**ほとんど**の時間は**コードを読む時間**であり、それでいうと読みやすさを追求するのはあたりまえのこと。
また、**設計**に比べ**容易**に導入できるので**今すぐに取り組むべき**である。

---

## **メソッドを使った整列**

だめな例

```java
DatabaseConnection database_connnection;
string error;
assert(ExpandFullName(database_connection, "Doug Adams", &error) == "Mr. Douglas Adams");
assert(error == "");
assert(ExpandFullName(database_connection, "Jake Brown", &error) == "Mr. Jacob Brown Ⅲ");
assert(error == "");
assert(ExpandFullName(database_connection, "No Such Guy", &error) == "");
assert(error == "no match found");
```

---

## **メソッドを使った整列**

良い例

```java
CheckFullName("Doug Adams", "Mr. Douglas Adams", "");
CheckFullName("Jake Brown,", "Mr. Jake Bron III", "");
CheckFullName("No Such Guy", "", "no match found");
CheckFullName("John", "", "more than one result");

void CheckFullName(...) {
  ...
}
```

---

## **メソッドを使った整列**

まとめ

- 重複がなくなり**簡潔**になった
- テストケースの**大事**な部分に目がいきやすくなった(差分がわかりやすい)
- テストの追加が**しやすくなった**

---

## **縦の線を整列する**

```java
CheckFullName("Doug Adams"  , "Mr. Douglas Adams", "");
CheckFullName(" Jake Brown,", "Mr. Jake Bron III", "");
CheckFullName("No Such Guy" , ""                 , "no match found");
CheckFullName("John"        , ""                 , "more than one result");
```

リーダブルコードではおすすめしているが、今のIDEとは相性が悪いので個人的にはあまり好きではない

---

## **一貫性と意味のある並び**

一連の同じデータを使用する際は並び順も同じにしておく

```python
details   = request.POST.get('details');
locations = request.POST.get('locations');
phone     = request.POST.get('phone');
```

```python
if details:   rec.details   = details
if phone:     rec.phone     = phone
if locations: rec.locations = locations
```

---

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

だめな例

```python
def suggest_new_friends (user, email_password):
   friends = user.friends()
   friend_emals = set(f.email for f in friends)
   contacts = import_contacts(user.email, email_password);
   contact_emals = set(c.email for c in contacts)
   non_friend_emails = contact_emals - friend_emails
   suggested_friends = USer.objects.select(email__in=non_friend_emails)
   display['user'] = user
   display['friends'] = friends
   display['suggested_friends'] = suggested_friends
   return render("suggested_friends.html", display)
```

---

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

良い例

```python
def suggest_new_friends (user, email_password):
   # ユーザの友達のメールアドレスを取得する。
   friends = user.friends()
   friend_emals = set(f.email for f in friends)
   
   # ユーザのメールアカウントからすべてのメールアドレスをインポートする。
   contacts = import_contacts(user.email, email_password);
   contact_emals = set(c.email for c in contacts)
   
   # まだ友達になっていないユーザを探す。
   non_friend_emails = contact_emals - friend_emails
   suggested_friends = USer.objects.select(email__in=non_friend_emails)

   # それをページに表示する
   display['user'] = user
   display['friends'] = friends
   display['suggested_friends'] = suggested_friends
   return render("suggested_friends.html", display)
```

---

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

まとめ

- 段落単位でコードを読むことが可能に
- 必要な箇所だけ読んで、不要な箇所は読まなくて済む
- ってか、段落にするならもはやメソッドに分けたほうが良くね？

---

## **まとめ**

- コードの美しさはコードの理解を助ける
- 同じ処理は同じシルエットにする
- 意味のある順序でコードを書く
- 空行を使ったブロック分けも倫理的な段落を意識する

---

## 参考

「リーダブルコード」を読む (第3章「理解しやすいコード」第4章「美しさ」) - FPGA開発日記
http://msyksphinz.hatenablog.com/entry/2017/11/19/230337