Slide 1

Slide 1 text

「テスト駆動開発」を通じて プログラマが コードと向き合う活動を 改めて学び直す おーい磯野〜♪ 多国通貨を写経しようぜ みんなのPython勉強会#37 家永英治

Slide 2

Slide 2 text

⾃⼰紹介 • 家永英治 • Tiwtter: @haru01 • 永和システムマネジメント • アジャイルコーチ • Scrumに限らず ユニットテスト リファクタリング TDD …の良さもお伝えしたい︕ • ときどき仕事や趣味でプログラマ • 実務はJavaが⼤半、Rubyが少々。 Pythonは趣味、最近はGoを勉強中 • ブログ︓https://twop.agile.esm.co.jp/ 2

Slide 3

Slide 3 text

3 https://agile.esm.co.jp/

Slide 4

Slide 4 text

今⽇の発表の⽬標: 書籍の多国通貨を お家で練習したくなる 4

Slide 5

Slide 5 text

ケントベックはTDDを使って プログラマのどんな フラストレーション を解消したかったんだろうか︖ 5

Slide 6

Slide 6 text

⽬標 「動作するきれいなコード」 動作するきれいなコードで得たいものは。。。。 6

Slide 7

Slide 7 text

動作するきれいなコードを使って プログラマが実現したいこと ✔ プログラミング活動を制御可能にしたい • 分析⿇痺で設計はきれいだが動かないで四苦⼋苦はヤダ • テスト⼯程という名のデバック地獄で、遅れて⽋陥の対応に追われる⽇々はヤダ • はじめから予期しない事が起こる複雑さがあるが、不安で押しつぶされるのはヤダ ✔ コードを通じてチームメイトと信頼関係を築きたい • 動作しないコードを渡されてるのはヤダ・渡すのはヤダ • 不吉な臭いがするコードを渡されるのはヤダ・渡すのはヤダ ✔ 作ったものでユーザに快適さを届けたい • いつまでたっても壊れた動かないソフトウェアで、顧客やユーザをイライラさせるのはヤダ ✔ 気持ちよくコードを書き続けたい • 半年後、⼀年後に不吉な匂いがするコードに囲まれて、⽬の輝きを失ってしまうはヤダ 7

Slide 8

Slide 8 text

But 8

Slide 9

Slide 9 text

A) あとから デバック地獄 9

Slide 10

Slide 10 text

“JUnitなどの⾃動テストの仕組みに出会うまでは、テストは⼿と⽬でやっていまし た。それがすごく⾯倒で⼼理的に負担だったので、テストは好きではありません でした。 若い頃は「⾃分が書いたコードにはバグがない」と⾃信過剰でした。しかし、実 際にプログラムを動かしてみると、全然動かない、あるいはバグだらけ。⾃分に 失望を感じ、それが痛みになっていました。 “⾃分のコードを嫌いにならない、そのためにやるべきこと” 和⽥卓⼈⽒ http://tech.nikkeibp.co.jp/atcl/nxt/column/18/00240/060600009/?P=6 10

Slide 11

Slide 11 text

3.プレシャー UP 1.⼿と⽬のテスト が⼿間で確認頻度 DOWN 2.意図せず ⽋陥混⼊UP あとでまとめて⾒つけた ⽋陥の対応に 追われて。。。 時間に追われて テストする 時間がなく。。。 11 プログラマは⽋陥対応に追われ コントロールを失い⾃信を喪失 ⼿と⽬に頼るため ⼼理的に負担のある作業 ※ 付録A、25章を参考にいろいろ追記

Slide 12

Slide 12 text

⽋陥数 時間 ※ イメージ図 12 ? 後でまとめて発覚 テスト未実施で ステータス不明 ௚͢ͷʹ ࢛ۤീۤ

Slide 13

Slide 13 text

「俺の環境では動い たよ」 ソフトウェアが壊れるだけでなく チームメイトや顧客との信頼関係も壊れてしまう 13

Slide 14

Slide 14 text

B)技術的負債の増⼤ 14

Slide 15

Slide 15 text

プレッシャー UP ⼿と⽬によるテストで 実施頻度DOWN ⽋陥数 UP 技術的負債 UP 怖くて リファクタリング出来ず 頻度DOWN 障害対応や要望 対応にてまどり。。 15 ※テスト熱中症、技術的負債を参考に記載

Slide 16

