2.9.4. オブジェクト指向設計

1. 概要

 オブジェクト指向設計は、ソフトウェア開発において広く使用される設計手法です。この手法は、実世界の概念をソフトウェアの構造に反映させることで、直感的で保守性の高いシステムを構築することを目指しています。オブジェクト指向設計の核心は、データ(属性)と処理(メソッド)を一体化した「オブジェクト」という単位でシステムを構築することにあります。

 この設計手法の重要性は、以下の点にあります:
1.1. 再利用性の向上:クラスを再利用できるため、開発の効率化が期待できます。
1.2. 保守性の向上:変更が発生しても、影響を受ける範囲を限定できるため、メンテナンスがしやすくなります。
1.3. 開発効率の向上:直感的な設計により、開発者間での理解が共有しやすくなり、協力して開発を進めることができます。
1.4. 現実世界のモデル化のしやすさ:実世界のオブジェクトをそのままモデル化できるため、システム設計が直感的に行えます。

2. 詳細説明

2.1. オブジェクト指向の基本概念

2.1.1. クラスとインスタンス

 クラスは、オブジェクトの設計図または型を表します。インスタンスは、そのクラスから生成された具体的なオブジェクトです。例えば、「車」クラスから「スポーツカー」というインスタンスを作成するようなイメージです。

2.1.2. 属性とメソッド

 属性はオブジェクトのデータを表し、メソッドはオブジェクトの振る舞いを定義します。例えば、「車」クラスの属性に「色」や「速度」があり、メソッドには「加速する」や「ブレーキをかける」などがあります。

2.1.3. カプセル化

 カプセル化は、オブジェクトの内部データと実装の詳細を隠蔽し、外部からのアクセスを制限する機能です。これにより、不正なデータの変更を防ぎ、オブジェクトの一貫性を保つことができます。

図1:カプセル化のイメージ図

2.1.4. 継承(インヘリタンス)

 継承は、既存のクラス(スーパークラス)の特性を新しいクラス(サブクラス)に引き継ぐ仕組みです。例えば、「車」クラスを基に「スポーツカー」や「トラック」クラスを作成し、それぞれに異なる機能を追加することができます。

2.1.5. 多相性

 多相性は、同じインターフェースを持つ異なるオブジェクトが、それぞれ独自の方法で動作する能力を指します。これにより、例えば「動物」クラスに「鳴く」メソッドを定義し、「犬」クラスと「猫」クラスで異なる実装をすることが可能です。

2.2. オブジェクト指向設計の手順

2.2.1. 要求分析

 システムの要求を分析し、必要な機能や仕様を明確にします。

2.2.2. クラスの識別と定義

 要求をもとに、システムを構成するクラスを特定し、それぞれの役割を定義します。

2.2.3. クラス間の関係の定義

 クラス同士の関連性(継承、集約、関連など)を定義します。

classDiagram
    class 車 {
        -エンジン: エンジン
        -タイヤ: タイヤ[4]
        -色: string
        +走る()
        +止まる()
        +給油(量: float)
    }
    
    class エンジン {
        -排気量: float
        -燃料タイプ: string
        +始動()
        +停止()
    }
    
    class タイヤ {
        -サイズ: int
        -空気圧: float
        +回転()
        +空気注入(圧力: float)
    }
    
    車 "1" *-- "1" エンジン : has
    車 "1" *-- "4" タイヤ : has

 この図は、「車」「エンジン」「タイヤ」という3つのクラスの関係を示すクラス図の例です。以下に図の説明を記します:

  1. 「車」クラス:
    • 属性:エンジン、タイヤ(4つ)、色
    • メソッド:走る()、止まる()、給油(量: float)
  2. 「エンジン」クラス:
    • 属性:排気量、燃料タイプ
    • メソッド:始動()、停止()
  3. 「タイヤ」クラス:
    • 属性:サイズ、空気圧
    • メソッド:回転()、空気注入(圧力: float)
  4. 関連:
    • 車は1つのエンジンを持つ(コンポジション関係)
    • 車は4つのタイヤを持つ(コンポジション関係)

 この図は以下の要素を示しています:

  • クラス間の関係(コンポジション)
  • 各クラスの属性とメソッド
  • 可視性(+ はpublic、- はprivate)
  • 多重度(車と4つのタイヤの関係)

 この例を通じて、クラス図がシステムの構造をどのように表現するか、またクラス間の関係をどのように示すかを理解することができます。これは、オブジェクト指向設計において重要な図の一つです。

