リーダブルコードをn読み解こう

: subtitle

3章 誤解されない名前

: author

須藤功平

: institution

株式会社クリアコード

: content-source

schoo

: date

2014/12/9

: allotted-time

40m

: theme

clear-code

質問(1)

((‘tag:center’)) プログラミングについて

* A:未経験
* B:学習中(('note:(schooや学校、独学など)'))
* C:趣味・仕事でたまに書く\n
  (('note:(趣味でWebサイトを作っている、職業がデザイナーなど)'))
* D:趣味・仕事でバリバリ書く\n
  (('note:(趣味でOSSを開発している、職業がエンジニアなど)'))

質問(2)

((‘tag:center’)) リーダブルコード(本)を…

* A:読んだ
* B:読んでいる
* C:まだ読んでいない

内容

* 自己紹介
* リーダブルコードとは
* 実例で考えよう
* 実際の改善にチャレンジ!
* まとめ
* 質疑応答

自己紹介(1)

* リーダブルコードの\n
  「解説」の著者\n
  (('note:http://www.clear-code.com/blog/2012/6/11.html'))

自己紹介(2)

* クリアコードの代表取締役
  * 「クリア」な(意図が明確な)\n
    「コード」を大事にする\n
    ソフトウェア開発会社

自己紹介(3)

# image
# src = images/github-kou-with-annotation.svg
# relative_height = 100

スライドプロパティー

: enable-title-on-image

false

リーダブルコードとは(1)

# blockquote
# title = はじめに p. x

本書の目的は、君のコードをよくすることだ

リーダブルコードとは(2)

# blockquote
# title = はじめに p. x

その中心となるのは、コードは理解しやすくなければいけないという考えだ

リーダブルコードとは(3)

# blockquote
# title = 1.2 読みやすさの基本定理 p. 3

「コードを理解する」というのは、変更を加えたりバグを見つけたりできるという意味

リーダブルコード

* 変更できるコード
* バグを見つけられるコード

((‘tag:center’))((‘tag:x-large’)) ↓n 読む人視点!

何をしているコード?

# coderay cpp

Node* node = list->head;
if (node == NULL) return;

while (node->next != NULL) {
    Print(node->data);
    node = node->next;
}
if (node != NULL) Print(node->data);

((‘tag:center’))((‘note:「優れた」コードって何? p. 2より’))

何をしているコード?

# coderay cpp

for (Node* node = list->head;
     node != NULL;
     node = node->next)
    Print(node->data);

((‘tag:center’))((‘note:「優れた」コードって何? p. 2より’))

どちらがリーダブル?

# coderay cpp

// どちらがリーダブルコード?どうして?
// リーダブルコード:変更できる・バグを見つけられるコード
// A.
Node* node = list->head;
if (node == NULL) return;
while (node->next != NULL) {
    Print(node->data);
    node = node->next;
}
if (node != NULL) Print(node->data);
// B.
for (Node* node = list->head; node != NULL; node = node->next)
    Print(node->data);

((‘tag:center’))((‘note:「優れた」コードって何? p. 2より’))

実例で考えよう

((‘tag:center’))((‘tag:large’)) 3章「誤解されない名前」n より

((‘ ’))

3.1 例:filter()(1)

# coderay python

results =
  Database.all_objects.filter("year <= 2011")

(({results}))はなに?

* 2011年以前のレコード?
* 2012年以降のレコード?

3.1 例:filter()(2)

* filterはあいまいな言葉
  * 選択する→(({select()}))
  * 除外する→(({exclude()}))

select("year <= 2011")
exclude("year <= 2011")

番外1:sort()(1)

* どっちの名前がよい?
  * sort()
  * quick_sort()/merge_sort()

番外1:sort()(2)

* ((*ソートすること*))が重要
  * sort()
* ソート((*方法*))が重要
  * quick_sort()/merge_sort()

ヒント:抽象化・カプセル化n ((‘note:(abstraction barrier, abstraction layer)’))

3.2 例:Clip()(1)

  # coderay python

  # textの最後を切り落として、
  # 「...」をつける
  def Clip(text, length):

* 最後から(({length}))文字を削除する?
* 最大(({length}))文字まで切り詰める?

3.2 例:Clip()(2)

切り詰めるなら:(({Clip}))→(({Truncate}))

# coderay python

def Clip(text, length):
# ↓
def Truncate(text, length):

3.2 例:Clip()(3)

((*最大*))(({length}))文字なら:(({max}))をつける

# coderay python

def Truncate(text, length):
# ↓
def Truncate(text, max_length):

3.2 例:Clip()(4)

最大(({length}))((*文字*))なら:n (({length}))→(({chars}))

# coderay python

