tdd & pull request入門

67
永永永永永永永永永永永永 永永永永 TDD & Pull Request 永永 永 永永永永永永永永永永永永永永永永永

Upload: eiji-ienaga

Post on 07-Aug-2015

2.462 views

Category:

Engineering


2 download

TRANSCRIPT

永和システムマネジメント家永英治

TDD & Pull Request 入門

〜 動作するきれいなコードを目指そう〜

今日のゴール➤TDD とは?を知る

➤Pull Request( プルリク ) とは?を知る

➤TDD & Pull Request の自習・学習方法を持ち帰る

※ ハンズオン形式で学ぶ講座ではありません。座学と見学で学ぶ講座です。 ※ 簡単な例を実演で提示します。

2

自己紹介➤家永英治

2003 年 永和システムマネジメント入社 2005 年頃 エクストリーム・プログラミングを

使ったチーム角谷に参画 . 角谷・ t-wada に感銘を受ける

最近は、 Scrum や TDD やテスト自動化の導入支援のコーチを行っている

3

学生の参加者の調査➤好きな言語、得意な言語

➤TDD 試したことあるよ

➤Pull Request 試したことあるよ

➤今日の講座の参加の動機

4

開発のよくある悪循環

5

やっつけ仕事

技術的負債レガシーコードスパゲティコード

時間がない

6

TDD と Pull Request の共通の軸

http://www.slideshare.net/YohNakamura/a3-38731262

不確実で難しい問題はトライ・アンド・エラーで素早くフィードバック

を得ながら関わることが大事8

9

XP の多重のフィードバックループとコード

Code

TDD &Pull Request の領域

10

学びの最大の障害物は “自分は解っている”の思い込み

予期せぬ驚きの発見に注意すること

https://www.flickr.com/photos/photohannah/512202109/

当初の計画【解き方 A 】では、大きな障害物に出会うこともあるしかし、早期にフィードバックを得ていれば慌てる時間ではないはず

素早く計画を変更し【解き方 B 】に切り替えことが重要( 必要であれば【問題 A 】を【問題 B 】に置き換えること )

11

http://blog.goo.ne.jp/junsky/e/7fe1362e7295d0249591931a03dfbb61

問題が難しいなら分解しステップ・バイ・ステップで解くことが大事

12

13

https://www.flickr.com/photos/ryanh/43936630/

早めに、こまめにリファクタリングすること

を忘れずに

継続的インテグレーション (CI)テスト駆動開発 (TDD)

どんなふうに問題を解く?どうやってつくる?

15

• 問題を理解する• 解き方を考える• 問題を解いて、ふりかえる

• スモール・イズ・ビューティフル• 一つのプログラムには一つのこと

をうまくやらせる• できるだけ早く試作を作成する。。。

テスト駆動開発とは?“ テスト駆動開発 ( てすとくどうかいはつ、 test-driven development; TDD) とは、プログラム開発手法の一種で、プログラムに必要な各機能について、最初にテストを書き(これをテストファーストと言う)、そのテストが動作する必要最低限な実装をとりあえず行った後、コードを洗練させる、という短い工程を繰り返すスタイルである。” -- Wikipedia より

16

http://blog.cleancoder.com/uncle-bob/2014/12/17/TheCyclesOfTDD.html

“ 「動作するきれいなコード」、ロン・ジェフ リーズのこの簡潔な言葉は、 TDD( テスト駆 動開発 ) の目標である。動作するきれいなコー ドは、あらゆる理由で価値がある。 ─ Kent Beck

17

@t-wada18

[TDD の見学 ]

➤ ライフゲームの練習お題を途中まで解く実演

※ 途中の掛け声をお願いすることがありますが、ご協力お願いします。

“ 実装する前に?” ー> “テスト!”

“ きりの良いレッドからグリーンに変わったら” -> (ハイタッチ!)

“ 実行結果がグリーンの時は?” -> “ リファクタリング!リファクタリング!”

19

20

ポイント

TODO- 誕生- 生存

図を描いたり、 TODO リストを用意するTDDサイクルを回す前に

21

➤問題を理解するため

➤解く道筋 ( 当初の計画、解き方 A案 ) を明らかにするため

※ はじめにすべて書き出す必要はない※あとから TODO を発見して追加しても OK※ あとで、解き方 A案に大きな障害物を発見して、捨てることもある

22

TODO-----○誕生 生存 過疎 過密

誕生

