コンポーネントの設計 - Microsoft

T1-404
保守で苦労しない
.NET アセンブリを作るには?
マイクロソフト株式会社
エンタープライズ プラットフォーム本部
エバンジェリスト
中原 幹雄
本セッションの範囲
“コンポーネントの設計”という観点から、
保守性を考慮した .NET アセンブリの設計に
ついてお話します
開発手法・プロセスやシステム・アプリケーション
全体の設計には触れず、コンポーネント設計の
みにフォーカス
本セッションの範囲外の内容:
ソフトウェア・プロダクトライン、アジャイル開発、
テスト駆動開発、Software Factories、MDA、
DSL、アスペクト指向、サブジェクト指向、SOA、
マルチパラダイム デザイン、DI コンテナ、…
何故保守性なのか?
システムは開発期間よりその後の運用期間
や機能拡張、すなわち保守期間の方が圧倒
的に長い
開発生産性も大切だが、保守性も大切
保守性を考慮した設計は、拡張性、再利用性
あるいはテスト容易性など、その他の内部品
質特性との関連性が強い
内部品質の向上に繋がる
何故コンポーネントの設計
なのか?
.NET において、コンポーネント (=アセンブ
リ) はアプリケーションを構築する上での基本
単位
アプリケーションは複数のコンポーネントに分割
され、構築される
アーキテクチャの設計は重要だが、その前提
としてコンポーネント レベルでしっかりと設
計・実装できることが大切
コンポーネント設計の本質的な部分の重要
性は、開発技術が進化しても変わらない
本セッションの用語を整理
プログラム
コンポーネント
モジュール
モジュール
要素
要素
要素
モジュール
コンポーネント
コンポーネント
複数のモジュールをパッケージ化した単位。
配置やバージョン管理の基本単位となる。
UML のコンポーネント図に対応。
.NET では“アセンブリ”と呼ばれ、主に DLL
や EXE として構築される。(アセンブリ=コンポ
ーネント)
プログラムのコンパイル可能な最小単位。
プログラム要素である型 (クラスや構造体) やサ
ブルーチンを含む。
.NET では拡張子 “.netmodule”。
しかしあまり使用されないため、モジュール=ア
センブリとなるケースが殆ど。
Agenda
コンポーネントの保守性向上について
.NET の特徴を考慮したコンポーネント設計
コンポーネントの
保守性向上について
チーム開発による保守性向上アプローチ
設計による保守性向上アプローチ
チーム開発による
保守性向上アプローチ
開発作業・開発する環境において、成果物の
作成・管理方法によって保守性を高める
コーディング規約
コーディング スタイルと命名規則を標準し、ソースコー
ドの記述感を統一
テストの自動化
モジュール変更時の回帰テストのコストを軽減
バージョン管理システム
ソースコード ファイルの世代管理のコストを軽減
設計による
保守性向上アプローチ
凝集性と結合性
オブジェクト指向設計の原則
オブジェクト指向設計パターン
凝集性 (Cohesion)
モジュールに対してどれだけ関連する特性
(データと処理) が集中しているか?
尺度: 低い ⇔ 高い
凝集性は高いこと (高凝集) が望ましい
関連する特性がモジュールに集中
⇒ モジュールの“責務”が明確化
“機能”の観点から見た変更・修正時の修正箇所
が特定のモジュールに局所化され易い
⇒ 保守性が高くなる
凝集性: イメージ
特性が複数の
モジュールに分散
低凝集
モジュール
モジュール
モジュール
特性 X
特性 Z
特性 Y
高凝集
特性がモジュー
ルに集中
モジュール
モジュール
モジュール
特性 X
特性 Y
特性 Z
結合性 (Coupling)
モジュールとモジュールの間に関連性がどれ
だけあるのか?
尺度: 疎 (弱い) ⇔ 密 (強い)
結合性は疎であること (疎結合) が望ましい
モジュール間の不要な関連性を少なくする
⇒ モジュールの独立性が高くなる
モジュール修正に対する影響範囲が最小化され
易い
⇒ モジュールの再利用性が高い
さらにモジュールの凝集性が高い場合、相乗的に保
守性が高くなる
結合性: イメージ
密結合
実装詳細に依存し、実装詳細
の変更の影響を受ける
モジュール
モジュール
実装詳細
疎結合
お互いに依存関係があり、
独立して存在できない
モジュール
インターフェイス
モジュール
実装詳細
インターフェイスのみ
に依存し、実装詳細の
変更の影響を受け難
い
オブジェクト指向設計の原則
オブジェクトやコンポーネントを設計する際に
考慮すべき基本原則
既知の設計問題を回避するための“すべし”と
“すべからず”
保守性、拡張性、再利用性
パターンの本質は、この原則を守るためのもの
Robert C. Martin の原則
オブジェクト設計の原則
コンポーネント設計の原則
オブジェクト設計の原則
原則名
要約
単一責務の原則: SRP
クラスを変更する理由は、1 つ以上存
在してはならない。
Single Responsibility Principle
開放・閉鎖の原則: OCP
Open-Closed Princilpe
リスコフの置換原則: LSP
Liskov Substitution Principle
依存関係逆転の原則: DIP
Dependency Inversion Principle
インターフェイス分離の原則: ISP
Interface Segregation Principle
クラスは拡張に対して開いていて、変
更に対して閉じていなければならない。
派生クラスは、その基底クラスと置換
可能でなければならない。
上位モジュールは下位モジュールに依
存してはならない。どちらも“抽象”に
依存すべきである。
“抽象”は実装の詳細に依存してはな
らない。実装の詳細が“抽象に”依存
すべきである。
クライアントに、クライアントが利用しな
いメソッドへの依存を強制してはならな
い。
典型的な原則違反例
Client
class Service {
void Foo() { // … }
依存関係逆転の原則
void Bar() { // … }
に違反
}
class Client {
開放・閉鎖の原則
public void Hoge() { に違反
Service service = new Service();
service.Foo();
}
}
Service
インターフェイス分離の原則
に違反
典型的な原則準拠例
Client
<<interface>>
ClientInterface
interface ClientInterface {
void Foo();
}
class Service : ClientInterface {
public void Foo() { // … }
public voic Bar() { // … }
}
class Client {
public void Hoge( ClientInterface service ) {
service.Foo();
}
}
Service
コンポーネント設計の原則
原則名
要約
再利用・リリース原則: REP
コンポーネントの再利用の単位とリ
リースの単位は、等価になる。
Reuse-Release Equivalency Principle
全再利用の原則: CRP
Common Reuse Princilpe
閉鎖性共通の原則: CCP
Common Closure Principle
非循環依存関係の原則: ADP
Acyclic Dependencies Principle
安定依存の原則: SDP
Stable Dependencies Principle
安定度・抽象度等価の原則: SAP
Stable Abstractions Principle
コンポーネントに含まれるクラスは、
すべて一緒に再利用される。
コンポーネントに含まれるクラスは、
みな同じ種類の変更に対して閉じ
ているべきである。
コンポーネントの依存グラフは循環
してはならない。
コンポーネントは安定する方向に依
存すべきである。
コンポーネントの抽象度と安定度と
は同程度でなければならない。
安定性: イメージ
安定したコンポーネント
コンポーネント
自身が依存するコ
ンポーネントがな
い
=独立している
コンポーネント
コンポーネント
不安定なコンポーネント
複数のコンポーネ
ントに依存している
=依存している
コンポーネント
コンポーネント
コンポーネント
コンポーネント
複数のコンポーネン
トから依存されてい
る =責任を負ってい
る
自身に依存している
コンポーネントがな
い
=責任を負わない
コンポーネント
安定性を考慮しない依存関係
B
A
C
不安定
不安定
不安定
X
不安定
安定
Y
不安定
安定しているコンポーネントが
、不安定なコンポーネントに依
存してしまっている!
安定性を考慮した依存関係
B
A
C
不安定
不安定
不安定
X
安定
Y Interfaces
<<interface>>
Y_Interface
安定
Y Implements
Y_Implement
不安定
オブジェクト指向設計パターン
Craig Larman のパターン
GRASP※1
オブジェクトに対する責務の割り当て方の基本方針と
なるパターン
主に分析・モデリング時に適用する
GoF※2 のデザインパターン
最もメジャーなオブジェクト指向の実装パターン
※1 GRASP=General Responsibility Assignment Software Patterns
※2 GoF=Gang of Four
GRASP
General Responsibility Assignment Software Patterns
パターン名
要約
情報エキスパート
オブジェクトに責務を割り当てる際の最も基本と
なるパターン。
Information Expert
生成者
Creator
高凝集性
High Cohesion
疎結合性
Low Coupling
コントローラ
Controller
クラスのインスタンスを生成する責務の割り当て
に関するパターン。
複雑さを制御しやすくする、すなわち保守性を高
めるためのパターン。
オブジェクト間の依存性を弱め、変更による影響
を小さくし、再利用性を高めるためのパターン。
システムイベント (ユースケースなど) を処理する
責務の割り当てに関するパターン。
GRASP
General Responsibility Assignment Software Patterns
パターン名
要約
間接化
疎結合性を維持するためのパターン。
Indirection
多態性
Polymorphism
純粋架空物 (でっちあげ)
Pure Fabrication
バリエーション防護
Protected Variations
クラスによって変化する選択肢を処理、またプラ
グイン可能なプログラムを作成するためのパター
ン。
情報エキスパート パターンによって抽出されたオ
ブジェクトが、高凝集性と疎結合性、あるいは他
の観点から見て適切でない場合の責務の割り当
てパターン。
変化しやすく不安定な要素が、他の要素に影響
を与えないようにするためのパターン。
GoF のデザインパターン
生成に関するパターン
Abstract Factory
Builder
Factory Method
.NET では ICloneable の実装
Prototype
Singleton
GoF のデザインパターン
構造に関するパターン
Adapter
Bridge
Composite
Decorator
Façade
Flyweight
Proxy
Template Method
GoF のデザインパターン
振る舞いに関するパターン
Chain Of Responsibility
単純な場合は、デリゲート構文
Command
Interpreter
IEnumerator / IEnumerable の実装と foreach 文
Iterator
C# 2.0 では yield return 文による“イテレータ構文”
をサポート
Mediator
Memento
イベント構文
Observer
State
Strategy
Visitor
コンポーネント設計における
注意点
100%変更不要なコンポーネントを作成する
ことは不可能
いくら設計原則を遵守しパターンを適用しても、
将来の“変化”を100%予測することはできない
設計原則を理解した上での妥協も必要
パターンは適度に活用する
乱用すると、返って複雑なプログラムになってし
まい、保守性が低下する恐れがある
リファクタリングすることも視野に
.NET の特徴を考慮した
コンポーネント設計
.NET アセンブリの特徴
.NET 2.0 の新機能
バージョニングについて
.NET アセンブリの特徴
配布とバージョン管理の単位
メタデータで自己情報を公開
依存するアセンブリ
保有する型情報
バージョン情報
署名機能
強固な一意性の保証、改竄を防止
SxS (Side-by-Side) 実行機能
同一アセンブリの複数バージョンが同居可能
“Step out of DLL hell”
Partial Type: .NET 2.0 新機能
1つのクラスを物理的に複数のファイルに分
離して実装できる機能
主にツールが自動生成するコードと開発者の記
述コードを分離するために使用
クラスの機能追加の差分管理に使用可能
コンパイラ
複数のファイルの内容が
合成されコンパイル
アセンブリ
// MyClass.1.cs
class MyClass
{
void Foo() { … }
}
// MyClass.2.cs
class MyClass
{
void Bar() { … }
}
.class MyClass
{
.method instance void Foo() cil managed
{…}
.method instance void Bar() cil managed
{…}
}
Partial Type による差分管理
Ver 2.0
<<Partial>>
MyClass
(Ver 2.0差分)
Ver 1.1
<<Partial>>
MyClass
(Ver 1.1差分)
<<Partial>>
MyClass
(Ver 1.1差分)
<<Partial>>
MyClass
(Ver 1.0)
<<Partial>>
MyClass
(Ver 1.0)
Ver 1.0
<<Partial>>
MyClass
(Ver 1.0)
バージョニングについて
.NET アセンブリのバージョニングについての
考察
バージョン関連属性の活用
SxS 実行機能の考察
バージョン関連属性の活用
バージョン関連属性
AssemblyVersion 属性
CLR が識別するバージョンを表記
CLR メタデータ
SxS など、CLR のバージョン管理に影響
AssemblyFileVersion 属性
アセンブリ ファイルのバージョンを表記
Win32 リソース
AssemblyInformationVersion 属性
アセンブリを含む製品のバージョンを表記
Win32 リソース
バージョン関連属性の活用
あくまで1つの案ですが…
バージョンアップの種類に合わせ、各種バーション
関連属性をうまく活用し、バージョンを管理
Assembly
Version
Assembly
File
Version
Assembly
Information
Version
バグフィックス
―
R
―
後方互換のある機能追加
R
B、R
B、R
後方互換のない機能追加
B、R
Ma、Mi
Ma、Mi
Ma、Mi
―
―
バージョンポリシーが必要
対象 CLR のバージョンアップ
バージョン番号 = {major}.{minor}.{build}.{revision}
Ma
Mi
B
R
SxS 実行機能の考察
極力プログラム実行の基点となるアセンブリ、
すなわち EXE を軸にバージョニングする
バージョニング境界
EXE
EXE
DLL
DLL
バージョニング境界
DLL
DLL
DLL
DLL
バージョニング境界
EXE
DLL
DLL
CLR v2.0
DLL
DLL
DLL
DLL
SxS 実行機能の考察
共有 DLL 群も別にバージョニングする
SxS 境界
SxS 境界
バージョニング境界
バージョニング境界
バージョンアップ
EXE
EXE
バージョニング境界
v1.0.0.0
DLL
DLL
v1.0.1.0
DLL
DLL
DLL
DLL
DLL
DLL
DLL
CLR v2.0
DLL
DLL
DLL
SxS 実行機能の考察
CLR のバージョンも絡む SxS
SxS 境界
SxS 境界
バージョニング境界
EXE
CLR に合わせて
バージョンアップ
バージョニング境界
For v2.0
DLL
DLL
CRL v2.0
EXE
For v3.0
DLL
DLL
バージョニング境界
DLL
DLL
DLL
DLL
DLL
CRL v2.0
DLL
CLR v3.0
DLL
DLL
SxS 実行機能の考察
注意点
アプリケーション間の通信、特にバイナリ ベース
の通信 (.NET Remoting など) は、異なるバー
ジョンの CLR 間で互換性がない場合がある
通信箇所はサービスインターフェイスやサービス エー
ジェントでラップし、影響範囲を最小化
同一 CLR バージョンにおいても、転送するオブ
ジェクトのバージョンがアプリケーション間で異な
ると SxS できない
通信に関わる箇所は安易に SxS しない
シリアライズに関わる箇所の SxS は要注意
Summary
保守で苦労しない
.NET アセンブリを作るには?
残念ながら“特効薬”は存在しない…
コンポーネント設計の基本と原則の理解
設計パターンの活用
.NET アセンブリの特徴を理解し、.NET にお
けるコンポーネント開発技術を活用
コンポーネント設計の本質を知ることは、アプ
リケーション アーキテクチャの構築の助けと
なり、また最新開発技術の本質を理解するこ
とにも繋がります
Appendix
参考書籍 ①
『オブジェクト指向入門』
Bertrand Meyer 原著
ISBN 4-7561-0050-3、ASCII出版局 [絶版]
『アジャイルソフトウェア開発の奥義』
Robert C. Martin 原著
ISBN 4-7973-2336-1、ソフトバンク パブリッシング
『オブジェクト指向における再利用のための デザインパターン』
Erich Gamma、Richard Helm、
Ralph Johnson、John Vlissides 原著 (GoF)
ISBN 4-7973-1112-6、ソフトバンク パブリッシング
参考書籍 ②
『実践 UML パターンによる統一プロセスガイド 第2版』
Craig Larman 原著
ISBN 4-89471-386-1、ピアソン エデュケーション
『リファクタリング プログラムの体質改善テクニック』
Martin Fowler 原著
ISBN 4-89471-228-8、ピアソン エデュケーション
『CODE COMPLETE 第2版』 上・下巻
Steve McConnel 原著
ISBN 4-89100-455-X、 ISBN 4-89100-456-8
日経BPソフトプレス
参考書籍 ③
『プログラミング Microsoft .NET Framework』
Jeffrey Richter 原著
ISBN 4-89100-303-0、日経BPソフトプレス
『Essential .NET 共通言語ランタイムの本質』
Don Box、Chris Sells 原著
ISBN 4-89100-368-5、日経BPソフトプレス
© 2005 Microsoft Corporation. All rights reserved.
This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.