def Truncate(text, max_length):
# ↓
def Truncate(text, max_chars):

番外2:add()(1)

* どの名前がよい?
  * add()
  * append()/prepend()

番外2:add()(2)

* ((*追加すること*))が重要\n
  (('note:例:集合に追加するとき'))
  * add()
* 追加する((*場所*))が重要\n
  (('note:例:リストに追加するとき'))
  * append()/prepend()

ヒント:抽象化・カプセル化n ((‘note:(abstraction barrier, abstraction layer)’))

3.3 限界値(1)

ショッピングカートに入る商品がn 最大10点のケース

# coderay python

CART_TOO_BIG_LIMIT = 10

if cart.num_items() >= CART_TOO_BIG_LIMIT:
    Error("カートにある商品数が多すぎます。")

3.3 限界値(2)

((‘tag:center’)) バグあり!n 9点までしか入らない

# coderay python

CART_TOO_BIG_LIMIT = 10

if cart.num_items() >= CART_TOO_BIG_LIMIT:
    Error("カートにある商品数が多すぎます。")

3.3 限界値(3)

* (({CART_TOO_BIG_LIMIT}))はあいまい
  * 未満?以下?→境界値の情報がない
* (({MAX_ITEMS_IN_CART}))は明確
  * この値が最大値(境界値を含む)
  * 最大値のときは(({max}))を使おう!\n
    (('note:(最小値のときは(({min})))'))

3.3 限界値(4)

# coderay python

# CART_TOO_BIG_LIMIT = 10
# if cart.num_items() >= CART_TOO_BIG_LIMIT:
#     Error("カートにある商品数が多すぎます。")
MAX_ITEMS_IN_CART = 10
if cart.num_items() > MAX_ITEMS_IN_CART:
    Error("カートにある商品数が多すぎます。")

他の例

* 範囲を指定するときは\n
  (({first}))と(({last}))を使う
* 包含/排他的範囲には\n
  (({begin}))と(({end}))を使う
* …
* (詳細は本を買ってください)

実際の改善にチャレンジ!

  # coderay php

  /* schooの学生名一覧を返す
     引数は返す学生名の最大値 */
  function student($num) {
    /* 処理の具体的な内容 */
  }

* 誤解されない名前に改善して投稿
* よい投稿に「いいね!」して応援

まとめ(1)

* リーダブルコードとは
  * 変更できるコード
  * バグを見つけられるコード
  * ↑は((*読む人視点*))

まとめ(2)

* 「誤解されない名前」を考えた
  * (({filter}))はあいまい
    * →(({select}))/(({exclude}))
  * (({Clip}))もあいまい
    * →(({Truncate}))
  * (({TOO_BIG_LIMIT}))もあいまい
    * →(({MAX_ITEMS_IN_CART}))

まとめ(3)

* 実際の改善にチャレンジした
  * 「((*読む人*))が理解しやすいか?」を\n
    とことん考えたはず

# blockquote
# title = 3章 誤解されない名前 p. 30

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

これから(1)

* これからも((*読む人*))のことを\n
  考えてコードを書こう
* ((*読む人*))のことを考えるには?
  * 読む経験をたくさん積む
  * たくさんコードを読もう

これから(2)

* たくさんコードを読むコツ
  * コードから学ぶ気持ちで読む
  * ×悪いこと探し
  * ○いいこと探し
  * 本来、コードを読むことは\n
    楽しいことのはず!

悪いコード

* 見つけやすい
  * 異質
  * リーダブルじゃない
* 過剰に指摘したくなる
  * 「マサカリを投げてみたい」

マサカリ投げたい症候群

((‘tag:center’))((‘tag:margin-bottom * 2’)) 早めに卒業しましょう

* 必要十分な事実伝達以外の\n
  否定的な情報を過剰に含む指摘\n
  (('note:必要十分な事実伝達がない場合もある'))
  * 必要十分な事実伝達:\n
    ○○な理由で××ではなく△△だ\n
    (('note:本に書いているから、は理由になっていない'))

((‘note:↑は最近の「マサカリを投げる」の捉えられ方’))n ((‘note:参考:元々のモヒカン・手斧の使われ方:’))n ((‘note:www.otsune.com/diary/2005/06/14/4.html#200506144’))

よいコード

* 見つけにくい
  * リーダブルだから
  * すーっと理解できてひっかからない
* これからのチャレンジ
  * 意識して見つけよう!

これから(3)

((‘tag:center’))((‘tag:large’)) 「解説」を読むn ((‘note:www.clear-code.com/blog/2012/6/11.html’))

* 本文:((*個人*))で\n
  リーダブルコードを書く方法
* 解説:((*チーム*))で\n
  リーダブルコードを書く方法