Field?

Cell--------rowcol

status

0 行

1 行

2 行

2 列0 列 1列

死んでいるセルに隣接する生きたセルがちょうど 3 つあれば、次の世代が誕生する。

1

n

TODO- 誕生- 生存

23

➤解き方のコアとなる骨組みを明らかにするため(解き方 (設計・実装 ) の学びが得られる TODO はどれだろうか? )

※ 途中で発見した正常系のバリエーションや異常系は TODO に積んで、あとで解く

ハッピーパス (正常系 ) を選択する一つ目のタスクを選ぶとき

TODO- 誕生- 生存

先にテストを書いて失敗を確認するタスクに着手したら

24

➤ 問題を実行可能なテストで明確にするため(何が実行できたら問題を解いたと言える?)

➤ テスト対象のメソッドの使い方例を明瞭にするため(クラスやメソッドを利用する人はどう使えると嬉しいだろうか?)

➤ テストが期待通り動作していることを確認するため

➤ 後日にまとめてテストでは、テストが記述が難しい実装になってしまうため(test で assert が書けるように実装するにはどうすればよいだろうか? )

※ 問題を解く前に問題を明瞭にするのは、問題を解くときのの基本鉄則。テストで表現するのがポイント※ただしテストファーストに慣れずに手が止まってしまうなら、 TDD の制約をゆるめ、“ちょっと実装したら直ぐテストで確認(つまり何の問題を解いてたのか?をテストで明瞭にしてみよう)”で始めるがオススメ

TODO- 誕生- 生存

テスト失敗は基本は1つにする問題を解いている時

25

➤一つの問題に集中してとりくむため。一度に複数の問題を相手して、混乱しないため( 自分が今、集中して解きたい問題は何だろうか? )

※ 誕生を解くことに集中※ Ignore やコメントアウトのほか、テスティングフレーワークの機能を使って特定のメソッドを指定して実行する

TODO- 誕生- 生存

26

➤前提条件 (Arrange) 、テスト対象への行為 (Act) 、期待結果の表明 (Assert) の3つで問題を整理して理解を深めるため(期待結果はなんだろうか?、操作や前提条件は?)

※ 3A の整理で迷ったら、まず期待結果の表明 (Assert) が何かを明らかにするがオススメ( Assert First )

Arrange Act Assert でテストコードを整理する

TODO- 誕生- 生存

失敗のレポートを読んで次の一手を考えるテスト失敗の時、実装が未完の時

27

➤エラーメッセージやテストの失敗レポートから、次に何をすべきかを把握できるため( コンピュータは僕に何を教えてくれている? )

※ コンピュータと対話しながら問題を解く※ IDE が使える言語なら、エラー箇所にジャンプやコンパイルエラー時にコード生成機能を駆使する※ エラーの意味がわからなければ、 Google や Stack Overflow などで検索

TODO- 誕生- 生存

テストの失敗時のレポートを読みやすくする失敗が読んでわかりにくい場合

28

➤自分が今何に取り組もうとしているかの問題を明瞭にするため

➤後日のテスト失敗時に、他の人が読んで直ぐ理解して対応できるようにするため※ たとえばテストのメソッド名を工夫する※ power-assert も テスト失敗時の内容がわかりやすくするための方法の1つ

TODO- 誕生- 生存

29

➤API や既存ライブラリの使い方がわかれば問題がより簡単に把握できるようになるため(巨人の肩にのる!)

※ かわりに REAP(対話シェル環境 ) を利用して学習するもオススメ

テストを使ってライブラリの使い方を学ぶ知らない API やライブラリを学びたい場合

TODO- 誕生- 生存

小さな問題に分割して解くレッドからグリーンに遷移させるのに時間がかかり難しい場合

30

➤分解した小さい問題をクリアできれば、以前より大きな問題は簡単に解けるようになるため(2 時間以上グリーンを観ていない。もっと小さく問題を分割して解けないだろうか? )

※ TODO リストに追加や順序の入れ替えを忘れずに

一つのプログラムには一つのことをうまくやらせる

31

TODO の見直しTODO-----○誕生 ○ Array の API の学習 (寄り道 ) 周囲の生きているセルの数 仮実装を置き換え

メソッドの移動 … 生存 過疎 過密

TODO- 誕生- 生存

32