Slide 16 text

ٕज़తෛ࠴ ˺௥Ճमਖ਼ͷਏ͞ ˺มߋίετ ࣌ؒ ※ イメージ図 16

Slide 17

Slide 17 text

重複や⻑過ぎるメソッド で頭痛 あとで修正の影響範囲調査でこまる。 ヌケモレが発⽣しがち 17

Slide 18

Slide 18 text

どうやって ⼆重の悪循環から 抜け出す︖ 18

Slide 19

Slide 19 text

⼿と⽬のテストの箇所が レバレッジポイントでは︖ 詳しくは25章を参照 19

Slide 20

Slide 20 text

⼿と⽬のテストの作業を コード化し機械にやってもらおう ⼈には不可だが、機械なら1⽇に100回、300回とテスト実施可能 20

Slide 21

Slide 21 text

テスト駆動開発の基本3ステップ • Red︓テストを⼩さく1つ書く。動作しない。 • Green︓テストをパスさせる。べた書きや、コピペなど⼤罪を 犯しても良い。 • Refactor: 重複を取り除く。 上をこまめに頻繁に繰り返す 21

Slide 22

Slide 22 text

3.プレッシャー UP 1.⼿と⽬によるテストで 実施頻度DOWN 2.1.⽋陥数 UP 2.2.2.技術的負債 UP 2.2.1.怖くて リファクタリング出来ず 頻度DOWN 障害対応や要望 対応にてまどり。。 意図せず ⽋陥を埋め込んで。。。 22

Slide 23

Slide 23 text

4.プレッシャー Down 2.機械によるテストで で実施頻度UP 2.1.⽋陥数 Down 3.2.2.技術的負債 DOWN 3-2-1.安⼼して リファクタリング 頻度UP 障害対応や要望 対応がスムーズになり 23 1.こまめにテスト (仕様の具体例) をコード化UP 早期に発⾒して対応できるので。。

Slide 24

Slide 24 text

保存すれば即テスト実⾏の 環境の中でコードを書くデモ 例えば jest --watch 24

Slide 25

Slide 25 text

修正で 壊れていないか確認する時間 を減らしていこう ⼿と⽬のテストを頻繁に実施するは⾟い 経済的な時間的コストのほか、プログラマとしてのペインの時間を減らす 25

Slide 26

Slide 26 text

コードを読んで理解するまでの時間 を減らしていこう 不吉な臭いがするコードを読むのは⾟い。 経済的な時間的コストのほか、プログラマとしてのペインの時間を減らす 26

Slide 27

Slide 27 text

プログラマが Happyにプログラミング する時間を増やしていこう 技術的負債に悩まずに、軽やかに&健やかにプログラミングする時間を増やそう 27

Slide 28

Slide 28 text

ユーザが Happyに過ごす時間 を増やしていこう コードがリポジトリーに眠ったままでは、顧客やユーザには嬉しさが届かない 本当に欲しかったものが何かの学びも得られない 動くソフトウェアをタイムリーにリリースしていこう 28

Slide 29

Slide 29 text

⽋陥数 時間 ⽋陥数 時間 ※ イメージグラフ 29 ?

Slide 30

Slide 30 text

技術的負債 ≒追加修正の⾟さ ≒変更コスト 時間 時間 ※ イメージグラフ 30 技術的負債 ≒追加修正の⾟さ ≒変更コスト

Slide 31

Slide 31 text

注意︓ TDDはテスト技法ではない︕ とWard Cunninghamが⾔っていた 31

Slide 32

Slide 32 text

“テスト︓ ⾃動化され、具体化された、明確なテスト。ボタンを押せば⾛り出す。 ⽪⾁なことに、TDDはテスト技法ではない(Cunninghamの公案)。 TDDは分析技法であり、設計技法であり、実際には開発のすべてのア クティビティを構造化する技法なのだ。” KentBeck. テスト駆動開発 32

Slide 33

Slide 33 text

“開発︓ ソフトウェア開発における伝統的な「フェーズ主義」の⾵潮が弱 まったのは、時間が離れると設計判断のフィードバックが難しく なるからだ。開発は分析、論理設計、物理設計、実装、テスト、 レビュー、結合、デプロイを伴う複雑なダンスに変わった。” KentBeck. テスト駆動開発 33

Slide 34

Slide 34 text

Spec Design Impl Testとい名は付いているが 実態はデバック地獄 時間 時間 事前計画、事前設計を重視でプログラミング フィードバックを重視で、テスト−仕様、実装、設計のダンス 34 AHA! AHA! Oh my gosh! AHA! AHA! AHA!

Slide 35

Slide 35 text

"テスト駆動開発は、プログラミング中の不安をコントロールす る⼿法だ。ここでは「不安」を悪い意味で使っているのではない (我々は⾚ちゃんではないからね)。「これは困難な問題なので、 最初からすべてを⾒通せるわけではない」という真っ当な感覚の ことだ。" KentBeck. テスト駆動開発 35

Slide 36

Slide 36 text

TDDを学ぶには︖ 36

Slide 37

Slide 37 text

1写経する 練習、練習、練習 や CODE KATA スポーツ選⼿がくり返し練習するように プログラマもプログラミングを練習する 37

Slide 38

Slide 38 text

TDDの定番の練習お題 • 書籍I部︓多国通貨 • 書籍II部︓テスティングフレームワーク • FizzBuzz • ボーリングゲーム • ⾃動販売機 • 整数の閉区間 • セマンティック・バージョニング • ライフゲーム • Etc… http://devtesting.jp/tddbc/ http://d.hatena.ne.jp/absj31/20120721/1342880403 http://cyber-dojo.org/ http://codingdojo.org/KataCatalogue/ (探せば、練習お題がいくつかある。) 38

Slide 39

Slide 39 text

お⼿本を⾒るには︖ • 和⽥さんのFizzBuzzお題でのTDDライブ • https://channel9.msdn.com/Events/de-code/2017/DO03 • Robert-c-martinによる TDD ボーリングゲームのKATAの ステップバイステップでつくる様⼦ • https://www.slideshare.net/lalitkale/bowling-game-kata-by- robert-c-martin (Youtubeを探せばTDDをやっている様⼦の動画がいくつか⾒つかる) 39

Slide 40

Slide 40 text

"本書『テスト駆動開発』の第I部、第II部が特殊な書き⽅を されているのは、この「過程」を読者に追体験してもらうた めです。テスト駆動開発の本質をつかむためには、まとまっ た量の、⼿を動かしながら学べる良質なチュートリアルが必 要なのです。" KentBeck. テスト駆動開発 付録C 40

Slide 41

Slide 41 text

2TDDのパターンを知る TDDのコツがパターンで整理されている 41

Slide 42

Slide 42 text

テスト駆動開発のパターン テスト(名詞) 独⽴したテスト TODOリスト テストファースト アサートファースト テストデータ 明⽰的なデータ レッドバーのパターン ⼀歩を⽰すテスト はじめのテスト 説明的なテスト 学習⽤テスト 脱線はTODOリストへ 回帰テスト 休憩 やり直す 安い机に良い椅⼦ テスティングのパターン ⼩さいテスト Mock Object(擬装オブジェクト) Self Shunt(⾃⼰接続) Log String(記録⽤⽂字列) Crash Test Dummy(衝突実験ダミー⼈形) 失敗させたままのテスト きれいなチェックイン グリーンバーのパターン 仮実装を経て本実装へ 三⾓測量 明⽩な実装 ⼀から多へ xUnitのパターン アサーション フィクスチャー 外部フィクスチャー テストメソッド 例外のテスト まとめてテスト デザインパターン Command Value Object Null Object Template Method Pluggable Object Pluggable Selector Factory Method Imposter Composite Collecting Parameter Singleton リファクタリング 差異をなくす 変更の分離 データ構造の変更 メソッドの抽出 メソッドのインライン化 インタフェースの抽出 メソッドの移動 メソッドオブジェクト パラメータの追加 メソッドからコンストラクタへ のパラメータの移動 42 3部の パターン一覧

Slide 43

Slide 43 text

TDDの 定番パターン 43

Slide 44

Slide 44 text

TODOリスト 44

Slide 45

Slide 45 text

脱線はTODOリストへ 45

Slide 46

Slide 46 text

テスト(名詞) 46

Slide 47

Slide 47 text

テストファースト 47

Slide 48

Slide 48 text

アサートファースト 48

Slide 49

Slide 49 text

説明的なテスト 49

Slide 50

Slide 50 text

⼩さいテスト 50

Slide 51

Slide 51 text

仮実装を経て 本実装へ 51

