SlideShare a Scribd company logo
1 of 63
継続的にテスト可能な設計を考える
ContinuousTestable Design
Atsushi Nakamura
About Me
Copyright 2017 @nuits_jp Slide 2
中村 充志 / Atsushi Nakamura
• リコージャパン株式会社 金融事業部所属
• Enterprise系SIerのITアーキテクト
• JavaからC#へ渡り歩く
• 趣味はXamarin?
• Blog http://www.nuits.jp
• Blog(英語) https://blog.nuits.jp
• Twitter @nuits_jp
テスト書いてますか?
Copyright 2017 @nuits_jp Slide 3
テストを維持し続けるのは難しい!
Copyright 2017 @nuits_jp Slide 4
ContinuousTestable Design
Today’s Goal
Today’s Goal
Slide 6Copyright 2017 @nuits_jp
継続的にテスト可能な設計を実現するには多くのエッセンスが必要です。
今日はそのうち、つぎの3つについてお話します。
1. 制御の流れと依存方向の分離
2. 依存方向の制御と、安定性と柔軟性の管理
3. 現実的なテスト戦略を考える(結論はこの場ではでない)
「継続的なテストの維持」に必要な一部のエッセンスですが、非常に重要なことです。
ContinuousTestable Design
Overview
1. テスト不可のアプリからスタート
2. リファクタリングしつつ、継続的にテスト可能な設計を目指す
3. テストの対象は「今回は」クラス単位を想定
Overview
• 対象システムは次のような特徴をもちます
• プロダクト別の総売上をCSV出力するコンソール アプリを想定
• 同一のデータベースを他の機能からも利用している
Overview
Copyright 2017 @nuits_jp Slide 9
SQL Server 2017
AdventureWorks2017
Other Functions
※英語含む、対象コードへのマサカリは「そっと」
Pull Requestを投げるというソフト対応をお願いします
https://github.com/nuitsjp/Continuous-Testable-Design
ContinuousTestable Design
プロダクト別 総売上 出力システム
まずはコードを見てみよう
Copyright 2017 @nuits_jp Slide 11
現在の構造
クラス間が直接依存しており
上流のクラスの単体テストができない
ControllerとBusinessLogicの関係
現在、ControllerとBusinessLogicの間には二つの依存関係がある
•BusinessLogicの生成
•BusinessLogicの利用
Controllerをテスト ダブル(Mock・Stub・Fakeなど)を利用してテストできるよ
うにリファクタリングする。
Copyright 2017 @nuits_jp Slide 13
インターフェースの抽出
Copyright 2017 @nuits_jp Slide 14
インターフェースの抽出結果
Copyright 2017 @nuits_jp Slide 15
○ 利用箇所はインターフェース依存になった
× 生成箇所に実装クラス依存が残っている
No. 方式 代表的なデザインパターン
1 Controllerが能動的に取得する Service Locator パターン
2 Controllerに外部から注入する Dependency Injection パターン
インスタンス生成を取り除く二つの方式
Copyright 2017 @nuits_jp Slide 16
基本的にいずれかに類似した方式をとります。
ここではDependency Injectionパターンを利用します。
Service Locator is an Anti-Pattern by Mark Seemann
http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/
• Service Locatorはstaticなレジストリなので並行テストが困難
• ControllerからBusinessLogicへ依存がなくなる代わりに、Service Locatorへ依存が増える
Business Logicをインジェクションする
Copyright 2017 @nuits_jp Slide 17
Dependency Injectionの適用結果
Copyright 2017 @nuits_jp Slide 18
IBusinessLogic businessLogic =
new BusinessLogic();
var controller =
new Controller(businessLogic);
controller.Execute("output.csv");
テスト ダブルの利用
Copyright 2017 @nuits_jp Slide 19
IBusinessLogic businessLogic =
newTestDouble();
var controller =
new Controller(businessLogic);
controller.Execute("output.csv");
さあ、すべてテスタブルに修正しましょう!
Copyright 2017 @nuits_jp Slide 20
しました!
Copyright 2017 @nuits_jp Slide 21
結果、こんな感じでテストできます
Copyright 2017 @nuits_jp Slide 22
単体テスト用DB
class Testable Models
Repositoryの単体テスト
BusinessLogicの単体テスト
Controllerの単体テスト
Controller «interface»
IBusinessLogic
BusinessLogic «interface»
IRepository
Repository
ControllerFixture
BusinessLogicMock
BusinessLogicFixture
RepositoryFixture
RepositoryMock
ところで、よく見ると
Copyright 2017 @nuits_jp Slide 23
なんか嫌な臭いがするぞ?
Copyright 2017 @nuits_jp Slide 24
特にこのあたりが...
Copyright 2017 @nuits_jp Slide 25
ここの向き
良く見てみよう
ControllerがViewに、依存している
一般的にViewは最も変化が多い
⇒ ControllerはViewに引きずられ変更過多になる
⇒ 結果、Controllerのテストコードもテストダブルも変更過多になる
⇒つらい
Copyright 2017 @nuits_jp Slide 26
もうひとつ
Copyright 2017 @nuits_jp Slide 27
ここもちょっとな...
Copyright 2017 @nuits_jp Slide 28
ここの向き
• 同一のデータベースを他の機能からも利用している
• データベースは他システム起因で変更が入る
• そもそもデータが安定的だというのは過去の神話で
ビジネスの変遷の早い現在は、データも安定的ではなくなっている
あらためて全体像を確認する
Copyright 2017 @nuits_jp Slide 29
SQL Server 2017
AdventureWorks2017
Other Functions
class Testable Models
Repositoryの単体テスト
BusinessLogicの単体テスト
Controllerの単体テスト
Controller «interface»
IBusinessLogic
BusinessLogic «interface»
IRepository
Repository
ControllerFixture
BusinessLogicMock
BusinessLogicFixture
RepositoryFixture
RepositoryMock
つまり参照してるテーブルが変更されると…
Copyright 2017 @nuits_jp Slide 30
単体テスト用DB
Breaking
Change!
Breaking
Change!
Breaking
Change!
Breaking
Change!
Breaking
Change!
Breaking
Change!
Breaking
Change!
Breaking
Change!
Breaking
Change!
Breaking
Change!
Breaking
Change!
最悪だ!!
Copyright 2017 @nuits_jp Slide 31
何が悪いのか?
Copyright 2017 @nuits_jp Slide 32
class BusinessLogic and Repository
BusinessLogics Repositories
BusinessLogic «interface»
IRepository
Repository
制御の流れに
引きずられて
安定させたい
モジュール
不安定な
モジュール
依存して
しまっている
解決策
Copyright 2017 @nuits_jp Slide 33
class BusinessLogic and Repository
BusinessLogics Repositories
BusinessLogic «interface»
IRepository
Repository
制御の流れから
依存方向を分離し
逆方向へ依存させる
できます!
Copyright 2017 @nuits_jp Slide 34
こうする!
重要なのは、インターフェースの移動ではなく
IRepositoryをBusinessLogicの文脈で定義すること
Copyright 2017 @nuits_jp Slide 35
class BusinessLogic and Repository
BusinessLogics Repositories
BusinessLogic «interface»
IRepository
Repository
class BusinessLogic and Repository
BusinessLogics Repositories
BusinessLogic «interface»
IRepository
Repository
Before
After
IRepositoryの詳細を見てみましょう
Copyright 2017 @nuits_jp Slide 36
IRepositoryのクラス図とER図
Copyright 2017 @nuits_jp Slide 37
class Repository Details
«interface»
IRepository
+ GetProducts(): IEnumerable<Product>
+ GetSalesOrderDetail(): IEnumerable<SalesOrderDetail>
SalesOrderDetail
«property»
+ CarrierTrackingNumber(): string
+ LineTotal(): decimal
+ ModifiedDate(): DateTime
+ OrderQty(): short
+ ProductID(): int
+ rowguid(): Guid
+ SalesOrderDetailID(): int
+ SalesOrderID(): int
+ SpecialOfferID(): int
+ UnitPrice(): decimal
+ UnitPriceDiscount(): decimal
Product
«property»
+ Class(): string
+ Color(): string
+ DaysToManufacture(): int
+ DiscontinuedDate(): DateTime?
+ FinishedGoodsFlag(): bool
+ ListPrice(): decimal
+ MakeFlag(): bool
+ ModifiedDate(): DateTime
+ Name(): string
+ ProductID(): int
+ ProductLine(): string
+ ProductModelID(): int?
+ ProductNumber(): string
+ ProductSubcategoryID(): int?
+ ReorderPoint(): short
+ rowguid(): Guid
+ SafetyStockLevel(): short
+ SellEndDate(): DateTime?
+ SellStartDate(): DateTime
+ Size(): string
+ SizeUnitMeasureCode(): string
+ StandardCost(): decimal
+ Style(): string
+ Weight(): decimal?
+ WeightUnitMeasureCode(): string
dm SalesOrderDetail and Product
Product
«column»
*PK ProductID: int
* Name: nvarchar(50)
* ProductNumber: nvarchar(25)
* MakeFlag: bit = 1
* FinishedGoodsFlag: bit = 1
Color: nvarchar(15)
* SafetyStockLevel: smallint
* ReorderPoint: smallint
* StandardCost: money
* ListPrice: money
Size: nvarchar(5)
FK SizeUnitMeasureCode: nchar(3)
FK WeightUnitMeasureCode: nchar(3)
Weight: decimal(8,2)
* DaysToManufacture: int
ProductLine: nchar(2)
Class: nchar(2)
Style: nchar(2)
FK ProductSubcategoryID: int
FK ProductModelID: int
* SellStartDate: datetime
SellEndDate: datetime
DiscontinuedDate: datetime
* rowguid: uniqueidentifier = newid()
* ModifiedDate: datetime = getdate()
SalesOrderDetail
«column»
*pfK SalesOrderID: int
*PK SalesOrderDetailID: int
CarrierTrackingNumber: nvarchar(25)
* OrderQty: smallint
*FK ProductID: int
*FK SpecialOfferID: int
* UnitPrice: money
* UnitPriceDiscount: money = 0.0
* LineTotal: numeric(38,6)
* rowguid: uniqueidentifier = newid()
* ModifiedDate: datetime = getdate()
クラス図 ER図
IRepositoryが完全にデータベースの文脈で記述されているのが見て取れる
BusinessLogicのインターフェースと比較する
Copyright 2017 @nuits_jp Slide 38
dm BusinessLogic
«interface»
IBusinessLogic
+ GetProductSalesList(): IEnumerable<ProductSales>
ProductSales
«property»
+ Name(): string
+ Sales(): decimal
プロダクト別の総売上額が欲しいだけ
class Repository Details
«interface»
IRepository
+ GetProducts(): IEnumerable<Product>
+ GetSalesOrderDetail(): IEnumerable<SalesOrderDetail>
SalesOrderDetail
«property»
+ CarrierTrackingNumber(): string
+ LineTotal(): decimal
+ ModifiedDate(): DateTime
+ OrderQty(): short
+ ProductID(): int
+ rowguid(): Guid
+ SalesOrderDetailID(): int
+ SalesOrderID(): int
+ SpecialOfferID(): int
+ UnitPrice(): decimal
+ UnitPriceDiscount(): decimal
Product
«property»
+ Class(): string
+ Color(): string
+ DaysToManufacture(): int
+ DiscontinuedDate(): DateTime?
+ FinishedGoodsFlag(): bool
+ ListPrice(): decimal
+ MakeFlag(): bool
+ ModifiedDate(): DateTime
+ Name(): string
+ ProductID(): int
+ ProductLine(): string
+ ProductModelID(): int?
+ ProductNumber(): string
+ ProductSubcategoryID(): int?
+ ReorderPoint(): short
+ rowguid(): Guid
+ SafetyStockLevel(): short
+ SellEndDate(): DateTime?
+ SellStartDate(): DateTime
+ Size(): string
+ SizeUnitMeasureCode(): string
+ StandardCost(): decimal
+ Style(): string
+ Weight(): decimal?
+ WeightUnitMeasureCode(): string
IRepositoryをBusinessLogicの文脈へリファクタリング
Copyright 2017 @nuits_jp Slide 39
リファクタリング後のIRepository
Copyright 2017 @nuits_jp Slide 40
dm Repositories
ProductName
«property»
+ Name(): string
+ ProductId(): int?
SalesLineTotal
«property»
+ LineTotal(): double
+ ProductId(): int
«interface»
IRepository
+ GetProductNames(): IEnumerable<ProductName>
+ GetSalesLineTotal(): IEnumerable<SalesLineTotal>
一旦整理しましょう
Copyright 2017 @nuits_jp Slide 41
「制御の流れ」と「依存方向」は、つぎの二つによりコントロール可能
• クラスとクラスは直接依存させず、インターフェース(抽象)に依
存させる(依存性逆転の原則)
• インターフェースを適切な文脈で定義する
「制御の流れ」と「依存方向」
Copyright 2017 @nuits_jp Slide 42
class BusinessLogics and Re...
Repositories
BusinessLogics
BusinessLogic
«interface»
IRepository
Repository
依存方向によって決まる、安定性と柔軟性
Copyright 2017 @nuits_jp Slide 43
Repository変更の影響を受けない ⇒ 安定性が高い
変更がRepositoryへ影響を与える ⇒ 柔軟性が低い
BusinessLogic変更の影響を受ける ⇒ 安定性が低い
変更がBusinessLogicへ影響を与えない ⇒ 柔軟性が高い
安定性と柔軟性は設計上トレードオフにある
あらためて全体を見てみる
Copyright 2017 @nuits_jp Slide 44
元々の安定度と柔軟性
Copyright 2017 @nuits_jp Slide 45
凡例
制御の流れ
依存関係
安定性③
柔軟性①
安定性①
柔軟性②
安定性②
柔軟性②
安定性①
柔軟性③
安定性①
柔軟性②
安定性①
柔軟性③
安定性と柔軟性 パッケージ
安定度:高 BusinessLogic
中間 Controller
柔軟性:高 View, Repository
安定性と柔軟性をコントロールする
Copyright 2017 @nuits_jp Slide 46
安定度と柔軟性をコントロールする
Copyright 2017 @nuits_jp Slide 47
凡例
制御の流れ
依存関係
安定性②
柔軟性②
安定性③
柔軟性①
安定性①
柔軟性③
安定性②
柔軟性①
継続的にテスト可能になった(はず)のクラス図
すべてのクラスを同じレベルでテストしますか?
Copyright 2017 @nuits_jp Slide 49
安定性(重要性)とテストの寿命
Copyright 2017 @nuits_jp Slide 50
安定性(重要性) テストコードの寿命
高 長い
低 短い
テスト価値と難易度には一貫性はない
Copyright 2017 @nuits_jp Slide 51
安定性 要素 テスト価値 テスト難易度
高 BusinessLogic 高 低
中
Repository 高 中
Controller 中 低
低 View 低 高
Viewのテストしたくねえな…
Copyright 2017 @nuits_jp Slide 52
そもそもクラス単体テストの価値って?
Copyright 2017 @nuits_jp Slide 53
システム
サブシステム
コンポーネント
ソフトウェアのフラクタル
Copyright 2017 @nuits_jp Slide 54
クラス
サブシステム
クラス
コンポーネント
クラス クラス
ソフトウェア エンティティすべてに、ここまでの話は適用可能
• 要素間のインターフェースの文脈により、制御の流れと依存関係は制御可能
• 依存関係によって、安定性と柔軟性をコントロール可能
ソ
フ
ト
ウ
ェ
ア
エ
ン
テ
ィ
テ
ィ
ソフトウェア エンティティ テスト価値 テスト難易度 障害発見
システム 高 高 遅い
サブシステム
コンポーネント
クラス 低 低 早い
ソフトウェア エンティティ別のテスト価値とテスト難易度
Copyright 2017 @nuits_jp Slide 55
品質をあ
げたい
テストを
増やす
テスト維
持コスト
上昇
維持でき
なくなる
品質が下
がる
テストのジレンマ
Copyright 2017 @nuits_jp Slide 56
テストには計画的な戦略が必要だ!
Copyright 2017 @nuits_jp Slide 57
などなど
テスト戦略の立案
Copyright 2017 @nuits_jp Slide 58
プロジェクト
計画
ビジネス
ユースケース
システム
ユースケース
機能要件
非機能要件
システム
アーキテクチャ
テスト戦略
What システム サブシステム コンポーネント クラス
Why
Who
When
Where
Hoe
How many
How Much
テスト戦略の立案
Copyright 2017 @nuits_jp Slide 59
先ほどのソフトウェア エンティティに対してmWnHで立てます
What システム
Why ビジネス シナリオ(業務)の実現性評価
Who 開発サイドのテストチーム
When 評価可能になり次第随時
Where システムテスト環境(Not顧客環境)
How ビジネス シナリオに則って手動で
How many 想定されるすべてのビジネスシナリオ
How Much 全ビジネスシナリオで〇〇人月
テスト戦略:システム
Copyright 2017 @nuits_jp Slide 60
ContinuousTestable Design
まとめ
まとめ
Slide 62Copyright 2017 @nuits_jp
1. 制御の流れに流されず、適切な依存方向にコントロールする
2. 依存方向によって安定性と柔軟性を、計画的に制御しましょう
3. 多面的な要素を考慮し、現実的なテスト戦略を立てましょう
ThankYou!
Any Questions?

