SlideShare a Scribd company logo
1 of 80
Download to read offline
リーダブルコード勉強会
 山﨑 陽平
● 「なんでリーダブルコード?」
AISCは研究機関でもある一方で、社会に役に立つものを作る機関でもある。
「社会に使われるコード = 他人が読むコード」
だと勝手に思っております。
案件の引き継ぎがあるかもしれないし、人が辞めるかもしれないし、
半年前の自分と向き合う必要もある。
そんな時に、「リーダブルコード」を書く技術は必要だと思いました。
はじめに:今回の勉強会の目的
● 「いいコード」と「悪いコード」に気づけるようになる。
● 「いいコード」の書き方がわかる。
● 「いいコード」についての、チームで共通の文脈を持つ。
はじめに:今回の勉強会の目標
はじめに:今回の勉強会の注意点
● 「強制」ではなく「推奨」
● 「正しさ」よりも「統一感」
● 知ってることも多分ある
● リーダブルコードが全て正しいわけではない
● 「綺麗」にこだわりすぎて「スピード」を落としすぎないで。
・「いいコード」とは
・表面上の改善
1. 名前の改善
2. コメントの改善
・ループとロジックの単純化
3. 制御フローの改善
4. 巨大な式の改善
・最後に
目次
・「いいコード」とは
・表面上の改善
1. 名前の改善
2. コメントの改善
・ループとロジックの単純化
3. 制御フローの改善
4. 巨大な式の改善
・最後に
目次
いいコードとは?
「コードは理解しやすくなければいけない」
いいコードとは?
理解しやすいコードの利点
● 他人が分かる。
● 変更を加えたり、バグを見つけやすくなる。
● コードの設計自体がしやすくなる。
いいコードとは?
短くするのではなく、理解しやすくする。
・「いいコード」とは
・表面上の改善
1. 名前の改善
2. コメントの改善
・ループとロジックの単純化
3. 制御フローの改善
4. 巨大な式の改善
・最後に
目次
● プログラムの名前ははっきりしないものが多い。(a とか tmpとか)
● sizeやgetといった一見問題のないものも、必要な情報がない時もある。
● 変数名は短いコメントであり、出現した時に毎回見るもの。
1:名前の改善
「名前に情報を詰め込む」
● 明確な単語を選ぶ
● 具体的な名前を選ぶ
● 接頭辞や接頭語で情報を追加する
● 名前の長さを決める
● 名前のフォーマットを意識する
1:名前の改善
1-1:明確な単語を選ぶ
例えば以下のコードの、「get」はあまり正確な単語ではない。
例えば、このメソッドはページを「どこから」とってくるのか?
1-1:明確な単語を選ぶ
例えば以下のコードの、「get」はあまり正確な単語ではない。
例えば、インターネットからなら以下の方がわかりやすい。
次はある二分木クラスの例。
何のSize()を返すのか?ツリーの高さ?ノードの数?メモリ消費量?
1-1:明確な単語を選ぶ
次はある二分木クラスの例。
ノードの数が欲しいなら、以下のようにした方がいい。
木の高さならHeight(), メモリ消費量ならMemoryBytes()などがいいだろう。
1-1:明確な単語を選ぶ
1-1:明確な単語を選ぶ
明確な単語を選ぶために、「カラフル」な単語を知っておこう。
(もちろん、やりすぎは良くない!)
例えば、以下はGoogleで使われてた昔のコードになる。
抽象的な名前から、具体的に何をするかわかるコードになっている。
1-2:具体的な名前を使う
以下は、読み込み時間を計測するコード。
1-3:名前に情報を追加する
以下は、読み込み時間を計測するコード。
1-3:名前に情報を追加する
実はgetTimeは「ミリ秒」を返すのでうまくいかない。
1-3:名前に情報を追加する
以下は、読み込み時間を計測するコード。
変数名に_msを追加すれば明確になる。
スコープが長い時には、mの型や目的が分かりづらい。検索もしづらい。
1-4:名前の長さを決める。
スコープが長い時には、mの型や目的が分かりづらくなる。
スコープが小さければ、短い名前でもすぐに理解できる。
1-4:名前の長さを決める。
※ プロジェクトや言語によってフォーマットは異なる
アンダースコア・大文字でフォーマットを決めて情報を詰め込んでいる。
1-5:名前のフォーマットで情報を伝える。
「当たり前!」と思ってるかもしれないが、
フォーマットに沿わないコードは非常に難解になる。
1-5:名前のフォーマットで情報を伝える。
● 明確な単語を選ぶ
● 具体的な名前を使って、詳細に説明する
● 変数名に大切な情報を追加する
● スコープの大きな変数には長い名前をつける
● 大文字やアンダースコアに意味をつける
1:名前の改善 まとめ
・「いいコード」とは
・表面上の改善
1. 名前の改善
2. コメントの改善
・ループとロジックの単純化
3. 制御フローの改善
4. 巨大な式の改善
・最後に
目次
● コメントの目的は「コードの動作を説明すること」だけ?
● コードを書いてる時には、
その人の頭の中だけにある情報がたくさんある。
● しかし、他の人が読む時にはその頭の中の情報は失われてしまう。
2:コメントの改善
「コメントの目的は、書き手の意図を読み手に伝える事」
● コメントを「すべきでない時」を知る
● コメントに自分の考えを記録する
● 読み手の立場で考える
● 正確で簡潔なコメントをする
2:コメントの改善
以下のように、コードからすぐにわかることをコメントしない。
2-1:コメントすべきでない時 (すぐ分かるコメント)
以下のように、コードからすぐにわかることをコメントしない。
2-1:コメントすべきでない時 (すぐ分かるコメント)
(理解するのに少し時間がかかることは、むしろ書くべき。)
以下のコードのコメントは必要だろうか?
2-1:コメントすべきでない時 (ひどいコード)
以下のコードのコメントは必要だろうか?
このコメントは「Clean」という雑な名前の意味を説明しているだけ。
関数名や変数名は「短いコメント」であり、いろんなところで用いられる。
   優れた名前 >>> 優れたコメント + ひどいコード
