¿Cómo se debieran definir los parámetros de un WS?

Que tal,

La siguiente es una consulta a los programadores experimentados que publican en este sitio.
Pasa que publiqué un WS con parámetros de distintos tipos, tanto Strings, Integer, Long, Double, pero luego con el líder del proyecto tuvimos la discusión sobre qué tipo de datos son los que se debería usar, si solo String o cualquier otro, porque no conocemos el manejo que le dará el cliente.

Esta discusión inició porque al estar haciendo pruebas, el usuario no escribió un parámetro de tipo Long, y tronó como era de esperarse porque el servicio espera un parámetros de otro tipo. Pero yo le había pasado ya al usuario la definición del servicio con sus tipos de datos, porque él iba a programar su cliente.

Revisando los WS de Amazon, vi que en todos sus WS siempre reciben Strings, supongo que para evitar este tipo de cosas.
No tengo problemas en recibir solo Strings y yo validar cada dato, sin embargo quiero conocer la opinión de los expertos. XD

¿Ustedes qué piensan? ¿Cómo lo han hecho?

Buen día.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

tipos

Yo solamente he publicado un web service, y para ello usé tipos de datos. Como dices, si el usuario crea mal su cliente y manda una cadena en un campo numérico, se le arroja una excepción. La aplicación se encarga de eso, no yo. Y con eso deberían darse cuenta de que están haciendo mal su cliente de web service, no está según la spec.

Posterior a eso, ya en mi método que se invoca desde el web service, aplico toda clase de validaciones a los datos que llegan, pero ya son validaciones de que por ejemplo un dato no venga nulo, o que las cadenas tengan la longitud esperada (mínima y máxima), los números estén dentro de rangos válidos, etc. Si alguno no pasa la validación, también arrojo una excepción, la cual recibirá el cliente, con un mensaje indicándole cuál es el problema.

Esto funciona sin importar si el cliente es Java o .NET; no sé en otras plataformas exactamente qué pasa cuando llega una excepción (tengo entendido que la excepción de Axis o del web service publicado directo con JavaSE 6 se hace de manera que la puedan manejar otras plataformas).

Si un requerimiento de tu web service es que no se arrojen excepciones en ningún caso y que siempre le llegue un mensaje de error al usuario, entonces sí, lo mejor es que de tu lado todo quede definido como puras cadenas para que tú hagas la conversión y si algo no sale bien, entonces le devuelvas un error al cliente en vez de que simplemente se arroje una excepción.

Deben de ser del tipo que tu

Deben de ser del tipo que tu servicio necesite, no solo strings, es una mala práctica hacerlo así y solo estarás postergando los errores. Incluso es preferible tener tipos complejos a muchos parametros simples. El criterio a aplicar aquí es exactamente el mismo al aplicar en la firma de un método; ¿que es mejor?:

    public void activa( String nombre, String apellido, String numeroEmpleado, String cantidad, String descripcion, String descuento, Stirng primeraCompra );

O

    public void activa( String nombre, String apellido, int numeroEmpleado, int cantidad, String descripcion, int  descuento, boolean primeraCompra );

O

    public void activa( Empleado e , Pedido p  );

Los webservices suportan incluso arreglos de bytes para enviar archivos si fuera necesario y también saben como mandar excepciones si algo sale mal.

El cliente debe de aduecuarse el WSDL que le des, imaginate que fuera el caso contrario y que le dijeras a Amazon "sabes que no me gustan los strings, cambialos". Por cierto los webservices de Amazon se ven super complejos y hay que considerar que ellos pueden tener diferentes necesidades.

Usando tipos de datos especificos ( int, long, binarios, o complejos ) se hace más fácil darle mantenimiento al código. La gran mayoría de los clientes webservice son generador por alguna herramienta leyendo el WSDL (pronunciese /guisdel/ ) entonces no debería de haber problema.

Enfoque del servicio

A mi me ha funcionado muy bien definir los parámetros como lo que son: cadenas, booleanos, numéricos cada uno con su tipo. En el WSDL se detallan los parámetros que esperas recibir sean simples o complejos. De modo complementario (casi siempre necesario) se le puede dar al cliente el contrato de interfaz correspondiente donde se detallan a fondo los tipos de datos, cuestiones de lógica de negocio etc.

Me gusta separar la lógica del servicio de manera natural, sea por ejemplo un servicio que haga la búsqueda sobre algún recurso, si existe tal recurso se regresa, si no existe se devuelve un nulo, si existió algún error en el proceso prefiero hacer uso de Faults que el usuario debe manejar.

He visto que muchas personas implementan servicios como lo pide tu líder, o incluso he visto servicios que piden todos los parámetros juntos en una sola cadena lo que me parece una atrocidad.

Supongo que en cuestiones de rendimiento no debe haber mucha diferencia el preferir cadenas a tipos de datos ya que la conversión a cadena y viceversa va implícita al crearse e interpretarse el envelope. Pero sí prefiero mantener todo como lo que es.

A veces es muy curioso cómo empezamos a desarrollar para un cliente en específico. De esta forma el sistema se ata a sus requerimientos y necesidades sacrificando muchas veces la escalabilidad.