Slide 52

Slide 52 text

明⽩な実装 52

Slide 53

Slide 53 text

三⾓測量 53

Slide 54

Slide 54 text

差異をなくす 54

Slide 55

Slide 55 text

きれいなチェックイン 55

Slide 56

Slide 56 text

休憩 56

Slide 57

Slide 57 text

やり直す 57

Slide 58

Slide 58 text

Design => Designing 不確実性がある前提で、初期に1回設計して終わりではなく、 反復のなかで予期せぬことから学びを得て、 ちょっとずつコードや設計を修復し続ける 有機的な設計、進化的設計 58

Slide 59

Slide 59 text

「インタフェースが使いづら いか︖」 メソッドネーミングがドメイン⽤語からかけ離れすぎている︖ 引数が多すぎる︖ コマンドとクエリが混ざっている︖ 副作⽤あり︖ 60

Slide 60

Slide 60 text

「テストが書きにくいか︖」 蜜結合では︖ 複数の責務をもっていないか︖ 61

Slide 61

Slide 61 text

「新たな機能追加が難しい か︖」 「追加が難しい」は、リファクタリングすべきのサインの⼀つ 62

Slide 62

Slide 62 text

「コードに読んで 不快に感じたか︖」 リファクタリングの「不吉な臭い」を参考に。 家をお掃除し続けるように、 コードもお掃除し続けなければ、散らかり不快な環境になる 63

Slide 63

Slide 63 text

実は TDDにもデザインパターンが 出てきます TDDは設計技法でもあるからね 65

Slide 64

Slide 64 text

テスト駆動開発のパターン テスト(名詞) 独⽴したテスト TODOリスト テストファースト アサートファースト テストデータ 明⽰的なデータ レッドバーのパターン ⼀歩を⽰すテスト はじめのテスト 説明的なテスト 学習⽤テスト 脱線はTODOリストへ 回帰テスト 休憩 やり直す 安い机に良い椅⼦ テスティングのパターン ⼩さいテスト Mock Object(擬装オブジェクト) Self Shunt(⾃⼰接続) Log String(記録⽤⽂字列) Crash Test Dummy(衝突実験ダミー⼈形) 失敗させたままのテスト きれいなチェックイン グリーンバーのパターン 仮実装を経て本実装へ 三⾓測量 明⽩な実装 ⼀から多へ xUnitのパターン アサーション フィクスチャー 外部フィクスチャー テストメソッド 例外のテスト まとめてテスト デザインパターン Command Value Object Null Object Template Method Pluggable Object Pluggable Selector Factory Method Imposter Composite Collecting Parameter Singleton リファクタリング 差異をなくす 変更の分離 データ構造の変更 メソッドの抽出 メソッドのインライン化 インタフェースの抽出 メソッドの移動 メソッドオブジェクト パラメータの追加 メソッドからコンストラクタへ のパラメータの移動 66 3部の パターン一覧

Slide 65

Slide 65 text

Red Green Refactor の試⾏錯誤のなかで 67

Slide 66

Slide 66 text

必要があれば、 デザインパターンを取り込む 68

Slide 67

Slide 67 text

不要であれば 取り込まない、取り外す KISS︓Keep it simple, stupid 69

Slide 68

Slide 68 text

https://twop.agile.esm.co.jp/tdd-and-incremental-design-with-patterns-c20179dffbea 70

Slide 69

Slide 69 text

詳しくは3部 71

Slide 70

Slide 70 text

写経 72

Slide 71

Slide 71 text

I部のお題は多国通貨 サンプルコードはJavaだけど、Pythonで練習すれば問題ない 73

Slide 72

Slide 72 text

書籍の2章までの 雰囲気をスライドでお届け 74

Slide 73

Slide 73 text

1章 仮実装を経て 本実装へ とてもベイビーステップでものづくりします 75

Slide 74

Slide 74 text

どこに向かって作業すれば︖ どこから始めよう︖ 76

Slide 75

Slide 75 text

パターン︓TODOリスト 何をテストすべきだろうかーー着⼿する前に、必要になりそうなテストを リストに書き出しておこう 77

Slide 76

Slide 76 text

TODO • $5 + 10CHF = $10 (レートが2:1の場合) • $5 * 2 =$10 78

Slide 77

Slide 77 text

いつからテストを始める︖ 79

Slide 78