More Related Content

What's hot

モジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェースモジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェースHajime Yanagawa
 
Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24
Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24
Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24Shin Ohno
 
マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!mosa siru
 
継承辺りのもしかしたらマイナーかもしれない C#
継承辺りのもしかしたらマイナーかもしれない C#継承辺りのもしかしたらマイナーかもしれない C#
継承辺りのもしかしたらマイナーかもしれない C#m ishizaki
 
ソフトウェア開発のやり方の改善
ソフトウェア開発のやり方の改善ソフトウェア開発のやり方の改善
ソフトウェア開発のやり方の改善増田 亨
 
Iocコンテナについて
IocコンテナについてIocコンテナについて
IocコンテナについてAkio Terayama
 
DDDのモデリングとは何なのか、 そしてどうコードに落とすのか
DDDのモデリングとは何なのか、 そしてどうコードに落とすのかDDDのモデリングとは何なのか、 そしてどうコードに落とすのか
DDDのモデリングとは何なのか、 そしてどうコードに落とすのかKoichiro Matsuoka
 
オブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツオブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツ増田 亨
 
ドメイン駆動設計 基本を理解する
ドメイン駆動設計 基本を理解するドメイン駆動設計 基本を理解する
ドメイン駆動設計 基本を理解する増田 亨
 
マイクロサービス 4つの分割アプローチ
マイクロサービス 4つの分割アプローチマイクロサービス 4つの分割アプローチ
マイクロサービス 4つの分割アプローチ増田 亨
 
エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織Takafumi ONAKA
 
Humble Object Patternな話
Humble Object Patternな話Humble Object Patternな話
Humble Object Patternな話Hiroto Imoto
 
テストコードの DRY と DAMP
テストコードの DRY と DAMPテストコードの DRY と DAMP
テストコードの DRY と DAMPYusuke Kagata
 
XunitとMoq 公開用
XunitとMoq 公開用XunitとMoq 公開用
XunitとMoq 公開用ESM SEC
 
DockerコンテナでGitを使う
DockerコンテナでGitを使うDockerコンテナでGitを使う
DockerコンテナでGitを使うKazuhiro Suga
 
テスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるなテスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるなKentaro Matsui
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」Takuto Wada
 
ソフトウェア開発における『知の高速道路』
ソフトウェア開発における『知の高速道路』ソフトウェア開発における『知の高速道路』
ソフトウェア開発における『知の高速道路』Yoshitaka Kawashima
 
ドメイン駆動設計 の 実践 Part3 DDD
ドメイン駆動設計 の 実践 Part3 DDDドメイン駆動設計 の 実践 Part3 DDD
ドメイン駆動設計 の 実践 Part3 DDD増田 亨
 
ドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Spring
ドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Springドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Spring
ドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Spring増田 亨
 

What's hot (20)

モジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェースモジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェース
 
Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24
Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24
Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24
 
マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!
 
継承辺りのもしかしたらマイナーかもしれない C#
継承辺りのもしかしたらマイナーかもしれない C#継承辺りのもしかしたらマイナーかもしれない C#
継承辺りのもしかしたらマイナーかもしれない C#
 
ソフトウェア開発のやり方の改善
ソフトウェア開発のやり方の改善ソフトウェア開発のやり方の改善
ソフトウェア開発のやり方の改善
 
Iocコンテナについて
IocコンテナについてIocコンテナについて
Iocコンテナについて
 
DDDのモデリングとは何なのか、 そしてどうコードに落とすのか
DDDのモデリングとは何なのか、 そしてどうコードに落とすのかDDDのモデリングとは何なのか、 そしてどうコードに落とすのか
DDDのモデリングとは何なのか、 そしてどうコードに落とすのか
 
オブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツオブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツ
 
ドメイン駆動設計 基本を理解する
ドメイン駆動設計 基本を理解するドメイン駆動設計 基本を理解する
ドメイン駆動設計 基本を理解する
 
マイクロサービス 4つの分割アプローチ
マイクロサービス 4つの分割アプローチマイクロサービス 4つの分割アプローチ
マイクロサービス 4つの分割アプローチ
 
エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織
 
Humble Object Patternな話
Humble Object Patternな話Humble Object Patternな話
Humble Object Patternな話
 
テストコードの DRY と DAMP
テストコードの DRY と DAMPテストコードの DRY と DAMP
テストコードの DRY と DAMP
 
XunitとMoq 公開用
XunitとMoq 公開用XunitとMoq 公開用
XunitとMoq 公開用
 
DockerコンテナでGitを使う
DockerコンテナでGitを使うDockerコンテナでGitを使う
DockerコンテナでGitを使う
 
テスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるなテスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるな
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
 
ソフトウェア開発における『知の高速道路』
ソフトウェア開発における『知の高速道路』ソフトウェア開発における『知の高速道路』
ソフトウェア開発における『知の高速道路』
 
ドメイン駆動設計 の 実践 Part3 DDD
ドメイン駆動設計 の 実践 Part3 DDDドメイン駆動設計 の 実践 Part3 DDD
ドメイン駆動設計 の 実践 Part3 DDD
 
ドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Spring
ドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Springドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Spring
ドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Spring
 

Similar to 継続的にテスト可能な設計を考える

α版 継続的にテスト可能な設計を考える
α版 継続的にテスト可能な設計を考えるα版 継続的にテスト可能な設計を考える
α版 継続的にテスト可能な設計を考えるAtsushi Nakamura
 
継続的にテスト可能な設計を考える ベータ版
継続的にテスト可能な設計を考える ベータ版継続的にテスト可能な設計を考える ベータ版
継続的にテスト可能な設計を考える ベータ版Atsushi Nakamura
 
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介Fumiya Sakai
 
「関心の分離」と「疎結合」 ソフトウェアアーキテクチャのひとかけら
「関心の分離」と「疎結合」   ソフトウェアアーキテクチャのひとかけら「関心の分離」と「疎結合」   ソフトウェアアーキテクチャのひとかけら
「関心の分離」と「疎結合」 ソフトウェアアーキテクチャのひとかけらAtsushi Nakamura
 
そのデータ、活かせていますか?
そのデータ、活かせていますか?そのデータ、活かせていますか?
そのデータ、活かせていますか?Miho Yamamoto
 
繋ぐだけじゃ終わらない! IoTを手軽にビジネスプロセスへ統合する Azure IoT + Dynamics 365 の紹介
繋ぐだけじゃ終わらない! IoTを手軽にビジネスプロセスへ統合する Azure IoT + Dynamics 365 の紹介繋ぐだけじゃ終わらない! IoTを手軽にビジネスプロセスへ統合する Azure IoT + Dynamics 365 の紹介
繋ぐだけじゃ終わらない! IoTを手軽にビジネスプロセスへ統合する Azure IoT + Dynamics 365 の紹介Kazuya Sugimoto
 
システムのモダナイズ 落ちても良いアプリの作り方
システムのモダナイズ 落ちても良いアプリの作り方システムのモダナイズ 落ちても良いアプリの作り方
システムのモダナイズ 落ちても良いアプリの作り方Chihiro Ito
 
Adobe XD Plugin「Scenegraph」の操作とDialogの作り方
Adobe XD Plugin「Scenegraph」の操作とDialogの作り方Adobe XD Plugin「Scenegraph」の操作とDialogの作り方
Adobe XD Plugin「Scenegraph」の操作とDialogの作り方Yoshiki Takeoka
 
20190515 hccjp hybrid_strategy
20190515 hccjp hybrid_strategy20190515 hccjp hybrid_strategy
20190515 hccjp hybrid_strategyOsamu Takazoe
 
CodeIgniter 〜 2008年大躍進のPHPフレームワーク
CodeIgniter 〜 2008年大躍進のPHPフレームワークCodeIgniter 〜 2008年大躍進のPHPフレームワーク
CodeIgniter 〜 2008年大躍進のPHPフレームワークkenjis
 
QualityとDeliveryを両立させるために僕らがやったこと
QualityとDeliveryを両立させるために僕らがやったことQualityとDeliveryを両立させるために僕らがやったこと
QualityとDeliveryを両立させるために僕らがやったことTakeshi Sekiguchi
 
OCHaCafe Season 2 #4 - Cloud Native時代のモダンJavaの世界
OCHaCafe Season 2 #4 - Cloud Native時代のモダンJavaの世界OCHaCafe Season 2 #4 - Cloud Native時代のモダンJavaの世界
OCHaCafe Season 2 #4 - Cloud Native時代のモダンJavaの世界オラクルエンジニア通信
 
iOSやAndroidアプリ開発のGoodPractice
iOSやAndroidアプリ開発のGoodPracticeiOSやAndroidアプリ開発のGoodPractice
iOSやAndroidアプリ開発のGoodPracticeKen Morishita
 
ヒーロー島 Visual Studio 2012
ヒーロー島 Visual Studio 2012ヒーロー島 Visual Studio 2012
ヒーロー島 Visual Studio 2012智治 長沢
 

