Submit Search
Upload
継続的にテスト可能な設計を考える ベータ版
•
Download as PPTX, PDF
•
3 likes
•
398 views
A
Atsushi Nakamura
Follow
.NET Conf 2018 Tokyo, Japanで発表するにあたり、セッション選択の参考の為、ほぼ固まった部分を一部先行公開します。
Read less
Read more
Software
Report
Share
Report
Share
1 of 51
Download now
Recommended
α版 継続的にテスト可能な設計を考える
α版 継続的にテスト可能な設計を考える
Atsushi Nakamura
継続的にテスト可能な設計を考える
継続的にテスト可能な設計を考える
Atsushi Nakamura
.NET の今とミライ (.NET Conf 2018 Japan Keynote)
.NET の今とミライ (.NET Conf 2018 Japan Keynote)
Akira Inoue
「関心の分離」と「疎結合」 ソフトウェアアーキテクチャのひとかけら
「関心の分離」と「疎結合」 ソフトウェアアーキテクチャのひとかけら
Atsushi Nakamura
世界一わかりやすいClean Architecture
世界一わかりやすいClean Architecture
Atsushi Nakamura
世界一わかりやすいClean Architecture - DroidKaigiバージョン
世界一わかりやすいClean Architecture - DroidKaigiバージョン
Atsushi Nakamura
C#メタプログラミング概略 in 2021
C#メタプログラミング概略 in 2021
Atsushi Nakamura
世界一わかりやすいClean Architecture alpha-1
世界一わかりやすいClean Architecture alpha-1
Atsushi Nakamura
Recommended
α版 継続的にテスト可能な設計を考える
α版 継続的にテスト可能な設計を考える
Atsushi Nakamura
継続的にテスト可能な設計を考える
継続的にテスト可能な設計を考える
Atsushi Nakamura
.NET の今とミライ (.NET Conf 2018 Japan Keynote)
.NET の今とミライ (.NET Conf 2018 Japan Keynote)
Akira Inoue
「関心の分離」と「疎結合」 ソフトウェアアーキテクチャのひとかけら
「関心の分離」と「疎結合」 ソフトウェアアーキテクチャのひとかけら
Atsushi Nakamura
世界一わかりやすいClean Architecture
世界一わかりやすいClean Architecture
Atsushi Nakamura
世界一わかりやすいClean Architecture - DroidKaigiバージョン
世界一わかりやすいClean Architecture - DroidKaigiバージョン
Atsushi Nakamura
C#メタプログラミング概略 in 2021
C#メタプログラミング概略 in 2021
Atsushi Nakamura
世界一わかりやすいClean Architecture alpha-1
世界一わかりやすいClean Architecture alpha-1
Atsushi Nakamura
Desktop app dev strategy for .net core 3.0
Desktop app dev strategy for .net core 3.0
Atsushi Nakamura
Test automation strategy for .net core 3 transition
Test automation strategy for .net core 3 transition
Tatsuya Ishikawa
デスクトップ向けUIコンポーネントの対応状況と今後の予定
デスクトップ向けUIコンポーネントの対応状況と今後の予定
インフラジスティックス・ジャパン株式会社
6万行の TypeScript 移行とその後
6万行の TypeScript 移行とその後
Shingo Sasaki
Settings SyncとCodespaceで体験する新世代へのパラダイムシフト
Settings SyncとCodespaceで体験する新世代へのパラダイムシフト
Atsushi Nakamura
Azureクラウドのネイティブアプリ、IoTとエッジAIの管理ソリューション
Azureクラウドのネイティブアプリ、IoTとエッジAIの管理ソリューション
Jingun Jung
『アプリケーション アーキテクチャ ガイド2.0』のガイド
『アプリケーション アーキテクチャ ガイド2.0』のガイド
Kentaro Inomata
IoT業界で必須サービスになってきたAzure Web PubSubとAzure IoT EdgeのEFLOWについてご紹介
IoT業界で必須サービスになってきたAzure Web PubSubとAzure IoT EdgeのEFLOWについてご紹介
Jingun Jung
Vision AI on Azure IoT Edge
Vision AI on Azure IoT Edge
Jingun Jung
Visual Studio 2019で始める「WPF on .NET Core 3.0」開発
Visual Studio 2019で始める「WPF on .NET Core 3.0」開発
Atsushi Nakamura
DDD Alliance レガシーなコードにドメイン駆動設計で立ち向かった5年間の軌跡
DDD Alliance レガシーなコードにドメイン駆動設計で立ち向かった5年間の軌跡
BIGLOBE Inc.
Adobe XD Plugin「Scenegraph」の操作とDialogの作り方
Adobe XD Plugin「Scenegraph」の操作とDialogの作り方
Yoshiki Takeoka
【de:code 2020】 Build 2020 最新情報 〜 Azure & Visual Studio & .NET 〜
【de:code 2020】 Build 2020 最新情報 〜 Azure & Visual Studio & .NET 〜
日本マイクロソフト株式会社
WeDX Flow Hands-on
WeDX Flow Hands-on
Jingun Jung
SIerで幸せな技術キャリアを築くために
SIerで幸せな技術キャリアを築くために
Takanari Konishi
Hacktoberfest 概要、Node-REDプロジェクト貢献手順
Hacktoberfest 概要、Node-REDプロジェクト貢献手順
Hitachi, Ltd. OSS Solution Center.
30分でできる!Adobe XDプラグイン開発!
30分でできる!Adobe XDプラグイン開発!
Yoshiki Takeoka
言語系サービスの統合ポータル Language Studio で Microsoft AI を再確認
言語系サービスの統合ポータル Language Studio で Microsoft AI を再確認
Yoshitaka Seo
Adobe XDプラグインをつくってみよう
Adobe XDプラグインをつくってみよう
Yoshiki Takeoka
DDD sample code explained in Java
DDD sample code explained in Java
増田 亨
お客様が望んでいるモダンデスクトップアプリとは?/傾向と対策 Part1
お客様が望んでいるモダンデスクトップアプリとは?/傾向と対策 Part1
インフラジスティックス・ジャパン株式会社
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
Fumiya Sakai
More Related Content
What's hot
Desktop app dev strategy for .net core 3.0
Desktop app dev strategy for .net core 3.0
Atsushi Nakamura
Test automation strategy for .net core 3 transition
Test automation strategy for .net core 3 transition
Tatsuya Ishikawa
デスクトップ向けUIコンポーネントの対応状況と今後の予定
デスクトップ向けUIコンポーネントの対応状況と今後の予定
インフラジスティックス・ジャパン株式会社
6万行の TypeScript 移行とその後
6万行の TypeScript 移行とその後
Shingo Sasaki
Settings SyncとCodespaceで体験する新世代へのパラダイムシフト
Settings SyncとCodespaceで体験する新世代へのパラダイムシフト
Atsushi Nakamura
Azureクラウドのネイティブアプリ、IoTとエッジAIの管理ソリューション
Azureクラウドのネイティブアプリ、IoTとエッジAIの管理ソリューション
Jingun Jung
『アプリケーション アーキテクチャ ガイド2.0』のガイド
『アプリケーション アーキテクチャ ガイド2.0』のガイド
Kentaro Inomata
IoT業界で必須サービスになってきたAzure Web PubSubとAzure IoT EdgeのEFLOWについてご紹介
IoT業界で必須サービスになってきたAzure Web PubSubとAzure IoT EdgeのEFLOWについてご紹介
Jingun Jung
Vision AI on Azure IoT Edge
Vision AI on Azure IoT Edge
Jingun Jung
Visual Studio 2019で始める「WPF on .NET Core 3.0」開発
Visual Studio 2019で始める「WPF on .NET Core 3.0」開発
Atsushi Nakamura
DDD Alliance レガシーなコードにドメイン駆動設計で立ち向かった5年間の軌跡
DDD Alliance レガシーなコードにドメイン駆動設計で立ち向かった5年間の軌跡
BIGLOBE Inc.
Adobe XD Plugin「Scenegraph」の操作とDialogの作り方
Adobe XD Plugin「Scenegraph」の操作とDialogの作り方
Yoshiki Takeoka
【de:code 2020】 Build 2020 最新情報 〜 Azure & Visual Studio & .NET 〜
【de:code 2020】 Build 2020 最新情報 〜 Azure & Visual Studio & .NET 〜
日本マイクロソフト株式会社
WeDX Flow Hands-on
WeDX Flow Hands-on
Jingun Jung
SIerで幸せな技術キャリアを築くために
SIerで幸せな技術キャリアを築くために
Takanari Konishi
Hacktoberfest 概要、Node-REDプロジェクト貢献手順
Hacktoberfest 概要、Node-REDプロジェクト貢献手順
Hitachi, Ltd. OSS Solution Center.
30分でできる!Adobe XDプラグイン開発!
30分でできる!Adobe XDプラグイン開発!
Yoshiki Takeoka
言語系サービスの統合ポータル Language Studio で Microsoft AI を再確認
言語系サービスの統合ポータル Language Studio で Microsoft AI を再確認
Yoshitaka Seo
Adobe XDプラグインをつくってみよう
Adobe XDプラグインをつくってみよう
Yoshiki Takeoka
DDD sample code explained in Java
DDD sample code explained in Java
増田 亨
What's hot
(20)
Desktop app dev strategy for .net core 3.0
Desktop app dev strategy for .net core 3.0
Test automation strategy for .net core 3 transition
Test automation strategy for .net core 3 transition
デスクトップ向けUIコンポーネントの対応状況と今後の予定
デスクトップ向けUIコンポーネントの対応状況と今後の予定
6万行の TypeScript 移行とその後
6万行の TypeScript 移行とその後
Settings SyncとCodespaceで体験する新世代へのパラダイムシフト
Settings SyncとCodespaceで体験する新世代へのパラダイムシフト
Azureクラウドのネイティブアプリ、IoTとエッジAIの管理ソリューション
Azureクラウドのネイティブアプリ、IoTとエッジAIの管理ソリューション
『アプリケーション アーキテクチャ ガイド2.0』のガイド
『アプリケーション アーキテクチャ ガイド2.0』のガイド
IoT業界で必須サービスになってきたAzure Web PubSubとAzure IoT EdgeのEFLOWについてご紹介
IoT業界で必須サービスになってきたAzure Web PubSubとAzure IoT EdgeのEFLOWについてご紹介
Vision AI on Azure IoT Edge
Vision AI on Azure IoT Edge
Visual Studio 2019で始める「WPF on .NET Core 3.0」開発
Visual Studio 2019で始める「WPF on .NET Core 3.0」開発
DDD Alliance レガシーなコードにドメイン駆動設計で立ち向かった5年間の軌跡
DDD Alliance レガシーなコードにドメイン駆動設計で立ち向かった5年間の軌跡
Adobe XD Plugin「Scenegraph」の操作とDialogの作り方
Adobe XD Plugin「Scenegraph」の操作とDialogの作り方
【de:code 2020】 Build 2020 最新情報 〜 Azure & Visual Studio & .NET 〜
【de:code 2020】 Build 2020 最新情報 〜 Azure & Visual Studio & .NET 〜
WeDX Flow Hands-on
WeDX Flow Hands-on
SIerで幸せな技術キャリアを築くために
SIerで幸せな技術キャリアを築くために
Hacktoberfest 概要、Node-REDプロジェクト貢献手順
Hacktoberfest 概要、Node-REDプロジェクト貢献手順
30分でできる!Adobe XDプラグイン開発!
30分でできる!Adobe XDプラグイン開発!
言語系サービスの統合ポータル Language Studio で Microsoft AI を再確認
言語系サービスの統合ポータル Language Studio で Microsoft AI を再確認
Adobe XDプラグインをつくってみよう
Adobe XDプラグインをつくってみよう
DDD sample code explained in Java
DDD sample code explained in Java
Similar to 継続的にテスト可能な設計を考える ベータ版
お客様が望んでいるモダンデスクトップアプリとは?/傾向と対策 Part1
お客様が望んでいるモダンデスクトップアプリとは?/傾向と対策 Part1
インフラジスティックス・ジャパン株式会社
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
Fumiya Sakai
Ms retail update ra 20191030
Ms retail update ra 20191030
Microsoft Azure Japan
JaSST2017_大規模業務システムにおける再利用可能なテスト自動化の取り組み
JaSST2017_大規模業務システムにおける再利用可能なテスト自動化の取り組み
Hideki Sugimoto
iOSやAndroidアプリ開発のGoodPractice
iOSやAndroidアプリ開発のGoodPractice
Ken Morishita
日立ソリューションズの取り組みとプラットフォーム関連セション内容のご紹介
日立ソリューションズの取り組みとプラットフォーム関連セション内容のご紹介
CASAREAL, Inc.
[Japan Tech summit 2017] DAL 006
[Japan Tech summit 2017] DAL 006
Microsoft Tech Summit 2017
ASP.NET MVC 2 ~新機能の紹介~
ASP.NET MVC 2 ~新機能の紹介~
Yoshitaka Seo
CodeIgniter 〜 2008年大躍進のPHPフレームワーク
CodeIgniter 〜 2008年大躍進のPHPフレームワーク
kenjis
システムのモダナイズ 落ちても良いアプリの作り方
システムのモダナイズ 落ちても良いアプリの作り方
Chihiro Ito
B13_株式会社資生堂 プロフェッショナル事業の日本とタイの基幹系業務を「 Microsoft Dynamics 365 」で統合管理 [Microsof...
B13_株式会社資生堂 プロフェッショナル事業の日本とタイの基幹系業務を「 Microsoft Dynamics 365 」で統合管理 [Microsof...
日本マイクロソフト株式会社
DeNA のデータ活用を支える BigQuery データの民主化とガバナンス強化の軌跡 | Google Cloud INSIDE Games & App...
DeNA のデータ活用を支える BigQuery データの民主化とガバナンス強化の軌跡 | Google Cloud INSIDE Games & App...
Google Cloud Platform - Japan
Intalio会社概要とbpmsの特長20100319
Intalio会社概要とbpmsの特長20100319
Tomoaki Sawada
SharePoint Business Connectivity Services を使用した外部アプリケーション連携
SharePoint Business Connectivity Services を使用した外部アプリケーション連携
Atsuo Yamasaki
ファーストアカウンティング会社説明資料 for engineer 2022年7月版
ファーストアカウンティング会社説明資料 for engineer 2022年7月版
ファーストアカウンティング 採用担当
Spring Fest 2017 「エンタープライズで利用するSpring Boot」#jsug #sf_h1
Spring Fest 2017 「エンタープライズで利用するSpring Boot」#jsug #sf_h1
Takeshi Hirosue
インタリオカンファレンス案内(修正版)3
インタリオカンファレンス案内(修正版)3
Tomoaki Sawada
ADO.NET Entity Framework
ADO.NET Entity Framework
Microsoft
そのデータ、活かせていますか?
そのデータ、活かせていますか?
Miho Yamamoto
【2018年3月時点】Oracle Data Visualizaion ご紹介
【2018年3月時点】Oracle Data Visualizaion ご紹介
オラクルエンジニア通信
Similar to 継続的にテスト可能な設計を考える ベータ版
(20)
お客様が望んでいるモダンデスクトップアプリとは?/傾向と対策 Part1
お客様が望んでいるモダンデスクトップアプリとは?/傾向と対策 Part1
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
Ms retail update ra 20191030
Ms retail update ra 20191030
JaSST2017_大規模業務システムにおける再利用可能なテスト自動化の取り組み
JaSST2017_大規模業務システムにおける再利用可能なテスト自動化の取り組み
iOSやAndroidアプリ開発のGoodPractice
iOSやAndroidアプリ開発のGoodPractice
日立ソリューションズの取り組みとプラットフォーム関連セション内容のご紹介
日立ソリューションズの取り組みとプラットフォーム関連セション内容のご紹介
[Japan Tech summit 2017] DAL 006
[Japan Tech summit 2017] DAL 006
ASP.NET MVC 2 ~新機能の紹介~
ASP.NET MVC 2 ~新機能の紹介~
CodeIgniter 〜 2008年大躍進のPHPフレームワーク
CodeIgniter 〜 2008年大躍進のPHPフレームワーク
システムのモダナイズ 落ちても良いアプリの作り方
システムのモダナイズ 落ちても良いアプリの作り方
B13_株式会社資生堂 プロフェッショナル事業の日本とタイの基幹系業務を「 Microsoft Dynamics 365 」で統合管理 [Microsof...
B13_株式会社資生堂 プロフェッショナル事業の日本とタイの基幹系業務を「 Microsoft Dynamics 365 」で統合管理 [Microsof...
DeNA のデータ活用を支える BigQuery データの民主化とガバナンス強化の軌跡 | Google Cloud INSIDE Games & App...
DeNA のデータ活用を支える BigQuery データの民主化とガバナンス強化の軌跡 | Google Cloud INSIDE Games & App...
Intalio会社概要とbpmsの特長20100319
Intalio会社概要とbpmsの特長20100319
SharePoint Business Connectivity Services を使用した外部アプリケーション連携
SharePoint Business Connectivity Services を使用した外部アプリケーション連携
ファーストアカウンティング会社説明資料 for engineer 2022年7月版
ファーストアカウンティング会社説明資料 for engineer 2022年7月版
Spring Fest 2017 「エンタープライズで利用するSpring Boot」#jsug #sf_h1
Spring Fest 2017 「エンタープライズで利用するSpring Boot」#jsug #sf_h1
インタリオカンファレンス案内(修正版)3
インタリオカンファレンス案内(修正版)3
ADO.NET Entity Framework
ADO.NET Entity Framework
そのデータ、活かせていますか?
そのデータ、活かせていますか?
【2018年3月時点】Oracle Data Visualizaion ご紹介
【2018年3月時点】Oracle Data Visualizaion ご紹介
More from Atsushi Nakamura
Unicodeで半角全角を扱うAmbiguous(曖昧さ)とUncertainty(不確実性)の恐怖
Unicodeで半角全角を扱うAmbiguous(曖昧さ)とUncertainty(不確実性)の恐怖
Atsushi Nakamura
世界一わかりやすいClean Architecture release-preview
世界一わかりやすいClean Architecture release-preview
Atsushi Nakamura
App center analyticsを使い倒そう
App center analyticsを使い倒そう
Atsushi Nakamura
Old:App center analyticsを使い倒そう
Old:App center analyticsを使い倒そう
Atsushi Nakamura
Xamarin.forms navigation overview
Xamarin.forms navigation overview
Atsushi Nakamura
App center analyticsを使い倒そう
App center analyticsを使い倒そう
Atsushi Nakamura
Blue monkey architecture overview
Blue monkey architecture overview
Atsushi Nakamura
Xamarin Dev days 2 xamarin.forms ja
Xamarin Dev days 2 xamarin.forms ja
Atsushi Nakamura
Why prism for xamarin.forms
Why prism for xamarin.forms
Atsushi Nakamura
Enterpriseから見たXamarinの可能性
Enterpriseから見たXamarinの可能性
Atsushi Nakamura
More from Atsushi Nakamura
(10)
Unicodeで半角全角を扱うAmbiguous(曖昧さ)とUncertainty(不確実性)の恐怖
Unicodeで半角全角を扱うAmbiguous(曖昧さ)とUncertainty(不確実性)の恐怖
世界一わかりやすいClean Architecture release-preview
世界一わかりやすいClean Architecture release-preview
App center analyticsを使い倒そう
App center analyticsを使い倒そう
Old:App center analyticsを使い倒そう
Old:App center analyticsを使い倒そう
Xamarin.forms navigation overview
Xamarin.forms navigation overview
App center analyticsを使い倒そう
App center analyticsを使い倒そう
Blue monkey architecture overview
Blue monkey architecture overview
Xamarin Dev days 2 xamarin.forms ja
Xamarin Dev days 2 xamarin.forms ja
Why prism for xamarin.forms
Why prism for xamarin.forms
Enterpriseから見たXamarinの可能性
Enterpriseから見たXamarinの可能性
継続的にテスト可能な設計を考える ベータ版
1.
継続的にテスト可能な設計を考える ContinuousTestable Design Atsushi Nakamura
2.
2018.10.12 時点で概ね固まった範囲を一旦公開します セッション選択の一助にご利用ください
3.
テスト書いてますか? Copyright 2017 @nuits_jp
Slide 3
4.
テストを維持し続けるのは難しい! Copyright 2017 @nuits_jp
Slide 4
5.
ContinuousTestable Design Today’s Goal
6.
Today’s Goal Slide 6Copyright
2017 @nuits_jp 継続的にテスト可能な設計を実現するには多くのエッセンスが必要です。 今日はそのうち、つぎの3つについてお話します。 1. 制御の流れと依存方向の分離 2. 依存方向の制御と、安定性と柔軟性の管理 3. 現実的なテスト戦略を考える(結論はこの場ではでない) 「継続的なテストの維持」に必要な一部のエッセンスですが、非常に重要なことです。
7.
ContinuousTestable Design Overview
8.
1. テスト不可のアプリからスタート 2. リファクタリングしつつ、継続的にテスト可能な設計を目指す 3.
テストの対象は「今回は」クラス単位を想定 Overview
9.
• 対象システムは次のような特徴をもちます • プロダクト別の総売上をCSV出力するコンソール
アプリを想定 • 同一のデータベースを他の機能からも利用している Overview Copyright 2017 @nuits_jp Slide 9 SQL Server 2017 AdventureWorks2017 Other Functions ※英語含む、対象コードへのマサカリは「そっと」 Pull Requestを投げるというソフト対応をお願いします https://github.com/nuitsjp/Continuous-Testable-Design
10.
ContinuousTestable Design プロダクト別 総売上
出力システム
11.
まずはコードを見てみよう Copyright 2017 @nuits_jp
Slide 11
12.
現在の構造
13.
現在の構造 クラス間が直接依存しており 上流のクラスの単体テストができない
14.
ControllerとBusinessLogicの関係 現在、ControllerとBusinessLogicの間には二つの依存関係がある •BusinessLogicの生成 •BusinessLogicの利用 Controllerをテスト ダブル(Mock・Stub・Fakeなど)を利用してテストできるよ うにリファクタリングする。 Copyright 2017
@nuits_jp Slide 14
15.
インターフェースの抽出 Copyright 2017 @nuits_jp
Slide 15
16.
インターフェースの抽出結果 Copyright 2017 @nuits_jp
Slide 16 ○ 利用箇所はインターフェース依存になった × 生成箇所に実装クラス依存が残っている
17.
No. 方式 代表的なデザインパターン 1
Controllerが能動的に取得する Service Locator パターン 2 Controllerに外部から注入する Dependency Injection パターン インスタンス生成を取り除く二つの方式 Copyright 2017 @nuits_jp Slide 17 基本的にいずれかに類似した方式をとります。 ここでは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へ依存が増える
18.
Business Logicをインジェクションする Copyright 2017
@nuits_jp Slide 18
19.
Dependency Injectionの適用結果 Copyright 2017
@nuits_jp Slide 19 var controller = new Controller( new BusinessLogic()); controller.Execute("output.csv");
20.
テスト ダブルの利用 Copyright 2017
@nuits_jp Slide 20 var controller = new Controller( newTestDouble()); controller.Execute("output.csv");
21.
さあ、すべてテスタブルに修正しましょう! Copyright 2017 @nuits_jp
Slide 21
22.
しました! Copyright 2017 @nuits_jp
Slide 22
23.
結果、こんな感じでテストできます Copyright 2017 @nuits_jp
Slide 23 単体テスト用DB class Testable Models Repositoryの単体テスト BusinessLogicの単体テスト Controllerの単体テスト Controller «interface» IBusinessLogic BusinessLogic «interface» IRepository Repository ControllerFixture BusinessLogicMock BusinessLogicFixture RepositoryFixture RepositoryMock
24.
ところで、よく見ると Copyright 2017 @nuits_jp
Slide 24
25.
なんか嫌な臭いがするぞ? Copyright 2017 @nuits_jp
Slide 25
26.
特にこのあたりが... Copyright 2017 @nuits_jp
Slide 26 ここの向き
27.
良く見てみよう ControllerがViewに、依存している 一般的にViewは最も変化が多い ⇒ ControllerはViewに引きずられ変更過多になる ⇒ 結果、Controllerのテストコードもテストダブルも変更過多になる ⇒つらい Copyright
2017 @nuits_jp Slide 27
28.
もうひとつ Copyright 2017 @nuits_jp
Slide 28
29.
ここもちょっとな... Copyright 2017 @nuits_jp
Slide 29 ここの向き
30.
• 同一のデータベースを他の機能からも利用している • データベースは他システム起因で変更が入る •
そもそもデータが安定的だというのは過去の神話で ビジネスの変遷の早い現在は、データも安定的ではなくなっている あらためて全体像を確認する Copyright 2017 @nuits_jp Slide 30 SQL Server 2017 AdventureWorks2017 Other Functions
31.
class Testable Models Repositoryの単体テスト BusinessLogicの単体テスト Controllerの単体テスト Controller
«interface» IBusinessLogic BusinessLogic «interface» IRepository Repository ControllerFixture BusinessLogicMock BusinessLogicFixture RepositoryFixture RepositoryMock つまり参照してるテーブルが変更されると… Copyright 2017 @nuits_jp Slide 31 単体テスト用DB Breaking Change! Breaking Change! Breaking Change! Breaking Change! Breaking Change! Breaking Change! Breaking Change! Breaking Change! Breaking Change! Breaking Change! Breaking Change!
32.
最悪だ!! Copyright 2017 @nuits_jp
Slide 32
33.
何が悪いのか? Copyright 2017 @nuits_jp
Slide 33 class BusinessLogic and Repository BusinessLogics Repositories BusinessLogic «interface» IRepository Repository 制御の流れに 引きずられて 安定させたい モジュール 不安定な モジュール 依存して しまっている
34.
解決策 Copyright 2017 @nuits_jp
Slide 34 class BusinessLogic and Repository BusinessLogics Repositories BusinessLogic «interface» IRepository Repository 制御の流れから 依存方向を分離し 逆方向へ依存させる
35.
できます! Copyright 2017 @nuits_jp
Slide 35
36.
こうする! 重要なのは、インターフェースの移動ではなく IRepositoryをBusinessLogicの文脈で定義すること Copyright 2017 @nuits_jp
Slide 36 class BusinessLogic and Repository BusinessLogics Repositories BusinessLogic «interface» IRepository Repository class BusinessLogic and Repository BusinessLogics Repositories BusinessLogic «interface» IRepository Repository Before After
37.
IRepositoryの詳細を見てみましょう Copyright 2017 @nuits_jp
Slide 37
38.
IRepositoryのクラス図とER図 Copyright 2017 @nuits_jp
Slide 38 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が完全にデータベースの文脈で記述されているのが見て取れる
39.
BusinessLogicのインターフェースと比較する Copyright 2017 @nuits_jp
Slide 39 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
40.
IRepositoryをBusinessLogicの文脈へリファクタリング Copyright 2017 @nuits_jp
Slide 40
41.
リファクタリング後のIRepository Copyright 2017 @nuits_jp
Slide 41 dm Repositories ProductName «property» + Name(): string + ProductId(): int? SalesLineTotal «property» + LineTotal(): double + ProductId(): int «interface» IRepository + GetProductNames(): IEnumerable<ProductName> + GetSalesLineTotal(): IEnumerable<SalesLineTotal>
42.
一旦整理しましょう Copyright 2017 @nuits_jp
Slide 42
43.
「制御の流れ」と「依存方向」は、つぎの二つによりコントロール可能 • クラスとクラスは直接依存させず、インターフェース(抽象)に依 存させる(依存性逆転の原則) • インターフェースを適切な文脈で定義する 「制御の流れ」と「依存方向」 Copyright
2017 @nuits_jp Slide 43
44.
class BusinessLogics and
Re... Repositories BusinessLogics BusinessLogic «interface» IRepository Repository 依存方向によって決まる、安定性と柔軟性 Copyright 2017 @nuits_jp Slide 44 Repository変更の影響を受けない ⇒ 安定性が高い 変更がRepositoryへ影響を与える ⇒ 柔軟性が低い BusinessLogic変更の影響を受ける ⇒ 安定性が低い 変更がBusinessLogicへ影響を与えない ⇒ 柔軟性が高い 安定性と柔軟性は設計上トレードオフにある
45.
あらためて全体を見てみる Copyright 2017 @nuits_jp
Slide 45
46.
元々の安定度と柔軟性 Copyright 2017 @nuits_jp
Slide 46 凡例 制御の流れ 依存関係 安定性③ 柔軟性① 安定性① 柔軟性② 安定性② 柔軟性② 安定性① 柔軟性③
47.
安定性と柔軟性 パッケージ 安定度:高 BusinessLogic 中間
Controller 柔軟性:高 View, Repository 安定性と柔軟性をコントロールする Copyright 2017 @nuits_jp Slide 47
48.
安定度と柔軟性をコントロールする Copyright 2017 @nuits_jp
Slide 48 凡例 制御の流れ 依存関係 安定性② 柔軟性② 安定性③ 柔軟性① 安定性① 柔軟性③ 安定性② 柔軟性①
49.
継続的にテスト可能になった(はず)のクラス図
50.
すべてのクラスを同じレベルでテストしますか? Copyright 2017 @nuits_jp
Slide 50
51.
To be continued ContinuousTestable
Design
Editor's Notes
みなさんこんにちは。 ご紹介いただきました。ニュイこと中村です。 今日は 継続的にテスト可能な設計を考える というTitleでお話しさせていただこうと思います。 よろしくお願いいたします。
ところで皆さん、日常的に自動テスト書いてますか? 私は結構書いてます。 SIerのテストというと、Excel!スクショ!エビデンス!的なイメージがあるかも知れませんが たまたま巡り合わせが良くて、2000年からJUnitを触っていたと思います。 SIerって、プロダクトチームの維持が難しくて、半年ごとに8割のメンバーが入れ替わってる みたいな地獄みたいな事が良くあるので、自動テストが無いと怖くて生きていけない というのが、私のテストのモチベーションなんだと思います。 ただ、テストを書くのは良いんですが、本当に難しいのはプロダクトの改修に追随して テストを維持していくことだと、私は思っています。
テストを維持し続けるのは本当に難しいです。 プロジェクトのスケジュールが厳しくなると、すぐ悪魔が囁き始めますし テストを維持する事自体が、ソフトウェアの変更を阻害するようなこともあります。 実際に、テストをいくらか破棄して泣く泣く規模を縮小したりしたこともあります。
という訳で、本日のゴールです。
今日は、そういった茨の道で試行錯誤してきたベストプラクティスの中から 特に大切だと思っている、三つのエッセンスについてお話ししたいと思います。
このセッションの概要ですが
実際のコードを見ながら、最初はテスト不可能なコードからスタートして リファクタリングしながら、継続的にテスト可能な設計を目指したいと思います。 なお、テストの対象は今回はクラス単位のテストをする前提とさせていただきます。
実際の例に用いるプログラムですが、SQL ServerのサンプルDBのAdventureWorksを 利用させてもらって、プロダクト別の総売上をCSV出力するような コンソールアプリを想定します。 そのアプリから利用するデータベースは、同一システムの別機能からも利用されるものとします。 コードはこちらのURLに公開しています。 なおコードや、コードの英語に不備不満のある方は、そっとプルリクを送っていただけると助かります。 まえに「その単語、不可算名詞だからsつくのおかしくね?」みたいなマサカリをぶん投げてきた人がいるんですが なるべく、そっとやさしくお願いします。 今日は強そうな人が多いので、重々よろしくお願いいたします。
では早速、本題に入りたいと思います。
まずはコードを見てください。
さて、今見ていただいたコードですが クラス図に落とすと、こんな感じです。 今日のテスト対象はクラスですから
① さて、今見ていただいたコードですが クラス図に落とすと、こんな感じです。 今日のテスト対象はクラスですから ② この辺のクラス間が直接依存してるせいで 上流のクラスが単体テストできない状態になっています。
例えばControllerとBusinessLogicの関係の詳細を見てみると その二つの間には、オブジェクトの生成と利用という2種類の依存関係があります。 これらが、Controllerをテストダブルを利用して単体テストすることを阻んでいます。 という訳で、これらのクラス間の直接的な依存関係を取り除いていきます。
まずはインターフェースを抽出します。 ここからは、またコードに戻ります。
さて、こうしたことで、BusinessLogicを利用している箇所の依存関係は クラスからインターフェース移すことができました。 ただし、インスタンスを生成する個所に依存がまだ残っています。
インスタンス生成の依存関係を取り除くには、基本的にはインスタンスの生成を つぎの二つの何れかの方法で解決する必要があります。 一つはControllerが能動的に、インスタンスをいずれかのレジストリーに取得しに行く方法。 もう一つは依存オブジェクトをControllerの外から、誰かに注入してもらう方法です。 それぞれ代表的な実現方法として、ServiceLocatorパターンとDependency Injectionパターンがあります。 今回はDependency Injectionパターン、つまりDIを利用します。 なぜDIを利用するかは、ざっくりいうと、ServiceLocatorには大きな問題が二つあって 一つはテストをマルチスレッドで実装しにくいということと ServiceLocatorパターンにするとBusinessLogicへの依存は減るけど、ServiceLocator への依存が増えて、依存数が減らないという欠点があるためです。
という訳でBusinessLogicをインジェクションするように修正します。
というわけで、無事にControllerからインスタンス生成のロジックも除去出来て 完全にクラス間の依存関係を無くせました。
こうする事で、簡単にBusinessLogicをテストダブルに置き換えが可能になって テスタブルになります。 ちなみにDIパターンとDIコンテナが混同されているケースがありますが DIコンテナはあくまでDIパターンを便利に実現するためのツールなので 必ずしも使わなくてもDIパターンは実現できます。普通は使いますけど。
では他の部分もテスタブルにしましょう!
はいできました!すいません、時間がないので3分間クッキング方式を 取らせていただきます。 Controller、View、BusinessLogic、Repositoryの全てに インターフェースを導出し、DIを適用します。 こうする事で
こんな感じで、全てのクラスにたいしてクラス単位のテストが実施できるようになりました。
ところでこのクラス図
良く見ると不吉なにおいがしますね?
特にこの、ControllerとViewの間です。
①ControllerがViewに依存している部分です。 ②一般的にViewは最も変化が多いと言われていますよね。 それが正しいとすると ③Viewに依存しているControllerはViewに引きずられて 頻繁に変更する必要がでてきます ④結果、プロダクションコードだけでなく、テストコードもテストダブルも 頻繁に変更しなくてはならなくなります ⑤これは辛いです
そしてもう一つ 個人的にはこっちの方が嫌な予感がします。
このBusinessLogicがRepositoryに依存しているところです。
最初にお話しした通り、このシステムで利用するデータベースは 他の機能からも利用されます。 ということは、このシステムではない、別の機能起因で変更が入る可能性があります。 そもそもデータが安定的であるというのも、私は懐疑的です。 現代において企業は、顧客に対して新しい価値を次々提供し続けなくてはなりません。 新しい価値を提供するためには、往々にして新しいデータが発生します。 データの取り扱いが無くなる事は少なくても、追加変更はそれなりに発生するのが現実だと 私は思っています。
①つまり、何らかの要因で参照しているテーブルに変更が発生すると ②リポジトリが変更されます ③当然そうなるとテストケースの修正が入って ④高い確率でリポジトリのインターフェースが変更されます ⑤するとビジネスロジックが影響を受けて ⑥リポジトリのモックとビジネスロジックのテストががががが 全部なおさなきゃ!
最悪だ!と、なってしまうかもしれないです。 実際稀に良くありますし。
つまり何が悪いかというと ①安定させたいビジネスロジックが ②不安定なモジュールにたいして ③制御の流れが原因で引きずられて ④依存してしまっているのが、この問題の根幹にあります これを解決するには
制御の流れから依存方向を分離して ①逆方向に依存させれば解決できます
もちろん実現可能です
具体的には、今こうなっているのを ①こうします。重要なのは、インターフェースを移動することではなくて ②リポジトリをビジネスロジックの文脈で定義することです
リポジトリの詳細を見てみましょう
現在の実装は、リポジトリが完全にデータベースの文脈で記述されているのが見て取れます。
しかし、ビジネスロジックで実現したいのは、プロダクト別の総売上額です。 ①つまりビジネスロジックに必要なのはこの4項目だけです。
という訳で、リポジトリインターフェースを ビジネスロジックの文脈へリファクタリングします
結果、こうなりました。 データベースの詳細が隠蔽されているのが 分かるかと思います。
一旦整理しましょう。
制御の流れと、依存方向は、必ずしも一致させる必要はありません。 クラスとクラスの直接依存を避けて、インターフェースを定義し、疎結合にした上で インターフェースを依存させたい側の文脈で定義することで 依存方向は制御の流れから分離して、自由にコントロールできます。
そして、依存方向によって安定性と柔軟性が変化します。 リポジトリインターフェースは、ビジネスロジックの文脈で記述されています。 ①つまり、データベースの影響を受けにくく、安定性が高くなります。 しかし逆にいうと、ビジネスロジックを変更すると、リポジトリの実装が影響を受ける可能性があるため ビジネスロジックの柔軟性は低くなります。 ②逆にリポジトリの実装はビジネスロジックの変更の影響を受ける為、安定性は低くなります。 しかし、リポジトリの変更はビジネスロジックへ影響を与えにくいため、変更しやすく、柔軟性が高いといえます。 ③つまり、安定性と柔軟性は設計上のトレードオフにあるわけです。
あらためて全体を見てみましょう。
クラスを書くと煩雑なので、パッケージだけ記述しました。 最初の設計では制御の流れと依存関係が一致していたため それぞれのパッケージの安定性と柔軟性は、この図のような 状態にあります。 ビューとリポジトリが一番安定している。つまり変更しに状態にあり それらを修正すると、システム全体への影響が大きい状態に なってしまっています。
実際には安定性と柔軟性は、だいたいこんな感じにしたいとします。 ビジネスロジックを最も安定させ ビューとレポジトリーは柔軟性を高めたい、つまり変更しやすくしたいとします。
その為にはコントローラーとビュー、ビジネスロジックとリポジトリの間の 依存関係を逆転してあげれば、望む通りの安定性と柔軟性を 得ることができるわけです。
これで変更を受けやすい部分の柔軟性が高くなり、それ以外への影響が およびにくくなりました。 つまり、テストコードへの影響も局所化できて、継続的にテストをしやすい状態に なったはずです。 なったんですが、そこで疑問が発生します。
全部テストできるからと、すべてのクラスを同じレベルでテストする必要があるんでしょうか?
以上で私の発表を終わります。 ご清聴ありがとうございました。
Download now