Slide 78 text

パターン︓テストファースト いつテストを書くべきだろうかーーそれはテスト対象のコードを書く前だ。 80

Slide 79

Slide 79 text

[pylint] E0401:Unable to import 'dollar' 81 import pytest from dollar import Dollar def test_money_multiplication(): five = Dollar(5) five.times(2) assert 10 == five.amount

Slide 80

Slide 80 text

エラーのほかに いろいろ問題があるコード 副作⽤ありのメソッド amountがpublic Etc.. 82

Slide 81

Slide 81 text

だけど、TODOに積んで、 後まわし Red Green Refactor中に後からカイゼンしたい項⽬のほか テスト項⽬を発⾒してTODOに積むこともあるよ。 83

Slide 82

Slide 82 text

パターン︓脱線はTODOリストへ 脇道のそれずに、(技術的な)疑問を検証するにはどうしたらよいだろう かーーもし脱線しそうなら、その疑問をTODOリストに加え、元の仕事に戻 ろう。 84

Slide 83

Slide 83 text

TODO • $5 + 10CHF = $10 (レートが2:1の場合) • $5 * 2 =$10 • amount を privateにする • Dollarの副作⽤ • Moneyの丸め処理どうする? 85

Slide 84

Slide 84 text

選択した 眼の前のタスクに集中 => $5 * 2 =$10 86

Slide 85

Slide 85 text

87 [pylint] E0401:Unable to import 'dollar' import pytest from dollar import Dollar def test_money_multiplication(): five = Dollar(5) five.times(2) assert 10 == five.amount

Slide 86

Slide 86 text

E AttributeError: 'Dollar' object has no attribute 'amount' 88 class Dollar: def __init__(self, amount): pass def times(self, multiplier): pass import pytest from dollar import Dollar def test_money_multiplication(): five = Dollar(5) five.times(2) assert 10 == five.amount

Slide 87

Slide 87 text

class Dollar: def __init__(self, amount): self.amount = 0 def times(self, multiplier): pass … E assert 10 == 0 E + where 0 = .amount 89 import pytest from dollar import Dollar def test_money_multiplication(): five = Dollar(5) five.times(2) assert 10 == five.amount

Slide 88

Slide 88 text

期待通りのRed 意図せずGreenならテストコードや実⾏⽅法にどこか間違いがあるかも︖ 90

Slide 89

Slide 89 text

エラーメッセージや テスト失敗メッセージは プログラマを導く良きパートナー 機械に怒られているのではない。 機械に次の⼀歩を教えてもらっている テスト失敗メッセージが分かりづらいなら メッセージがわかりやすいように修正。 91

Slide 90

Slide 90 text

よしGreenにするぞ︕ 速攻でGreenにするには︖ テストで解くべきExpectedとActualのギャップが明確になった状態 92

Slide 91

Slide 91 text

パターン︓仮実装を経て本実装へ 失敗するテストを書いてから、最初に⾏う実装はどのようなものだろう かーーベタ書きの値を返そう。それでテストが通るようになったら、ベタ 書きの値をだんだん本物の式や変数に置き換えていく 93

Slide 92

Slide 92 text

class Dollar: def __init__(self, amount): self.amount = 0 def times(self, multiplier): pass 94 import pytest from dollar import Dollar def test_money_multiplication(): five = Dollar(5) five.times(2) assert 10 == five.amount … E assert 10 == 0 E + where 0 = .amount

Slide 93

Slide 93 text

class Dollar: def __init__(self, amount): self.amount = 10 def times(self, multiplier): pass 95 import pytest from dollar import Dollar def test_money_multiplication(): five = Dollar(5) five.times(2) assert 10 == five.amount

Slide 94

Slide 94 text

やったー︕ 仮実装で意図せずRedになったら、もしかしたら テストコードやテスト実⾏の仕⽅に間違いがあるかも 96

Slide 95

Slide 95 text

もちろん ベタ書きなので タスク完了とは⾔えない 97

Slide 96

Slide 96 text

ここまでやったステップ • ⼩さいテストを1つ書く。 • すべてのテストを実⾏し、1つ失敗することを確認する。 • ⼩さい変更を⾏う。 • 再びテストを実⾏し、すべて成功することを確認する。 •リファクタリングを⾏い、重複を除去する。 98

Slide 97

Slide 97 text

リファクタリングで 本物の実装に近づく 99