No puedo asegurarte que es la mejor práctica en WS pero es la que me ha funcionado.
Espero te sea útil.

Imagen de luxspes

Comunicacion

Pasa que publiqué un WS con parámetros de distintos tipos, tanto Strings, Integer, Long, Double, pero luego con el líder del proyecto tuvimos la discusión sobre qué tipo de datos son los que se debería usar, si solo String o cualquier otro, porque no conocemos el manejo que le dará el cliente.

Independientemente del manejo que le de el cliente, si el parametro se llama "nombre" seguro que no sera Integer, o Long o Boolean.... por otro lado, hay nombres de campos para los que es mas dificil escoger el tipo, como "precio" puede ser Integer, o BigDecimal (no Double, nunca Double) o inclusive ser string por que lo quieran con representacion en letra "quinientos" en ves de con "500".

Pero, si el nivel de comunicacion con el cliente es tan malo, que al definir el webservices no saben que tipos ponerle a los parametros, creo que estan en gravisimo riesgo de no estar entendiendo el sistema que estan construyendo ni siquiera en lo mas fundamental y eso deberia encender focos rojos con respecto al proyecto

Esta discusión inició porque al estar haciendo pruebas, el usuario no escribió un parámetro de tipo Long, y tronó como era de esperarse porque el servicio espera un parámetros de otro tipo. Pero yo le había pasado ya al usuario la definición del servicio con sus tipos de datos, porque él iba a programar su cliente.

Un simple error que se arregla poniendose de acuerdo. Si tu lider de proyecto no entiendo eso, si yo fuera tu, empezaria a buscar chamba en otro lado.

Revisando los WS de Amazon, vi que en todos sus WS siempre reciben Strings, supongo que para evitar este tipo de cosas.

No he usado los WS de Amazon, pero si efectivamente estan configurados como dices es posible que se deba a que los parametros son muy abiertos y para propositos muy genericos: dudo que ese sea tu caso.

No tengo problemas en recibir solo Strings y yo validar cada dato, sin embargo quiero conocer la opinión de los expertos. XD
¿Ustedes qué piensan? ¿Cómo lo han hecho?

Usa tipos, seria mi recomendacion. Si tu jefe no lo entiende, correlo (busca otro trabajo)

Usar String para un

Usar String para un reemplazar un tipo de dato puede ser útil cuando manejes formatos. Que por alguna razón tu recibes un numero como este 123,456,789.90 una fecha como esta 20110516 o por ejemplo un entero de esta forma 0000001

@jdd En ese caso estas

@jdd En ese caso estas manejando la "representación" de un numero, fecha o entero como un string, lo cual es válido. Pero si lo que en realidad quieres es tener el número, la fecha o el entero, entonces, solamente estas pidiendo problemas de conversión.

Totalmente de acuerdo, lei

Totalmente de acuerdo, lei tambien que se habla de postergar los errores al recibir Strings y claro que eso es correcto. Bueno a lo que iba es que por ejemplo me ha tocado que existen empresas que quieren que sus cantidades esten formateadas de x manera y pues hay que respetarlas... Las necesidades de las empresas a veces nos obligan a salirnos de las buenas practicas.

Imagen de ezamudio

formatos

Otra razón por la que alucino los web services. "empresas que quieren que sus cantidades estén formateadas de x manera" es válido EN UNA INTERFAZ O REPORTE, no en un web service. Sólo confirman lo que siempre he dicho: el XML está hecho para ser parseado por humanos, no máquinas. Es muy ineficiente. Y como es fácilmente parseable por humanos, nunca falta un idiota que dice "pero es que se vería más bonito <precio>$1,234.56</precio> que solamente 1234.56" cuando en realidad el segundo formato es más válido porque ES UN DATO y no tiene por qué ir formateado en un contexto de INTERCAMBIO DE DATOS.

Incluso las fechas, por eso existe un formato estándar para fechas en XML 2011-05-17T14:20 con opción para ponerle segundos, milisegundos y zona horaria (recomendable siempre ponerlo, tipo 2001-05-17T09:36:29.345-0500).

Eso de formatear datos de cierta forma rompiendo un estándar no se me hace una necesidad, sino una necedad. Si una empresa ya tuvo la necedad de romper el estándar publicando un web service mal hecho con datos formateados para humano y no para máquina, pues sí, ni modo, si quieres consumir ese web service tendrás que hacer varias cosas a patín porque el stub de tu herramienta favorita no podrá lidiar con esos formatos y te los dará como cadenas o tendrás que modificar el stub, etc.

Pero en este caso Jesfre pregunta la mejor manera de publicar un web service, por tanto tiene la oportunidad de hacerlo bien y siguiendo estándares.

Entendido

Después de leer sus comentarios quedo más convencido del deber ser. Por ahora quedará con Strings, pero en otra ocasión habré de ser más claro al respecto.

Mi idea es también, y como buena práctica, recibir los tipos de datos que deben ser. En el caso de los formatos, como comenta @jdd es muy válido, aunque para este caso, les comento, que el cliente mismo definió el formato de fecha que se iba a pasar.

