Muchos de vosotros habréis conocido los gloriosos días en que las conectividades (ej. la empresa A envía en tiempo real el estado del almacén a otra empresa B) se hacían directamente por TCP y se definían hermosas tarjetas que mostraban la longitud de tal o cual campo ("...el teléfono 30 char..."). En realidad, ninguna de las partes tenía ninguna gana de definir el formato, crear el cliente/servidor, parsear las entradas, etc... cambios en los formatos debían hacerse con cautela y representar caracteres extendidos era algo que sencillamente, ni se planteaba (ASCII era todo lo que había). Es decir, un pichoche de mucho cuidado, para total, que el programador de la empresa A, pudiera llamar a la función void UpdateInventory(string productCode, int newInventory); que tenía implementada el otro programador en la empresa B.
Si el programador B ya tiene esa función en su sistema ¿porqué el programador A no puede sencillamente invocarla?.
No cabe duda que suena raro que hoy en día sigamos sin poder, sencillamente, invocar la función que nuestro colega ya tiene implementada en el otro extremo. Pero más raro es, que no es porque no se pueda, sino porque nos empeñamos en no apoyar aquellas tecnologías que lo hacen posible.
Veámoslo con un ejemplo real.
Supongamos que Marvel decide exportar la información de todos sus cómics (en la estructura de datos sobre el tipo Comic) y que para ello quiere publicar una API con diferente funcionalidad (como el método GetComic que devuelve información detallada de un cómic dado su Id).
En tal caso, podría definir toda una serie de puntos de servicio REST con una extensa documentación sobre cuales son las estructuras que deben enviarse y cuales se reciben. Debiendo ser tú mismo quien identifique la forma de cada punto de servicio, los parámetros que deben enviarse, analice la estructura devuelta, etc... lógicamente, si otro desarrollador, para tu plataforma, hace un wrapper (como éste), tú lo podrás usar, pero sólo sirve para esa plataforma, lo ha tenido que hacer alguien y, si hay cambios, deben analizarse de nuevo ¡a mano!. ¿Quieres echarle un vistazo al tipo de código que ha debido generar tan valeroso developer?.
Si por el contrario, tanto Marvel como el resto de agentes involucrados en nuestro problema de análisis (la interoperabilidad en el siglo XXI), centraran los esfuerzos en fijar un protocolo de intercambio que abstraiga completamente el proceso que media entre que un developer escribe un tipo o función (ej. int Sumar(int a, int b) { return a + b; }) y otro developer lo consume (ej. int c = Sumar(3, 4);), podría haber definido el acceso a dicha API como:
Y podría exponer dicha funcionalidad con algún middleware que adapte su actual backend con la definición anterior, por ejemplo:
En general, si ha tenido cuidado en las definiciones y estructura de su backend no debería tener ningún problema en exponerlo "casi directamente", con un código muy similar al anterior (realmente menos, porque el control de existencia ya debería hacerlo el backend que en el ejemplo consiste únicamente en deserializar un XML).
Entonces, cualquiera que desee interoperar con Marvel y obtener información de sus cómics, únicamente tiene que consumir el servicio. Un ejemplo completo, que funciona perfectamente en PHP y cuyo requisito previo únicamente es conocer la definición del servicio expuesto (en este caso un WSDL que consiste en una única URL), sería:
Escribiendo en bruto la información del cómic solicitado
El proceso de integración anterior es independiente de las plataformas, pero obviamente, si una plataforma no da soporte a este nivel de integración (tanto del lado del cliente como del servidor), no es posible realizar de ese modo la integración.
Otro aspecto importante es el soporte (al estándar de integración) dado por la plataforma, por ejemplo en Java, C#, F# y seguro otros lenguajes la generación automática de un wrapper aporta de forma automática información de los métodos, tipos y comentarios como si de un "API local" se tratara evitando tener que estudiar una documentación desacoplada del contexto en el que el consumidor está usando el API.
Por ejemplo, si a mi me dan un único punto de servicio y mi plataforma se lo trabaja, me debería desplegar ahí mismo la información (documentación) relativa únicamente al punto de servicio (ej. los diferentes espacios de nombres en que un buen diseñador del API dividiría las funcionalidades); entrando en alguno de ellos, me podría listar los diferentes métodos (cuya única documentación consiste en qué hacen esos métodos, no cosas como la forma de construir una URL o el objeto de petición; en muchos casos como Comic GetComic(int comicId), dicha documentación se reduce a cero).
Así, hoy día nos encontramos "plataformas de desarrollo" como el combinado "explorador + javascript" con un soporte muy pobre. En este caso, el cliente SOAP para javascript que he podido encontrar, sólo parece ser compatible con la versión .Net 2.0 en tal caso, podemos usar nuestro "despliegue" anterior como middleware para crear un punto de servicio compatible escribiendo:
Usando este cliente SOAP para JavaScript, consumir el anterior endpoint en JavaScript consiste en escribir:
Obteniendo en la consola el objeto que describe el cómic solicitado:
A mi personalmente, tanto me da el nombre que tenga una tecnología, tanto me da si se llama XML, JSON, SOAP, REST, WCF, CORBA u otra de las miles que seguro habrá por ahí.
Si HTTP ha podido poner en contacto a miles de clientes con miles de servidores, no creo que sea porque es sencillo (reto a aquellos que dicen que SOAP es complicdo que hagan un servidor y un cliente HTTP conforme a estándar y por sus propios medios), sino por algo tan sencillo como que todo el mundo decidió usarlo y mejorarlo (y no reinventar el suyo propio).
Sí, yo abogo por "universalizar" las comunicaciones con SOAP, pero me daría igual cualquier otra que suministre las características que ésta.
Como nota final, decir que nada he dicho sobre otros escenarios en que otras tecnologías sean más adecuadas pero... ¿estás seguro que no es por la falta de apoyo a tecnologías como SOAP que en muchos escenarios se hacen "preferibles" otras? (la pescadilla que se muerde la cola). Por ejemplo, yo mismo usaría JSON+REST en un escenario en el que una gran cantidad de clientes deban ser implementados en una gran cantidad de plataformas en que se desconoce el soporte a SOAP (más que probable motivo por el que Marvel optó por JSON+REST) pero eso no hace mejor a JSON+REST que a XML+SOAP.
En los primeros JDK de las televisiones interactivas tampoco había soporte para JSON y las menos malas opciones pasaban por wrappear los servicios "a la antigua usanza" ¡pero eso no hace un protocolo adhoc por TCP mejor que JSON+REST!.
Por poner sólo algunas ventajas de un protocolo como SOAP:
-
permita publicar de la forma más automatizada posible (en el ejemplo indicado, un middleware decente puede publicarse con un esfuerzo mínimo).
-
permita consumir de la forma más automatizada posible (siendo PHP y JavaScript algunos de los peores escenarios para consumir SOAP, la estandarización de SOAP ha permitido que un ordenador pueda reconocer un servicio de forma completamente automática).
-
minimice el conocimiento y configuraciones previas (...reconocer un servicio de forma completamente automática a partir únicamente de una dirección URL).
-
cambios en cualquiera de las partes puedan ser cotejadas de forma completamente automática (en el ejemplo, un cambio en el backend de Marvel, produciría un cambio en las definiciones de contrato del servicio y el cliente lo detectaría elevando una excepción). Añadido ésto con un sistema de tipos, el programador B puede visualizar automáticamente todas las partes del interface afectadas (ej. se ha eliminado un campo).
-
cambios en cualquiera de las partes puedan ser refactorizadas de forma automática (que yo sepa no forma parte del estándar SOAP, pero de forma similar a un pullrequest pueden fluir las refactorizaciones desde el programador A al B; por ejemplo, un cambio de nombre)
-
etc...