Где золотая середина между классом и объектом в UML? - PullRequest
2 голосов
/ 18 мая 2009

Допустим, вы хотите построить класс 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 - по одной на каждые @nodes и @edges. Затем строка has-many (1: 0 .. *) от Set до Node и еще одна от Set до Edge. Но сейчас я говорю, что каждый набор может иметь любое сочетание Node с и Edge с, что не соответствует действительности. И это не помогает поместить два Set элемента на диаграмму (с двумя соответствующими линиями Composed-Of (1: 1)), так как это один и тот же объект.

Так что я подумал: ну, может быть, UML хочет, чтобы я был более C ++ / Java-EY. Шаблонные Set<Node> и Set<Edge> невозможны в UML, но я мог бы создать подклассы: NodeSet и EdgeSet.

Наконец, я рассмотрел диаграмму объектов, но это не так. Я говорю о Set классе, а не отдельных Set экземплярах.

Есть ли лучший ответ? Или я уже нашел «наименее плохой»?

Позже

Ответы, которые Марк W и Пит Киркхам являются фантастическими для вопроса, как я его сформулировал. Проблема в том, что я пытался использовать простую аналогию с моей реальной проблемой, потому что я не могу раскрыть проблему, как она существует. Я действительно только после того, как рассказал о двух одинаковых классах, которые имеют разные отношения, но действуют одинаково и имеют одинаковые атрибуты (хотя и не значения атрибутов).

Давайте попробуем еще раз с некоторыми другими моделями: ActiveDirectory, Firewall и двумя Router с. Один маршрутизатор (LAN) имеет ссылки на ActiveDirectory и Firewall; другой (WAN) имеет ссылки на Firewall и некоторое количество публичных серверов (мы проигнорируем их на этой диаграмме). Вполне возможно, что оба Router имеют одну и ту же марку, модель и т. Д. У них будут разные серийные номера (объекты разные), но они определенно оба Router s. Тем не менее, чтобы поместить оба в диаграмму классов, я должен разделить Router на LANRouter и WANRouter. Аналогия с решением Marc W заключается в прямом соединении Firewall и ActiveDirectory, оставляя реализацию (Router) для определения класса. Но абстракция должна утечь, если UML будет использоваться для фактического построения системы.

Ответы [ 2 ]

3 голосов
/ 18 мая 2009

Если вы моделируете домен, а не реализацию, UML предоставляет стереотипы для отношений. В этом случае вы бы пометили узлы и ребра как {неупорядоченные}, что относится к сумке или набору, и {уникальные}, которые сужают их до набора. Я не вижу никаких ограничений на тип узла или ребра, поэтому, если его там нет, не пытайтесь добавить его:

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

Хороший инструмент для генерации кода / обратного инжиниринга будет отображать {неупорядоченные, уникальные} коллекции UML в / из наборов в исходном коде.

Возможно, вы захотите сделать Map параметрическим типом в вашей доменной модели, если эта информация вам полезна. Но так как информация не используется в реализации, немного сложно понять суть, и создание максимально простой вещи без потери полезности всегда является целью моделирования.

Если вы хотите задокументировать, что определенный класс реализован с использованием наборов, вы можете сделать это с помощью ассоциаций. Вы правы в том, что C ++ или Java позволяют вам объявлять тип элемента в наборе, и это соответствует параметрическим типам в UML. AFAIK Ruby не имеет механизма для реализации таких ограничений типа, поэтому, чтобы документировать реализацию вашей карты в Ruby, документируйте только то, что находится в реализации - у Map есть две ассоциации для Set и не накладывает никаких ограничений на то, что находится в Set. (возможно, вы захотите задокументировать его как инвариантное ограничение, которое затем будет проверено модулем, а не ограничением типа, но, опять же, немного сложно понять, почему вы будете работать в Ruby, если вам нужна ограничительная статическая проверка типов)

2 голосов
/ 18 мая 2009

Не рисуйте линии от Map до Set. В этом случае Set - это просто структура данных, предоставленная вам Руби, содержащая объекты, которые действительно имеют значение. Будь то Set, HashMap, Array и т. Д., Зависит от реализации и не имеет значения для UML. Просто составьте составную строку (1: 0 .. *) от Map до Node и от Map до Edge. В конце концов, на английском языке ваш Map действительно состоит из узлов и ребер, верно? Причина, по которой вы включаете Map в диаграмму, заключается в том, что вы на самом деле создаете класс.

Вы правы насчет диаграммы объекта: в этом случае это не нужно. То же самое с предложенным вами синтаксисом шаблонов.

...