Slide 98

Slide 98 text

“つまり、TDDでは例えばベタ書きの値を変数に置き換える変更 であっても、胸を張ってそれを「リファクタリング」と呼べる。 なぜなら、通っているテストは変わらず通り続けるからだ。” KentBeck.テスト駆動開発 100

Slide 99

Slide 99 text

class Dollar: def __init__(self, amount): self.amount = 10 def times(self, multiplier): pass 101 import pytest from dollar import Dollar def test_money_multiplication(): five = Dollar(5) five.times(2) assert 10 == five.amount

Slide 100

Slide 100 text

class Dollar: def __init__(self, amount): self.amount = 5 * 2 def times(self, multiplier): pass 102 import pytest from dollar import Dollar def test_money_multiplication(): five = Dollar(5) five.times(2) assert 10 == five.amount

Slide 101

Slide 101 text

class Dollar: def __init__(self, amount): self.amount = amount * 2 def times(self, multiplier): pass 103 import pytest from dollar import Dollar def test_money_multiplication(): five = Dollar(5) five.times(2) assert 10 == five.amount

Slide 102

Slide 102 text

class Dollar: def __init__(self, amount): self.amount = amount def times(self, multiplier): self.amount = self.amount * 2 104 import pytest from dollar import Dollar def test_money_multiplication(): five = Dollar(5) five.times(2) assert 10 == five.amount

Slide 103

Slide 103 text

class Dollar: def __init__(self, amount): self.amount = amount def times(self, multiplier): self.amount = self.amount * multiplier 105 import pytest from dollar import Dollar def test_money_multiplication(): five = Dollar(5) five.times(2) assert 10 == five.amount

Slide 104

Slide 104 text

class Dollar: def __init__(self, amount): self.amount = amount def times(self, multiplier): self.amount *= multiplier 106 import pytest from dollar import Dollar def test_money_multiplication(): five = Dollar(5) five.times(2) assert 10 == five.amount

Slide 105

Slide 105 text

やったー︕ 107

Slide 106

Slide 106 text

Greenを保ちながら ベイビーステップで プログラミング 108

Slide 107

Slide 107 text

TODO • $5 + 10CHF = $10 (レートが2:1の場合) • $5 * 2 =$10 • amount を privateにする • Dollarの副作⽤ • Moneyの丸め処理どうする? 109

Slide 108

Slide 108 text

2章 明⽩な実装 Value Objectを使っての インタフェースの修復 110

Slide 109

Slide 109 text

TODO • $5 + 10CHF = $10 (レートが2:1の場合) • $5 * 2 =$10 • amount を privateにする • Dollarの副作⽤ • Moneyの丸め処理どうする? 111

Slide 110

Slide 110 text

TODOに積んだ 副作⽤に取り組む 112

Slide 111

Slide 111 text

これは無理が ある 副作⽤あり five は $10 に import pytest from dollar import Dollar def test_money_multiplication(): five = Dollar(5) five.times(2) assert 10 == five.amount five.times(3) assert 15 == five.amount 113

Slide 112

Slide 112 text

副作⽤ありの インタフェースの設計 に問題あり 114

Slide 113

Slide 113 text

パターン︓Value Object 広く共有されるものの、同⼀インスタンスであることはさほど重要でない オブジェクトを設計するにはどうしたらよいだろうか――オブジェクト作 成時に状態を設定したら、その後決して変えないようにする。オブジェク トへの操作は必ず新しいオブジェクトを返すようにしよう。 115

Slide 114

Slide 114 text

Value Objectパターン を取り込んで インタフェースを修復 116

Slide 115

Slide 115 text

> assert 10 == product.amount E AttributeError: 'NoneType' object has no attribute 'amount' 117 import pytest from dollar import Dollar def test_money_multiplication(): five = Dollar(5) product = five.times(2) assert 10 == product.amount product = five.times(3) assert 15 == product.amount class Dollar: def __init__(self, amount): self.amount = amount def times(self, multiplier): self.amount *= multiplier

Slide 116

Slide 116 text

インタフェースが変わって 失敗 timesメソッドは今は何もリターンしない。 118

Slide 117

Slide 117 text

すぐにGreenにできるなら︖ 仮実装が不要なら︖ 119

Slide 118

Slide 118 text

