@alexg-nn

Как лучше организовать событие предметной области на простом примере?

Всем привет.

Упражняюсь в ООП с DDD подходом на простом примере. Допустим, у нас есть в саду есть кран для полива грядок. Попытаемся смоделировать его работу. Итак, кран может быть открыт и закрыт. Пусть у нас будет агрегат Tap

class Tap {
 // ... id и другие свойства опущены
 public function open() { // Emit TapOpened event }
 public function close() { // Emit TapClosed event }
}

class TapOpened extends DomainEvent {
  // tapId и другие свойства
}

class TapClosed extends DomainEvent {
  // tapId и другие свойства
}


Теперь усложняем задачу - мы не хотим стоять целый час у крана и ждать, пока польются грядки. Мы хотим настроить автоматическое выключение (для простоты) крана по таймеру. В реализации крана ничего не меняется. В качестве таймера мы используем внешний сервис TimerService, который можно попросить выбросить событие TimerCreated и TimerTimeout в нужное время. Клиентов у этого сервиса может быть много, поэтому событие TimerTimeout он выбрасывает одно на всех:

interface TimerService {
  public function windUp(period): TimerIdentity;
}

class TimerCreated extends DomainEvent {
  // timerId и другие свойства
}

class TimerTimeout extends DomainEvent {
  // timerId и другие свойства
}


Для активации такого усовершенствованного крана используем сервис TapAutoCloser

class TapAutoCloser {
  private timeService;

  public function openTapFor(tap, period) {
    tap.open();
    timer = timeService->windUp(period);
    //...
  }

  public function timeoutHandler(timerTimeoutEvent) {
   // ..
   tap.close()
   // ..
  }
}


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

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

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

Но чтобы они могли рассчитать своё состояние сами, они должны знать, когда кран запланирован к закрытию. А в нашем случае контекст крана сообщает только, что он открыт (TapOpened), но ничего не говорит о том, когда он будет закрыт (ведь он и не знает). Где в этой схеме передать знание о времени работы крана через события в другие контексты?

Мне видится только один вариант - сервис таймера знает о наличии крана и вместо обезличенных TimerCreated и TimerTimeout будет выбрасывать что то типа TapAutocloseTimerCreated и TapAutocloseTimerTimeout. Но тогда сервис таймера выходит узконаправленным. А если теперь и свет надо будет включать по таймеру, то неужели для этого создавать свой таймер. Будет TapCloseTimer и LightSwitchTimer и т.д.? Или же их как то можно объединить?
  • Вопрос задан
  • 60 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы