23
わわわわわわ わわわわわわ #37 1 C# でで でででででででで TDD でで #25 BluewaterSoft 2015/11/14 biac

わんくま名古屋 #37 (20151114) TDD道場 #25

Embed Size (px)

Citation preview

Page 1: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 1

C# での

リファクタリング

TDD 道場 #25

BluewaterSoft 2015/11/14 biac

Page 2: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 2

スピーカー紹介 : biac as 山本 康彦

• 宇宙世紀以前の生まれスプートニク 1 号より 3 ヶ月ほど前

• 最初は HONDAクルマの設計 / 研究を 10 年くらいやってた

• 今は BluewaterSoftを名乗ってアプリ開発とか技術解説記事とか

• 「 NUnitの全貌」⇒CodeZine 2012/4

Page 3: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 3

【 CM 】 C# で始めるテスト駆動開発入門

• CodeZine 連載再開♪• #08 「ユニバーサル

Windowsアプリのユニットテスト(前編)」

• #09 「ユニバーサルWindowsアプリのユニットテスト(後編)」

• #10 「状態を持つクラスをテストファーストする」

Page 4: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 4

TDD = テスト ファースト + リファクタリング

•テスト ファースト : RED と GREEN の繰り返し•リファクタリング : GREEN を維持したまま実装を改善失敗するはずのユニット テストを 1 つ書

き、失敗することを確認 (=RED)

ユニット テストに通るだけの実装を追加し、成功することを確認 (=GREEN)

Page 5: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 5

TDD 3 原則 by Robert C Martin

•ArticleS.UncleBob.TheThreeRulesOfTdd (2005) より。 ※ 実質は「テスト ファースト 3 原則」

1. 失敗するユニットテストを成功させるためにしか、プロダクトコードを書いてはならない。

2. 失敗させるためにしか、ユニットテストを書いてはならない。コンパイルエラーは失敗に数える。

3. ユニットテストを 1 つだけ成功させる以上に、プロダクトコードを書いてはならない。

Page 6: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 6

TDD MANTRA• 『

Test-Driven Development: By Example』からの引用

• テスト駆動開発において我々は、・自動テストが失敗している場合に限り、 新しいコードを書く・重複を取り除く

• OneDrive で公開http://1drv.ms/1uz3Z2P

Page 7: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 7

今年のテーマ

•TDD の半分はテスト ファースト。残り半分は…

リファクタリング(refactoring)

Page 8: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 8

リファクタリング by Martin Fowler

•「リファクタリングとは、コードの外的な振る舞いを変更せずに、内部の構造を作りかえること」http://refactoring.com/

Refactoring is … altering its internal structure without changing its external behavior.

Page 9: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 9

リファクタリングを学ぶには ? •「リファクタリング ― 既存のコードを安全に改善する ―」by Martin Fowlerhttp://amzn.to/1C6rzHL

※ 原書は 1999/6 発行

Page 10: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 10

「リファクタリング」 は造語

•「リファクタリング」は造語•考案者は不明。 Fowler ではない

( 例 : 1992年の論文)

The refactorings are defined to be behavior preserving, ( リファクタリングは、振る舞いを維持するように定義される… )

Page 11: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 11

リファクタリング本にないリファクタリング

・リファクタリングを学ぶには、「リファクタリング本」❢・でも、原著は J2SE 1.2 時代のもの・今どきの Java では ?・今どきの C# では ?

Page 12: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 12

原著のリファクタリング例

•「コレクションのカプセル化」より ( 新版 p.210)class Person … private Set _courses; public void setCourses(Set arg) { _courses = arg; }

class Person … … public void initializeCourses(Set arg) { Assert.isTrue(_coursec.isEmpty()); Iterator iter = arg.Iterator(); while(iter.hasNext()) { addCourse((Course)iter.next()); } }

・意図を明確化・安全性を向上

でも、このへんはダサイよね❢

Page 13: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 13

今どきの Java なら