Gracias a todos por sus comentarios. Ahora tengo una idea más clara de cómo lo hacen otros programadores y cómo determinar la definición de mi WS.

Tomando en centa esto de los

Tomando en centa esto de los numeros y los Strings... como seria la mejor manera de representar el resultado de dividir 1/3 en un WS???

a) 1/3 <- String
b) 0.3333333333333333 <- Double

será que dependa realmente del requerimiento de tu aplicacion? ... tu como lo publicarias? que retornarias?

@Jesfre: ".. pero en otra

@Jesfre: ".. pero en otra ocasión habré de ser más claro al respecto.." jejej esa otra ocasión nunca llegará, ya lo verás.

@jdd, si lo que quieres es "Un tercio" lo mejor sería que serializaras un tipo de dato complejo como "Fracción":

class Fraccion {
private final int numerador;
private final int denominador;
}

Si lo que quiere es una double, pues el double.

Imagen de ezamudio

jajaj

comienza la xmlitis aguda

<fraccion>
<numerador>1</numerador>
<denominador>3</denominador>
</fraccion>

Por cierto, devolver "1/3" como String sólo es útil si lo vas a presentar así a un humano, o si vas a evaluar la expresión del lado del cliente, para obtener 0.333333333333333333333333333 a la precisión que el cliente necesite.

Y NO usen Double por favor. Con un BigDecimal podrían devolver 0.33 o 0.33333333333333333333333333333333333333333333333333 y se va a ver exactamente así (porque se va a transmitir como cadena porque es vil XML). Si usan Double puede que salga algo medio raro por ahí, ya sea a la hora de codificar como cadena o a la hora de parsear o a la hora de usar el Double resultante.

o tambien (tomando lo de

o tambien (tomando lo de OscarRyz y Ezamudio... y mi cosecha)

para una fraccion:
<number type="fraction" numerator="1" denominator="3" value="0.333333333333" />
...
para un decimal:
<number type="decimal"  value="0.123" />
...
para un entero:
<number type="integer" value="123" />

justo pense que representar 1/3 en un String no seria conveniente pues vovlemos a lo mismo, me imagino que para "1/3".split("/") habria que vigilar que exista realmente el "/" y despues ver que tanto la posicion [0] y la [1] sean numericos enteros (al menos qe sea valido 1.2/3.4, cosa que no va)... mmm con eso de la xmlitis aguda puedo decir que tiene muchas ventajas frente a JSON por ejemplo e mas importante es la validacion contra XSD por ejemplo... ya sé yaa sé que hay mucha basura en abrir/cerrar etiqueta per pues eso de XSD/DTD/XSLT son la ley para un docmento de intercambio

Imagen de luxspes

JSON, una de las muchas curas para la xmlitis

. mmm con eso de la xmlitis aguda puedo decir que tiene muchas ventajas frente a JSON por ejemplo e mas importante es la validacion contra XSD por ejemplo... ya sé yaa sé que hay mucha basura en abrir/cerrar etiqueta per pues eso de XSD/DTD/XSLT son la ley para un docmento de intercambio

Pues, para los schemas, puedes usar JSON Schema o alguna otra cosa similar.

Para XSLT... bueno... cualquier que este de acuerdo en que XML es un horror, evitara XSLT.

Vaya eso de los JSON Schema

Vaya eso de los JSON Schema no los conocia. Los XSD si son super engorrosos por la misma razon que son XML... A mi me gustan mucho por tener un docmeto de validacion semantico/sintactico que la verdad me ha solucionado muchisimas cosas en mis sistemas. Ahora que ya se que sé que existe lo que se mencona de JSON Schema claro que lo voy a provar porque JSON es algo que tambien se ve muy muy prometedor y es mas ligero que XML...

Por cierto regresando a los WS: tambien hay WS que retornan JSON

Quizá el problema con el JSON

Quizá el problema con el JSON schema es que no muchos clientes lo van a poder leer.

No debería de haber mucho problema con el XML pues al final es solo la forma en la que se serializa la información y la generación del servicio y del cliente siempre lo hace una herramienta por tí. Si lo están haciendo a mano lo están haciendo mal.

Imagen de ezamudio

broncas con XML

Un problema con la verborrea del XML, aparte del costo de desempeño por parsear tanto texto, es que en plataformas móviles consume más memoria el parseo, y además la transmisión y recepción consume más ancho de banda. JSON al ser más compacto, puede disminuir los costos de uso de un web service desde una plataforma móvil. Si se usa REST por ejemplo, con respuestas en formato JSON y peticiones con formato estándar de petición URL, se transmiten y reciben menos datos, la petición es más fácil de construir en la plataforma móvil, y la respuesta es más fácil de parsear.

Es un aspecto que hay que considerar al hacer un web service: si está orientado a plataformas móviles, mejor implementar algo tipo REST que un web service tradicional SOAP-RPC-XML.

O YAML :)

O YAML :)

Interesante...

Gracias por el tip. Esa no me la sabía.
Ya haré unas pruebas usando JSON.