На ревью нашли ошибку в UML-модели предметной области. Определите, какое семантическое утверждение модели неверно.
@startuml
class Заказ
class Товар
Заказ "1" *-- "1..*" Товар
class Каталог
Каталог "1" o-- "0..*" Товар
@enduml
Ошибка в том, что один и тот же объект Товар показан как составная часть Заказа и одновременно как агрегируемая часть Каталога. Композиция означает исключительное владение частью одним составным объектом в каждый момент времени, поэтому товар из каталога не должен моделироваться той же сущностью, которая физически входит в заказ.
Корректнее отделить Товар как самостоятельную сущность от Строки заказа, которая композиционно принадлежит заказу. Каталог при этом следует связать с товаром обычной ассоциацией либо использовать слабую агрегацию только если такая семантика действительно нужна.
В UML отношения между объектами нужны не только для отображения ссылок, но и для фиксации смысла предметной области. Для отношения «целое—часть» появились специальные варианты агрегации: композиция с чёрным ромбом и разделяемая агрегация с белым ромбом.
Композиция помогает выразить более сильное владение: часть принадлежит одному целому, а её существование и жизненный цикл связаны с этим целым. Это отличает её от обычной ассоциации, которая сама по себе не задаёт владение или порядок удаления объектов.
В примере Товар — это самостоятельная сущность каталога: один товар может присутствовать в каталоге независимо от конкретного заказа и использоваться во многих заказах. Если одновременно трактовать его как композиционную часть заказа, модель утверждает, что заказ владеет самим товаром.
Такое решение приводит к неверным выводам о жизненном цикле и идентичности. Удаление заказа может ошибочно интерпретироваться как удаление товара, а один и тот же товар окажется частью нескольких заказов, что противоречит смыслу композиции.
Композиция Заказ *-- СтрокаЗаказа означает, что строка заказа принадлежит конкретному заказу. В каждый момент времени у неё не должно быть нескольких композиционных владельцев; при удалении заказа его строки обычно также перестают существовать как части этого заказа.
Но товар и строка заказа — разные понятия. Товар описывает позицию каталога: наименование, артикул и общие характеристики. Строка заказа фиксирует контекст покупки: выбранный товар, количество и цену на момент оформления.
Модель можно исправить так:
Здесь СтрокаЗаказа является частью заказа, а Товар остаётся независимым объектом. Связь каталога с товаром показана обычной ассоциацией, потому что UML-агрегация с белым ромбом во многих моделях не добавляет практически полезных ограничений сверх явно заданных связей и кратностей.
Важно не делать вывод о физическом удалении автоматически. UML-модель задаёт семантику предметной области, но конкретное каскадное удаление, хранение снимка цены и правила архивирования определяются требованиями и реализацией.
В интернет-магазине аналитик сначала связал заказ с товаром композицией. На ревью выяснилось, что после удаления тестового заказа товар исчезал из логики каталога, а исторические заказы должны были сохранять название и цену покупки.
Рассматривались два варианта. Можно было оставить композицию непосредственно с товаром и запретить удаление товара, но это противоречило бы смыслу композиции и создало бы исключения в правилах жизненного цикла. Можно было заменить композицию на обычную ассоциацию, однако тогда модель перестала бы явно выражать, что заказ состоит из самостоятельных строк.
Выбрали СтрокуЗаказа как композиционную часть заказа, а товар связали со строкой обычной ассоциацией. В строке дополнительно зафиксировали цену и отображаемое наименование на момент покупки. Это сохранило независимость каталога, историческую корректность заказов и ясную границу жизненного цикла строк.
Вопрос: Может ли один товар входить в несколько заказов при такой исправленной модели?
Ответ: Да. Один объект Товар может быть связан с множеством строк разных заказов, поскольку связь строки с товаром — обычная ассоциация. При этом каждая СтрокаЗаказа принадлежит только одному заказу через композицию. Ограничения на повторное добавление одного товара в один заказ задаются отдельным бизнес-правилом, а не самим фактом ассоциации.
Вопрос: Обязывает ли композиция всегда физически удалять часть при удалении целого?
Ответ: Композиция выражает зависимость жизненного цикла части от целого, но не является прямой инструкцией конкретной базе данных или ORM. В предметной модели строки заказа не должны продолжать существовать как части удалённого заказа, однако система может использовать мягкое удаление, архивирование или запрет удаления заказа. Эти решения должны быть согласованы с требованиями хранения истории.
Вопрос: Чем белый ромб принципиально лучше обычной ассоциации в данном примере?
Ответ: Не обязательно лучше. Разделяемая агрегация может визуально подчеркнуть отношение «каталог содержит товары», но сама по себе не описывает столь строгий жизненный цикл, как композиция, и часто не добавляет проверяемых ограничений. Если важны только доступность товара через каталог и кратности, обычная ассоциация обычно точнее и не создаёт ложного впечатления владения.