2

假设您要绘制一个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堂课。美好的。现在我将绘制一条 Composed-Of(1:2) 线,从MapSet—— 每个@nodes@edges。然后是从 to 的 has-many(1:0..*) 行和从Setto 的Node另一SetEdge。但是现在我说每个集合都可以有Nodes 和Edges 的任意组合,这是不正确的。并且在图表上放置两个Set元素(有两条对应的 Composed-Of(1:1) 线)也无济于事,因为它们是同一个对象。

所以我想:嗯,也许 UML 想让我更像 C++/Java-ey。在 UML 中不可能使用模板化Set<Node>,但我可以创建子类:和.Set<Edge>NodeSetEdgeSet

最后我考虑了一个对象图,但那是不对的。我说的是Set类,而不是个别Set实例。

有更好的答案吗?还是我已经找到了“最不坏”的那个?

之后

正如我最初所说的那样,Marc WPete Kirkham的回答非常适合这个问题。问题是我试图对我的实际问题使用一个简单的类比,因为我无法揭示存在的问题。我真的只是在了解如何拥有两个具有不同关系但行为相同并具有相同属性(尽管不是属性值)的同一类。

让我们用一些不同的模型再试一次:an ActiveDirectory、aFirewall和 two Routers。一台路由器(LAN 一台)引用了ActiveDirectoryFirewall; 另一个(广域网)引用了Firewall一些公共服务器(我们将在此图中忽略它们)。完全可以想象,两个Routers 的品牌、型号等都相同。它们会有不同的序列号(对象不同),但它们肯定都是Routers。然而,要将两者都放在类图上,我必须将其子类Router化为LANRouterand WANRouter。类比 Marc W 的解决方案是直接连接Firewalland ActiveDirectory,留下实现 (Router) 到类来确定。但是,如果要使用 UML 来实际构建系统,则抽象必须泄漏。

4

2 回答 2

3

如果您正在对领域进行建模,而不是对实现进行建模,那么 UML 为关系提供了原型。在这种情况下,您会将节点和边标记为 {unordered},这与袋子或集合有关,而 {unique} 将其缩小为集合。我看不到对节点或边缘类型的任何限制,所以如果它不存在,那么不要尝试添加它:

class Map
  +nodes : { unordered, unique } object[0..*]
  +edges : { unordered, unique } object[0..*]
  +minimum_spanning_tree(mst_algorithm:callable)

一个好的代码生成器/逆向工程工具会将 { unordered, unique } UML 集合映射到源代码中的 Set 或从 Set 映射。

如果该信息对您有用,您可能希望在您的域模型中使 Map 成为参数类型。但是由于这些信息没有在实现中使用,所以有点难以理解这一点,并且在不失去实用性的情况下使事情尽可能简单一直是建模的目标。

如果你想记录一个特定的类是使用 Sets 实现的,你可以用关联来做到这一点。没错,C++ 或 Java 允许您在 Set 中声明元素的类型,并且这些映射到 UML 中的参数类型。AFAIK Ruby 没有实现此类类型限制的机制,因此要记录 Map 的 Ruby 实现,仅记录实现中的内容 - Map 与 Set 有两个关联,并且对 Set 中的内容没有任何限制。(您可能希望将其记录为不变约束,然后进行单元测试而不是类型约束,但是如果您想要限制性的静态类型检查,又很难理解为什么要在 Ruby 中工作)

于 2009-05-18T18:07:11.410 回答
2

不要从Mapto画任何线Set。在这种情况下,Set它只是 Ruby 提供给您的一个数据结构,其中包含真正重要的对象。是否是 a Set、 a HashMap、 anArray等是特定于实现的,对于 UML 无关紧要。Map只需从toNode和 from Mapto制作一条 Composed-of(1:0..*) 行Edge。毕竟,在英语中,你Map真的是由节点和边组成的,对吗?您包含Map在图表中的原因是因为您实际上是创建类的人。

您对对象图是正确的:在这种情况下没有必要。与您建议的模板语法相同。

于 2009-05-18T17:34:33.207 回答