¿Por qué un pequeño vocabulario fijo se considera una ventaja para los servicios RESTful?

13

Entonces, un servicio RESTful tiene un conjunto fijo de verbos en su vocabulario. Un servicio web RESTful toma estos de los métodos HTTP. Hay algunas supuestas ventajas de definir un vocabulario fijo, pero realmente no entiendo el punto. Quizás alguien pueda explicarlo.

¿Por qué un vocabulario fijo como lo describe REST es mejor que definir dinámicamente un vocabulario para cada estado? Por ejemplo, la programación orientada a objetos es un paradigma popular. RPC se describe para definir interfaces fijas, pero no sé por qué la gente supone que RPC está limitado por estas restricciones. Podríamos especificar dinámicamente la interfaz tal como un servicio RESTful describe dinámicamente su estructura de contenido.

Se supone que REST es ventajoso porque puede crecer sin ampliar el vocabulario. Los servicios RESTful crecen dinámicamente al agregar más recursos. ¿Qué tiene de malo extender un servicio especificando dinámicamente un vocabulario por objeto? ¿Por qué no solo usamos los métodos que se definen en nuestros objetos como vocabulario y hacemos que nuestros servicios describan al cliente cuáles son estos métodos y si tienen o no efectos secundarios?

Esencialmente tengo la sensación de que la descripción de una estructura de recursos del lado del servidor es equivalente a la definición de un vocabulario, pero luego nos vemos obligados a usar el vocabulario limitado para interactuar con estos recursos.

¿Un vocabulario fijo realmente desacopla las preocupaciones del cliente de las preocupaciones del servidor? Seguramente tengo que preocuparme por alguna configuración del servidor, esta es normalmente la ubicación de los recursos en los servicios RESTful. Quejarse por el uso de un vocabulario dinámico parece injusto porque de todos modos tenemos que razonar dinámicamente cómo entender esta configuración de alguna manera. Un servicio RESTful describe las transiciones que puede realizar al identificar la estructura del objeto a través de hipermedia.

Simplemente no entiendo qué hace que un vocabulario fijo sea mejor que cualquier vocabulario dinámico autodescriptivo, que fácilmente podría funcionar muy bien en un servicio similar a RPC. ¿Es esto solo un mal razonamiento para el vocabulario limitante del protocolo HTTP?

Reflexión

Solo para aclarar mis pensamientos un poco mejor de lo que lo he hecho. Supongamos que está diseñando cualquier API de propósito general, tal vez ni siquiera frente a la web. ¿Sería feliz si alguien dijera que solo puede usar estos nombres de método en sus objetos? REST no está restringido a HTTP, pero considere la situación en la que cada API que escribe, frente a la web o de otra manera simplemente consistía en objetos que contienen métodos GET POST PUT y DELETE. Entonces, ese método object.foo que quería definir no es posible. Debe definir un nuevo objeto llamado foo y llamar a su método GET. Así es esencialmente cómo funciona REST, y me hace sentir un poco incómodo pensar en ello. No tiene una mejor comprensión genérica de lo que hace foo, simplemente se vio obligado a crear un nuevo objeto para lo que es esencialmente un método en un objeto principal. Además, su API no es menos compleja, acabas de ocultar la complejidad de la interfaz creando más objetos. Los servicios web RESTful nos obligan a adoptar una interfaz que puede o no ser suficiente en el contexto de la API que estamos exponiendo. Quizás haya una buena razón para hacerlo con las API orientadas a la web, pero una buena razón para no adoptar interfaces estándar para cada objeto en cada API de propósito general. Un ejemplo práctico sería apreciado.

Matt Esch
fuente
Para ayudar a los usuarios a analizar rápidamente sus preguntas y respuestas, puede considerar agregar sus "Actualizaciones" como respuestas separadas (particularmente la sección "Otra actualización"). Esto se recomienda: blog.stackoverflow.com/2011/07/…
Johann
@Johann gracias, las actualizaciones posteriores ahora existen como la respuesta aceptada para esta pregunta.
Matt Esch

Respuestas:

9