パターン︓明⽩な実装 シンプルな操作を実装するにはどうすればよいだだろうかーーそのまま実 装しよう。 120

Slide 119

Slide 119 text

> assert 10 == product.amount E AttributeError: 'NoneType' object has no attribute 'amount' 121 import pytest from dollar import Dollar def test_money_multiplication(): five = Dollar(5) product = five.times(2) assert 10 == product.amount product = five.times(3) assert 15 == product.amount class Dollar: def __init__(self, amount): self.amount = amount def times(self, multiplier): self.amount *= multiplier

Slide 120

Slide 120 text

122 import pytest from dollar import Dollar def test_money_multiplication(): five = Dollar(5) product = five.times(2) assert 10 == product.amount product = five.times(3) assert 15 == product.amount class Dollar: def __init__(self, amount): self.amount = amount def times(self, multiplier): return Dollar(self.amount * multiplier)

Slide 121

Slide 121 text

やったー︕ 123

Slide 122

Slide 122 text

仮実装を経て本実装へ と 明⽩な実装 124

Slide 123

Slide 123 text

2つの歩幅の調整を 上⼿く使い分ける 125

Slide 124

Slide 124 text

すぐに解けるなら 「明⽩な実装」 126

Slide 125

Slide 125 text

道のりが⻑い場合 「仮実装を経て本実装へ」 10min以上Redが続いている場合、ステップ幅を⼩さく。 「明⽩な実装」の⽅針をやめて 「仮実装」に切り替え 道のりが⻑い場合は「⼩さいテスト」の別選択もある 127

Slide 126

Slide 126 text

TODO • $5 + 10CHF = $10 (レートが2:1の場合) • $5 * 2 =$10 • amount を privateにする • Dollarの副作⽤ • Moneyの丸め処理どうする? 129

Slide 127

Slide 127 text

2章完 130

Slide 128

Slide 128 text

パターン︓やったー︕ テストが期待通りパスしたり、すっきりとリファクタリングできたり、タスクがドーンと完了した ら︖ーー ⼩さくてもうまく出来たことの成功を祝おう。まだまだ道のり⻑いが、勇気を持って歩み づづけるために。ペアプロやモブプロを実施している場合は、両⼿を上げるやフィスト・バンプやハ イタッチなど体を使って表現すると、喜びをより倍増できる。 (オリジナルにはない。書籍のフェアレスチェンジの「⼩さな成功」「ステップバイステップ」やペ アプログラミングやWEB+DBを参照) 131

Slide 129

Slide 129 text

3章以降は︖ 132

Slide 130

Slide 130 text

予告 133

Slide 131

Slide 131 text

3章 134

Slide 132

Slide 132 text

参上︕三⾓測量 仮実装、明⽩な実装と⽐較される3番⽬のキャラ 135

Slide 133

Slide 133 text

4章 136

Slide 134

Slide 134 text

説明的なテストで 意図を伝える テスト対象の仕様や意図が伝わるように書き直す テストコードは機械だけでなくチームメイトにも理解できるように書く 137

Slide 135

Slide 135 text

5章 138

Slide 136

Slide 136 text

Kent Beck コピペの禁忌に⼿を出す DollarをコピペしてFranc作成 この先どうなっちゃう︖ 139

Slide 137

Slide 137 text

11章 140

Slide 138

Slide 138 text

さらば 重複コード Dollar&Franc ついに消し去る。 141

Slide 139

Slide 139 text

6章からの重複の取 り除きの道のりには いったい何があった のか︖ 142

Slide 140

Slide 140 text

詳しくは 写経して のお楽しみ 143

Slide 141

Slide 141 text

まとめ 144

Slide 142

Slide 142 text

ケントベックはTDDを使って プログラマのどんな フラストレーション を解消したかったんだろうか︖ 145

Slide 143

Slide 143 text

動作するきれいなコードを使って プログラマが実現したいこと ✔ プログラミング活動を制御可能にしたい • 分析⿇痺で設計はきれいだが動かないで四苦⼋苦はヤダ • テスト⼯程という名のデバック地獄で、遅れて⽋陥の対応に追われる⽇々はヤダ • はじめから予期しない事が起こる複雑さがあるが、不安で押しつぶされるのはヤダ ✔ コードを通じてチームメイトと信頼関係を築きたい • 動作しないコードを渡されてるのはヤダ・渡すのはヤダ • 不吉な匂いがするコードを渡されるのはヤダ・渡すのはヤダ ✔ 作ったものでユーザに快適さを届けたい • いつまでたっても壊れた動かないソフトウェアで、顧客やユーザをイライラさせるのはヤダ ✔ 気持ちよくコードを書き続けたい • 半年後、⼀年後に不吉な匂いがするコードに囲まれて、⽬の輝きを失ってしまうはヤダ 146

