UML におけるクラスとオブジェクトの中間点はどこにあるのでしょうか?
-
22-08-2019 - |
質問
を図示したいとします。 Map
クラス (地図作成の種類ではなく、数学の種類)。Ruby では、次のようなものが考えられます。
class Map
attr_accessor :nodes, :edges
def initialize
@nodes = Set.new
@edges = Set.new
end
def minimum_spanning_tree(&mst_algorithm)
mst_algorithm.call(@nodes, @edges)
end
...
end
これを図解し始めると、私の考えは次のようになります。
クラスについて話しているので、クラス図を試してみましょう。を作成します Map
クラス。そして、 Node
クラス。と Edge
クラス。そして、 Set
クラス。大丈夫。ここで、次から構成された (1:2) の線を描画します。 Map
に Set
-- それぞれ 1 つ @nodes
そして @edges
. 。次に、 has-many(1:0..*) 行 Set
に Node
そしてもう一つから Set
に Edge
. 。しかし今私が言いたいのは、各セットには以下を任意に組み合わせることができるということです。 Node
砂 Edge
s、それは真実ではありません。そして、2つを置くのは役に立ちません Set
これらは同じオブジェクトであるため、図上の要素 (対応する 2 つの Compused-Of(1:1) 行を含む)。
ので、私は考えました:そうですね、UML は私にもっと C++/Java っぽくなってほしいと思っているのかもしれません。テンプレート化された Set<Node>
そして Set<Edge>
UML では不可能ですが、サブクラスを作成することはできます。 NodeSet
そして EdgeSet
.
最後にオブジェクト図を考えましたが、それは正しくありません。私が話しているのは、 Set
個人ではなくクラス Set
インスタンス。
もっと良い答えはあるでしょうか?それとも、「最も悪い」ものをすでに見つけましたか?
後で
という答えが マーク・W そして ピート・カーカム 私が最初に述べたように、質問としては素晴らしいです。問題は、実際の問題をそのまま明らかにすることができないため、実際の問題に単純な類似点を使用しようとしていたことです。私は実際には、異なる関係を持つ同じクラスの 2 つをどのようにして同じように動作し、同じ属性 (ただし属性値ではない) を持つようにするかについて少しだけ知りたかったのです。
いくつかの異なるモデルでもう一度試してみましょう。の ActiveDirectory
, 、 Firewall
, 、そして2つ Router
s.1 つのルーター (LAN ルーター) には、 ActiveDirectory
そしてその Firewall
;もう一方 (WAN 側) には、 Firewall
そしていくつかのパブリック サーバー (この図では無視します)。両方とも十分に考えられます Router
メーカー、モデルなどが同じです。シリアル番号は異なりますが(オブジェクトは異なります)、間違いなく両方です Router
s.両方をクラス図に配置するには、サブクラス化する必要があります Router
の中へ LANRouter
そして WANRouter
. 。Marc W のソリューションに似ているのは、 Firewall
そして ActiveDirectory
実装はそのままにして直接(Router
) を決定するクラスに追加します。ただし、UML を使用して実際にシステムを構築する場合は、抽象化がリークする必要があります。
解決
実装ではなくドメインをモデル化している場合、UML は関係のステレオタイプを提供します。この場合、ノードとエッジを、バッグまたはセットに関連する {unowned} としてマークし、それを Set に絞り込むための {unique} としてマークします。ノードまたはエッジのタイプに関する制限は見当たりません。そのため、それが存在しない場合は追加しないでください。
class Map
+nodes : { unordered, unique } object[0..*]
+edges : { unordered, unique } object[0..*]
+minimum_spanning_tree(mst_algorithm:callable)
優れたコード ジェネレーター/リバース エンジニアリング ツールは、ソース コード内のセットとの間で { unordered, unique } UML コレクションをマッピングします。
その情報が役立つ場合は、Map をドメイン モデルのパラメトリック タイプにするとよいでしょう。ただし、その情報は実装では使用されないため、要点を理解するのが少し難しく、実用性を失わずに物事をできるだけ単純にすることがモデリングの常に目標となります。
特定のクラスが Set を使用して実装されていることを文書化したい場合は、関連付けを使用してそれを行うことができます。C++ または Java では Set 内の要素の型を宣言でき、これらは UML のパラメトリック型にマップされるというのは正しいことです。私の知る限り、Rubyにはそのような型制限を実装するメカニズムがないため、マップのRuby実装を文書化するには、実装内にあるもののみを文書化してください。マップにはSetへの2つの関連付けがあり、セット内にあるものには制限はありません。(これを不変制約として文書化し、型制約ではなく単体テストすることもできますが、やはり、制限的な静的型チェックが必要な場合になぜ Ruby で作業するのか理解するのは少し難しいです)
他のヒント
~からは線を引かないでください Map
に Set
. 。この場合、 Set
は、本当に重要なオブジェクトを保持する Ruby によって与えられる単なるデータ構造です。かどうか Set
, 、 HashMap
, 、 Array
, などは実装固有であり、UML には関係ありません。次から Compused-of(1:0..*) 行を作成するだけです。 Map
に Node
そしてから Map
に Edge
. 。結局のところ、英語では、あなたの Map
実際にはノードとエッジで構成されていますよね?含める理由 Map
あなたの図にあるのは、実際にクラスを作成しているのはあなただからです。
オブジェクト図については正しいです。この場合は必要ありません。あなたが提案したテンプレート構文と同じです。