La terminología "verbo" y "sustantivo" es algo desafortunada aquí. Como ya mencionó, puede crear fácilmente objetos para la función. Todos los lenguajes orientados a objetos, excepto Java, tienen esa transformación incorporada y en Java terminas haciéndolo todo el tiempo de todos modos, terminando con muchos objetos con un solo método y, a menudo, uno llamado "invocar", "ejecutar", "aplicar" o somesuch (por lo que es en los lenguajes de programación donde la distinción "verbo" / "sustantivo" en realidad no tiene sentido).

Los "verbos" de REST se parecen más a clasificar sus métodos en getters, setters (eliminadores; pueden considerarse como tipo de setters) y otros. Y tratando de hacer todo con getters y setters. La razón de esto es:

  1. Semántica más fácil ante fallas de comunicación, ya que tanto los captadores como los colocadores son idempotentes. Obtener el recurso dos veces no tiene ningún efecto adicional y tampoco lo establece al valor que ya tiene.
  2. Definir algunas semánticas que pueden usarse mediante el almacenamiento en caché del proxy que no comprende la interfaz específica. Los captadores se almacenan en caché y se sabe que los establecedores invalidan el caché.

HTTP se diseñó desde el principio teniendo en cuenta tanto la memoria caché como la tolerancia a errores, por lo que estos dos puntos conducen a sus cuatro métodos básicos:

  • GETEs un captador. Se supone que no modifica el estado del servidor y devuelve el mismo valor cada vez con la posibilidad de especificar la política de vencimiento y revalidación.
  • PUTy DELETEson setter y deleter (= setter con nil). Normalmente no se usan en el contexto de la web normal, pero tienen sentido para REST.
  • POST es un fregadero de cocina genérico "invocar" para el que los cachés no pueden asumir nada.

REST es un patrón de diseño que describe cómo usar HTTP sin procesar o protocolos de red similares para implementar una interfaz que permite manejar fácilmente las fallas mediante un simple reintento y funciona bien con los servidores proxy de almacenamiento en caché.

No se corresponde fácilmente con la API de programación orientada a objetos normal. Creo que en realidad es algo bueno. Los desafíos de la interfaz a través de la red, que es inherentemente poco confiable y donde los viajes de ida y vuelta son mucho más lentos que la transferencia de una cantidad incluso moderada de datos, requieren un enfoque de diseño diferente al API en proceso, por lo que cuando se ve diferente, la gente no intenta aplicar tanta experiencia inválida del otro dominio (esa es la maldición de SOAP, XML-RPC y tal; parece una llamada a un procedimiento, pero no funciona así y termina siendo difícil trabajar con él).

Jan Hudec
fuente
2

La idea esencial es que la complejidad se expresa a través de la representación de recursos, por lo que no se necesitan verbos adicionales. Como algunos lo han dicho: "En REST, los sustantivos son buenos, los verbos son malos".

Si observa los cuatro verbos REST, pueden asignarse a las operaciones básicas de CRUD, lo que esencialmente le permite hacer lo que quiera con sus recursos. Es decir -

POST: crea el recurso

OBTENER - Lea el recurso

PUT - Actualizar el recurso

BORRAR - Eliminar el recurso

Que más necesitas?

Craig Schwarze
fuente
Puedo facilitar un verbo en un servicio RESTful creando un recurso para hacerlo. Como dices, no necesito verbos adicionales, solo más recursos. Simplemente no veo por qué es mejor fingir que un verbo abstracto es un sustantivo cuando lo que quiero hacer es realmente un verbo. Parece que los verbos están restringidos por la fuerza sin ningún motivo, y estoy evitando el problema creando sustantivos que realizan las acciones requeridas cuando se accede con un pequeño conjunto de verbos. ¿Por qué sería mejor hacer eso? Tiene que haber una buena razón para ello, algo que pueda cuantificar como un ejemplo práctico.
Matt Esch
44
Obtenga una lista de todos los recursos, obtenga una lista de todos los recursos con restricciones dadas, actualice o elimine un montón de recursos al mismo tiempo, cree dos tipos diferentes de recursos juntos atómicamente (para que ambas creaciones fallen o tengan éxito), elimine todos los recursos Satificando una condición dada ... La lista de cosas que uno puede querer hacer es bastante larga. Uno puede encajarlos en una API REST, pero no siempre es natural. Tampoco ayuda que GET no permita un cuerpo, por lo que las condiciones de filtrado complejas se vuelven incómodas.
Andrea
PARCHEAR recursos también es genial.
Wyatt Barnett
2

Considere un lenguaje donde todas las construcciones (como las funciones) son objetos. Entonces los verbos RESTful simplemente están llamando a convenciones y declaraciones de asignación. Para JavaScript, puede definir una sintaxis de verbo fijo como INVOKE para invocar una función, DELETE (lo mismo que delete en js) para eliminar un objeto en otro objeto, SET para asignar un valor y RETURN para devolver un valor. Podríamos usar los verbos HTTP para referirnos a la función de invocación POST equivalente, PUT - asignar valor, GET - devolver un valor, - DELETE - eliminar un objeto. Estaba atrapado en la idea de que los métodos HTTP en realidad estaban describiendo métodos de objetos, interfaces de objetos reales, y no pude ver que en realidad podría describir conceptos de niveles mucho más bajos, como las construcciones de lenguaje básicas que son claramente fijas y finitas. Lenguas sanas.

Y, por supuesto, es útil para el enrutamiento / proxy tener un vocabulario fijo para reflexionar.

Matt Esch
fuente
1
  • Porque un programador profesional anticipa cientos, si no miles de nombres de métodos. Lo que parece inútil en un pequeño más pequeño puede ser un gran problema a medida que la aplicación se hace más grande.

  • Porque no hay necesidad de estándares sobre los nombres de métodos cuando ya están definidos.

  • Porque el objetivo principal del código es ser legible sin tales traducciones adicionales.

  • Porque alienta y ayuda en la identificación de "cuándo" se debe dividir otra clase.

  • Cuando se hace cargo del código, es razonable y realmente posible entender qué y cómo lo hace mucho más rápido.

  • Proporciona un vocabulario común y, por lo tanto, un nivel de abstracción para que pueda concentrarse en otros detalles y ver patrones.

  • Facilita la búsqueda de errores, ya que el código común y los enfoques se pueden verificar fácilmente.

  • Cuando trabajas con varias 'capas' como una en el desarrollo web, saber qué URL coinciden con qué nombres de acción es muy útil para la depuración.

En general, no siempre lo necesita, pero como la mayoría de los estándares, ¡tiene mucho sentido tratar de usarlo!

Michael Durrant
fuente
Abordado en el orden 1) ¿Entonces un programador anticipa cientos, si no miles de recursos? Ya anticipamos métodos en las bibliotecas que utilizamos. 2) ¿Necesitamos estándares para los nombres de los métodos pero no para los nombres de los recursos? No puedo seguir esa lógica. 3) No estoy seguro de lo que quieres decir con traducciones. Si me dices que existe un recurso, tengo que entenderlo. Si te digo que existe un método, tienes que entenderlo. Lo único que realmente me importa es cuál de mis acciones tendrá efectos secundarios 4) ¿Podría expandirse
Matt Esch
5) nuevamente, ¿podrías expandirte? Soy un programador. Estoy acostumbrado a trabajar con estructuras de objetos bien definidas. ¿Por qué no usaríamos este mismo mecanismo para definir todas nuestras API si es realmente mejor? 6) No vale la pena considerar ningún nivel de abstracción sin justificación 7) Nuevamente, ¿podría expandirse? Si nos beneficiamos de esta manera, seguramente deberíamos codificar todas nuestras API de esta manera. 8) Esperaría que cualquier objeto exponga sus métodos directamente. / object / method no se puede confundir. Definimos los estándares al elegir adoptarlos. Me falta motivación en este momento.
Matt Esch
Matt, pareces un poco discutidor, pero diré que para 2) No dije que el recurso no necesitaría estándares 3) No necesitarás entender un método como 'actualizar' o 'nuevo' o crear 'porque sabes exactamente lo que hacen de acuerdo a los estándares. Sin embargo, ¿qué pasa con 'MsgToPrimary' qué hace eso? ¿Crear un mensaje? ¿Actualizar un estado? ¿Enviar un correo electrónico? 7) Sí, la mayoría de las API podrían beneficiarse de esto y muchas lo hacen. Intentaría centrarme en la noción de que los estándares y convenciones estándar son útiles y puedo ver que sus actualizaciones lo demuestran.
Michael Durrant
Solo estoy tratando de entender los beneficios. Los fuertes contraargumentos deben abordarse para aclarar el problema. Aún así, entiendo que un conjunto fijo de verbos es una especie de descripción del lenguaje, pero realmente no estoy de acuerdo con que sea más fácil de entender. No puedes quitar un conjunto expresivo de verbos y decir hola, ahora entendemos todos los verbos, cuando no entendemos todos los recursos. Los recursos están reemplazando los verbos. Reemplazamos el verbo arbitrario foo con un recurso llamado foo. Nuestra comprensión de foo no es más clara de lo que era cuando foo era un verbo.
Matt Esch
1