Similar to 継続的にテスト可能な設計を考える (20)

α版 継続的にテスト可能な設計を考える
α版 継続的にテスト可能な設計を考えるα版 継続的にテスト可能な設計を考える
α版 継続的にテスト可能な設計を考える
 
継続的にテスト可能な設計を考える ベータ版
継続的にテスト可能な設計を考える ベータ版継続的にテスト可能な設計を考える ベータ版
継続的にテスト可能な設計を考える ベータ版
 
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
 
お客様が望んでいるモダンデスクトップアプリとは?/傾向と対策 Part1
お客様が望んでいるモダンデスクトップアプリとは?/傾向と対策 Part1お客様が望んでいるモダンデスクトップアプリとは?/傾向と対策 Part1
お客様が望んでいるモダンデスクトップアプリとは?/傾向と対策 Part1
 
[Japan Tech summit 2017] DAL 006
[Japan Tech summit 2017] DAL 006[Japan Tech summit 2017] DAL 006
[Japan Tech summit 2017] DAL 006
 
Ms retail update ra 20191030
Ms retail update ra 20191030Ms retail update ra 20191030
Ms retail update ra 20191030
 
「関心の分離」と「疎結合」 ソフトウェアアーキテクチャのひとかけら
「関心の分離」と「疎結合」   ソフトウェアアーキテクチャのひとかけら「関心の分離」と「疎結合」   ソフトウェアアーキテクチャのひとかけら
「関心の分離」と「疎結合」 ソフトウェアアーキテクチャのひとかけら
 
ファーストアカウンティング会社説明資料 for engineer 2022年7月版
ファーストアカウンティング会社説明資料 for engineer 2022年7月版ファーストアカウンティング会社説明資料 for engineer 2022年7月版
ファーストアカウンティング会社説明資料 for engineer 2022年7月版
 
そのデータ、活かせていますか?
そのデータ、活かせていますか?そのデータ、活かせていますか?
そのデータ、活かせていますか?
 
繋ぐだけじゃ終わらない! IoTを手軽にビジネスプロセスへ統合する Azure IoT + Dynamics 365 の紹介
繋ぐだけじゃ終わらない! IoTを手軽にビジネスプロセスへ統合する Azure IoT + Dynamics 365 の紹介繋ぐだけじゃ終わらない! IoTを手軽にビジネスプロセスへ統合する Azure IoT + Dynamics 365 の紹介
繋ぐだけじゃ終わらない! IoTを手軽にビジネスプロセスへ統合する Azure IoT + Dynamics 365 の紹介
 
システムのモダナイズ 落ちても良いアプリの作り方
システムのモダナイズ 落ちても良いアプリの作り方システムのモダナイズ 落ちても良いアプリの作り方
システムのモダナイズ 落ちても良いアプリの作り方
 
Angularreflex20141210
Angularreflex20141210Angularreflex20141210
Angularreflex20141210
 
Adobe XD Plugin「Scenegraph」の操作とDialogの作り方
Adobe XD Plugin「Scenegraph」の操作とDialogの作り方Adobe XD Plugin「Scenegraph」の操作とDialogの作り方
Adobe XD Plugin「Scenegraph」の操作とDialogの作り方
 
JavaOne2017参加報告 Microservices topic & approach #jjug
JavaOne2017参加報告 Microservices topic & approach #jjugJavaOne2017参加報告 Microservices topic & approach #jjug
JavaOne2017参加報告 Microservices topic & approach #jjug
 
20190515 hccjp hybrid_strategy
20190515 hccjp hybrid_strategy20190515 hccjp hybrid_strategy
20190515 hccjp hybrid_strategy
 
CodeIgniter 〜 2008年大躍進のPHPフレームワーク
CodeIgniter 〜 2008年大躍進のPHPフレームワークCodeIgniter 〜 2008年大躍進のPHPフレームワーク
CodeIgniter 〜 2008年大躍進のPHPフレームワーク
 
QualityとDeliveryを両立させるために僕らがやったこと
QualityとDeliveryを両立させるために僕らがやったことQualityとDeliveryを両立させるために僕らがやったこと
QualityとDeliveryを両立させるために僕らがやったこと
 
OCHaCafe Season 2 #4 - Cloud Native時代のモダンJavaの世界
OCHaCafe Season 2 #4 - Cloud Native時代のモダンJavaの世界OCHaCafe Season 2 #4 - Cloud Native時代のモダンJavaの世界
OCHaCafe Season 2 #4 - Cloud Native時代のモダンJavaの世界
 
iOSやAndroidアプリ開発のGoodPractice
iOSやAndroidアプリ開発のGoodPracticeiOSやAndroidアプリ開発のGoodPractice
iOSやAndroidアプリ開発のGoodPractice
 
ヒーロー島 Visual Studio 2012
ヒーロー島 Visual Studio 2012ヒーロー島 Visual Studio 2012
ヒーロー島 Visual Studio 2012
 

More from Atsushi Nakamura

Settings SyncとCodespaceで体験する新世代へのパラダイムシフト
Settings SyncとCodespaceで体験する新世代へのパラダイムシフトSettings SyncとCodespaceで体験する新世代へのパラダイムシフト
Settings SyncとCodespaceで体験する新世代へのパラダイムシフトAtsushi Nakamura
 
C#メタプログラミング概略 in 2021
C#メタプログラミング概略 in 2021C#メタプログラミング概略 in 2021
C#メタプログラミング概略 in 2021Atsushi Nakamura
 
Unicodeで半角全角を扱うAmbiguous(曖昧さ)とUncertainty(不確実性)の恐怖
Unicodeで半角全角を扱うAmbiguous(曖昧さ)とUncertainty(不確実性)の恐怖Unicodeで半角全角を扱うAmbiguous(曖昧さ)とUncertainty(不確実性)の恐怖
Unicodeで半角全角を扱うAmbiguous(曖昧さ)とUncertainty(不確実性)の恐怖Atsushi Nakamura
 
世界一わかりやすいClean Architecture - DroidKaigiバージョン
世界一わかりやすいClean Architecture - DroidKaigiバージョン世界一わかりやすいClean Architecture - DroidKaigiバージョン
世界一わかりやすいClean Architecture - DroidKaigiバージョンAtsushi Nakamura
 
世界一わかりやすいClean Architecture release-preview
世界一わかりやすいClean Architecture release-preview世界一わかりやすいClean Architecture release-preview
世界一わかりやすいClean Architecture release-previewAtsushi Nakamura
 
世界一わかりやすいClean Architecture alpha-1
世界一わかりやすいClean Architecture alpha-1世界一わかりやすいClean Architecture alpha-1
世界一わかりやすいClean Architecture alpha-1Atsushi Nakamura
 
