WCF / SOA - ¿Por qué debería crear objetos de parámetros para solicitudes simples?

12

Nuestra compañía está comenzando una iniciativa SOA bastante grande. Estamos haciendo muchas cosas bien: hay buena comunicación; dinero para herramientas cuando sea apropiado; y hemos aportado una buena experiencia para ayudarnos con la transición.

Estamos tratando de desarrollar estándares que podamos seguir como grupo, y uno de los estándares propuestos me está molestando bastante:

Hemos estandarizado el patrón donde cada operación toma un objeto de solicitud y devuelve un objeto de respuesta.

Me doy cuenta de que este es un enfoque más o menos estándar para mucha gente, pero me pregunto por qué debería molestarme. (No soy tan bueno con la sabiduría recibida, necesito algunos por qué).

La mayoría de los servicios que proporcionaré son simples recuperaciones de metadatos organizacionales. Por ejemplo, encuentre la política de seguridad para un usuario en particular. Esto necesita una identificación de usuario y nada más. El estándar me dice que debería envolver esta solicitud en un objeto y envolver la política devuelta en un objeto de respuesta.

Mi inquietud se amplifica con una mirada al WSDL que se genera a partir de nuestros contratos. WCF genera mensajes de solicitud y respuesta automáticamente y ajusta incluso el objeto de solicitud / respuesta.

Entiendo completamente que si está haciendo una solicitud compleja, entonces un objeto de entrada complejo está garantizado. Eso es lo que haría incluso si los servicios no estuvieran involucrados.

Mi pregunta es por qué debería ajustar automáticamente las solicitudes y respuestas cuando:

  • Hace que los servicios simples sean menos expresivos
  • Lo harías de todos modos para un servicio complejo
  • WCF crea un mensaje de solicitud / respuesta de todos modos

He encontrado los siguientes argumentos a favor de este enfoque:

Admite el control de versiones al permitir que parámetros opcionales se deslicen en el objeto de solicitud.

En el pasado, hice una buena cantidad de COM, y consideraría que esto es casi un antipatrón para el control de versiones. Para algunas cosas, supongo que ayudaría, pero espero que donde ayude, de todos modos ya tenga un objeto de parámetro.

Permite aislar datos y comportamientos comunes a una clase base

Este tiene algo de peso conmigo.

Aleja a las personas de un comportamiento de estilo RPC hacia un comportamiento de mensajería

Leí esto en el sitio de Microsoft y lo escuché de nuestro gurú, pero todavía no tengo una idea clara de lo que significan o por qué es valioso. ¿Es que las interfaces de aspecto natural hacen que las personas tiendan a olvidar que están llamando a un servicio remoto?

Estoy buscando refactorizar las firmas de quizás 300 métodos, por lo que esta es una cantidad no trivial de dolor. Soy un gran fanático de la coherencia en las implementaciones, así que estoy dispuesto a asumir el dolor, solo ayudará a saber que al final todo valdrá la pena.

Andy Davis
fuente

Respuestas:

3

Creo que el control de versiones es probablemente el mejor argumento. Cuando tienes un contrato de operación existente como

int GetPersons(int countryId);

que desea mejorar, por ejemplo, mediante otro filtro más adelante

int GetPersons(int countryId, int age);

Tendría que escribir un nuevo contrato de operación y con un nuevo nombre ya que debe ser único. O bien, debe mantener el nombre y publicar una nueva v2 de su servicio con la antigua v1 todavía disponible para la compatibilidad con versiones anteriores.

Si ajusta el parámetro en un objeto, siempre puede extenderlo con parámetros predeterminados / opcionales y todos sus clientes existentes no se verán afectados cuando reutilice el mismo contrato de operación.

Sin embargo, también instaría a nombrar sus objetos apropiadamente. Incluso si solo envuelve un int, si comienza con IntMessagealgo similar, no se está haciendo un favor extendiéndolo. PersonFilterDebería nombrarlo, por ejemplo, desde el principio, lo que significa que debe pensar un poco en lo que esta llamada de servicio debe esperar semánticamente y, por lo tanto, en lo que se supone que debe hacer. Tal vez (y eso es muy vago tal vez) eso ayudará a desarrollar los servicios correctos y a mantener una API de tamaño decente.

Permite aislar datos y comportamientos comunes a una clase base

Eso es algo con lo que hay que tener cuidado. Los contratos de herencia y datos no van tan bien juntos. Funciona, pero tendrá que especificar todos los subtipos conocidos del contrato que podrían pasar por alto, de lo contrario, el serializador del contrato de datos no se queja de tipos desconocidos.

Pero lo que podría hacer (pero probablemente no debería, todavía estoy indeciso sobre esto) es reutilizar los mismos mensajes entre diferentes servicios. Si coloca los contratos de datos en un dll separado, puede compartirlo entre el cliente y el servicio y no necesita convertir entre tipos cuando llama a diferentes servicios que esperan básicamente el mismo mensaje. Por ejemplo, crea un PersonFilter y lo envía a un servicio para obtener una lista de filtro de personas y luego a otro servicio y tiene los mismos objetos en el cliente. Sin embargo, no puedo encontrar un buen ejemplo del mundo real para eso y el peligro siempre es que una extensión de los contratos de datos no es lo suficientemente general para todos los servicios que utilizan este contrato.

En general, aparte de las versiones, tampoco puedo encontrar la razón asesina para hacerlo de esa manera.

Andreas
fuente
Creo que la razón por la que tomo el
Andy Davis
(lo siento, la interfaz de comentarios me da pena) Gracias por responder. Creo que la razón por la que tomo el argumento del control de versiones con tanta fuerza es que si agregaste un nuevo argumento, probablemente cambiaste la semántica. Si (como en su ejemplo) acaba de agregar una edad, entonces la semántica probablemente era para buscar y tenía un "objeto de búsqueda" para comenzar.
Andy Davis el
Ahora considere mi ejemplo de política de seguridad. Tal vez decidamos que para suministrar adecuadamente una política de seguridad, necesitamos conocer no solo al usuario, sino también la instalación en la que están trabajando. Esto es mucho más que agregar un argumento, hemos cambiado la semántica de la llamada. Suponiendo que de alguna manera podamos proporcionar esta información para una persona que llama de la versión anterior, creo que tiene más sentido versionar el contrato de servicio. Entonces, la implementación de la versión anterior puede aislarse y no terminas mezclando la semántica antigua con la nueva.
Andy Davis el
0

Las notas de Martin Fowler sobre el objeto de transferencia de datos son apropiadas aquí, creo.

Cuando trabaja con una interfaz remota, como Remote Facade (388), cada llamada es costosa. Como resultado, debe reducir la cantidad de llamadas, y eso significa que necesita transferir más datos con cada llamada. Una forma de hacerlo es usar muchos parámetros. Sin embargo, esto es a menudo incómodo de programar; de hecho, a menudo es imposible con lenguajes como Java que solo devuelven un valor único.

La solución es crear un objeto de transferencia de datos que pueda contener todos los datos para la llamada. Debe ser serializable para cruzar la conexión. Por lo general, se utiliza un ensamblador en el lado del servidor para transferir datos entre el DTO y cualquier objeto de dominio.

Lo mismo podría aplicarse a las solicitudes. En cuanto a RPC, y por qué es malo:

¿Es que las interfaces de aspecto natural hacen que las personas tiendan a olvidar que están llamando a un servicio remoto?

Creo que es cierto, pero no es la razón principal. Otra razón para evitar RPC es que puede fomentar clientes y servicios estrechamente vinculados.

Kyle Hodgson
fuente
Gracias por el aporte, pero no creo que la discusión de DTO sea tan relevante. Es la misma cantidad de llamadas, y si observa el WSDL, todo se empaqueta automáticamente en un objeto de solicitud y respuesta. La convención trata sobre la semántica visible , es decir, las personas deberían pensar en esto como una solicitud y respuesta en lugar de una llamada a un método remoto.
Andy Davis
¿Le gustaría dar más detalles sobre los RPC que fomentan clientes y servicios estrechamente vinculados? No puedo ver que esto afecte el servicio en absoluto. Para el cliente, realmente tampoco veo cómo algo realmente cambia. En cualquier caso, tengo al cliente con un proxy que describe una serie de operaciones proporcionadas por un servicio. Quien realmente implementa el otro lado del servicio no es asunto del cliente en ningún caso.
Andy Davis