Text
Page: 1
リーダブルコードの意義
と、実践の方法
結城洋志
株式会社クリアコード
リーダブルコード演習
2021-09-13
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 2
全体の流れ
✓ 1日目(本日)
✓ 前半:概要と進め方の説明
✓ 後半:チームで実装
✓ 2日目(明日)
✓ 前半:チーム同士で実装を交換、
続きを実装
✓ 後半:全体で結果を共有
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 3
講師紹介
結城洋志(ゆうき ひろし)
aka Piro
✓ 株式会社クリアコード所属
✓ FirefoxやThunderbirdの
法人サポートに従事
✓ トラブルの原因や対策を探るため
ソースコードを調査することが多い
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 4
チューター紹介
足永拓郎
(あしえ たくろう)
✓ 株式会社クリアコード所属
✓ Fluentd開発メンバー
✓ 参加者のサポート係(オンライ
ン)
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 5
チューター紹介
大場光一郎
(おおば こういちろう)
✓ 株式会社Speee所属
✓ JRubyコミッター
✓ 参加者のサポート係
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 6
アジェンダ
✓ 講座の目的を確認
✓ リーダブルコードの
必要性を確認
✓ リーダブルコードの
実践方法を紹介
✓ 実践方法を練習 (次のコマから)
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 7
講座の目的
✓ リーダブルコードを
日常的に書く上での
基礎となる考え方
を実践し、持ち帰る
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 8
目的でないこと
✓ テクニックをたくさん覚える
✓ 難しいプログラムを実装する
✓ プログラムを速く実装する
✓ 高性能なプログラムを実装する
✓ 奇抜な方法で目立つ
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 10
そもそもの話
✓ リーダブルコードはなぜ必要か
✓ 何の役に立つのか?
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 11
リーダブルコードが必要な理
由
✓ 既存のコードを読んで
素早く内容を把握したい
✓ 既存のコードに
素早く手を加えたい
✓ 開発速度を落としたくない
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 12
「速度」?
✓ 「読みやすさに気をつけたら
開発スピードが
落ちそう……」
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 13
むしろ「読みにくいと開発が
遅くなる」
✓ 既存のコードを
理解しにくいと……
✓ 修正・機能追加に時間がかかる
(理解しないと変更できない)
✓ 後退バグが発生しやすい
(理解しないまま変更すると問題発生)
→コストがかかる
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 14
時間が経つほど影響大
開発
速度
リーダブルな場合
開発速度が落ちにくい
リーダブルじゃない場合
開発速度が落ちやすい
時間
(注意:グラフではなく概念図です)
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 15
つまり
✓ 現実的なコストの範囲で
✓ 既存のコードを継続的に、
無理なく改良・修正したい
→なので、リーダブルコード
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 16
既存のコードを読んだり手を
加えたりする場面
在学中だとどんな場面がありそう?
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 17
既存のコードに手を加える場
面
✓ 複数人で研究
✓ 共同研究、院生と学部生で分担
✓ 自分の研究を発展
✓ 修士で作った物を博士で使う
✓ 途中で方針修正・転換
✓ 先輩の研究を参照
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 18
既存のコードを読む場面
✓ 論文に含まれるコード
を読むとき
✓ 自分が誰かの論文を読むとき
✓ 自分の論文が誰かに読まれるとき
コードがリーダブルだと参照されやすくなるかも……
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 19
営利企業ではどうか
✓ 分かる人が1人しかいない→危険
✓ 実装者が抜けたら詰む
✓ 変更できてもものすごくコストがかかる
↓
チームで開発し、
チームの誰でも作業を引き継げる
状態にしておきたい
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 21
リーダブルコードの実践
どうすれば無理なく実践できる?
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 22
リーダブルコードの実践
コードを読む
習慣を作る
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 23
読む?書くじゃないの?
✓ リーダブルコードを書くには
コードを読むことが欠かせない
✓ なぜ?
↓
書いている最中は
読みやすさ・読みにくさ
を実感しにくいから
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 24
実際のコードで考えてみる
✓ Excelワークシートの生成で
見出しセルを結合する関数
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 25
やりたいことを言語化してみ
る
関数 項目の見出し列(B~C)のセルを結合する(行番号, 項目):
項目の選択肢の数が1以下だったら:
何もせず終了
そうでないなら(選択肢が2つ以上あるなら)、
「見出し列の定義の配列」の全要素について、 要素の番号 を使って:
シートの範囲を結合(
開始行 → 行番号,
開始列 → 要素の番号,
終了行 → 行番号 + 選択肢の数 - 1,
終了列 → 要素の番号)
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 26
項目の見出し列の……
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 27
セルを結合する
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 28
見出し列の定義の配列
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 29
シートの範囲を指定して結合
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 30
実際のコード
def m(s, n, i):
if len(i['o']) <= 1:
return
s2 = s.s
for i2, c in enumerate(hcol):
s2.merge_range(n, i2,
n + len(i['o']) - 1, i2,
'')
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 31
書いた本人の視界
関数 項目の見出し列(B~C)のセルを結合する(行番号, 項目):
項目の選択肢の数が1以下だったら:
何もせず終了
そうでないなら(選択肢が2つ以上あるなら)、
「見出し列の定義の配列」の全要素について、
要素の番号 を使って:
シートの範囲を結合(開始行番号, 開始列番号,
開始行番号 + 選択肢の数 - 1, 終了列番号)
----------------------------------------------------------
def m(s, n, i):
if len(i['o']) <= 1:
return
s2 = s.s
for i2, c in enumerate(hcol):
s2.merge_range(n, i2,
n + len(i['o']) - 1, i2,
'')
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 32
第三者の視界
def m(s, n, i):
if len(i['o']) <= 1:
return
s2 = s.s
for i2, c in enumerate(hcol):
s2.merge_range(n, i2,
n + len(i['o']) - 1, i2, '')
------------------------------------------------
関数 何か(何か, 何か, 何か):
何かの数が1以下だったら:
何もせず終了
そうでないなら、
何か = 何かが保持している何か
何かについて、 何か を使って:
何かの範囲を結合(何か, 何か,
何か + 何か - 1, 何か)
前情報無しだと、意味ある情報を読み取るのは困難……
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 33
リーダブルなコードの場合
def try_merge_item_heading(self, row, item):
if len(item['options']) <= 1:
return
sheet = self.sheet
for index, _column in enumerate(HEADING_COLUMNS):
sheet.merge_range(row, index,
row + len(item['options']) - 1, index,
'')
-----------------------------------------------------------
関数 項目の見出しセルを結合してみる(自分, 行, 項目):
項目の選択肢の数が1以下だったら:
何もせず終了
そうでないなら、
シートは自分が保持している
見出しの列 の全項目について、 番号 を使って:
シートの、範囲を結合( 行, 番号,
行 + 項目の選択肢の数 - 1, 番号,
'')
先の例よりは意味のある情報を読み取れるはず
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 34
よく聞く話
✓ 手紙を書いたら一晩寝かせろ!
✓ 試験の回答文は、最後に
もう一回読み返せ!
前提を知らない読み手
の気持ちになろう
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 36
実際のコードを読んでみよう
Excelのワークシートを
自動生成するPythonスクリプト
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 37
ビジネス上の要件
✓ Firefoxを法人運用向けに
設定したい
✓ 設定を一覧で管理したい
✓ 「自動更新:有効/無効」など
✓ 顧客ごとに設定内容を変えたい
✓ バージョンごとの変化を見たい
✓ Firefox 78からFirefox 91の間で
追加された設定、廃止された設定
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 38
元々はExcelワークシートを
手作りしていた
✓ Gitでバージョン管理しにくい
✓ 同じ変更内容を複数顧客の
ワークシートに反映するのに
手間がかかる
どうにかしたかった
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 39
自動化を図った
✓ 資料自体を
バージョン管理しやすく
✓ プレーンテキスト形式のソースから
Excelワークシートを自動生成
✓ 1. 設定項目の定義
✓ 2. 前バージョンのFirefox用の設定情報
✓ 3. 今バージョンのFirefox用の設定情報
✓ 初版はPythonに慣れた人が実装
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 40
読んでみよう1
build-xlsx-1.py
ざっと見て概要を掴んでみよう
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 41
ポイント
✓ 少数の短い関数
✓ 分かりやすい名前付け
✓ 列番号はべた書き
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 42
試しに探してみよう1
✓ 「...→...での変更」の列に
「新規」と出力する条件は
どこで判定している?
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 43
試しに読んでみよう2
build-xlsx-2.py
第三者が手を加えた物
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 44
改修の経緯
✓ 要件が増えた
✓ 比較対象の数が可変になった
✓ 改修前:「Firefox 78」と
「Firefox 91」
✓ 改修後:「Firefox 78」と
「Firefox 91(デスクトップPC)」
「Firefox 91(ノートPC)」...
✓ 行数は約1.2倍に増加
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 45
試しに探してみよう2
✓ 「検証手順書対応番号」
の列に出力する内容は
どこで決まっている?
さっきより大変なはず
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 46
リーダブルだった書き方がア
ンリーダブルに……
✓ 関数の数が少ない
✓ 個々の関数が肥大化し、
全体像の把握が困難に
✓ if-elif/elseでの条件分岐
✓ 階層が複雑化して
処理の実行条件を追いにくい
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 47
試しに読んでみよう3
build-xlsx-3.py
大幅に改修した物
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 48
改修の要旨
✓ 複雑化した問題に合わせて
「リーダブル」の基準を変えた
何がリーダブルかは状況に依存する
✓ 定数を使う部分を増やした
✓ メソッド・変数のスコープを小さく
✓ コードの行数は約1.5倍に増加
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 49
試しに探してみよう3
✓ 「検証済み」という列を
「検証手順書対応番号」
の列の右隣に追加したい
(セルの内容は空でよい)が、
どこに手を入れればいい?
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 50
試しに探してみよう3
✓ 「検証済み」という列を
「検証手順書対応番号」
の列の右隣に追加したい
(セルの内容は空でよい)が、
どこに手を入れればいい?
✓ →探し方のコツがある
✓ 改修前:全体を読んで覚えて探す
✓ 改修後:必要な部分だけ読んで探す
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 51
つまり、ここでの「リーダブ
ル」とは
✓ 全体を一望するのが難しい
複雑なコードについて
✓ 一度に読むことは諦めて
✓ 必要な部分だけ読む
という前提での「読みやすい」
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 52
ふつうのOSS開発者の日常
✓ × イメージ
✓ コード全体を詳細・完璧に把握
✓ ノールックで修正
✓ ◯ 実態
✓ 全体像はボンヤリ把握
✓ 都度必要な部分を読み直して
調べ直しながら修正
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 53
自分で書いたコードでも、覚
えてないのが当たり前!
✓ 覚えておかなくていいように
するのがリーダブルコード
✓ 書籍「リーダブルコード」
巻末の「解説」も読んでみて!
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 55
リーダブルコードの実践
✓ 別の切り口でも考えてみよう
✓ なぜアンリーダブル化する
のか?
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 56
アンリーダブル化する原因
考えてみよう
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 57
アンリーダブル化する原因
(例)
✓ コードが状況の変化に
追従できていない
✓ コードの規模や前提は
徐々に変化する
✓ 気付かないうちに進行する!
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 58
状況の変化に気付けても、追
従できない……
✓ 既存のコードを書き直せない
✓ 書き直して動かなくなるのが怖い
✓ 「とりあえず動くように」で焦って
「書き足す」一辺倒になる
✓ 冷静に見直す余裕がない
→良くない兆候を見て見ぬフリ
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 59
ベテランはどうする?
✓ 悪い兆候を見逃さない
✓ 既存のコードを
書き直すのをためらわない
✓ 書き直さない方が、
後で痛い目を見ると知っている
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 60
悪い兆候に敏感になろう
✓ マメに読み返していると、
アンリーダブルのなり始めに
すぐ気付ける
✓ 「アンリーダブルに
なり始めてる……?」
→書き直しを考えるタイミング
後回しにしない!
(すぐやらないなら、せめてコメントを残す)
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 61
ためらわずに書き直せるよう
にするために(1)
✓ わけが分からないままにしない
✓ 自分が今何をしているかを
正しく理解するよう努めてる
✓ 不安が少しでも生じたら
立ち止まって考える
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 62
ためらわずに書き直せるよう
にするために(2)
✓ 便利な道具で補う
✓ 自動テストで結果の同値性を保証
自動テストは大事!
✓ Gitでいつでも巻き戻せる安心感
バージョン管理システムは大事!
✓ コードフォーマッターで
安全にコードを整形
「リーダブルにする」はある程度自動化できる
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 63
早め早めのリカバリー
✓ なるべく早くリーダブルに直す
✓ 書く→直す のサイクルを回す
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 64
参考:良い分割の仕方
✓ "良いコードとは何か - エンジ
ニア新卒研修 スライド公開"
✓ https://note.com/cyberz_cto/n/
n26f535d6c575#E0aBe
✓ サイバーエージェント社の新卒研修の資料
✓ 「凝集度と結合度」が参考になる
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 66
リーダブルコードの練習
✓ コードを書く→読む→直す
のサイクルを体験しよう
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 67
チームで開発してみよう
✓ まずは、チームの中で
コードを読みあってみる
✓ 自分で書いた物を読むよりは
客観的に読みやすい
✓ 交代で書く / 感想を述べ合う
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 68
注意点
✓ なるべくポジティブな提案を
✓ ◯「この書き方はリーダブルだね」
✓ ×「これはアンリーダブルだね」
(粗をあげつらうだけなら誰でもできる)
✓ ◯「こうした方がリーダブルじゃない?」
✓ チーム内で皆が納得できる
リーダブルの基準を見つけよう
✓ 既存の基準をベースにするのはアリ
(例:書籍「リーダブルコード」の内容など)
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 69
明日の後半戦
✓ (進捗次第では、
今日の後半の続きをやる)
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 70
明日の後半戦
✓ 他のチームが
書いたコードを読んでみる
(自分のチームの物を読むよりは客観的に読みやすい)
✓ チーム間で感想を共有
✓ より多くの人が納得できる
リーダブルの基準を見つけよう
✓ 開発を継続してみる
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 71
最終目標:コードを読む文化
を持ち帰ろう
✓ 「コードは読む物」
という認識を持つ
✓ 自分だけからチームへ
✓ チームだけから全体へ
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 72
この後の予定まとめ
✓ 本日の後半:課題を実装
✓ リーダブルコードを書く体験
✓ 明日の前半:実装チェンジ
→開発継続
✓ 既存のコードを読んで変更する体験
✓ 明日の後半:ふりかえり
✓ リーダブルコードの基準を
共有する体験
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 73
おさらい
✓ 講座の目的?
✓ リーダブルコードの必要性?
✓ 講座でやること?
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 74
講座の目的
✓ リーダブルコードを
日常的に書く上での
基礎となる考え方
を実践し、持ち帰る
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 75
リーダブルコードが必要な理
由
✓ 既存のコードを読んで
素早く内容を把握したい
✓ 既存のコードに
素早く手を加えたい
✓ 開発速度を落としたくない
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 76
変更コストと開発速度
開発
速度
リーダブルな場合
開発速度が落ちにくい
リーダブルじゃない場合
開発速度が落ちやすい
時間
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 77
講座でやること
✓ コードを読む文化作りの体験
✓ チームの中でコードを
読みあってみる
✓ チーム内でリーダブルコードの
基準を共有する
✓ 他のチームともリーダブルコードの
基準を共有する
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 78
ここまでの説明
腑に落ちました
か?
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 79
ここから先は、「まとめと次のステップ」の内容です
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 80
次のステップ
✓ もっともっとコードを読もう!
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 81
次のステップの例1
✓ ゼミの他の人や
同じ学部の人が書いたコードを
読んでみよう
✓ 研究の合間に
✓ 論文執筆の合間に
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 82
次のステップの例2
✓ 使うライブラリやツールの
コードを読んでみよう
✓ OSSのコードは
リーダブルであることが多い
✓ 「こういう結果を得るには
こう書くんだ!」と
実感を伴って読める
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 83
次のステップの例3
✓ コミット単位で読んでみよう
✓ コード全体ではなく差分を読む
✓ コードの中身・設計の仕方ではなく
コードの書き方・開発の仕方に注目
する
✓ リーダブルなコードを
見つけるのに使いやすい
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 84
コードを読む文化を後輩につ
なごう
✓ ゼミの後輩にも「コードを読む
文化」に馴染んでもらおう
✓ 皆さんが書いたコードが
資産として受け継がれる
✓ 口頭での詳しい説明なしでも
コードを読んで伝わる情報が増える
後輩に手取り足取り教えずに済む→先輩も楽になる
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 85
新しい人との関わりが、リー
ダブルの基準の見直し機会に
なる
これまで大事にしてきたことを
後輩と共有
↓
✓ 「もっとこっちの方が
リーダブルでは?」
✓ リーダブル基準の見直しのよい機会
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 86
サポート
✓ 今日の資料はすべて再利用可能
https://github.com/clear-code/readable-code-workshop/
tree/master/20210913
( https://slide.rabbit-shocker.org/authors/Piro/ )
✓ 迷ったら読み返せる
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 87
クリアコード
✓ クリアなコードが大切
✓ クリア == clear == 意図が明確
✓ クリアなコードはリーダブルコード
みなさんのコーディングライフで
リーダブルコードが当たり前に
なることを応援します!
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1
Page: 88
課題(宿題)
✓ 過去作成した何らかの
プログラムについて
✓ リーダブルになるよう編集する
✓ リーダブルにした点を
1つ以上メモに書き出す
✓ 以下の3つを併せて提出する
✓ 変更前のプログラム
✓ 変更後のプログラム
✓ リーダブルにした点のメモ
リーダブルコードの意義と、実践の方法
Powered by Rabbit 2.2.1