➤難しい問題も簡単なベタ書きなら停滞せずに先に進め、以前よりも解き方の理解が捗るため(あれ?長時間レッドだな。落ち着こう。ベタ書きにするとどうなるだろうか?)( 問題が難しそう?一旦ベタ書きからはじめてみよう )

➤テストが期待通り動作(グリーン)することを確認するため

ベタ書きから一般化で問題を解くレッドの時に次の一手がむずかしい場合

TODO- 誕生- 生存

33

ベタ書きを一般化不吉な臭いオブジェクト指向SOLID原則パターン関数型プログラミングイディオムコーディング規約…

現状のコードや設計の良し悪しを判断するテスト結果がグリーンの時に

KISS名前重要DRY原則スモールイズビューティフル…

TODO- 誕生- 生存

こまめにリファクタリングするテスト結果がグリーンの時はチャンスタイム!!

34

➤あとから自分や他人が読んで直ぐに理解できるようにするため

➤あとから(予期せぬ)コード修正をできるようにするため

➤気分すっきり!※ レッド時にリファクタリングは、危険な作業※ レッド時に発見した修正したい項目は TODO などに積んで、あとで実施する※ TDD の文脈では、ベタ書きから一般化もリファクタリングの一つ

35

グリーンの時はリファクタリング チャンスタイム!

TODO- 誕生- 生存

36

➤小さく回すのは「下手な長考休むに似たり」の代わりに、早く実験して【学び】を得たいから(サイクルの結果、問題や解き方(実装や設計)について学んだことは何だろうか?)

➤ 言い換えると、問題把握ー>解決ー>整理整頓の繰り返しのリズム( TDD のサイクルの目安は 10 分だが実際は何分サイクルだろうか? )

➤ プログラミングの現状の透明性を高めるため(今は問題定義している時?解いている最中?解けた状態?リファクタして壊していない?)

Red Green Refactor のリズムでステップ・バイ・ステップに解く

TODO- 誕生- 生存

37

➤期待通りテストが機能しているかを再確認するため

コードの一部をコメントアウトするテストが本当に機能しているか不安を感じたとき

TODO- 誕生- 生存

38

➤うまくできなかった時に、すぐにセーブポイントに戻って、作業を再開できるようにするため

※ エディタの戻るや履歴機能の代替案も※ ブランチで作業して捨てる。あるコミット地点に戻る

バージョン管理を使うキリの良い作業単位が終わった時、テストがグリーンの時

TODO- 誕生- 生存

39

➤「当初の計画(解き方 A案)がまずかった」も TDDサイクルで得た学びの1つ

※ 別の解き方 B を試す※ 問題 A を問題 B に再設定して、問題と解き方を共にシンプル ( 解くコストに見合う価値のある。読みやすい。後から修正しやすい… ) にできないかも検討する

別の解き方 B案に切り替える当初の計画 ( 解き方 A案 ) に大きな障害物を発見した場合

TODO- 誕生- 生存

40

➤テストの抜け漏れを発見するため(境界値・同値分割の観点からは?異常系は?)

➤他の人が読みやすくするため(テストもリファクタリング対象)

➤不要なテストを削除してメンテナンスしやすくするため( 試行錯誤の過程で必要だったテストも完成すれば、不要になることもある )

テストを見直し整理整頓する

テストの書き方のポイント 抜粋

41

➤テストコードも失敗レポートも人が読んで理解できるように書くあとで読んで直ぐに理解し、修正しやすくするため

➤テスト間は独立して実行できるように書く失敗時に問題箇所を特定しやすくするため

➤ALL テストが繰り返し グリーンになるように書くメンテナンスしやすくするため。例えば時間に依存したテストは注意

➤テストの実行時間が長いスローテストに注意する実行に時間がかかりすぎると問題発見が遅れるやテスト実行しなくなるた

➤ ちょっとした修正で予期せずテストが大量に失敗してしまう脆いテストに注意する脆いなら自動テストの費用対効果は低い。設計・実装・テストに何か不味いことがある兆候

TDD の嬉しさって?➤高速の試行錯誤で問題や解き方を学び

ながら進めることができる単位時間あたりの学びの量と質を上げる

➤頻繁にコードや設計の見直しの機会があり、安心してリファクタリングできるテストがあるおかげ

➤新たな要望 (追加問題 ) にも自信をもって修正できるコードを手に入れられるシンプルなコードと自動化されたリグレッションテスト

42

オススメの TDD の自習・学習➤ TDD本、Rails Tutorial を写経

(真似てタイプして著者の追体験する)

