クラス図の情報量を激増させる線と多重度
「クラス図を書いてある人に説明資料として渡したいが、書いたことがないので何を書いておけば良いのかわからない」という話をした。
「これは大事じゃね」ってことをいくつか話したんだけど、それをさっとまとめて即席ポエムにしちゃおうと思ったのがこれ。
結論
個人的には 線の向き と 多重度 が超大事だと思っている。
線の向きは欲を言えば線の種類まで気をつけると良いと思う。
線の向きと多重度のあるなし
例えば、ある 箱と線だけ の適当な例を用意してみた。
ここから読み取れる 情報量 はどれくらいだろう?
登場する名詞くらいしかわからない。
これでコードは書けないな?
多重度 と 線 をちゃんと書いたらどうだろう?
多重度からわかること
線の端に書いてある*
とか0..1
のこと。
*
は任意数を、n..m
は最低 n 最高 m 個を、それぞれ示している。[1]
User
はFavorite
をいくつでも登録できる、User
はNickame
を設定してもしなくても良い、ということが*
と0..1
というちょっとのサインでわかってしまう。
線からわかること
向きのない絵ではUser
とPayment
の関係はわからない。
CreditCard
とPayPay
両方の登録をPayment
として取りまとめている絵とも読めてしまう。
だが 線の向き と 線の種類 があるだけで、User
にPayment
を登録したい、かつUser
からCreditCard
かPayPay
かは認識できない様にしたい、というメッセージを受け取れる。
ただ線の終点を白抜き ( implement
) にするだけで、SOLID 原則の Dependency Inversion Principle をしたがっていることが一発で把握できてしまう。
構成 ( Composition ) と集約 ( Aggregation )
構成はオブジェクトのライフサイクルが連動するもの、親がないと子供も存在できない関係のこと。
黒塗りで示す。
集約は親がなくても子供だけで存在するもの、取りまとめる関係のこと。
白塗りで示す。
ただ僕はぶっちゃけこの違いにはあまりこだわりがない。
いつもは手抜きでどっちもただの--->
で書いちゃってます。
ポイントは情報の密度
インスタンスのイメージ図はキリがないが、クラス図は定義的
この絵のクラスを実際にnew
してインスタンス ( 変数と思っても ok ) を想像しようと思うと、例えばこういう絵になる。
nickname
は 1 つでfavorite
が 3 つだから、正しい。
けど、これも
これも、正しい絵だ。
こういう絵を書いたらキリがないので、クラス図で*
と 0..1
を使って 定義的 に数をアピールしているんだ。
多重度ありクラス図は情報の密度がすごい高い気がするよね?
実装のイメージがブレない
この絵を Java 風味に実装すると、コードはこんな感じ。
class User {
Option<Nickname> nickname
List<Favorite> favorites
Payment payment
}
0..1
がOption
に、*
がList
に、そのまま実装できる。
というかこれ以外実装しようがない。
ただ 多重度 を書くだけで、「コード書いたぜ」「えっニックネームって必須だっけ??」ということが限りなく起こらなくなる。
やっぱり多重度ありクラス図は情報の密度がすごい高い気がするよね?
別の絵でもう少し実感してみる
これはコンポジットパターンの絵だ。
少し不思議な感じがする絵だけど、線 と 多重度 からどんなパターンか読み取ってみる。
まず 線 を見ると、Directory
とFile
はともにEntry
を実装している。これ自体はよく見る形だ。
次に 多重度 を見ると、Directory
はEntry
を複数持てることがわかる。
つまりDirectory
はEntry ( Directory | File )
をいくつでも持ち、そのDirectory
がまたEntry ( Directory | File )
をいくつでも持つことが示されている。
ファイラがたったこれだけで表現し終わっているんだ。
インスタンスのイメージ図だと、こんな感じ。
これだけの複雑な絵をたった 3 つの箱と 線 と 多重度 で示せてしまうなんて、すごい情報密度だと思わないか?
この絵じゃ無理だろう?
コンポジットパターンおまけ
あまり自分でこれを実装することはないけど、実は結構いろいろなところにいるぞ。
例えば HTML も似ている。
<div>
みたいなタグを持てるタグと<br>
みたいなタグを持たないタグを、この絵だけで表現できる。
List もこの絵で表現できる。
Javaslang というライブラリのList
は、実際にこんな形をしている。
Cons
は値 1 つとList
1 つを持っていて、Nil
は何も持たない。
ただこれだけでList("foo", "bar", "pon")
が表現できる。
情報量すごいな?
まとめ
線 と 多重度 は書いておこう!!!
-
僕は
1
の場合は何も書かない。大半がそうだから。 ↩︎
Discussion