La alternativa es algo horrible: WSDL (también conocido como lenguaje de definición de servicio web), que es una forma (torpe) de describir mediante programación (algo) APIS arbitrario.

REST limita severamente los verbos, empujando casi todas las variaciones específicas de la aplicación a la carga útil del documento. El beneficio de hacerlo es que muchas implementaciones de clientes pueden comunicarse con muchos servicios heterogéneos. Los clientes y servidores pueden ser completamente desconocidos entre sí, algunos aún no se han escrito.

Hay un podcast en el que Stefan Tilkov explica REST muy bien .

cbare
fuente
1

Sí, una API de descanso tiene un conjunto fijo de verbos, pero no tiene que limitarse a (o incluir GET, POST, PUT, DELETE). Consideraría GET, POST, PUT, DELETE como una implementación predeterminada de REST que funciona para el 80% de todos los sistemas existentes.

Otros sistemas que implementan más que operaciones crud pueden (y lo hacen) implementar sus propios verbos para sus API REST. Los verbos como Publicar, Consumir, Calificar, Comentar, Buscar, Examinar se pueden agregar e implementar en un sistema REST. Si bien algunos podrían decir que un vocabulario más amplio podría hacerlo más complicado, mi respuesta es que depende. Si su usuario objetivo son jefes de tecnología que entienden qué es un POST, entonces sí, podría ser más complicado; sin embargo, si los usuarios objetivo de su API son personas reales (es decir, personas que no codifican y no saben qué es una POST), entonces los verbos reales son mucho más fáciles de usar. De hecho, tener un conjunto apropiado de verbos para su API ayuda a mantener las URL cortas (lo cual es importante si desea que los usuarios las escriban en un navegador. Si usa un vocabulario personalizado, usted ' Quisiera asegurarme de que su API y sus verbos estén bien documentados. Cuando use una API REST personalizada, querrá asegurarse de que sus 'acciones de solo lectura' como HTTP GET y 'escribir acciones' con POST.

La red social para adolescentes, Piczo.com, (que descanse en paz) presentó una API REST extendida (incluidos los verbos mencionados anteriormente) que se implementó en 7 idiomas diferentes.

Andrés
fuente
0

Lo simple es bueno.

Hay casos en los que necesita verbos y complejidad adicionales, pero la mayoría de los problemas se pueden reducir a simples acciones CRUD en los recursos, y eso es lo que REST intenta promover. Cuando piensa en la mayoría de las aplicaciones web, al final leen y conservan registros en un almacén de datos, que utilizan las mismas acciones muy simples.

object.foo () está todo bien, pero ¿qué hace? ¿Qué está volviendo? ¿Está modificando el estado del objeto o alguna de sus dependencias? ¿Puedes llamarlo dos veces y obtener el mismo resultado o te dará dos valores diferentes? Si también tiene object.bar (), ¿deben llamarse en un orden específico?

Se requiere mucho conocimiento para usar una API enriquecida, y generalmente tienen sus propias convenciones (es decir, setFoo va a mutar el objeto, getBar probablemente sea idempotente, disponer () o destruir () significa que no hay otras llamadas en el mismo objeto será posible, etc ...)

ptyx
fuente