Visual Studio 2019で始める「WPF on .NET Core 3.0」開発
Visual Studio 2019で始める「WPF on .NET Core 3.0」開発Visual Studio 2019で始める「WPF on .NET Core 3.0」開発
Visual Studio 2019で始める「WPF on .NET Core 3.0」開発Atsushi Nakamura
 
Desktop app dev strategy for .net core 3.0
Desktop app dev strategy for .net core 3.0Desktop app dev strategy for .net core 3.0
Desktop app dev strategy for .net core 3.0Atsushi Nakamura
 
App center analyticsを使い倒そう
App center analyticsを使い倒そうApp center analyticsを使い倒そう
App center analyticsを使い倒そうAtsushi Nakamura
 
Old:App center analyticsを使い倒そう
Old:App center analyticsを使い倒そうOld:App center analyticsを使い倒そう
Old:App center analyticsを使い倒そうAtsushi Nakamura
 
Xamarin.forms navigation overview
Xamarin.forms navigation overviewXamarin.forms navigation overview
Xamarin.forms navigation overviewAtsushi Nakamura
 
App center analyticsを使い倒そう
App center analyticsを使い倒そうApp center analyticsを使い倒そう
App center analyticsを使い倒そうAtsushi Nakamura
 
Blue monkey architecture overview
Blue monkey architecture overviewBlue monkey architecture overview
Blue monkey architecture overviewAtsushi Nakamura
 
Xamarin Dev days 2 xamarin.forms ja
Xamarin Dev days 2   xamarin.forms jaXamarin Dev days 2   xamarin.forms ja
Xamarin Dev days 2 xamarin.forms jaAtsushi Nakamura
 
Why prism for xamarin.forms
Why prism for xamarin.formsWhy prism for xamarin.forms
Why prism for xamarin.formsAtsushi Nakamura
 
Enterpriseから見たXamarinの可能性
Enterpriseから見たXamarinの可能性Enterpriseから見たXamarinの可能性
Enterpriseから見たXamarinの可能性Atsushi Nakamura
 

More from Atsushi Nakamura (16)

Settings SyncとCodespaceで体験する新世代へのパラダイムシフト
Settings SyncとCodespaceで体験する新世代へのパラダイムシフトSettings SyncとCodespaceで体験する新世代へのパラダイムシフト
Settings SyncとCodespaceで体験する新世代へのパラダイムシフト
 
C#メタプログラミング概略 in 2021
C#メタプログラミング概略 in 2021C#メタプログラミング概略 in 2021
C#メタプログラミング概略 in 2021
 
Unicodeで半角全角を扱うAmbiguous(曖昧さ)とUncertainty(不確実性)の恐怖
Unicodeで半角全角を扱うAmbiguous(曖昧さ)とUncertainty(不確実性)の恐怖Unicodeで半角全角を扱うAmbiguous(曖昧さ)とUncertainty(不確実性)の恐怖
Unicodeで半角全角を扱うAmbiguous(曖昧さ)とUncertainty(不確実性)の恐怖
 
世界一わかりやすいClean Architecture - DroidKaigiバージョン
世界一わかりやすいClean Architecture - DroidKaigiバージョン世界一わかりやすいClean Architecture - DroidKaigiバージョン
世界一わかりやすいClean Architecture - DroidKaigiバージョン
 
世界一わかりやすいClean Architecture release-preview
世界一わかりやすいClean Architecture release-preview世界一わかりやすいClean Architecture release-preview
世界一わかりやすいClean Architecture release-preview
 
世界一わかりやすいClean Architecture alpha-1
世界一わかりやすいClean Architecture alpha-1世界一わかりやすいClean Architecture alpha-1
世界一わかりやすいClean Architecture alpha-1
 
Visual Studio 2019で始める「WPF on .NET Core 3.0」開発
Visual Studio 2019で始める「WPF on .NET Core 3.0」開発Visual Studio 2019で始める「WPF on .NET Core 3.0」開発
Visual Studio 2019で始める「WPF on .NET Core 3.0」開発
 
Desktop app dev strategy for .net core 3.0
Desktop app dev strategy for .net core 3.0Desktop app dev strategy for .net core 3.0
Desktop app dev strategy for .net core 3.0
 
App center analyticsを使い倒そう
App center analyticsを使い倒そうApp center analyticsを使い倒そう
App center analyticsを使い倒そう
 
Old:App center analyticsを使い倒そう
Old:App center analyticsを使い倒そうOld:App center analyticsを使い倒そう
Old:App center analyticsを使い倒そう
 
Xamarin.forms navigation overview
Xamarin.forms navigation overviewXamarin.forms navigation overview
Xamarin.forms navigation overview
 
App center analyticsを使い倒そう
App center analyticsを使い倒そうApp center analyticsを使い倒そう
App center analyticsを使い倒そう
 
Blue monkey architecture overview
Blue monkey architecture overviewBlue monkey architecture overview
Blue monkey architecture overview
 
Xamarin Dev days 2 xamarin.forms ja
Xamarin Dev days 2   xamarin.forms jaXamarin Dev days 2   xamarin.forms ja
Xamarin Dev days 2 xamarin.forms ja
 
Why prism for xamarin.forms
Why prism for xamarin.formsWhy prism for xamarin.forms
Why prism for xamarin.forms
 
Enterpriseから見たXamarinの可能性
Enterpriseから見たXamarinの可能性Enterpriseから見たXamarinの可能性
Enterpriseから見たXamarinの可能性
 

継続的にテスト可能な設計を考える