2.2.4. クラス図の作成

 クラス間の関係を図にまとめ、システム全体の構造を視覚化します。

2.2.5. メソッドの詳細設計

 各クラスのメソッドの動作を具体的に設計します。

2.3. 設計の主要概念

2.3.1. 抽象クラス

 抽象クラスは、直接インスタンス化されることのない基本クラスで、サブクラスで実装されるべき抽象メソッドを定義します。

2.3.2. インターフェース

 インターフェースは、クラスが実装すべきメソッドの集合を定義します。これにより、異なるクラスでも同じ操作が可能になります。

2.3.3. パッケージ

 パッケージは、関連するクラスをグループ化する仕組みです。

2.3.4. 関連と派生関連

 関連は、クラス間の関係を表します。派生関連は、既存の関連から導き出される新たな関連です。

2.3.5. 集約と組成

 集約は「持っている」関係を、組成はより強い「構成要素である」関係を表します。

classDiagram
    class 大学 {
        +名前: string
    }
    class 学部 {
        +名前: string
    }
    class 会社 {
        +名前: string
    }
    class 部門 {
        +名前: string
    }
    
    大学 o-- 学部 : 集約
    会社 *-- 部門 : 組成
    
    note for 大学 "大学は学部を持つが、\n学部は大学なしでも\n存在できる"
    note for 会社 "会社は部門で構成され、\n部門は会社なしでは\n存在できない"

 この図は、集約と組成の違いを示す比較図です。以下に図の説明を記します:

  1. 集約の例:
    • 大学と学部の関係を示しています。
    • 大学は複数の学部を持ちますが、学部は大学から独立して存在することも可能です。
    • 図では中空のダイヤモンドで表現されています。
  2. 組成の例:
    • 会社と部門の関係を示しています。
    • 会社は複数の部門で構成され、部門は会社の一部として存在し、会社なしでは存在できません。
    • 図では塗りつぶされたダイヤモンドで表現されています。
  3. 注釈:
    • 各関係の特徴を説明する注釈が追加されています。

 この図によって、以下の点が理解できます:

  • 集約は「持っている」関係を表し、構成要素が独立して存在できる緩やかな関係です。
  • 組成は「構成要素である」関係を表し、構成要素が全体に強く依存する密接な関係です。

 集約と組成の違いを理解することは、システムの構造を適切にモデル化する上で重要です。この図を通じて、オブジェクト間の関係をより正確に表現し、設計の意図を明確に伝えることができます。

2.3.6. 汎化と特化

 汎化は共通の特性を抽出してより一般的なクラスを作成する過程を、特化はより具体的なクラスを作成する過程を指します。

3. 応用例

3.1. ソフトウェア開発

 オブジェクト指向設計は、大規模なソフトウェア開発プロジェクトで広く使用されています。例えば、銀行システムの開発では、「口座」クラス、「顧客」クラス、「取引」クラスなどを定義し、それらの関係を明確にすることで、システムの構造を理解しやすくし、保守性を向上させています。【図4:銀行システムのクラス図】

classDiagram
    class 顧客 {
        -顧客ID: string
        -名前: string
        -住所: string
        +口座情報取得()
        +個人情報更新(情報: object)
    }
    class 口座 {
        -口座番号: string
        -残高: float
        +入金(金額: float)
        +出金(金額: float)
        +残高照会()
    }
    class 取引 {
        -取引ID: string
        -日時: datetime
        -金額: float
        -種類: string
        +取引詳細取得()
    }
    class 普通口座 {
        -利率: float
        +利息計算()
    }
    class 当座口座 {
        -貸越限度額: float
        +貸越チェック(金額: float)
    }
    
    顧客 "1" -- "1..*" 口座 : 所有する
    口座 <|-- 普通口座
    口座 <|-- 当座口座
    口座 "1" -- "0..*" 取引 : 記録する

 この図は、簡略化された銀行システムのクラス図です。以下に図の説明を記します:

  1. 顧客クラス:
    • 属性:顧客ID, 名前, 住所
    • メソッド:口座情報取得(), 個人情報更新()
  2. 口座クラス(抽象クラス):
    • 属性:口座番号, 残高
    • メソッド:入金(), 出金(), 残高照会()
  3. 普通口座クラス(口座クラスを継承):
    • 追加属性:利率
    • 追加メソッド:利息計算()
  4. 当座口座クラス(口座クラスを継承):
    • 追加属性:貸越限度額
    • 追加メソッド:貸越チェック()
  5. 取引クラス:
    • 属性:取引ID, 日時, 金額, 種類
    • メソッド:取引詳細取得()