2-1:コメントすべきでない時 (ひどいコード)
以下のコードのコメントは必要だろうか?
変数名に情報を持たせて、コメントを減らすことができる。
2-1:コメントすべきでない時 (ひどいコード)
コードには以下のような考えを残してくのは重要だ。
コメントから情報を得ることで、再度バイナリツリーを試す必要がなくなる。
2-2:自分の考えを記録する (背景について)
コードが汚いということをコメントしてもいい。
コードに欠陥があることは防げない。
その欠陥を恥ずかしがったり文書化しないことは良くない。
改善が必要な時は以下のように書く。
# TODO: もっと高速なアルゴリズムにする。
コードが未完成の時は以下のようにも書いていい。
# TODO(ダスティン): JPEG以外のフォーマットに対応する。
2-2:自分の考えを記録する (欠陥について)
欠陥を記述する時に、プログラマが良く使う記法
2-2:自分の考えを記録する (欠陥について)
記法 典型的な意味
TODO : あとで手をつける
FIXME : 既知の不具合があるコード
HACK : あまり綺麗じゃない解決策
XXX : 危険! 大きな問題があるかも。
以下の定数について、特段悪いところはなさそうだ。
しかし、この値の決め方がわからない。
NUM_TREADS = 8
2-2:自分の考えを記録する (定数に対して)
以下の定数について、特段悪いところはなさそうだ。
しかし、この値の決め方がわからない。
NUM_TREADS = 8
コメントをつけると
値の決め方がわかる。(1だと小さすぎるし50だと大きすぎる)
NUM_TREADS = 8 # >= 2 * num_processorsで十分
2-2:自分の考えを記録する (定数に対して)
定数値は厳密じゃなくてもいい場合もある。
const int MAX_RANGE = 999999 // これ以上大きなサイズの画像はありえない。
値がいい感じに設定されてるので、調整する必要のない場合もある。
image_quality = 0.72 // 0.72ならユーザはサイズと品質の面で妥協できる。
既知じゃない定数についてはコメントをできるだけ残そう。
2-2:自分の考えを記録する (定数に対して)
textsという文字列を引数にとる関数。
2-3:読み手の立場になる (疑問に思うところ)
以下のコードに、疑問に思うところがないだろうか?
2-3:読み手の立場になる (疑問に思うところ)
2-3:読み手の立場になる (疑問に思うところ)
textsという文字列を引数にとる関数。
以下のようなコメントがある方が読み手にわかりやすい。
2-3:読み手の立場になる (全体像に対して)
新しいチームメンバーにとって最も難しいのは「全体像」の理解である。
● クラスや関数はどのように連携しているのか
● データはどのように流れているのか
● etc …
高レベルの情報についてのコメントも書くようにしよう。
(READMEやDocStringでももちろんいい。)
2-4:正確で簡潔なコメントをする
● コメントは出来るだけ簡潔に
● 曖昧な代名詞を避ける
● 関数の動作を正確に記述する
● 入出力の実例を使う
● コードの意図を書く
2-4:正確で簡潔なコメントをする (正確な表現)
以下のコメントだと、なんの行数かわからない。
2-4:正確で簡潔なコメントをする (正確な表現)
以下のコメントだと、なんの行数かわからない。
より正確な表現を用いる。
2-4:正確で簡潔なコメントをする (実例を用いる)
文字列の一部を除去する関数があるとする。
しかしこのコメントでは、以下のようなことがわからない。
● charsは「文字列」なのか、「文字集合」なのか
● srcの末尾に複数のcharsがあったらどうなるのか
文字列の一部を除去する関数があるとする。
適切な実例をコメントに付け加えるだけで、イメージができる。
2-4:正確で簡潔なコメントをする (実例を用いる)
● ライターズブロックとは?
「コメントはうまく書かなきゃ」と思って結局コメントを書かない。
● 自分の考えてることはとりあえず書き出す
2-5:ライターズブロックを乗り越える
● 具体例
ある関数を作っていて、
「やばい、これはリストに重複があったら面倒になことになる」と思ったら
と書けば良い。(無いよりマシ。)
2-5:ライターズブロックを乗り越える
可能なら言い回しをより正確で簡潔なものにしよう。
○ やばい => 注意:
○ これ => 入力を処理するコード
○ 面倒なことになる => 実装が難しくなる
2-5:ライターズブロックを乗り越える
● コメントすべきで「ない」こと
○ コードからすぐわかることや、ひどいコードのためのコメント
● 自分の考えを記録する
○ 監督コメンタリー・コードの欠陥・定数の裏にある背景
● 読み手の立場になって考える
○ 読み手が戸惑うだろう事や、全体像についてコメントする
● コメントは正確で簡潔に書く
○ コメント領域に対する情報の比率を高くする
● ライターズブロックを乗り越える
2:コメントの改善 まとめ
目次
・「いいコード」とは
・表面上の改善
1. 名前の改善
2. コメントの改善
・ループとロジックの単純化
3. 制御フローの改善
4. 巨大な式の改善
・最後に
● 条件やループなどの制御フローのないコードはわかりやすい。
● 雑に制御フローを使うと、途端にわかりづらくなる。
3:制御フローの改善
条件やループなどの制御フローは出来るだけ「自然」にして、
コードの読み手が立ち止まったり読み返したりしないようにする。
● 条件式の引数の並びを意識する
● if / else の順番を意識する
● ネストを浅くする
3:制御フローの改善
以下の二つの式のどっちの方がわかりやすいだろうか?
if (length <= 10):
if (10 >= length):
current_size = get_current_size()
while (current_size > min_size):
while (min_size < current_size):
どちらも最初の条件式の方が読みやすいのではないか?
3-1:条件式の引数の並び順
引数の並び順の指針。
これは言葉の用法に似ている。
「もし君の年齢(調査対象)が18才(比較対象)以上ならば」 … 自然
「もし18才(比較対象)という年が君の年齢(調査対象)以下なら」 … 不自然
3-1:条件式の引数の並び順
左側 右側
「調査対象」の式。変化する。 「比較対象」の式。あまり変化しない。
● 条件は否定形よりも肯定系を使う
● 単純な処理となる条件を先に書く。(if/elseが同じ画面にでる。)
● 関心を引く条件や目立つ条件を先に書く。
3-2:if/else ブロックの並び順
以下のコードをぱっと見ただけで理解できるだろうか?
3-3:ネストを浅くする (深いネストの例)
読み手は、精神的なスタックに様々な条件を追加しなければならない。
最初は非常にシンプルなコードだった。
3-3:ネストを浅くする (なぜ深くなる?)
ここからどうやって深くなっていったのだろうか?
書いた人にとっては簡潔だが、文脈がわからない人には難しくなっている。
新しい条件が追加され、コードが追加される。
書いた人にとっては簡潔だが、文脈がわからない人には難しくなっている。
3-3:ネストを浅くする (なぜ深くなる?)
今回の例では、「失敗ケース」を早めに返すことでネストを削除する。
3-3:ネストを浅くする (ネストの削除)
ガード節(関数の上部で単純な条件を先に処理する)を意識するといい。
● 条件式の引数の並びを意識する
変化する値を左に、安定した値を右に配置する。
● if / else の順番を意識する
一般的には、肯定系・単純・目立つものから先に処理する。
● ネストを浅くする
○ ガード節を意識した処理フローにする。
3:制御フローの改善 まとめ
目次
・「いいコード」とは
・表面上の改善
1. 名前の改善
2. コメントの改善
・ループとロジックの単純化
3. 制御フローの改善
4. 巨大な式の改善
・最後に
● 人間は一度にそんなに多くのことを考えられない。
● 巨大なものには名前をつけた方が理解しやすい。
4:巨大なコードを分割する
巨大な式は飲み込みやすい大きさに分割する。
無関係の下位問題を抽出する。
● 説明変数・要約変数を導入して式を短くする。
● 「頭のいい」コードに気をつける
● 無関係の下位問題を抽出する
4:巨大なコードを分割する
いくつかのメソッドがチェインしたコードはよく見かけると思う。
上記の`line.spleit(‘: ’)[0].strip()`が何を表しているか分かりづらいので、
以下のようにまとめてあげた方がいいだろう。
4-1:説明変数を使う
すぐに意味がわかりそうな場合はどうだろうか?
request.user.id == document.owner_id はそれほど難解な式ではない。
4-2:要約変数を使う
このような場合も、式の意味を要約してあげるといい。
「ユーザは文書を保持しているか?」という概念なので、
変数にすることでそれを伝えらえる。
4-2:要約変数を使う
これは「キーのバケツを取得する。もしバケツがnull出ないなら、
中身が入ってないか確認する」というコードである。
4-3:「頭がいい」コードに気をつける
これは「キーのバケツを取得する。もしバケツがnull出ないなら、
中身が入ってないか確認する」というコードである。
少し変数をつけてあげた方がずっと分かりやすくなった。
かっこいい短いコードは、他人から喜ばれるどころか疎まれるかもしれない。
4-3:「頭がいい」コードに気をつける
一文一文は難しくないが、束になることで難しくなっている。
また、同一の式が複数あるが、それらを同一とみなすのは簡単じゃない。
4-3:巨大な文を分割する。
同一の式や何度も変わる文字は変数としてまとめてしまう。
4-3:巨大な文を分割する。
与えられた経度緯度に最も近いarrayの要素を返す。
4-4:無関係の下位問題を抽出する。
distを計算する部分は無関係なものとして抽出できる。
これを「無関係の下位問題の抽出」と呼ぶ。
4-4:無関係の下位問題を抽出する。
● 説明変数や要約変数を導入する
○ 長い式を分割できる
○ 簡潔な名前で式を説明する事で、コードを文書化できる
● 無関係の下位問題を抽出する
○ 一つの関数に複数ののことをさせてないかを意識する
○ 関数間の抽象度を意識する
4:巨大なコードを分割する まとめ
目次
・「いいコード」とは
・表面上の改善
1. 名前の改善
2. コメントの改善
・ループとロジックの単純化
3. 制御フローの改善
4. 巨大な式の改善
・最後に
● 「リーダブルコード」を読んでみよう。
● 実際にやってみよう。
● コードを他の人に読んでもらおう。
● 「綺麗なコードを書く意識」を当たり前にしよう。
最後に
Thank you

More Related Content

Similar to Readable coder (6)

研究・企業・生き方について 情報科学若手の会2011
研究・企業・生き方について 情報科学若手の会2011研究・企業・生き方について 情報科学若手の会2011
研究・企業・生き方について 情報科学若手の会2011
 
○○について考える
○○について考える○○について考える
○○について考える
 
エンタメとテクノロジー
エンタメとテクノロジーエンタメとテクノロジー
エンタメとテクノロジー
 
文章を企画・設計する
文章を企画・設計する文章を企画・設計する
文章を企画・設計する
 
197x 2nd Lt Up
197x 2nd Lt Up197x 2nd Lt Up
197x 2nd Lt Up
 
アイデアを塩漬けにしない-世界中の人に手伝ってもらう方法-
アイデアを塩漬けにしない-世界中の人に手伝ってもらう方法-アイデアを塩漬けにしない-世界中の人に手伝ってもらう方法-
アイデアを塩漬けにしない-世界中の人に手伝ってもらう方法-
 

Readable coder