Из приведенного вами описания кажется, что Point на самом деле не является частью вашего Ubiquitous Language - Зона есть. Вы не устанавливаете точку для хранения - вы назначаете ей зону. Другими словами, подпись этой операции не должна быть setLocation(Point location)
- она должна быть assignZone(Zone locationZone)
. Перевод между точкой, выбранной пользователем, и зоной должен произойти до того, как будет выполнена операция модели домена. Вот как я это смоделирую.
Пример добавлен после комментариев (C #, если вы не возражаете - и показывает только концепцию). Код предполагает командный подход к выполнению действий пользователя - так я обычно это делаю, но может быть даже Application Service
или Controller
, в зависимости от структуры вашего приложения.
public class StoreLocationHandler : Handles<LocateStoreCommand>
{
public void Handle(LocationStoreCommand command)
{
// Location contains coordinates as well as zone info and can be obtained only via LocationService
Location location = LocationService.IdentifyZone(command.Coordinates);
Store store = StoreRepository.Get(command.StoreId);
store.AssignLocation(location);
// persist changes - either by Unit of Work or Repository
}
}
Дело в том, что вам не нужно создавать все внутри сущностей вашего домена - Zone, похоже, является Value Object с точки зрения Store. Кроме того, дальнейшее разделение этих двух концепций может привести к дополнительным возможностям, таким как идентификация зоны не в сети, а посредством какого-то фонового процесса (ради производительности или масштабируемости). Кроме того, на мой взгляд, он подходит лучше, учитывая принцип Dependency Injection .
В конце концов, домен не заботится о том, как создается или восстанавливается зона, он заботится об ассоциации между Магазином, его местоположением и зоной, в которую он попадает. Почему он должен отвечать за перевод между точкой и зоной? По крайней мере, так я это вижу.