コンポジションの間で関連が複雑に張られてしまうようなクラス図をシンプルに書きたい


次のようなクラス図を書きたいとします。

  1. ドローンシステム1つは,リモコンとドローンを複数コンポジションとして持つ
  2. リモコンとドローンは1対1の関係にある

1を表現するのに次のようにクラス図を書きます。

2を表現するのに次のようにクラス図を書きます。

この2つを合わせると次のようなクラス図になります。

しかし,このような書き方だと,リモコンやドローンのような部品の種類が増えた時に,複雑に関連が入り乱れるようになります。どのように記述するとシンプルになるでしょうか?

汎化とOCLを用いた解法例

「汎化と関連を組合せてクラス図を書いた時,サブクラスのインスタンスの種類や個数の制約を定義したい」で紹介したように,汎化と関連を組合わせたクラス図を書き,それにOCLを追加することで解決してみることを考えます。

まずリモコンとドローンのスーパークラスを考えるのですが,たとえば「ペアリング機器」とでも命名してみましょうか。

ペアリング機器同士が1対1の自分自身への関連を持つというようにして,ドローンシステムがペアリング機器を複数持つ,というようにすると良さそうです。

ではOCLを定義してみましょう。

context ペアリング機器 inv:
  self.oclAsType(リモコン) implies self.ペアリング.oclAsType(ドローン)
  and self.oclAsType(ドローン) implies self.ペアリング.oclAsType(リモコン)

これの意味するところを日本語で書くと次のようになります。

  • 次の条件のどちらも成立する
    • ペアリング機器がリモコンクラスだったならば,そのペアリング機器のペアリング先のクラスはドローンである
    • ペアリング機器がドローンクラスだったならば,そのペアリング機器のペアリング先のクラスはリモコンである

つまり,ペアリングの関連の一方がリモコンでもう一方がドローンであることを保証します。

なお,ペアリング機器がリモコンクラスでなかった場合,self.oclAsType(リモコン) は偽になるので, self.oclAsType(リモコン) implies self.ペアリング.oclAsType(ドローン) は前提条件を満たさず真になることに注意してください。(「AならばB」という命題がある時,Aが偽だった時にはBが真でも偽でも「AならばB」は真になる)