Недостаток архитектуры в размещении ссылки на сервис внутри модели домена? (Джава)
Тема ссылается на решение, приведенное ниже, и задаюсь вопросом, какие у него недостатки в общем контексте, а также в конкретном контексте.
Вопросы для ответа:
- Какую архитектуру следует выбрать для такого рода проблем / приложений в мире Java? (общий контекст)
- Какие недостатки имеет следующий способ моделирования приложения?
- Является ли предложенное решение приемлемым для данного контекста? (конкретный контекст)
Общий контекст:
У нас есть вид приложения с основным конвейером с потоковой обработкой. Давайте назовем это приложение AnimalSpecialDayCycle. Подумайте об этом как о "особом дне в отеле для животных".
Животные будут приходить один за другим, и отель будет делать для них особый день, предлагая им еду, дрессировку, размножение и хороший сон.
Давайте рассмотрим модель анемичной области, такую как:
Animal
- gender
DigestingSystem
- type (vegetable|meat)
- foodReservesLevel
MuscoskeletalSystem
- membersTypeSet (legs|wings|fins)
- hasTail
- musclesPowerLevel
ReproductiveSystem
- type (eggs|insemination)
Mood:
- energyLevel
- happiness
Предложенное решение:
Мы разделили это приложение на разные модули (отдельные приложения), которые взаимодействуют между собой через общую модель предметной области под названием "Animal" (которая преобразуется в JSON|XML).
Modules:
EatModule
EatServiceInterface (with method "eat(Animal)")
- MeatEattingService
- VegetableEattingService
TrainModule
TrainServiceInterface (with method "train(Animal)")
- FlyableTrainService
- RunningTrainService
- SwimmingTrainService
BreedModule
BreedServiceInterface (with method "breed(Animal)")
- EggsBreedingService
- InseminationBreedingService
SleepModule
SleepServiceInterface (with method "sleep(Animal)")
- FlyableSleepingService
- LaydownSleepingService
- StandingSleepingService
- UnderwaterSleepingService
Пример использования животных и услуг, которые они используют:
- Собака (MeatEattingService, RunningTrainService, InseminationBreedingService, LaydownSleepingService)
- Horse (VegetableEattingService, RunningTrainService,
InseminationBreedingService, StandingSleepingService) - Aligator (MeatEattingService, Плавательный тренинг, сервис по разведению яиц, UnderwaterSleepingService)
- Попугай (VegetableEattingService, FlyableTrainService, Служба разведения яиц, FlyableSleepingService)
Теперь я предлагаю расширить модель домена Animal в каждом модуле, например:
public class AnimalEattingModel extends Animal {
public EattingServiceInterface eattingServiceInterface;
public void eat() {
eattingServiceInterface.eat(this);
}
}
То же самое для других модулей.
Когда животное входит в модуль, и мы создаем объект из JSON|XML (или того, что Fromat имеет сообщение из предыдущего модуля), мы также устанавливаем правильную реализацию службы для этого модуля.
(Например, если Акула попадет в EatModule, мы установим в его поле eattingServiceInterface правильную реализацию для своего типа.)
Практически, я ищу способ сохранить полиморфизм, но отделить поведение от состояния объекта, сохраняя модель анемичной области.
Преимущества, которые я вижу:
- развязать деловое поведение в своих классах и легко изменять их
- полиморфизм и избегание сложной структуры "если" и грязного кода в этой сервис-ориентированной архитектуре и анемичной модели
Недостатки:
- зависимости: домен зависит от сервиса, а сервис от домена
Особый контекст:
Мы разработали приложение сверху с нуля, и, скажем, мы сделали 50% (серьезные усилия уже вложены).
Нам нужен объект "Animal" в каждом модуле, потому что в конце модуля мы отправляем "событие" с "новым состоянием" объекта Animal.
Я не доволен тем, как все происходит. Теперь, когда мы разрабатываем, мы просто включили много "если" в нашем коде.
У нас нет подклассов, потому что, когда я предложил создать их, мне ответили, что мы не должны создавать подкласс только потому, что у нас есть разные значения в одном поле, поле, которое можно использовать только один раз, чтобы выполнить оператор "если" в один из модулей.
Теперь я считаю, что нам нужен полиморфизм, но у нас нет шансов отойти от SOA и модели анемичной области, поэтому я подумал над решением выше.