オブジェクト指向設計の原則NPO アイネタ・ジャパン 理事日本XPユーザ会 運営メンバー小井土 亨
自己紹介仕事パッケージベンダーで、パッケージを開発具体的な作業内容開発のガイドラインを作る開発プロセスを設計する開発プロセスを支える環境を構築し、運用する各種ツールの選択や開発ビルド環境の整備、各種管理ツールの整備ソフトウェア・アーキテクチャの決定する基盤フレームワークの設計と実装基盤の共通ライブラリの設計と実装開発上のいろいろな相談を受ける今日の目的オブジェクト指向における設計の基本原則やデザインパターンなどについて、良い設計という観点で議論したいと思います特に、アーキテクチャと設計の関係について、会場のみなさんと考えたいと思います2
本日のアジェンダ3
ソフトウェア開発とはソフトウェア開発の本質解決すべき問題をより単純な問題に分割する分割した問題に解法を適応する解法を適応したものを組み立てる4
設計に関する質問要求を完全に理解できたとした場合、設計結果は同じとなる?Yes /No5
設計に関する質問機能仕様が同じ場合、設計は、だれが行っても同じ結果となる?Yes /No6
設計に関する質問去年の自分と今年の自分が同じ仕様に対して設計したら、同じ結果となる?Yes /No7
設計とは設計の本質要求、分析の結果をどのように実現するかを解決させる活動設計は、問題を解く作業なので、唯一の正解はなく、あるのは最適解設計の基本分析の全ての機能を正しく実現するソフトウェアの完全な姿を提供すべきである設計結果は、ドキュメントとして提供されることが多いドキュメントベースのコミュニケーション設計結果を利用する人が読みやすく理解しやすい8
設計の目的9
悪い設計良い設計10
設計の難しさ11
心がけていること12
設計の原則プログラムをモジュールに分割する分割することで、プログラムが複雑になるのを避けるモジュール間の依存関係を明確にするモジュール間の結合度が低いモジュール間の結合度が低いほうが良い修正や問題が影響する範囲が少なくなるモジュールの凝集度が高い各モジュール内の凝集度を高くすることで、モジュール間の結合度が低くなる再利用率モジュール分割し、モジュール間の結合度を低くして再利用率を上げる13
イベント駆動型サービス要求があった場合にサービスを実行する。例は?利点は?14
バッチ処理型サービス決められた計画に沿ってサービスを実行する。例は?利点は?15
アーキテクチャと品質「人を移動させる」という要求に対して、イベント駆動型とバッチ処理型のサービスでは、品質にどのような違いがあるでしょうか?16
イベント駆動とバッチ処理イベント駆動によるサービス要求があった場合にサービスを実行するイベント駆動の例タクシーのサービス利点要求された時だけサービスを行うことで運用コストを減らすバッチ処理によるサービス事前に決められた計画に沿ってサービスを実行するバッチ処理の例ダイヤを決めて運行する電車やバスのサービス利点まとめて行うことでコストを減らすサービスを行う回数を少なくして運用コストを減らす17
ソフトウェアアーキテクチャソフトウェアアーキテクチャとはソフトウェア構造や構造化の原則ソフトウェアアーキテクチャの目的ソフトウェアの品質特性を強制(支配)する構造を構築する品質特性とはソフトウェアが実現するべき品質の特徴代表的なものパフォーマンス(性能・速度)安全性信頼性可用性(Availability)堅牢性(セキュリティ)ユーザビリティ(使いやすさ)拡張性18
ソフトウェアアーキテクチャの定義ソフトウェアアーキテクチャの定義複数の定義が必要複数の角度からの表現を組み合わせて定義を行うソフトウェア開発のビジョンを実現するために必要なソフトウェア構造構造化原則抽象的な構造やガイドライン概念的な構造(モデリング)ANSI/IEEE Std 1471-2000構成要素を統合したシステムの基本的な構造,構成要素の相互および構成要素と環境間の関係,そしてシステム設計と発展を導く方針全体の分け方と、分けた部分をどのように関係づけるか19
ソフトウェアアーキテクチャの構築アーキテクチャへの要求達成すべき品質特性への要求各品質特性は、相反する項目があるトレードオフを考慮し、アーキテクチャを決定する要求の種類非機能要求長期的な機能要求アーキテクチャ構築時の考慮点可変性変わる要求と変わらない要求の分析リスクの方針さまざまの視点からリスクの洗い出しと方針を決定20
アーキテクチャの複数のビュービューポイントとはステークホルダの関心事に応じた視点ビューとは複数の関連した視点(ビューポイント)によって、アーキテクチャを記述するものがビューである4つのビュー論理ビューシステムが必要とされている機能を実現する、論理的な構造実行ビュー実行時のプロセスやタスクやスレッドといった実行時の単位の構造開発ビューシステムが開発時のファイル等を単位とした構造配置ビューシステムをどのようなマシン上で動作させ、各プロセスがどのマシン(CPU)上に配置されるか等を表した構造21
パターンに関する質問デザイン・パターンを勉強したことは?Yes /No22
パターンに関する質問パターンを書いたことは?Yes /No23
パターンに関する質問パタン・ランゲージを説明してください。24
パタン・ランゲージデザイン・パターン経験に基づいて、繰り返し考え出されてきた、設計についての解決策を一定の形式で記述したもの名前/目的/動機/適用可能性/構造/構成要素/協調関係/結果/実装/関連するパターン名前/問題/解決策/効果(トレードオフ)/関連パタン・ランゲージ何らかの活動に必要なパターンの集まりパターンを組合わせて作られる体系25
パターンに関する質問アーキテクチャをパタン・ランゲージで体系化することについて?〇(有効) or ×(有効でない)26
設計方針に関する質問仕様変更が繰り返されると、設計は悪くなる(設計の悪臭)?Yes /No27
設計方針に関する質問先を見越して、発生しそうな仕様変更に対する仕組みを組み込むべきである?Yes /No28
設計方針に関する質問仕様変更は、予測できる?(予測できない、仕様変更はない)Yes /No29
悪い設計の兆候硬さ変化しにくいシステム1つの変更が全体に影響し、多くの変更が必要になるもろさ1つの変更で、論理的には関連のない箇所まで正常動作しなくなる扱いにくさ正しいことをすることが難しいシステム不透明さ読みにくく、わかりにくい不必要な複雑さ本質的に意味を持たない構造が含まれているシステム不必要な繰り返し同じような構造が繰り返し現われ、共通化できる部分がされていない移植性のなさ再利用できる部分を切り出すことができない30
良い設計とは(設計品質特性)正確性仕様を正しく満たしていること理解性設計結果が読みやすく理解しやすいこと一貫性(統一性)設計上の個々の概念が首尾一貫して、ぶれがない変更容易性機能強化などに伴う変更が容易であること頑健性誤った使い方に対して、システムが適切に対処できることシステムの一部のバグが全体に波及しないこと移植性いろいろなハードウェア、ソフトウェア環境へ容易に移植できること効率性実行効率、資源効率ともに十分実用に適応していること31
テスト容易性と設計テスト容易性は設計の指針となるか?Yes /No32
良いテストの条件テスト目的が明確である何をテストするか明確であるその目的も明確で、更にひとつであることテストの判定が正しいテストの成功、失敗が正しく判定されているテストを独立して実行することができるテストが他のテストに依存することなく、独立している繰り返し実行することができる何度でも繰り返して、テストを実行することができるテストを実行しても、状態が変化しないテストを実行し、成功した場合でも失敗した場合でも、テストを実行する前と後で何も変わらない33
良いテストの効果メソッドが一つの機能を実現しているメソッドが明確な一つの機能だけを提供するメソッドの結果を提供する外部に対して、メソッドの処理結果を判断できるような何らかの方法を提供するクラスやメソッドの独立度が高いことクラスやメソッドの、他のクラスやメソッドへの依存度が低い特定の環境への依存度が低い特定のファイルやデータベース構造などに対する依存度が低い34
良い設計の特徴完全性と十分性システムが目的を達成するために必要な機能のみを含んでいる原子性1つのサービスを実現することに焦点があたっている高凝集度少数に絞られた責務を持ち、その責務を実装するためだけの機能を持つ低結合度他の部分との連携が必要最低限である35
設計品質とテスト容易性良いテストの効果と良い設計の相関関係36
重複をなくすDRY原則(Don't Repeat Yourself.)例は? 有効性は? 理由は?37
DRY原則(Don't Repeat Yourself.)DRY原則重複をなくす重複コードを書かないための設計を行うソフトウェア開発全般での適応設計、プログラミング以外でも、重複をなくす38
設計の原則 単一責任の原則SRP(The Single Responsibility Principle)クラスは、1つの役割(責任)だけを持つ1つの理由のみによって、クラスが変更される役割を単独でテストできる役割=変更理由=テスト単位凝集(cohesion)と同意凝集とは、モジュールに含まれる要素間の機能的な結び付き原則の適用条件役割の変更が確実に想定される場合理由なく適応すると、「不必要に複雑な設計」となる役割をテストする必要がある場合問題の予兆(もろい設計)ある役割の変更に伴い、本来関係ないと思われる役割のクラスに変更の影響がある独立したテストが困難なクラスがある39
設計の原則 オープン・クローズドの法則OCP(The Open-Closed Principle)ソフトウェアの構成要素(クラス、モジュール、関数など)は拡張に対して開いていて、修正に対して閉じていなかればならない拡張に対して開いているとは構成要素の振る舞いを拡張できる修正に対して閉じているとはモジュールの振る舞いを拡張しても、既存のモジュールは変更の必要がない原則の適用長く使い続けられるシステムを開発するシステムに機能の追加や変更をし、成長させる必要がある確実でない変化に対応するための準備は 「無意味に複雑な設計」となる問題の予兆(硬い設計)ちょっとした変更でさえ、修正箇所と依存関係のある全ての箇所を修正する必要がある機能の追加や修正を行なったときに、それに伴って修正しなければならないif文やswitch文が数多くあるコピー&ペーストで、大量の同じコード存在する40
設計の原則 リスコフの置換原則LSP(The Liskov Substitution Principle)派生クラスは、その基本クラスと置換え可能でなければならない派生クラスは、基本クラスが許可する全てを許可しなければならい原則の適応条件基本クラスの派生型を作成する場合契約による設計派生クラスは、基本クラスの事前条件より等しいか弱いか派生クラスは、基本クラスの事後条件より等しいか強いか単体テストによって契約を明記する問題の予兆(もろい設計)派生クラスが増えた場合に基本クラスに変更が必要派生クラスごとの分岐処理が基本クラスに存在する基本クラスの機能を派生クラスが無力化する基本クラスの機能を派生クラスで何もしない動作と置き換える41
設計の原則 依存性逆転の原則DIP(The Dependency Inversion Principle)上位モジュールは、下位モジュールに依存してはならない抽象(目的)に依存させる実装の詳細に依存させない原則の適応条件レイヤ構造によって、システムの複雑性を低くする変更に耐えられるコードを構築する必要があるコードの保守が想定される問題の予兆(もろい設計)下位モジュールの変更が上位モジュールに影響する42AAIBBB
設計の原則 インターフェイス分離の原則ISP(The Interface Segregation Principle)クライアントに、クライアント依存しないメソッドへの依存性を強制してはならないインターフェイス内の強い関連があるものをグループ化して分離する原則の適応条件変更に強いシステムを開発する多目的なインターフェイスを目的ごとに分離し、不用意な結びつきを避けるクラス間の依存度を下げて、低結合度を実現する目的ごとのテストを作成する問題の予兆(もろい設計)クライアントが利用していないメソッドの変更に影響されるインターフェイスの実装クラスの変更が広範囲に影響するインターフェイスが部分的(グループ単位)にしか強い関連を持っていない43
テスト駆動開発とはTDDの目的テスト利用して、良いソフトウェアを開発するTDDの定義(規則)失敗する自動テストコードを作成するまで、プロダクトコードを書かないコードの重複をなくすTDDのテストコードとはプロダクトコードが実現しなければならないことプロダクトコードのインターフェイスを洗練させるものTDDの設計(シンプルな設計)すべてのテストにパスするテストにパスするのに必要なコード最適な範囲で、最小限の数のクラス最適な範囲で、最小限の数のメソッド44
TDDと設計TDDでは、設計せずに、すぐに実装を行う?Yes / No45
誤解と実際誤解設計せずに、すぐに実装を行う
実装を始める前に、全てのテストを作成する
コードが唯一のドキュメントである実際コードを重要なドキュメントのひとつと位置づける
要件をテストという形で明確化する
自動テストを作成してから実装を行う
テストを単位として、小さいステップでソフトウェア開発を進める46
コードの位置づけコードは重要なドキュメントのひとつ目標「動作するきれいなコード」詳細かつ正確なドキュメントドキュメントとして認識して、クリアで読みやすくするテストコードは貴重なリソースのひとつ継続的な開発で繰り返し利用される運用で問題が発生した場合テストを追加する既存のテストを実行し、修正を確実に行う47
リファクタリングリファクタリング(再設計)は、設計力がない人が行うものである?Yes / No48

オブジェクト指向設計の原則

Editor's Notes

  • #4 これは、概要スライドの 別の例です。
  • #10 これは、切り替えを使用した 概要スライドの例です。