Должен ли один корень быть для всего совокупного графа или несколько корней должны быть в одном графе? - PullRequest
0 голосов
/ 03 ноября 2018

Я запутался в структуре следующего агрегата в моем дизайне.

Должен ли один корень быть для всего агрегированного графа или несколько корней должны быть в одном графе?

Мой случай:

WorktimeRegulation

Id|    Name            |   NumberOfAvailableRotations|  IsActive 
 1|    General Rule    |          2                  |    true 

WorkTime

Id|  Name   |   NumberOfHours| NumberOfShortDays |WorkTimeRegulationId 

1 | Winter  |     8          |    1              |    1
2 | Summer  |     6          |    0              |    1

WorkTimeActivation

 Id|  StartDate  | EndDate      | IsDeFacto |WorkTimeId    
 1 |  2018-10-1  | 2018-12-30   |    1      |    1

Примечание: я считаю (StartDate & EndDate) как DateTimeRange (значениеобъекта)


Теперь Должен ли я считать WorktimeRegulation корнем для всего графа, чтобы он контролировал оба (WorkTime,WorkTimeActivation)?

WorktimeRegulation(ROOT)
        |
        V
    WorkTime
        |
        V
WorkTimeActivation

Или у меня должно быть два агрегата вроде этого:

WorktimeRegulation(ROOT)          |        WorkTime(ROOT)  
        |                         |             |
        V                         |             V
    WorkTime                      |      WorkTimeActivation

Итак, во втором решении у меня два корня! Но если я рассматриваю WorkTime как корень, он будет доступен для использования отдельно от WorktimeRegulation, и я не хочу этого, потому что это нарушит целостность первого агрегата.


Или у меня должно быть два агрегата вроде этого:

WorktimeRegulation(ROOT)          |      WorkTimeActivation(ROOT)  
        |                         |             |
        V                         |             V
    WorkTime                      |         WorkTime

Основано на комментарии:

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

  • Каждый WorkTimeRegulation должен иметь хотя бы один WorkTime, чтобы быть действительным. Таким образом, при создании WorkTimeRegulation я обязательно применяю этот инвариант.
  • Мне нужно проверить любые конфликты между активированными WorkTime с, поэтому после этого я применяю определенную активацию на основе недавней активации или IsDeFacto, примененную пользователем

  1. Какое поведение может быть выполнено в WorkTime? До сих пор я вижу, что это может быть активирован.

    Да, кроме обновления WorkTime, его можно активировать.

  2. Для подтверждения активации вам нужен весь История активации или только последнее событие?

    Не вся история активации, я бы сказал, самая последняя отдельная история активации.

  3. Охватывает ли правила активации несколько рабочих времен (например, если активен то другой не может быть)?

    Да за WorktimeRegulation Я имею в виду Если у меня WorktimeRegulation содержит 3 WorkTimes, то для этого правила есть один и только один активный Worktime.

  4. Можно ли изменить имя, число часов и т. Д. Активаций?

    Если Вы имели в виду IsDeFacto для Activation, тогда да (С помощью этого атрибута пользователь может принудительно активировать определенную активацию, если произошел конфликт между двумя активациями одного и того же WorktimeRegulation), и поскольку предыдущие атрибуты в вашем вопрос принадлежит WorkTime не Activation, numberOfHours можно изменить.

  5. Должно ли изменение этих деталей вступать в конфликт с другим бизнесом операции (например, активация WorkTime?

    Если Вы имели в виду these details предыдущие атрибуты, то ответ - нет.

  6. "если был конфликт между двумя активациями одного и того же WorktimeRegulation "Не могли бы вы рассказать о том, какие конфликты могут произойти? Разве система не должна предотвращать конфликты активации от происходящий? Как работает процесс активации?

    Согласно объяснению бизнес-эксперта: может возникнуть конфликт, и система не должна его предотвращать, но предупреждает этот конфликт для конечного пользователя. Активация выполняется так: Пользователь выбирает конкретную WorkTime в WorkTimeRegulation для активации, затем всплывающее окно активации, позволяющее пользователю вставить StartDate и ожидаемую EndDate, и когда пользователь нажимает активировать, он должен проверять любой конфликт с предыдущей активацией в той же WorkTimeRegulation и предупредить пользователя, если он хочет приоритет для предыдущей активации, тогда он должен использовать IsDefacto для принудительного применения одного из них в случае конфликтов. ПРИМЕЧАНИЕ. Конечный пользователь не знает точно конечную дату для предварительной активации рабочего времени, поэтому он вставляет ожидаемую конечную дату, поэтому может возникнуть конфликт.

  7. сколько будет стоить пункт WorktimeRegulation для несуществующий WorkTime в течение короткого периода времени (например, lation.activateWorkTime (workTimeId), но затем активированная работа элемент будет удален)? Может ли WorkTime быть удаленным / заархивированным?

    WorktimeRegulation не может указывать на несуществующее WorkTime рабочее время не может быть удалено или заархивировано, если оно хотя бы раз активировано, просто активировано и (деактивировано, когда активируется другое рабочее время в те же правила)

  8. Может ли WorkTime быть связан с другим Регламентом после его создание

    Нет

  9. Вы уверены, что не имеет значения, например, имя или числоOfHours меняется одновременно с попыткой активировать WorkTime?

    Теперь я получил ваш вопрос. Пользователь не может изменить WorkTime после первой активации.

  10. Мне до сих пор не ясно, почему могут происходить конфликтующие активации. Почему вы хотите разрешить перекрывающиеся периоды активации, но потом используйте флаг, чтобы определить, какой из них применять. Кажется достаточно легко вместо этого предотвратить перекрывающиеся периоды активации, нет? Это действительно возможно с точки зрения бизнеса, что два периода активации концептуально перекрываются? Почему пользователи даже вводят startDate и endDate вручную? Не могли бы вы просто отслеживать даты, в которые активация / деактивация происходит в системе?

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

  11. Каково действительное деловое значение активации / деактивации WorkTime?

    В течение года, сотрудники, для которых действуют определенные WorkTimeRegulation, их WorkTimes изменились на основе the activation, я имею в виду, что WorkTime может быть 8 часов с октября по декабрь, а затем переключен на 6 часов (еще один WorkTime) с января по сентябрь и т. д. Это похоже на цикл.

Примечание: решение предусматривает только дату начала (например, зима WorkTime начинается с даты ...) и не указав дату окончания! Так оно вставлено примерно и как В результате дата начала следующей активации может конфликтовать с дата окончания предыдущего)

  1. Это потому, что они могут создавать активации раньше времени? В этом дело то же самое ИМО. Обеспечение даты окончания конфликтная активация должна быть точно, когда первичная активация Начало - это почти то же самое, что иметь концепцию deFacto, потому что когда вы используете deFacto, чтобы вызвать активацию над другим, что перекрывается, вы неявно заявляете, что другая активация закончилась когда начинается де-факто, нет?

    Спросив об этом бизнес-эксперта, он объяснил случай следующим образом: отдел кадров отправляет предложение на период активации (дата начала, ожидаемая дата окончания) руководителю компании, после того как менеджер подтвердил предложение , HR выполняет предложение, и им нужно предупредить до даты окончания текущего активного worktime, чтобы уведомить их, чтобы отправить следующее предложение руководителю компании, чтобы они могли использовать defacto для принудительного применения следующего периода или просто активация не перекрывается worktime, так что да, активация сделала головокружение