関連:

  • 顧客は1つ以上の口座を所有する(1対多の関連)
  • 口座は0個以上の取引を記録する(1対多の関連)
  • 普通口座と当座口座は口座クラスを継承している(継承関係)

 この銀行システムのクラス図は以下の特徴を示しています:

  1. 継承:口座クラスを基底クラスとし、普通口座と当座口座がそれを継承しています。
  2. 関連:顧客と口座、口座と取引の間に関連があります。
  3. 多重度:一人の顧客が複数の口座を持つ可能性や、一つの口座に複数の取引が紐づく可能性を表現しています。

 この図を通じて、実際のシステム設計においてオブジェクト指向設計の概念がどのように適用されるかを理解することができます。また、クラス間の関係や、各クラスの役割が明確に示されており、システムの全体像を把握するのに役立ちます。確に表現し、設計の意図を明確に伝えることができます。

3.2. ゲーム開発

 ゲーム開発では、キャラクター、アイテム、環境要素などをクラスとして定義し、それらの相互作用を設計することで、複雑なゲームワールドを効率的に構築しています。例えば、「キャラクター」クラスを基に「プレイヤー」と「敵」を派生させ、それぞれ異なる動作を実装することが可能です。

3.3. モバイルアプリケーション開発

 スマートフォンアプリの開発では、UIコンポーネント、データモデル、ネットワーク通信クラスなどを部品化し、再利用することで、開発効率を高めています。特に、MVVM(Model-View-ViewModel)パターンを使用することで、コードの分離と再利用性が向上します。

4. 例題

例題1: クラス設計

問題:以下の要件を満たすクラス図を作成してください。

  • 「社員」クラスを定義し、属性として「社員ID」「氏名」「部署」を持つ。
  • 「社員」クラスのサブクラスとして「正社員」と「契約社員」を定義する。
  • 「正社員」クラスは追加の属性として「基本給」を持つ。
  • 「契約社員」クラスは追加の属性として「時給」と「労働時間」を持つ。
  • すべてのクラスに「給与計算」メソッドを定義する。

回答例:

classDiagram
    社員 <|-- 正社員
    社員 <|-- 契約社員
    
    class 社員 {
        +int 社員ID
        +string 氏名
        +string 部署
        +給与計算() float
    }
    
    class 正社員 {
        +float 基本給
        +給与計算() float
    }
    
    class 契約社員 {
        +float 時給
        +int 労働時間
        +給与計算() float
    }

図5:社員クラスのクラス図

例題2: オブジェクト指向設計の概念

問題:以下の各文について、対応するオブジェクト指向の概念を選んでください。
a) 「車」クラスから「スポーツカー」クラスを作成する。

b) 「動物」クラスに「鳴く」メソッドを定義し、「犬」クラスと「猫」クラスでそれぞれ異なる実装をする。
c) 「銀行口座」クラスの残高を外部から直接変更できないようにする。
d) 「図形」クラスを作成し、そこから「四角形」や「三角形」クラスを派生させる。

回答例:
a) 継承(インヘリタンス)
b) 多相性
c) カプセル化
d) 汎化(「図形」クラス)と特化(「四角形」「三角形」クラス)

5. まとめ

 オブジェクト指向設計は、ソフトウェアの構造をより現実世界に即した形で表現し、再利用性、保守性、拡張性を高めるための手法です。主要な概念として、クラス、インスタンス、継承、カプセル化、多相性があります。設計プロセスでは、要求分析からクラスの識別、関係の定義、クラス図の作成を経て詳細設計に至ります。

 この手法を適切に活用することで、複雑なシステムを効率的に開発し、長期的な保守や拡張を容易にすることができます。例えば、クラス設計を工夫することで、変更が他の部分に影響を及ぼしにくくなり、保守性が向上します。