➤ 練習お題を繰り返し解くプログラミングの学習法として、Code Kata 、「写経」、「練習、練習、練習」などが知られているが TDDも練習が必要- http://d.hatena.ne.jp/absj31/20120721/1342880403- http://devtesting.jp/tddbc/?TDDBC%E4%BB%99%E5%8F%B003%2F%E8%AA%B2%E9%A

1%8C

➤ 同じ学生仲間で集まってチャレンジして、意見交換する

➤ TDDBCや Coderetreat などのプログラミングを学ぶイベントに参加。自分よりうまい人から教わるhttp://devtesting.jp/tddbc/

➤ パターンなど一般的な設計の本を読む。ネットで調べる

43

継続的インテグレーション (CI)Q&A

Pull Request

Pull Request とは?➤“ プルリクエストは、 Bitbucket を

使った開発者のコラボレーションを促進する機能の 1 つです。使いやすい Web インターフェイスで、提案された変更を公式プロジェクトに統合する前に議論することができます。”

https://www.atlassian.com/ja/git/workflows#!pull-request

46

Github Flow

https://guides.github.com/introduction/flow/index.htmlhttps://gist.github.com/Gab-km/3705015

http://scottchacon.com/2011/08/31/github-flow.html

フィードバック コメント & 修正

47

Pull Request

[Pull Request の見学 ]➤重複コードを修正する簡単なシナリオ

トピック・ブランチの作成 修正・コミット・プッシュ Pull Request の作成 第三者のコメント コメントのフィードバック対応 マージ

※ 今日は一人で行っていますが通常は、複数人で行います※ https://www.railstutorial.org/ を参考にお題を作成

48

49

ポイント

50

➤「真似て学ぶ」は学習の基本

➤他人のプルリクへのコメントを読めばコードの書き方の注意点も学ぶことができる

➤知らないライブラリやコードのイディオムを見つけて、より良いコードの書き方を学ぶことができる

他人のプルリクを読む

51

➤大きすぎる1つのプルリクで問題を解決しようとすると、レビューがむずかしい、設計議論が収束しない、マージが難しいなどが発生してしまうため

※ 手頃なサイズに明確な基準はないけれど、人によっては例えば、変更が 200 行程度の量、 4 日以内で終わる量、ある作業を2つの意味のある作業単位で分割してプルリクを目安に

プルリクは手頃なサイズにする

ユーザストーリー

XP(Scrum)- プルリクの連動

2週間タイムボックス

プランニング

レビュー

モ)プランニング

レビュー

モ)プランニング

レビュー

モ)プランニング

レビュー

モ)

市場にフィッ

トするプロダクト(

動作するコー

をつくる目標に向かっ

ステッ

プバイステッ

プで開発

ユーザストーリー

ユーザストーリー

タスクタスクタスク

フィードバック

52

予期せぬ修正に対応できるようにメンテナンスできるコード(きれいなコード)を書く

53

➤手遅れになる前に、途中段階から素早くコードの書き方や設計判断等のフィードバックもらうため

➤リポジトリにバックアップを残すため※ ✗ 10 日の作業をまとめてプルリク => ○午前中の作業までを プルリク※ 未完のプルリクは、タイトルに “ WIP” や 作業中であることがわかるラベルを付ける※1人で解くには問題が難しくもっと早くフィードバックが欲しい場合は、問題や解き方を紙に描いて他人に話してから開発する、ペアプロやモブプログラミングで対話しながらつくる代替案も

完成しなくてもプルリクを投げる設計などで相談に乗って欲しい場合

Title や Description を書くプルリクの作成時

54

➤周囲にどんな作業をしているか知ってもらいフィードバックをもらいやすくするため

➤他人に説明することで、問題や解き方や要確認事項等の理解を整理するため( ゴムのアヒルちゃん )

※ フォーマットは様々だが、 Title には何をやったのか(やろうとしているか)の要約、 Description には リクエストがなぜ必要とされるかの背景や理由 , やったことリスト( Todo リスト)、 Issue やチケット管理等のリンク , 相談や外部に確認したい項目などなどが記載される

UI の画像をプルリクに添付するUI ありでものをつくる場合、細かな UI イメージが決まっていない場合

55

➤何をつくるとよいか(問題の定義)の議論を UI を使って明確にするため

※ 仕事を依頼する人、デザインする人、プログラムを作る人が、プルリクに添付された UI 画像を参照しオンライン上で議論し、収束

※ Gif で動きを見せたり、 Before/After を見せたり工夫も

※ プルリクのオンライン上ではなく会議室で収束させる代替案も

56

➤テストは読み手にとって、何の問題を解こうとして実装しているを理解する手がかりとなり、フィードバックしやすくなるため

➤第三者によるテストの抜け漏れも、フィードバックできるから

プルリクに自動テストのコードを含める

➤レビューアが読みやすくフィードバックしやすくするため

※ 期待通り動作することを確認して commit, リファクタリングして commit したのをプルリク※ あとで見直して、問題のあるコードをリファクタリングしてプルリク※ 問題を解く前に、修正しやすくするためにリファクタのみをテーマにしたプルリクをなげ、そののちに問題を解くプルリクを投げる

57

リファクタリングと問題を解く実装は分ける

➤迷った設計判断などを記述しておけば、周囲からフィードバックが得やすいため

※ プルリクに自分でコメントかコード中にコメントを書く

58

相談に乗って欲しい箇所は明示的にコメントを書く

➤助け合いの関係を醸成するため

➤楽しく作業するため

※ オンライン上のコミュニケ ーションは殺伐とした関係になりがちなので注意が必要。「いいね!」や「感謝の気持ち」などを絵文字で表現すると文字だけで伝えづらいことも伝えられる

※ コメントをもらう人とまだ信頼関係が醸成されていない場合は、直接対話でフィードバックもらってコメントに記録する代替案も

59

会話に絵文字を利用する

60

プルリクで略語用語を利用する

➤圧縮してコミュニケ ーションを成立させるため

WIP 作業中

LGTM OK! いいね!(私は問題ないと思うよ)

Must 必ず直すべき

Nits 細かい指摘

IMO 私の見解では。。。

Fix xxx バグ修正

Cosmetic、Refactor コード整形

61

➤チームメンバーに素早く通知し、素早くフィードバックもらうため

➤フィードバックをもらった後に直ぐに対応できるようにするため

※ Slack や HipChat などが有名。永和だと idobata

GitHub と Chatツールを連携する

GitHub とチャットツール連携pushPull Request

コメントMerge ( Accepted なら)

checkout –bcommit

通知

通知

62

プルリクと外部ツールを連携させる

63

たとえば、

➤プルリクをトリガーに CI を実行するビルドエラーを早期に発見し対応するため

➤プルリクをトリガーにデプロイする本番に近い環境に即デプロイし動作確認しフィードバックを得て対応するため

Pull Request の嬉しさって?➤オープンに/頻繁なコードレビュー

バグ、仕様(問題の設定)の齟齬の早期発見良い設計案の選択技術的負債の防止

➤オンライン上で共に学習と成長コードベースに文法やイディオムやライブラリの理解やドメイン知識の共有、スキルアップ

➤メール代替の効果的なコラボエンジニア同士でコードを中心にしたコミュニケ ーション外部のオープンソースのコミュニティへの参画のしやすさビジネス側と開発側のコラボレーション

64

オススメのプルリクの自習・学習➤ Github 実践入門本を写経

(真似てタイプして著者の追体験する)

➤ 練習、練習、練習https://github.com/octocat/Spoon-Knifehttps://github.com/github-book/first-pr

➤ オープンソースのプルリクを覗いてみる

➤ ライブラリの学習でついでにプルリク投げることサブ目 標 にする(ドキュメントの記述間違いなどは初心者もプルリクしやすい)

➤ 学生向けイベントに参加して、自分よりうまい人と出会う http://www.seplus.jp/sezemi/github/http://www.seplus.jp/sezemi/ohw/

➤ 同じ研究室内の学生同士でプルリクを試してみる。

➤ オープンソースのコードを読んでみる

65

継続的インテグレーション (CI)Q&A

67

コアとなる問いかけ

“ 問題 A に取り組む理由は?”

“ 期待する振る舞いや結果は何だろうか?”

“ 期待と実際とのギャップを埋めるにはどうしたら良いのだろうか?” “解き方 A は妥当と判断する理由は?”

“ トライ・アンド・エラーのサイクルの結果、私はいったい、何を発見し学んだだろうか?”

“ どうすれば単位時間あたりのトライ・アンド・エラーの数(学びの数)を圧倒的に伸ばすことができるだろうか?”

http://c2.com/cgi/wiki?TestDrivenDevelopment