13. Я думаю, единственное, что нам нужно выяснить, является ли несколько Активировать предложения можно параллельно и по каким правилам?

Не допускается параллельное включение нескольких предложений для одного и того же WorkTimeRegulation, это может быть для нескольких WorkTimeRegulation, но не для одного и того же WorkTimeRegulation.

  1. Кроме того, необходимо ли смоделировать процесс утверждения предложения в системе (например, отслеживание, кто одобрил, возможно, путем загрузки электронная копия подтверждения)?

    Этот процесс не выполняется вручную, его моделировать не нужно.

  2. Наконец, если вы сможете активировать только предложенную активацию что было одобрено?

    YES

Ответы [ 3 ]

0 голосов
/ 09 ноября 2018

Должен ли один корень быть для всего агрегированного графа или несколько корней должны быть в одном графе?

Это зависит.

Более важный момент: он очень мало зависит от структуры отношений между сущностями домена.

Определение совокупных границ в первую очередь связано с тем, как изменяется состояние объектов; в частности, если любое из этих изменений требует одновременной координации между двумя объектами.

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

Разделение сущностей на отдельные агрегаты значительно упрощает параллельное редактирование, но при этом становится сложнее координировать изменения между сущностями.

Один агрегат действительно хочет иметь одно хранилище - попытка координировать записи в двух разных местах (так называемая двухфазная фиксация) - это перетаскивание. Если два объекта принадлежат разным агрегатам, модель подразумевает, что они могут храниться в отдельных устройствах.

Также предполагается, что они имеют независимые жизненные циклы - одно из преимуществ агрегатов заключается в четком понимании графа объектов, которые архивируются вместе.

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

Вы также можете посмотреть на источник данных - особенно источники изменений во времени. Если изменения всегда исходят из одних и тех же авторитетов, то, скорее всего, это будет один агрегат. С другой стороны, если данные WorktimeRegulation и Worktime поступают из разных источников, это повышает вероятность одновременных изменений, что намекает на несколько агрегатов.

Важный вопрос для изучения: какова стоимость бизнеса, если предприятия не в точном согласии? Если данные, хранящиеся в Worktime, в течение минуты не согласуются с WorktimeRegulation, кто-нибудь замечает? Случаи, когда у вас есть некоторая свобода выстраивать порядок вещей, когда вы можете гибко определять порядок внесения изменений, имеют тенденцию к множественным агрегатам.

