Skip to content

Instantly share code, notes, and snippets.

@istepaniuk
Last active October 19, 2020 22:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save istepaniuk/2175b451505ff1a69d82546406437948 to your computer and use it in GitHub Desktop.
Save istepaniuk/2175b451505ff1a69d82546406437948 to your computer and use it in GitHub Desktop.
Domain-driven Design & REST: ¿Amigos o enemigos?

REST vs. DDD

Al implementar DDD, solemos chocar de frente con cómo se diseñan habitualmente las APIs REST. ¿Estamos haciendo algo mal?

Hemos debatido un poco sobre los puntos en los que choca la expresividad de nuestro dominio con el diseño de una API realmente RESTful (no RESTish).

Se han expuesto varias alternativas:

1. Hacer POST /commands

{"cmd": "approve", "invoiceId": 4}

Los comandos se añaden en recurso aparte, los recursos que representan entidades son de solo lectura.

2. Hacer PUT /invoice/approval

Intentamos crear subrecursos y "Sustantivizar" las operaciones para señirnos al paradigma de documentos de REST, sacrificando los verbos del lenguaje ubicuo.

3. NO usar REST, usar RPC.

Cortar por lo sano y no usar REST sino RPC, sobre todo para disparar procesos de negocio, y respetando los verbos del lenguaje ubicuo. La lectura puede hacerse en recursos separados (si tenemos un read model, se puede exponer con REST)

4. Comandos como subrecurso: POST /invoice/operations

{"cmd": "approve"}

Definir subrecursos que admitan añadir operaciones que exponen los verbos del lenguaje ubiquo. El estado expuesto en el recurso principal no se puede modificar (PUT/PATCH) directamente.

5. Verbos en los enlaces de hipermedia

Al recuperar un recurso (con GET), los enlaces de hipermedia contienen el verbo (comando), aunque este no se utiliza al enviar la peticion de cambio. El atributo rel (de relation) suele equipararse al texto de un enlace HTML, como "Texto" en <a href="link">Texto</a>. Entonces nuestros controles de hipermedia quedarían así:

GET /toaster/3

{
  "id": "toaster/3",
  "state": "off",
  "operations": [
    {
      "rel": "turnOn", 
      "method": "PUT", 
      "href": "/toaster/3", 
      "expects": {"state": "on"}
    }
  ]
}

(aunque seguramente sería mejor utilizar otro campo o seguir un mediatype establecido)

Y luego para la operación: PATCH /toaster/3

{
  "state": "on"
}

6. Usar algun esquema de hipermedia que soporte esto

Ej: Siren

7. Utilizar verbos como: PUT /invoice/aprove

Más RESTish que RESTful: Usar verbos en las URIs, y no reparar en la interfaz uniforme de REST. Un POST a /aprove cambia el estado approved de /invoice.

Conclusiones

Como conclusión hemos puesto sobre la mesa que hay un espectro continuo de soluciones, algunas más fieles al dominio y otras mas fieles a los principios RESTful. También hemos hablado de que es imporante reparar en el público (las desarrolladoras) que consumirán este código, ya que no es lo mismo una API interna, que una pública y abierta.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment