WCF / SOA - Почему я должен создавать объекты параметров для простых запросов

12

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

Мы пытаемся разработать стандарты, которым мы можем следовать как группа, и один из предложенных стандартов меня немного беспокоит:

Мы стандартизировали шаблон, в котором каждая операция принимает объект запроса и возвращает объект ответа.

Я понимаю, что это более или менее стандартный подход для многих людей, но я спрашиваю, почему я должен беспокоиться? (Я не так хорош с полученной мудростью, мне нужно кое-что, почему).

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

Мое беспокойство усиливается от взгляда на WSDL, который генерируется из наших контрактов. WCF генерирует сообщения запроса и ответа автоматически и переносит даже объект запроса / ответа.

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

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

  • Это делает простые услуги менее выразительными
  • Вы бы сделали это в любом случае для комплексного обслуживания
  • WCF в любом случае создает запрос / ответное сообщение

Я нашел следующие аргументы в пользу этого подхода:

Он поддерживает управление версиями, позволяя вставлять необязательные параметры в объект запроса.

В свое время я сделал достаточно COM, и я бы посчитал это почти анти-паттерном для управления версиями. Для некоторых вещей, я полагаю, это помогло бы, но я ожидаю, что там, где это помогло бы, у вас уже есть объект параметра в любом случае.

Это позволяет изолировать общие данные и поведение от базового класса

Этот имеет некоторый вес со мной.

Он уводит людей от поведения в стиле RPC и к поведению обмена сообщениями

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

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

Энди Дэвис
источник

Ответы:

3

Я думаю, что версионирование, вероятно, лучший аргумент. Когда у вас есть действующий договор на эксплуатацию, как

int GetPersons(int countryId);

что вы хотите улучшить, например, с помощью другого фильтра позже

int GetPersons(int countryId, int age);

Вам нужно будет написать новый контракт на эксплуатацию и с новым именем, поскольку он должен быть уникальным. Или вы можете оставить имя и опубликовать новый v2 вашего сервиса со старым v1 для обратной совместимости.

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

Однако я также призываю назвать ваши объекты соответствующим образом. Даже если он просто оборачивает int, если вы начинаете с IntMessageчего-то подобного, вы не делаете себе одолжение, расширяя его. Вы должны были бы назвать его, например, PersonFilterс самого начала, что означает, что вы должны немного подумать о том, что этот сервисный вызов должен ожидать в качестве параметра семантически и, следовательно, что он должен делать. Может быть (и это очень расплывчато, может быть), это поможет в разработке правильных сервисов и поддержании достойного размера API.

Это позволяет изолировать общие данные и поведение от базового класса

С этим нужно быть осторожным. Контракты на наследование и передачу данных не очень хорошо сочетаются друг с другом. Это работает, но вам нужно будет указать все известные подтипы контракта, которые могут передаваться по проводам, в противном случае сериализатор контракта данных не сможет пожаловаться на неизвестные типы.

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

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

Andreas
источник
Я думаю, что причина, почему я беру
Энди Дэвис
(извините, интерфейс комментариев вызывает у меня горе) Спасибо за ответ. Я думаю, что причина, по которой я принимаю аргумент управления версиями с такой долей соли, состоит в том, что если вы добавили новый аргумент, вы, вероятно, изменили семантику. Если (как в вашем примере) вы только что добавили возраст, то семантика, вероятно, была предназначена для поиска, и у вас был «поисковый объект» для начала.
Энди Дэвис,
Теперь рассмотрим мой пример политики безопасности. Возможно, мы решили, что для правильного предоставления политики безопасности нам нужно знать не только пользователя, но и средство, в котором он работает. Это гораздо больше, чем добавление аргумента, мы изменили семантику вызова. Предполагая, что мы каким-то образом можем предоставить эту информацию для вызывающего абонента предыдущей версии, я думаю, что имеет больше смысла версия контракта на обслуживание. Тогда реализация старой версии может быть изолирована, и вы не будете смешивать старую семантику с новой.
Энди Дэвис,
0

Думаю, что заметки Мартина Фаулера об объекте передачи данных здесь уместны.

Когда вы работаете с удаленным интерфейсом, таким как Remote Facade (388), каждый его вызов обходится дорого. В результате вам нужно уменьшить количество вызовов, а это значит, что вам нужно передавать больше данных с каждым вызовом. Один из способов сделать это - использовать множество параметров. Тем не менее, это часто неудобно для программирования - на самом деле, это часто невозможно с такими языками, как Java, которые возвращают только одно значение.

Решение заключается в создании объекта передачи данных, который может содержать все данные для вызова. Это должно быть сериализуемым, чтобы пройти через соединение. Обычно на стороне сервера используется ассемблер для передачи данных между DTO и любыми объектами домена.

То же самое может относиться к запросам. Что касается RPC, и почему это плохо:

Неужели естественные интерфейсы заставляют людей забывать, что они вызывают удаленный сервис?

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

Кайл Ходжсон
источник
Спасибо за вклад, но я не думаю, что обсуждение DTO является настолько важным. Это такое же количество вызовов, и если вы посмотрите на WSDL, все автоматически упаковывается в объект запроса и ответа. Соглашение касается видимой семантики, то есть люди должны думать об этом как о запросе и ответе, а не как о вызове удаленного метода.
Энди Дэвис
Не могли бы вы рассказать о RPC, поощряющих тесно связанных клиентов и услуги? Я не вижу, что это влияет на сервис вообще. Для клиента я действительно не вижу, как что-то действительно меняется. В любом случае, у меня есть клиент с прокси, который описывает ряд операций, предоставляемых службой. Кто на самом деле реализует другую сторону сервиса, в любом случае не является делом клиента.
Энди Дэвис,