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.
© Copyright 2024 ExpyDoc