Я работаю над проектом, в котором мы пытаемся применить как доменный дизайн, так и REST к сервис-ориентированной архитектуре. Мы не беспокоимся о 100% соблюдении REST; вероятно, было бы лучше сказать, что мы пытаемся создать ресурсно-ориентированные HTTP API (~ Уровень 2 модели зрелости REST Ричардсона). Тем не менее, мы стараемся держаться подальше от использования HTTP-запросов в стиле RPC, т.е. мы пытаемся реализовать наши HTTP-глаголы в соответствии с RFC2616, вместо того, чтобы использовать , например, POST
делать IsPostalAddressValid(...)
.
Тем не менее, акцент на этом, кажется, происходит за счет нашей попытки применить доменно-ориентированный дизайн. Только с GET
, POST
, PUT
, DELETE
и несколько других редко используемыми методами, мы склонны строить Cruddy услуги, а также услуги Cruddy , как правило, имеют анемию модели предметной области.
POST
: Получить данные, проверить их, сбросить в данные. GET
: Получить данные, вернуть их. Там нет реальной бизнес-логики. Мы также используем сообщения (события) между сервисами, и мне кажется, что большая часть бизнес-логики строится вокруг этого.
Находятся ли REST и DDD в напряжении на каком-то уровне? (Или я что-то здесь неправильно понимаю? Возможно, мы делаем что-то еще не так?) Возможно ли построить сильную модель предметной области в сервис-ориентированной архитектуре, избегая при этом вызовов HTTP в стиле RPC?
IsPostalAddressValid(...)
будет соответствовать "Предоставлению блока данных, такого как результат отправки формы, процессу обработки данных"?Ответы:
Первый закон распределенных систем Мартина Фаулера: «Не распространяй свои объекты!» Удаленные интерфейсы должны быть грубыми, а внутренние интерфейсы - точными. Зачастую модель богатых доменов применяется только в ограниченном контексте .
REST API разделяет два разных контекста, каждый из которых имеет свои собственные внутренние модели. Контексты взаимодействуют через грубый интерфейс (REST API) с использованием «анемичных» объектов (DTO).
В вашем случае это звучит так, будто вы пытаетесь распространить контекст через границу, которая является REST API. Это может привести к детализированному удаленному интерфейсу или анемичной модели. В зависимости от вашего проекта это может быть или не быть проблемой.
источник
POST был намеренно разработан, чтобы быть «намеренно расплывчатым»; Результат POST зависит от реализации. Что мешает вам делать то, что делают Twitter и другие разработчики API, и определять каждый метод POST в части API, не относящейся к CRUD, в соответствии с вашими конкретными требованиями? POST - это заглавный глагол. Используйте его, когда ни один из других глаголов не подходит для операции, которую вы хотите выполнить.
Другими словами, ваш вопрос может быть в равной степени сформулирован так: «Стимулируют ли« умные »объекты дизайн в стиле RPC?» Даже Мартин Фаулер (который придумал термин «Модель анемичной области») признает, что голые DTO имеют некоторые преимущества:
Что касается модели зрелости Ричардсона , вы можете перейти на уровень 3, не беспокоясь о «моделях анемичной области». Помните, что вы никогда не собираетесь передавать поведение в браузер (если только вы не планируете вводить Javascript через свои модели).
REST - это в основном независимость от машины; реализовать модель REST в той степени, в которой вы хотите, чтобы ваши конечные точки представляли ресурсы, и чтобы пользователи вашего API могли легко получать доступ к этим ресурсам и поддерживать их стандартным способом. Если это кажется анемичным, то пусть будет так.
Смотрите также
мне нужно больше глаголов
источник
REST API - это всего лишь один тип уровня представления. Это не имеет ничего общего с моделью предметной области.
Вопрос, который вы опубликовали, возник из-за вашего заблуждения, что вам как-то нужно адаптировать одно к другому. Вы не
Вы сопоставляете модель своего домена с REST API так же, как вы сопоставляете модель своего домена с RDBMS через ORM - должен существовать этот слой отображения.
Домен ← ORM →
Домен СУБД ← Отображение REST → API REST
источник
ИМХО, я не думаю, что они склонны поощрять модели анемичных доменов (ADM), но они требуют, чтобы вы потратили некоторое время и все обдумали.
Прежде всего, я думаю, что основной характеристикой ADM является то, что они почти не ведут себя в них. Это не значит, что система не имеет поведения, просто она обычно находится в каком-то классе обслуживания (см. Http://vimeo.com/43598193 ).
И, конечно, если поведение не существует в ADM, то что же? Ответ, конечно же, данные. И как это соотносится с REST API? Предположительно, данные сопоставляются с содержимым ресурса, а поведение - с глаголами HTTP.
Таким образом, у вас есть все, что нужно для построения модели расширенного домена, вам просто нужно увидеть, как глаголы HTTP отображаются на операции домена над данными, а затем поместить эти операции в те же классы, которые инкапсулируют ваши данные.
Я думаю, что люди обычно сталкиваются с проблемами в том, что им трудно увидеть, как глаголы HTTP отображаются на поведение их домена, когда поведение выходит за рамки простого CRUD, то есть, когда есть побочные эффекты в других частях домена за пределами ресурс, изменяемый запросом HTTP. Один из способов решения этой проблемы - с помощью доменных событий ( http://www.udidahan.com/2009/06/14/domain-events-salvation/ ).
источник
Эта статья довольно связана с предметом, и я верю, что отвечает на ваш вопрос.
Основная концепция, которая, я думаю, хорошо отвечает на ваш вопрос, резюмируется в следующем абзаце из упомянутой статьи:
«Очень важно различать ресурсы в REST API и доменные объекты в доменно-ориентированном дизайне. Доменно-ориентированный проект применяется к аспектам реализации (включая реализацию API), в то время как ресурсы в REST API определяют структуру и контракт API. Ресурс API выбор не должен зависеть от деталей реализации базового домена. "
источник
Несколько достаточно успешных реализаций, которые я видел / построил, отвечают на вопрос о том, как они смешивают метафору глагол + существительное, используя грубые «дружественные бизнесу» методы, которые воздействуют на сущности.
Таким образом, вместо (обреченного)
getName()
метода / службы, выставьтеgetPerson()
, передавая такие вещи, как идентификатор типа / ID, возвращая всюPerson
сущность.Поскольку поведение объекта Person в таком контексте не может быть адекватно передано (и, возможно, оно не должно быть в контексте, ориентированном на данные, как это), вполне разумно определить модель данных (по сравнению с объектом) для пар запрос / ответ услуга / с.
Сами службы и определенные глаголы добавят некоторые допустимые доменные поведения, элементы управления и даже правила перехода состояний для объектов. Например, в отношении того, что происходит при
transferPerson()
вызове службы , будет существовать логика, специфичная для предметной области, но сам интерфейс будет определять только входные / выходные сущности / данные без определения их внутреннего поведения.Я не согласен с авторами, которые скажут, например, что реализация глагола передачи принадлежит классу Person или связана с сервисом, ориентированным на человека. Действительно, способ переноса для a
Person
и его варианты (в этом простом примере) будут лучше определены как aCarrier
, где онPerson
может не знать даже, какие способы переноса доступны или как вообще происходит перенос (кто знает, как работают реактивные двигатели) так или иначе).Делает ли это
Person
сущность анемичной? Я так не думаю.Может / должна быть логика в отношении вещей, характерных для личности, которые являются внутренними для человека, например, состояние их здоровья, которое не должно определяться внешним классом
Однако, в зависимости от вариантов использования, вполне допустимо, чтобы у класса объекта не было важных / соответствующих поведений в определенных системах, таких как служба назначения мест в транспортной системе. Такая система может хорошо реализовывать службы на основе REST, которые имеют дело с экземплярами Person и соответствующими идентификаторами, но никогда не определяют / не реализуют их внутреннее поведение.
источник
Ваша проблема в том, что вы пытаетесь втиснуть свою модель в базовый набор глаголов, максимально используя POST?
В этом нет необходимости - я знаю, что для большинства людей REST означает POST, GET, PUT и DELETE, но http rfc говорит:
И системы, такие как SMTP, используют тот же стиль методов, основанных на глаголах, но с совершенно другим набором.
Таким образом, нет никакой причины, по которой вы должны их использовать, вы можете использовать любой набор глаголов, который вам нравится (хотя, действительно, вы обнаружите, что можете делать все, что вам нужно в основной четверке, немного подумав). То, что отличает REST от других механизмов, заключается в том, что эти глаголы используются без сохранения состояния и последовательны. Вы не должны пытаться внедрить систему передачи сообщений между уровнями, так как тогда вы в основном не выполняете REST, вместо этого вы используете механизм передачи сообщений, RPC или очереди сообщений, который, несомненно, лишит вас преимуществ REST (т.е. простота, которая заставляет его действительно хорошо работать через соединение http).
Если вам нужен полнофункциональный, сложный протокол обмена сообщениями, создайте его (если вы можете сделать это через Интернет, есть причина, почему REST так популярен), но в противном случае попробуйте придерживаться архитектурного дизайна REST.
источник