•新版 p.423 よりclass Person … … public void initializeCourses(Set arg) { Assert.isTrue(_course.isEmpty()); Iterator iter = arg.Iterator(); while(iter.hasNext()) { addCourse((Course)iter.next()); } }

J2SE 5 で再リファクタリング

ジェネリクスと for eachclass Person … … public void initializeCourses(Set<Course> arg) { assert _course.isEmpty(); for(Course aCourse : arg) { addCourse(aCourse)); } }

Page 14: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 14

今どきの C# なら

•当然、ジェネリクスと foreach 使えclass Person … … public void InitializeCourses(IEnumerable<Course> arg) { Debug.Assert(_course.Count == 0); foreach(var aCourse in arg) { AddCourse(aCourse); } }

Page 15: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 15

今どきの C# のリファクタリング

今どきの C# でのリファクタリングをいくつか紹介・ループ・ null チェック・画面のデータ・テンプレート パターン

Page 16: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 16

C# : ループを LINQ にリファクタリング

•コレクションに対するループ処理

public bool HasAdvancedCourse{ get { foreach (var c in Courses) if (c.IsAdvanced) return true; return false; }}

C# 6 でリファクタリング

LINQ (+ ラムダ式 )

public bool HasAdvancedCourse => Courses.Any(c => c.IsAdvanced);

Page 17: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 17

C# : ガード節を null propagation 演算子に

•null チェック( リファクタリング本では null オブジェクトを導入 )

public string Foo(SampleClass arg){ if(arg == null || arg.Bar == null) return null; return arg.Bar.Buz();}

C# 6 でリファクタリング

null propagation 演算子

public string Foo(SampleClass arg){ return arg?.Bar?.Buz();}

Page 18: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 18

C# : 画面のデータをデータバインディングで分離

• 「観察されるデータの複製」 ( 複製されたデータが画面にある )⇨ データバインディングでロジック側のデータと同期 ( リファクタリング本では Observer パターンの導入 )

• データバインディングは、 .NET では汎用的なスキルWindows Forms / WPF / ストアアプリ / UWP アプリ

Page 19: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 19

C# : テンプレートパターン ラムダ式 ⇨ (その 1)•似た処理を同じ順序で実行する 2 つのクラス( リファクタリング本ではテンプレートパターンを導入 )

public class SampleClass{ // テンプレートメソッド public int Calc(int x) { var work = Foo(x); work = Bar(work); // ☜ この中身だけがちょっと違う 2 つの処理 return Buz(work); }

private SampleClass() { // 外部からのインスタンス化を禁止 }

Page 20: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 20

C# : テンプレートパターン ラムダ式 ⇨ (その 2)•問題の本質は、安全にメソッドを差し替えること

// テンプレートメソッド内で使うメソッド定義 int Foo(int x) => x % 7; Func<int, int> Bar; // 差し替え可能 int Buz(int x) => x + 1;

// Bar メソッドを確定してインスタンスを生成 public static SampleClass CreateInstanceA() { return new SampleClass() { Bar = (x) => x * 2, }; } public static SampleClass CreateInstanceB() { return new SampleClass() { Bar = (x) => x * 3, }; }}

Page 21: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 21

まとめ : リファクタリング マスターへの道

•基礎 : 「リファクタリング ― 既存のコードを安全に改善する ―」by Martin Fowlerhttp://amzn.to/1C6rzHL

⇩•最新の開発環境に合ったリファクタリングの研究

Page 22: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 22

Visual Studio Community 2015•無償の Visual Studio•ライセンス制限アリ (個人利用なら無条件でOK!) 詳細は⇒ http://www.microsoft.com/ja-jp/dev/products/community.aspx

•Professional とほぼ同等•ダウンロード

https://www.visualstudio.com/products/visual-studio-community-vs

Visual Studio Community は、個人の開発者、オープン ソース プロジェクト、アカデミックな研究、教育、中小企業の専門家チームのための無料のコミュニティです。

Page 23: わんくま名古屋 #37 (20151114) TDD道場 #25

わんくま同盟 名古屋勉強会 #37 23

ご清聴ありがとうございました