Atsushi4のブログ

へたれQtプログラマの備忘録的ななにか

多重度を正しく書けていますか

はじめに

これはETロボコン Advent Calendar 2014 - Adventarの9日目のエントリーです。昨日はY_uuuさんのユニットテストの話でした。ユニットテスト必要ですよねー。QtにもQTestLibが有りますよ!ってその話はまた今度。


今日はクラス図の、それも多重度について「だけ」書いていきます。クラス図の関連につける多重度、みなさん正しく書けていますか?

ETロボコン2014の公式資料には多重度が誤って書かれているものが複数ありました。
全体メーリングリストでも指摘をしましたが、説明不足かと思うのでこちらに書いておきます。
とはいえ私はUMLの専門家ではなく、認識の誤りなどもあるかと思います。お気づきの点あればご指摘頂けると幸いです。

誤った多重度の例

fig.1 多重度を誤ってつけたクラス図
f:id:Atsushi4:20141209052719j:plain

さて、fig.1を見て「このクラス図おかしいな」と思われたでしょうか。これは多重度を誤っている例です。今年のETロボコンに参加された方は見覚えがあるのではないかと思います。説明のために関連名を追加してあります。

どこがおかしい?

多重度を誤っている、と書きましたが、UMLの記法から逸脱している部分はありません。ただ、意味的に倒立振子と合わない部分があります。これはオブジェクト図と見比べれば分かると思います。

fig.2 倒立走行のオブジェクト図
f:id:Atsushi4:20141210035455j:plain

fig.2は倒立振子で想定される倒立走行とモーターの関係を表したオブジェクト図です。説明のためにリンク名を書いてあります。オブジェクト図では、「クラス」は「オブジェクト」として、「関連」は「リンク」としてインスタンス化されます。

倒立走行クラスから見たモータークラスへの関連は「関連_左」「関連_右」の二つ、モータークラス側の多重度はどちらも1です。これはオブジェクト図の「倒立走行1」オブジェクトから見て「リンク_左」「リンク_右」にインスタンス化されています。

モータークラスから見た倒立走行クラスへの関連は同じく「関連_左」「関連_右」の二つ、倒立走行クラス側の多重度はどちらも1です。ところが、「モーター左」オブジェクトから見た「関連_左」は「リンク_左」にインスタンス化されていますが、「関連_右」がインスタンス化されていません。
これではクラス図における「関連_右」の倒立走行クラス側多重度1、という設計と合わず、「モーター左」オブジェクトはクラス図のクラス設計に沿ってインスタンス化されていない、という事になります。
同様に、「モーター右」オブジェクトも相手側多重度が1であるはずの「関連_左」がインスタンス化されておらず、クラス図とのトレーサビリティがとれていません。

どう修正すればいい?

この場合はオブジェクト図が正しく、整合のとれないクラス図の方が間違っていそうです。モーター側からみた関連が二つあってどちらも相手側多重度が1、というのが問題です。

インスタンス化されない関連の多重度には0を含める

最も簡単な修正の方法は、倒立走行側の多重度の記述を削除してしまうことです。以下3つは全て同じ意味です。

  • 多重度の記述無し
  • 多重度「*」
  • 多重度「0..*」

モータークラスから見て一つの関連の先の倒立走行クラスは最大1つ、という事を表すには「0..1」とします。

fig.3 修正したクラス図
f:id:Atsushi4:20141210043814j:plain

これで少なくともfig.2のオブジェクト図との不整合はなくなりました。このように、ある関連がオブジェクト図においてインスタンス化されない可能性がある場合、その関連の相手側多重度には0を含まなければいけません。

さらに曖昧さを取り除く

クラス図としてはこれでも充分と思いますが、このクラス図はまだ曖昧さを含んでいます。例えば次のようなオブジェクト図もこのクラス図から書くことができます。

fig.4 誤解されたオブジェクト図1
f:id:Atsushi4:20141210044323j:plain
fig.5 誤解されたオブジェクト図2
f:id:Atsushi4:20141210044329j:plain

どちらもクラス図と整合しており、UMLの表記上も問題ありません。でも倒立振子とは合わないオブジェクト図になってしまいました。このような誤解は実際の設計でも起こり得ると思います。
このような誤解をさける方法として、抽象クラスでまとめる方法、コメントを使う方法、xor制約を使う方法、unionを使う方法などが株式会社豆蔵様ホームページで紹介されています。
誤解しがちなモデリングの技:第2回:隠れた曖昧さ | 豆蔵ソフト工学ラボ

実際にこのケースでunionを使用した例を書いてみます。

fig.6 unionを使って曖昧さを取り除いたクラス図
f:id:Atsushi4:20141210045754j:plain

どうでしょうか。fig.2のオブジェクト図にマッチしていてなおかつfig.4やfig.5のオブジェクト図に誤解されるような曖昧さが排除されています。

おわりに

ここでは倒立走行とモーターの関係のみを見てきましたが、尻尾制御に同じモータークラスを使用する場合は、fig.6ではunionの倒立走行側多重度が「0..1」となり結局曖昧さを含むクラス図になってしまいます。これを無理にxor制約を使って書いたりすると、曖昧さは無くなっても読みにくい図になってしまうかもしれません。
そもそも技術教育資料のクラス図に合わせて書いてきましたが、実際のところモータークラスが単独で存在できないような制限をつけることにはほぼ利点が無いです。普通に倒立走行クラス側にコンポジションをきちんと書いて、モータークラス側多重度を1にするだけで良いと思います。xor制約とかunion書いても見にくくなるだけです。
それから、この辺りは審査委員さんの中でも解釈が異なるようで、ETロボコンに限っては正しい多重度を書いても評価に反映されないかもしれません。(技術教育の時に講師の方に、地区大会懇親会でも別の運営委員の方にお話ししたのですが、資料のクラス図は間違っていないと言われてしまいました。)


ともかく、モデルは人に伝えるために書くのだという事をいつも意識して、伝わりやすいモデルを書けるように勉強しなければ、と思う今日このごろです。駄文にお付き合いくださいましてありがとうございました。





fig.7 尻尾制御入れてunion+xorでなんとかしてみた。すごく…見にくいです…
f:id:Atsushi4:20141210052101j:plain

fig.8 (誤ったクラス図)元のクラス図にxor制約を入れると倒立走行が二つのモーターを持てなくなる?
f:id:Atsushi4:20141210052119j:plain