Два агрегата WorkTime - это ребенок в обоих из них

Каждая сущность в вашей модели должна принадлежать ровно одному агрегату; теоретически можно иметь WorkTime внутри WorktimeRegulation и WorkTime внутри WorktimeActivation, но иметь то же самое рабочее время внутри агрегата WorktimeRegulation и внутри агрегата WorktimeActivation - "против правила". Это подразумевает, что либо изменения WorktimeActivation могут повлиять на WorktimeRegulation, либо сам WorkTime является чем-то, что следует разбить на две отдельные части.

0 голосов
/ 12 ноября 2018

Принимая следующие правила:

  • В любой момент времени может быть только одно активное рабочее время на регламент рабочего времени.

  • В любой момент времени может быть только одно ожидающее предложение активации рабочего времени.

  • Процесс утверждения предложений не должен отслеживаться в системе.

  • Регулирование рабочего времени не может указывать на несуществующее рабочее время. Рабочее время нельзя удалить или заархивировать, если оно было активировано один раз.

Я думаю, что было бы разумно смоделировать это так, чтобы WorkTimeRegulation был агрегированным корнем, который имеет коллекцию WorkTime сущностей. Кроме того, ему необходимо смоделировать текущее предложение об активации, а также текущий активный WorkTime, чтобы обеспечить соблюдение вышеупомянутых правил. Предложение / активное состояние может быть смоделировано на самих WorkTimeRegulation или WorkTime экземплярах (в этом случае корень должен гарантировать, что только один активен одновременно и т. Д.). Это действительно предпочтение дизайна на тот момент, и обе стратегии позволят вам защитить инварианты. Кроме того, сущность WorkTime должна также отслеживать, была ли она когда-либо активирована, чтобы предотвратить дальнейшие изменения ее других атрибутов (например, numberOfHours).

Вот пример того, как это может выглядеть:

enter image description here

Приведенная выше модель гарантирует, что все необходимые данные для проверки инвариантов являются частью одного корня и моделирует минимальную структуру, необходимую для хранения состояния и применения правил в памяти.

Однако эта модель сама по себе не решает проблему истории активации. Вам не нужна вся история для реализации инвариантов, поэтому вам не нужно моделировать ее в границах AR, но бизнесу, безусловно, все еще будут нужны такие данные.

На данный момент есть несколько стратегий, которые вы можете использовать, например:

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

  • Модель неизменяемая ActivationHistoryEntry AR. Например. historyEntry = regulation.activate(workTimeId); save(historyEntry); save(regulation);. Это очень похоже на доменные события.

Вышеуказанная модель, конечно, не идеальна и может быть усовершенствована. Например, я также думал о моделировании концепции Activation VO вместо использования логического флага, который может быть разных типов (активный, неактивный, предложенный). Это, возможно, позволило бы использовать более выразительный язык, где, например, ActiveActivation можно получить только путем активации ActivationSuggestion, где ActiveActivation удерживает предложенную дату окончания (если доступно, чтобы уведомить HR, который им нужен отправить следующее предложение).

0 голосов
/ 06 ноября 2018

Вы ошибаетесь во втором варианте. Рабочее время не относится к первому агрегату как дочерний объект. Он просто принадлежит ко второму агрегату как корень. Первый агрегат будет ссылаться на второй агрегат. Вы сказали, что не хотите этого, потому что это нарушит целостность. Ну, это все о том, где вы хотите поставить транзакционные границы. Если вы хотите изменить три объекта в одной транзакции, перейдите к первому мнению (один агрегат). Если вы можете жить с задержками, выберите второй вариант (две совокупности) с возможной согласованностью между ними.

UPDATE:

Похоже, у вас неправильное представление о агрегатах. Ваш новый рисунок:

WorktimeRegulation(ROOT)      |      WorkTimeActivation(ROOT)
    |                         |             |
    V                         |             V
WorkTime                      |         WorkTime

тоже неправильно. Если WorkTime является дочерним объектом в агрегате, то другой агрегат должен ссылаться на корень, а не на дочерний объект. И, кроме того, WorkTime является одной сущностью. Вы не можете нарисовать это два раза, принадлежащих к обоим агрегатам. Сущность просто принадлежит одному агрегату.

У вас есть 3 объекта. У вас есть следующие возможности агрегатов:

  • Одна совокупность с 3 сущностями.
  • Два агрегата: один с двумя объектами; и еще один с другой сущностью.
  • Три совокупности: каждая с одной сущностью.

Некоторые основные правила:

  • Если агрегат ссылается на другой, он должен ссылаться на корень, вызывая поведение, которое предлагает корень.
  • Следовательно, дочерняя сущность агрегата не может ссылаться на сущность другого агрегата.
  • Дочерняя сущность агрегата может ссылаться на другой корень агрегата.

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...