Slide 144

Slide 144 text

3.プレッシャー UP 1.⼿と⽬によるテストで 実施頻度DOWN 2.1.⽋陥数 UP 2.2.2.技術的負債 UP 2.2.1.怖くて リファクタリング出来ず 頻度DOWN 障害対応や要望 対応にてまどり。。 意図せず ⽋陥を埋め込んで。。。 147

Slide 145

Slide 145 text

4.プレッシャー Down 2.機械によるテストで で実施頻度UP 2.1.⽋陥数 Down 3.2.2.技術的負債 DOWN 3-2-1.安⼼して リファクタリング 頻度UP 障害対応や要望 対応がスムーズになり 148 1.こまめにテスト (仕様の具体例) をコード化UP 早期に発⾒して対応できるので。。

Slide 146

Slide 146 text

⽋陥数 時間 ⽋陥数 時間 ※ イメージグラフ 149 ?

Slide 147

Slide 147 text

技術的負債 ≒追加修正の⾟さ ≒変更コスト 時間 時間 ※ イメージグラフ 150 技術的負債 ≒追加修正の⾟さ ≒変更コスト

Slide 148

Slide 148 text

コードを読んで理解するまでの時間 を減らしていこう 不吉な臭いがするコードを読むのは⾟い。 経済的な時間的コストのほか、プログラマとしてのペインの時間を減らす 151

Slide 149

Slide 149 text

修正で 壊れていないか確認する時間 を減らしていこう ⼿と⽬のテストを頻繁に実施するは⾟い 経済的な時間的コストのほか、プログラマとしてのペインの時間を減らす 152

Slide 150

Slide 150 text

プログラマが Happyにプログラミング する時間を増やしていこう 技術的負債に悩まずに、軽やかに&健やかにプログラミングする時間を増やそう 153

Slide 151

Slide 151 text

ユーザが Happyに過ごす時間 を増やしていこう コードがリポジトリに眠ったままでは、顧客やユーザには嬉しさが届かない 本当に欲しかったものが何かの学びも得られない。 動くソフトウェアをタイムリーにリリースしていこう 154

Slide 152

Slide 152 text

テスト駆動開発のパターン テスト(名詞) 独⽴したテスト TODOリスト テストファースト アサートファースト テストデータ 明⽰的なデータ レッドバーのパターン ⼀歩を⽰すテスト はじめのテスト 説明的なテスト 学習⽤テスト 脱線はTODOリストへ 回帰テスト 休憩 やり直す 安い机に良い椅⼦ テスティングのパターン ⼩さいテスト Mock Object(擬装オブジェクト) Self Shunt(⾃⼰接続) Log String(記録⽤⽂字列) Crash Test Dummy(衝突実験ダミー⼈形) 失敗させたままのテスト きれいなチェックイン グリーンバーのパターン 仮実装を経て本実装へ 三⾓測量 明⽩な実装 ⼀から多へ xUnitのパターン アサーション フィクスチャー 外部フィクスチャー テストメソッド 例外のテスト まとめてテスト デザインパターン Command Value Object Null Object Template Method Pluggable Object Pluggable Selector Factory Method Imposter Composite Collecting Parameter Singleton リファクタリング 差異をなくす 変更の分離 データ構造の変更 メソッドの抽出 メソッドのインライン化 インタフェースの抽出 メソッドの移動 メソッドオブジェクト パラメータの追加 メソッドからコンストラクタへ のパラメータの移動 155 3部の パターン一覧

Slide 153

Slide 153 text

“テスト︓⾃動化され、具体化された、明確なテスト。ボタンを 押せば⾛り出す。⽪⾁なことに、TDDはテスト技法ではない (Cunninghamの公案)。TDDは分析技法であり、設計技法で あり、実際には開発のすべてのアクティビティを構造化する技法 なのだ。” 156

Slide 154

Slide 154 text

TDDを学ぶには、 定番の多国通貨の 写経を複数回試すが おすすめ! 157