UMLのクラス図で要素間の関係を可視化しよう

n-ozawan

皆さん、こんにちは。技術開発グループのn-ozawanです。
「ググる」という言葉が死語になりつつあると聞きました。これからは「コパる(Copilotで検索する)」もしくは「ジピる(ChatGPTで検索する)」なんだそうです。

本題です。
前回のシーケンス図に続き、今回はクラス図のお話です。クラス図はシーケンス図と並ぶ人気の図です。クラス図はシステムを構成する要素間の関係性を可視化するのに利用されます。特にJava言語などのオブジェクト指向言語を実装する際に、クラス間の関係性を整理する際に利用されます。

クラス図

概要

クラス図は、システムを構成する要素の構造とその関連性を表現した図です。クラス図を利用するとシステムを構成する要素を可視化することができ、関係者間で共有することが出来ます。また、Java言語やC#言語などのオブジェクト指向言語ではclassを定義することでシステムを構築しており、詳細設計などで利用されています。

クラス図の仕様はUMLで定義されています。シーケンス図と並び良く使われる図ですので、見たことがある人も多いかもしれません。

凡例

クラス図の凡例を以下に示します。

説明
クラス
システムの要素(クラス)を表します。四角を3つに分割した図となっており、上から「クラス名」「属性」「操作」になります。 Java言語であれば「クラス名」「メンバ変数」「メソッド」になります。「属性」「操作」は省略することも可能です。

属性や操作の冒頭にある記号は可視性を表します。+はpublic、-はprivate、#はprotected、~はpackage privateを表します。 また、属性の後ろにある「:(コロン)」の後に続くのは、その属性の型です。intやStringなどの型があります。 操作の後ろにある「:(コロン)」の後に続くのは、その操作の戻り値の型です。voidやintなどの型があります。
汎化
クラス間の関係を表します。汎化はオブジェクト指向における「継承」です。is-aの関係になります。例えば、「猫は動物です」は、「Cat is an animal」であり、is-aの関係となります。
実現
インターフェースの実装を表します。クラスがインターフェースを実装する場合に使用されます。点線の矢印で表現され、矢印の先がインターフェースを指します。
集約
クラス間の関係を表します。has-aの関係になります。例えば、「車はエンジンを持っている」は、「Car has an engine」となり、has-aの関係となります。
コンポジション
集約と同じくクラス間の関係を表します。has-aの関係になります。集約と異なる点は、コンポジションは部分と全体のライフサイクルが同じであることです。 例えば、「家は部屋を持っている」は、「House has rooms」となり、has-aの関係となります。家が存在しないと部屋も存在しないため、コンポジションの関係になります。
関連
クラス間の関係を表します。関連はクラス間の接続を表し、関連の名前はその接続の性質を表します。例えば、「学生が受講する」という関連は、学生と授業の間の関連を表します。
依存
クラス間の関係を表します。クラスからクラスへの依存を表しています。例えば、車のエンジンはガソリンが無いと走ることができませんので、「エンジンはガソリンを使用する」という依存関係があると言えます。

サンプル

クラス図のサンプルです。イメージがつきやすいように、Java言語のソースコードも添えます。

汎化

// 動物 クラス
class Animal {
}

// 猫 クラス
class Cat extends Animal {
}

// 犬 クラス
class Dog extends Animal {
}

実現

// 電源装置
interface Powerable {
    // 電源を入れる
    void turnOn();
    
    // 電源を切る
    void turnOff();
}

// テレビ
class Television implements Powerable {
    @Override
    public void turnOn() {
        System.out.println("テレビの電源が入った");
    }

    @Override
    public void turnOff() {
        System.out.println("テレビの電源が切れた");
    }
}

// エアコン
class AirConditioner implements Powerable {
    @Override
    public void turnOn() {
        System.out.println("エアコンの電源が入った");
    }

    @Override
    public void turnOff() {
        System.out.println("エアコンの電源が切れた");
    }
}

集約とコンポジション

// エンジン
class Engine {
}

// 車
class Car {
  private Engine engine;  // 集約:車はエンジンを持つが、エンジンは他でも使える
}

// 部屋
class Room {
}

// 家
class House {
  private Room room;  // コンポジション:家は部屋を所有しており、家がなくなると部屋もなくなる
}

おわりに

クラス図はオブジェクト指向言語の詳細設計などで使われることが多いと思います。しかし、私の経験上、オブジェクト指向言語の詳細設計でクラス図を用いると、後々メンテナンスが困難になるので、あまりお勧めできません。理由は、システムを構成するクラスの数が膨大であり、図で表現しきれなくなるからです。クラス図はフレームワークなどの基盤となる領域のみにとどめると良いかと思います。

また、クラス図はシステムを構成する要素を説明する図としても有用であり、上流工程でも扱うことの出来る図でもあります。要件定義などでも活用していきたいですね。

ではまた。

Recommendおすすめブログ