Дизайн отношений сущностей: взаимоисключающие отношения Has-A - PullRequest
0 голосов
/ 05 февраля 2019

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

Пример:

У меня есть и проекты, и процедуры.Каждый может содержать несколько задач.Задача может принадлежать Проекту или Процедуре, но не более чем одновременно.Задача может быть перемещена из Проекта в Процедуру и наоборот.

Таким образом, в любой конкретный момент Задача имеет отношение один-ко-многим с Проектом или отношение один-ко-многим с Процедурой.

В данный момент я рассматриваюЗадача как таковая:

   class Task(id, name, project_id, procedure_id):
       if project_id and procedure_id:
           throw Exception("A Task can not be assigned to a Project and a Procedure at the same time")

       self.id = id
       self.name = name
       self.project_id = project_id
       self.procedure_id = procedure_id

   def move_to_project(project_id):
       self.procedure_id = None
       self.project_id = project_id

   ...

Задача защитит инвариант, что она может принадлежать только одному проекту или процедуре.Фабричные методы в Project и Процедуре могут создавать Задачу с соответствующим ID отношения.

Задача не находится в одной и той же совокупности, поэтому я хочу смоделировать отношения по идентичности.

Мне кажется, что единственный способ защитить этот инвариант - это смоделировать задачупуть.В противном случае я бы получил гигантскую совокупность процедур / проектов / задач.

Похоже ли это на здравый подход, или у кого-нибудь есть советы по альтернативным подходам к проектированию, которые, возможно, стоит изучить?

Ответы [ 2 ]

0 голосов
/ 05 февраля 2019

У вас должны быть методы TaskService.AssignToProject () и TaskService.AssigneToProcedure () на прикладном уровне TaskService.Если Задача - это отдельная совокупность, это означает, что она может жить своей жизнью без Процедуры или Проекта.Они могут быть пустыми в течение некоторого периода времени.ИД процедуры или ИД проекта должны быть назначены при вызове TaskService.AssignToProject () или TaskService.AssigneToProcedure ().Таким образом, в вашем TaskService.AssignToProject () вы получаете Task и Project из db и вызываете task.AssignTo (project).Затем вы проверяете, имеет ли значение ModuleId значение NULL, и делаете то, что вам нужно (выдает исключение или UnassignFromProcedure ()).После того, как назначение выполнено, вы вызываете событие домена TaskAssignedToProject, перехватываете его и в ДРУГОМ ТРАНЗАКЦИИ вызываете ProjectService.CommitTask ().Это добавит эту задачу во внутреннюю коллекцию CommittedTasks в агрегате проекта.

0 голосов
/ 05 февраля 2019

Если задача не может быть связана с проектом и процедурой одновременно, у меня не будет конструктора с двумя идентификаторами.У меня был бы один для идентификатора проекта и другой для идентификатора процедуры.И я сделал бы это с фабричными методами, названными согласно UL.Таким образом вы создаете задачу, связанную либо с проектом, либо с процедурой, но не с обеими.

...