Editor's Notes

  1. みなさんこんにちは。 ご紹介いただきました。ニュイこと中村です。 今日は 継続的にテスト可能な設計を考える というTitleでお話しさせていただこうと思います。 よろしくお願いいたします。
  2. まずは自己紹介から 中村充志と申します。 リコージャパン株式会社の金融ソリューション開発部 というところに所属しています。 Enterprise系SIerでITアーキテクトをやらせてもらっています。
  3. ところで皆さん、日常的に自動テスト書いてますか? 私は結構書いてます。 SIerのテストというと、Excel!スクショ!エビデンス!的なイメージがあるかも知れませんが たまたま巡り合わせが良くて、2000年からJUnitを触っていたと思います。 SIerって、プロダクトチームの維持が難しくて、半年ごとに8割のメンバーが入れ替わってる みたいな地獄みたいな事が良くあるので、自動テストが無いと怖くて生きていけない というのが、私のテストのモチベーションなんだと思います。 ただ、テストを書くのは良いんですが、本当に難しいのはプロダクトの改修に追随して テストを維持していくことだと、私は思っています。
  4. テストを維持し続けるのは本当に難しいです。 プロジェクトのスケジュールが厳しくなると、すぐ悪魔が囁き始めますし テストを維持する事自体が、ソフトウェアの変更を阻害するようなこともあります。 実際に、テストをいくらか破棄して泣く泣く規模を縮小したりしたこともあります。
  5. という訳で、本日のゴールです。
  6. 今日は、そういった茨の道で試行錯誤してきたベストプラクティスの中から 特に大切だと思っている、三つのエッセンスについてお話ししたいと思います。 ①一つは制御の流れと依存性の分離について ②二つ目は依存方向の制御と、安定性と柔軟性の管理について ③そして最後に現実的なテスト戦略について です。当然これだけで継続的なテストの維持ができるようになる訳ではありませんが、特に重要なことだと私は思っていますのでお付き合いください。
  7. このセッションの概要ですが
  8. 実際のコードを見ながら、最初はテスト不可能なコードからスタートして リファクタリングしながら、継続的にテスト可能な設計を目指したいと思います。 なお、テストの対象は今回はクラス単位のテストをする前提とさせていただきます。
  9. 実際の例に用いるプログラムですが、SQL ServerのサンプルDBのAdventureWorksを 利用させてもらって、プロダクト別の総売上をCSV出力するような コンソールアプリを想定します。 そのアプリから利用するデータベースは、同一システムの別機能からも利用されるものとします。 コードはこちらのURLに公開しています。 なおコードや、コードの英語に不備不満のある方は、そっとプルリクを送っていただけると助かります。 まえに「その単語、不可算名詞だからsつくのおかしくね?」みたいなマサカリをぶん投げてきた人がいるんですが なるべく、そっとやさしくお願いします。 今日は強そうな人が多いので、重々よろしくお願いいたします。
  10. では早速、本題に入りたいと思います。
  11. まずはコードを見てください。
  12. ① さて、今見ていただいたコードですが クラス図に落とすと、こんな感じです。 今日のテスト対象はクラスですから ② この辺のクラス間が直接依存してるせいで 上流のクラスが単体テストできない状態になっています。
  13. 例えばControllerとBusinessLogicの関係の詳細を見てみると その二つの間には、オブジェクトの生成と利用という2種類の依存関係があります。 これらが、Controllerをテストダブルを利用して単体テストすることを阻んでいます。 という訳で、これらのクラス間の直接的な依存関係を取り除いていきます。
  14. まずはインターフェースを抽出します。 ここからは、またコードに戻ります。
  15. さて、こうしたことで、BusinessLogicを利用している箇所の依存関係は クラスからインターフェース移すことができました。 ただし、インスタンスを生成する個所に依存がまだ残っています。
  16. インスタンス生成の依存関係を取り除くには、基本的にはインスタンスの生成を つぎの二つの何れかの方法で解決する必要があります。 一つはControllerが能動的に、インスタンスをいずれかのレジストリーに取得しに行く方法。 もう一つは依存オブジェクトをControllerの外から、誰かに注入してもらう方法です。 それぞれ代表的な実現方法として、ServiceLocatorパターンとDependency Injectionパターンがあります。 今回はDependency Injectionパターン、つまりDIを利用します。 なぜDIを利用するかは、ざっくりいうと、ServiceLocatorには大きな問題が二つあって 一つはテストをマルチスレッドで実装しにくいということと ServiceLocatorパターンにするとBusinessLogicへの依存は減るけど、ServiceLocator への依存が増えて、依存数が減らないという欠点があるためです。
  17. という訳でBusinessLogicをインジェクションするように修正します。
  18. というわけで、無事にControllerからインスタンス生成のロジックも除去出来て 完全にクラス間の依存関係を無くせました。
  19. こうする事で、簡単にBusinessLogicをテストダブルに置き換えが可能になって テスタブルになります。 ちなみにDIパターンとDIコンテナが混同されているケースがありますが DIコンテナはあくまでDIパターンを便利に実現するためのツールなので 必ずしも使わなくてもDIパターンは実現できます。普通は使いますけど。
  20. では他の部分もテスタブルにしましょう!
  21. はいできました!すいません、時間がないので3分間クッキング方式を 取らせていただきます。 View、BusinessLogic、Repositoryの全てに インターフェースを導出し、DIを適用します。 こうする事で
  22. こんな感じで、全てのクラスにたいしてクラス単位のテストが実施できるようになりました。
  23. ところでこのクラス図
  24. 良く見ると不吉なにおいがしますね?
  25. 特にこの、ControllerとViewの間です。
  26. ①ControllerがViewに依存している部分です。 ②一般的にViewは最も変化が多いと言われていますよね。 それが正しいとすると ③Viewに依存しているControllerはViewに引きずられて 頻繁に変更する必要がでてきます ④結果、プロダクションコードだけでなく、テストコードもテストダブルも 頻繁に変更しなくてはならなくなります ⑤これは辛いです
  27. そしてもう一つ 個人的にはこっちの方が嫌な予感がします。
  28. このBusinessLogicがRepositoryに依存しているところです。
  29. 最初にお話しした通り、このシステムで利用するデータベースは 他の機能からも利用されます。 ということは、このシステムではない、別の機能起因で変更が入る可能性があります。 そもそもデータが安定的であるというのも、私は懐疑的です。 現代において企業は、顧客に対して新しい価値を次々提供し続けなくてはなりません。 新しい価値を提供するためには、往々にして新しいデータが発生します。 データの取り扱いが無くなる事は少なくても、追加変更はそれなりに発生するのが現実だと 私は思っています。
  30. ①つまり、何らかの要因で参照しているテーブルに変更が発生すると ②リポジトリが変更されます ③当然そうなるとテストケースの修正が入って ④高い確率でリポジトリのインターフェースが変更されます ⑤するとビジネスロジックが影響を受けて ⑥リポジトリのモックとビジネスロジックのテストががががが 全部なおさなきゃ!
  31. 最悪だ!と、なってしまうかもしれないです。 実際稀に良くありますし。
  32. つまり何が悪いかというと ①安定させたいビジネスロジックが ②不安定なモジュールにたいして ③制御の流れが原因で引きずられて ④依存してしまっているのが、この問題の根幹にあります これを解決するには
  33. 制御の流れから依存方向を分離して ①逆方向に依存させれば解決できます
  34. もちろん実現可能です
  35. 具体的には、今こうなっているのを ①こうします。重要なのは、インターフェースを移動することではなくて ②リポジトリをビジネスロジックの文脈で定義することです
  36. リポジトリの詳細を見てみましょう
  37. 現在の実装は、リポジトリが完全にデータベースの文脈で記述されているのが見て取れます。
  38. しかし、ビジネスロジックで実現したいのは、プロダクト別の総売上額です。 ①つまりビジネスロジックに必要なのはこの4項目だけです。
  39. という訳で、リポジトリインターフェースを ビジネスロジックの文脈へリファクタリングします
  40. 結果、こうなりました。 データベースの詳細が隠蔽されているのが 分かるかと思います。
  41. 一旦整理しましょう。
  42. 制御の流れと、依存方向は、必ずしも一致させる必要はありません。 クラスとクラスの直接依存を避けて、インターフェースを定義し、疎結合にした上で インターフェースを依存させたい側の文脈で定義することで 依存方向は制御の流れから分離して、自由にコントロールできます。
  43. そして、依存方向によって安定性と柔軟性が変化します。 リポジトリインターフェースは、ビジネスロジックの文脈で記述されています。 ①つまり、データベースの影響を受けにくく、安定性が高くなります。 しかし逆にいうと、ビジネスロジックを変更すると、リポジトリの実装が影響を受ける可能性があるため ビジネスロジックの柔軟性は低くなります。 ②逆にリポジトリの実装はビジネスロジックの変更の影響を受ける為、安定性は低くなります。 しかし、リポジトリの変更はビジネスロジックへ影響を与えにくいため、変更しやすく、柔軟性が高いといえます。 ③つまり、安定性と柔軟性は設計上のトレードオフにあるわけです。
  44. あらためて全体を見てみましょう。
  45. クラスを書くと煩雑なので、パッケージだけ記述しました。 最初の設計では制御の流れと依存関係が一致していたため それぞれのパッケージの安定性と柔軟性は、この図のような 状態にあります。 ①ビューとリポジトリが一番安定している。つまり変更しにくい状態にあり それらを修正すると、システム全体への影響が大きい状態に なってしまっています。
  46. 実際には安定性と柔軟性は、だいたいこんな感じにしたいとします。 ビジネスロジックを最も安定させ ビューとレポジトリーは柔軟性を高めたい、つまり変更しやすくしたいとします。
  47. その為にはコントローラーとビュー、ビジネスロジックとリポジトリの間の 依存関係を逆転してあげれば、望む通りの安定性と柔軟性を 得ることができるわけです。
  48. これで変更を受けやすい部分の柔軟性が高くなり、それ以外への影響が およびにくくなりました。 つまり、テストコードへの影響も局所化できて、継続的にテストをしやすい状態に なったはずです。 なったんですが、そこで疑問が発生します。
  49. 全部テストできるからと、すべてのクラスを同じレベルでテストする必要があるんでしょうか?
  50. 当たり前のことですが、重要なクラスの安定性が高くなるようにコントロールすることで 重要なクラスへのテストコードの寿命は延びます。 逆に言うと、安定性の低いクラスのテストコードの寿命は短くなります。
  51. また、この表はあくまで例ですが、テスト価値と、テストの難易度には一貫性がないのではないかと感じています。 重要な部分はテストしにくい部分から切り離す努力はしますが、かならずしもできるとは限りません。 例えばViewなんかは安定性が低いわりに、テスト難易度が高かったりして、きっと皆さん思いますよね?
  52. Viewのテストしたくねえなあって。 また別の視点もあります
  53. そもそも、クラス単体でテストする価値ってどのくらいあるんでしょうか?
  54. ①ソフトウェアはクラスとクラスがまとまってコンポーネントとなり ②コンポーネントとコンポーネントがまとまってサブシステムになります。そして ③サブシステムとサブシステムがまとまってシステムになります。 ④ここではクラス・コンポーネント・サブシステム・システムを、ソフトウェア エンティティと呼ぶことにします。 ⑤ソフトウェアエンティティのすべてにおいて、ここまでした話の内容は適用できます。 もちろんサブシステム間は例えばWeb APIになったりするでしょうけど どの要素間であっても、インターフェースの文脈を管理する事で 制御の流れと依存関係は制御することが可能です。 そして依存関係を制御することで、安定性と柔軟性をコントロールすることが可能となります
  55. そしてソフトウェア エンティティのレベルが高くなれば高くなるほど それらに対するテストの価値は高まります。 ただし、難易度も併せて高くなります。 クラスが動いても、システムが動かなければ価値を生まないので当たり前ですよね。 ただし、テストの比率を上位レイヤーに置くと、障害の発見が遅れます。 さらにここでジレンマが発生します。
  56. ①ソフトウェアの品質を上げたいという要求があったら ②通常、テストを増やして品質をあげますよね。ところがテストを増やすと ③当然ながら、テスト維持コストが上昇します。その結果 ④テストが維持できなくなります。その結果 ⑤品質が下がり そして最初にもどるという。 つまり継続的にテストをするには、テスト技術だけじゃどうにもなんないわけです。
  57. 我々には計画的なテスト戦略が絶対に必要です。 ではテスト戦略ってどうたてればいいのか。 ここからは完全にオレオレ方式というか、弊社方式オレ編みたいなもんですが
  58. テスト戦略の立案には ①プロジェクト計画や②ビジネスユースケースだったり③システムユースケース④機能要件や⑤非機能要件⑥システムアーキテクチャ ⑦などなどをインプットにして立案していきます
  59. で、どんな内容を計画していくかというと インプットになった情報をもとに、どの要件をどのレイヤーで、どうテストするか この表みたいな感じで例えばここでは5W3Hなどで整理していくと うまく行くことが多いです。
  60. もうちょっと掘り下げてみてみましょう。 例えばシステムテストであれば、こんな感じです。 システムテストは、ビジネスシナリオの実現性を評価します。 評価は開発サイドのテストチームが、評価可能になったビジネスシナリオから逐次テストします。 システムテスト用の環境でビジネスシナリオに則って手動でテストし、 想定されうるビジネスシナリオすべてに対して行います。 全ビジネスシナリオで〇〇人月投入します。 みたいな感じです。 もちろん、これは方針レベルでしかないものですが、ここから初めて詳細に落としていくやり方をとっています。
  61. とうわけで、最後のテスト戦略に関してはふわっとした物になってしまって申しえ訳ありませんが、私からお伝えしたいことは以上です。 最後に改めてまとめたいと思います。
  62. 継続的にテスト可能な設計を目指すには、次の三つのエッセンスが重要だと、私は考えています。 ①制御の流れ流されず、適切に依存方向をコントロールする必要があります ②依存方向によって安定性と柔軟性を、計画的に制御しましょう ③そして、そういった技術論だけでは継続的なテストの維持は困難なので 多面的な要素を考慮した、現実的なテスト戦略を立てる必要があるかと思います。 テスト戦略の話は、抽象的な話に終始してしまいましたが 先に話した二つのエッセンスを
  63. 以上で私の発表を終わります。 ご清聴ありがとうございました。