Vam tancar el mòdul 1 dient que tocava passar de comprendre a construir. Abans d'escriure la primera línia de servidor, hi ha una etapa que massa gent s'estalvia i que és exactament on es guanyen o es perden els projectes d'API: el disseny del contracte. Aquesta lliçó és la lliçó paraigua del mòdul 2. Encara no entra en com s'anomenen les URIs ni en quin codi d'estat cal retornar —això són les lliçons següents—, sinó en el mètode de treball: com es decideix quina API cal construir, amb quins principis rectors i amb quins artefactes. Al final de la lliçó tindràs a la mà la guia d'estil de l'API de la Botiga Aroma, un document viu que les set lliçons següents aniran omplint i que el mòdul 3 implementarà al peu de la lletra.
Contingut
- API-first davant de code-first
- El procés de disseny en set passos
- Pas 1: identificar consumidors i casos d'ús
- Pas 2: extreure els substantius del domini
- Pas 3: decidir què es converteix en recurs i què no
- Principis rectors del disseny
- Granularitat: ni massa fina ni massa gruixuda
- Dissenyar per al consumidor, no per a la base de dades
- Tolerància a l'evolució i principi de robustesa
- La guia d'estil de l'API de la Botiga Aroma
- Mapa del mòdul 2
- API-first davant de code-first
Hi ha dues maneres d'arribar a tenir una API, i no donen el mateix resultat.
En l'enfocament code-first s'escriu primer l'aplicació i l'API apareix després, gairebé com un subproducte: s'agafen els serveis que ja existeixen, se'ls penja una capa HTTP i es genera la documentació a partir del codi. És ràpid al principi i funciona raonablement bé quan l'únic consumidor és el teu propi frontend.
En l'enfocament API-first es fa el contrari: el contracte es dissenya, es revisa i s'acorda abans d'implementar res. L'especificació és l'artefacte principal; el codi n'és la realització. Els consumidors poden començar a treballar contra un simulacre (mock) generat des del contracte mentre l'equip de servidor l'implementa.
| Criteri | Code-first | API-first |
|---|---|---|
| Punt de partida | El codi existent | El contracte acordat |
| Qui decideix la forma de l'API | La implementació i l'ORM | Els consumidors i el domini |
| Quan poden començar els clients | Quan hi ha servidor funcionant | El primer dia, contra un mock |
| Cost d'un canvi de disseny | Alt: hi ha codi escrit | Baix: s'edita un document |
| Risc de filtrar detalls interns | Alt | Baix |
| Documentació | Generada al final, a remolc | És la font, sempre al dia |
| Bo per a | Prototips, API interna d'un sol client | APIs amb diversos consumidors o externes |
La Botiga Aroma té quatre consumidors diferents i un d'ells és una empresa externa. Redissenyar el contracte després que RàpidEnviaments hagi integrat els seus sistemes costa reunions, versions i diners. Per això el curs adopta API-first: el mòdul 2 sencer dissenya el contracte sobre el paper i el mòdul 3 l'implementa.
Un matís honest: API-first no vol dir "dissenyar-ho tot perfecte abans de tocar codi". Vol dir que el contracte va al davant i es revisa com es revisa el codi. Es pot iterar, però s'itera sobre el document, no sobre una API ja publicada.
- El procés de disseny en set passos
graph TD
A["1. Identificar consumidors<br/>i casos d'ús"] --> B["2. Extreure substantius<br/>del domini"]
B --> C["3. Decidir què és recurs<br/>i què no"]
C --> D["4. Anomenar URIs i<br/>definir jerarquies"]
D --> E["5. Assignar mètodes,<br/>codis i representacions"]
E --> F["6. Escriure el contracte<br/>(OpenAPI) i revisar-lo"]
F --> G["7. Publicar mocks i<br/>validar amb consumidors"]
G -.->|"troballes"| A
Els passos 1 a 3 són aquesta lliçó. Els passos 4 i 5 són les lliçons 02-02 a 02-06. El pas 6 aterra a 02-07 i 02-08. El pas 7 es treballa a fons a 05-04. El cicle es tanca: allò que aprens validant amb consumidors torna al principi.
- Pas 1: identificar consumidors i casos d'ús
Una API no es dissenya "per al domini": es dissenya per a algú que la cridarà. El primer lliurable no és una llista d'endpoints, sinó una llista de consumidors amb les seves necessitats reals.
| Consumidor | Qui és | Què necessita | Restriccions |
|---|---|---|---|
| SPA de la botiga web | Aplicació al navegador | Catàleg, fitxa de cafè, cistella, checkout | Navegador: CORS, latència visible, sense secrets |
| Aroma Mòbil | App nativa iOS/Android | El mateix, en pantalles petites | Xarxa mòbil variable, versions antigues convivint mesos |
| Panell intern | Eina de back-office | Gestió d'estoc, moderació de ressenyes, comandes | Volums grans, llistats amb filtres, temps real |
| RàpidEnviaments | Soci de missatgeria | Rebre comandes pagades, informar d'enviaments | Extern: contracte estable, reintents, signatura HMAC |
D'aquí surten els casos d'ús, escrits com a frases d'usuari, no com a endpoints:
- "Com a visitant vull veure els cafès disponibles filtrats per origen i torrefacció."
- "Com a client vull afegir dues bosses d'Etiòpia Yirgacheffe a la meva cistella i pagar-les."
- "Com a client vull consultar l'estat de la meva comanda i descarregar la factura."
- "Com a moderador vull aprovar o rebutjar una ressenya pendent."
- "Com a RàpidEnviaments vull assabentar-me que una comanda s'ha pagat sense haver de preguntar-ho cada minut."
Aquest darrer cas d'ús és el que va fer aparèixer els webhooks a 01-07: la llista de casos d'ús també decideix l'arquitectura, no només els endpoints.
Un detall important: els consumidors tenen necessitats diferents i de vegades enfrontades. Aroma Mòbil vol respostes petites perquè paga la xarxa; el panell intern vol respostes riques perquè pinta taules amb moltes columnes. Aquesta tensió no es resol creant dues APIs paral·leles, sinó amb mecanismes de contracte: selecció de camps i expansió, que es dissenyen a 02-05.
- Pas 2: extreure els substantius del domini
La tècnica és deliberadament simple: escriu en prosa què fa el negoci i subratlla els substantius.
"Un client navega pel catàleg de cafès, cadascun amb el seu origen, la seva torrefacció i les seves notes de tast. Afegeix línies a la seva cistella i confirma una comanda, que té un total i un estat. La comanda es paga i genera una factura. Quan es paga, RàpidEnviaments crea un enviament. Després, el client pot escriure una ressenya d'un cafè, que un moderador aprova o rebutja, i a la qual la botiga pot publicar una resposta."
Substantius candidats: client, catàleg, cafè, origen, torrefacció, notes de tast, línia, cistella, comanda, total, estat, pagament, factura, enviament, ressenya, resposta, moderador.
I els verbs, que anotem a part perquè són la font dels problemes més interessants: navegar, afegir, confirmar, pagar, generar, aprovar, rebutjar, respondre.
- Pas 3: decidir què es converteix en recurs i què no
No tots els substantius mereixen una URI. Aplica aquests filtres:
- Té identitat pròpia? El pots assenyalar i dir "aquest d'aquí"? Una comanda sí (
com_5001); un total, no: és un atribut d'una comanda. - Algú necessita adreçar-lo per separat? Una ressenya sí: es modera d'una en una. Una torrefacció no: és un valor d'un enumerat.
- Té cicle de vida propi? Un enviament neix, canvia d'estat i acaba. Una nota de tast no: viu i mor amb el seu cafè.
- Es manipula independentment del seu pare? Una línia de cistella sí, perquè se'n canvia la quantitat sense tocar la resta.
Aplicat a la Botiga Aroma:
| Substantiu | És recurs? | Decisió |
|---|---|---|
| Cafè | Sí | Col·lecció /cafes |
| Client | Sí | Col·lecció /clients |
| Comanda | Sí | Col·lecció /comandes |
| Ressenya | Sí | Col·lecció /ressenyes, també imbricada sota el seu cafè |
| Cistella | Sí | Col·lecció /cistelles |
| Línia de cistella | Sí, subrecurs | /cistelles/{id}/linies/{cafeId} |
| Pagament | Sí, subrecurs | /comandes/{id}/pagament |
| Factura | Sí, subrecurs | /comandes/{id}/factura |
| Enviament | Sí, subrecurs | /comandes/{id}/enviament |
| Catàleg | No | És la col·lecció /cafes, no un recurs a part |
| Origen, torrefacció, notes de tast | No | Atributs d'un cafè |
| Total, estat | No | Atributs d'una comanda |
| Moderador | No a la v1 | És un rol d'usuari, no un recurs públic |
La columna de la dreta es justifica a 02-02, que és on s'expliquen les regles d'anomenament, la imbricació i els singleton. Aquí l'important és el criteri: recurs és allò que té identitat, cicle de vida i necessitat de ser adreçat.
- Principis rectors del disseny
Aquests sis principis són els que aplicarem, lliçó rere lliçó, cada vegada que calgui decidir alguna cosa.
6.1. Consistència per damunt de l'elegància puntual
Si /cafes accepta ?limit=20, aleshores /comandes accepta ?limit=20, encara que per a comandes haguessis preferit dir-li ?mida. Una API amb vint decisions bones però diferents entre si és pitjor que una API amb vint decisions acceptables i idèntiques: el consumidor n'aprèn la primera i dedueix les dinou restants.
6.2. Previsibilitat ("endevinabilitat")
Un desenvolupador que ja ha fet servir GET /v1/cafes/caf_001 hauria de poder escriure GET /v1/comandes/com_5001 sense obrir la documentació i encertar-la. Prova pràctica: ensenya tres endpoints a algú i demana-li que n'escrigui el quart. Si l'encerta, l'API és previsible.
# Si això funciona així...
curl https://api.botigaaroma.example/v1/cafes/caf_001
curl "https://api.botigaaroma.example/v1/cafes?torrefaccio=mitja&limit=10"
# ...això hauria de funcionar igual, sense consultar la documentació
curl https://api.botigaaroma.example/v1/comandes/com_5001
curl "https://api.botigaaroma.example/v1/comandes?estat=pagat&limit=10"6.3. Orientació a recursos i no a accions
L'API exposa coses sobre les quals s'opera amb els mètodes d'HTTP, no funcions remotes. POST /v1/comandes/com_5001/pagament en lloc de POST /v1/pagarComanda. Això ja ho vam justificar a 01-04 i 01-05; el cas difícil —les accions que no encaixen en CRUD— es resol a 02-02.
6.4. Simetria entre operacions
Si el GET d'un cafè retorna preuEuros i estoc, el POST que el crea hauria d'acceptar aquests mateixos noms de camp. Si POST /cafes retorna el recurs creat, PUT /cafes/{id} també hauria de retornar el recurs actualitzat. Les asimetries gratuïtes obliguen a memoritzar excepcions.
6.5. Contracte explícit i estable
Tot allò que el consumidor pot observar forma part del contracte: noms de camp, tipus, codis d'estat, capçaleres, missatges d'error, ordre per defecte d'una col·lecció. El que no vulguis garantir, no ho exposis. I el que exposis, no ho canviïs sense versionar (02-07).
6.6. Errors que ensenyen
Un error és una resposta més i es dissenya igual de bé que un èxit. Ha de dir què ha fallat, per què i què pot fer el client. El format el fixa 02-04.
- Granularitat: ni massa fina ni massa gruixuda
La granularitat és quanta feina fa una sola crida. És una de les decisions amb més conseqüències i no té resposta universal.
API massa fina. Cada recurs mínim té el seu endpoint i el client compon. Pintar la fitxa d'un cafè obliga a: demanar el cafè, demanar-ne les ressenyes, demanar el client de cada ressenya... És la chattiness (verbositat): moltes anades i vingudes. En una xarxa mòbil amb 150 ms de latència, vuit crides encadenades són més d'un segon perdut només en viatges.
API massa gruixuda. Un únic endpoint retorna el cafè amb les seves ressenyes, els clients de les ressenyes, l'estoc per magatzem i les recomanacions. Una sola crida, però: respostes enormes, gairebé tot sense fer servir (over-fetching), memòria cau inútil (qualsevol canvi ho invalida tot) i un contracte acoblat a una pantalla concreta que es trencarà quan la pantalla canviï.
| Símptoma | Diagnòstic | Remei de disseny |
|---|---|---|
| El client fa 5+ crides per a una pantalla | Massa fina | Expansió opcional (expandir=), subrecursos amb dades incrustades |
| Es descarreguen camps que ningú no fa servir | Massa gruixuda | Selecció de camps (camps=), enllaços en lloc d'incrustar |
| Un endpoint només el fa servir una pantalla | Acoblada a la interfície | Redissenyar al voltant del recurs, no de la vista |
| Canviar una pantalla obliga a tocar l'API | Acoblada a la interfície | Tornar a l'orientació a recursos |
La postura de la Botiga Aroma: una API de granularitat mitjana orientada a recursos, amb dues vàlvules d'escapament controlades que es dissenyen a 02-05 —expansió (expandir) per reduir crides i selecció de camps (camps) per reduir pes— i dades ja incrustades on l'ús real ho demana (el nom del cafè dins d'una línia de comanda, perquè el client no hagi de resoldre cada cafeId).
- Dissenyar per al consumidor, no per a la base de dades
L'error més freqüent i més car: publicar les taules. S'agafa l'esquema relacional, es genera un endpoint per taula i a això se'n diu API REST.
Què passa quan exposem la taula cafes tal com és:
{
"id_cafe": 1,
"nom_cafe": "Etiòpia Yirgacheffe",
"fk_origen": 12,
"cod_torrefaccio": 1,
"preu_centims": 1450,
"estoc_actual": 120,
"esborrat_logic": 0,
"data_alta": "2026-01-15 08:30:00",
"usuari_alta": "admin",
"versio_fila": 7
}Problemes: el consumidor ha de traduir cod_torrefaccio: 1 a "clar" amb una taula que no té; fk_origen: 12 no li diu res; preu_centims l'obliga a conèixer una decisió d'emmagatzematge; esborrat_logic, usuari_alta i versio_fila són lampisteria interna que ara forma part del contracte i no es pot treure sense trencar clients. I si demà es normalitza la taula, l'API es trenca.
La representació dissenyada per al consumidor:
{
"id": "caf_001",
"nom": "Etiòpia Yirgacheffe",
"origen": "Etiòpia",
"torrefaccio": "clar",
"preuEuros": 14.50,
"estoc": 120,
"notesTast": ["cítric", "floral", "te negre"],
"dataCreacio": "2026-01-15T08:30:00Z"
}La regla és: la representació és una projecció pensada per a qui la llegeix, no un abocament de la fila. La base de dades pot continuar guardant cèntims, claus foranes i banderes d'esborrat; això és cosa de la capa de persistència (03-05).
- Tolerància a l'evolució i principi de robustesa
El principi de robustesa de Jon Postel diu: "sigues conservador en allò que envies, liberal en allò que acceptes". Traduït a una API:
- Com a servidor: emet exactament allò que promet el contracte. Res de camps que apareixen de tant en tant ni de tipus que canvien.
- Com a client: no et trenquis perquè arribi un camp que no esperaves. Això és el tolerant reader, i és el que permet que el servidor afegeixi camps sense publicar una versió nova.
Conseqüències de disseny que adoptem ja:
- Els enumerats poden créixer. Si demà apareix
torrefaccio: "molt_fosc", els clients l'han d'ignorar amb elegància, no petar. Es documenta des del primer dia. - Els camps nous són opcionals i additius.
- Mai no es reutilitza un nom de camp amb un altre significat.
- Les col·leccions van embolcallades en un objecte (
{"dades": [...], "total": n}) precisament per poder afegir metadades sense canviar el tipus de la resposta. S'argumenta a 02-05.
Què és exactament un canvi trencador i què no, i com es gestiona la depreciació, és la lliçó 02-07.
- La guia d'estil de l'API de la Botiga Aroma
Aquest és l'artefacte central del mòdul. Una guia d'estil és un document curt, versionat al repositori, on s'escriuen les convencions que tota l'API respecta. Serveix per a tres coses: decidir ràpid, revisar en pull request i acollir gent nova.
Comencem amb les decisions ja preses (mòdul 1) i les que aquest mòdul anirà tancant:
| Àmbit | Convenció de la Botiga Aroma | Exemple | Es detalla a |
|---|---|---|---|
| Base URL | https://api.botigaaroma.example/v1 |
— | 02-07 |
| Noms de col·lecció | Substantiu en plural, minúscules | /cafes, /comandes |
02-02 |
| Paraules compostes a la URI | kebab-case | /notes-tast |
02-02 |
| Identificadors | Opacs, amb prefix de tipus | caf_001, com_5001 |
02-02 |
| Accions no CRUD | Subrecurs + POST | POST /comandes/{id}/pagament |
02-02 |
| Mètodes | GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS | — | 02-03 |
| Actualització parcial | PATCH amb JSON Merge Patch |
application/merge-patch+json |
02-03 |
| Reintents segurs | Capçalera Idempotency-Key en POST sensibles |
pagament d'una comanda | 02-03 |
| Codis d'estat | Els estàndard, sense inventar | 201 + Location en crear |
02-04 |
| Format d'error | {"error": {"codi", "missatge", "detalls"}} |
cafe_no_trobat |
02-04 |
| Noms en JSON | camelCase | preuEuros, dataCreacio |
02-05 |
| Dates i hores | ISO-8601 en UTC amb Z |
2026-03-14T10:32:00Z |
02-05 |
| Imports | Nombre en euros amb dos decimals, sufix Euros |
14.50 |
02-05 |
| Enumerats | snake_case en minúscules, ampliables |
pendent_pagament |
02-05 |
| Col·leccions | Embolcall {"dades": [...], "total": n} |
— | 02-05 |
| Enllaços | Nivell Richardson 2 amb hipermèdia selectiva | _links.self |
02-05 |
| Idioma del contingut | Accept-Language per a notesTast |
es, ca, en |
02-05 |
| Paginació | limit + desplacament, més capçalera Link |
?limit=20 |
02-06 |
| Ordenació | ?ordenar=camp / ?ordenar=-camp |
?ordenar=-preuEuros |
02-06 |
| Cerca | ?q= sobre la col·lecció |
?q=yirgacheffe |
02-06 |
| Versionat | A la ruta: /v1 |
— | 02-07 |
| Depreciació | Capçaleres Deprecation i Sunset |
— | 02-07 |
| Documentació | OpenAPI 3.1 al repositori | openapi.yaml |
02-08 |
| Idioma del codi | Identificadors i comentaris en català | obtenirCafes |
Mòdul 3 |
Dos advertiments sobre les guies d'estil:
- S'escriuen per complir-se. Una guia que ningú no revisa a les pull requests és decoració. A 05-05 veurem com automatitzar part de la comprovació (linters d'OpenAPI).
- Les convencions són arbitràries, la consistència no.
camelCaseno és objectivament millor quesnake_case; el que sí que és objectivament pitjor és fer servir totes dues.
- Mapa del mòdul 2
graph LR
L1["02-01<br/>Principis<br/><i>el mètode</i>"] --> L2["02-02<br/>Recursos i URIs<br/><i>el què i l'on</i>"]
L2 --> L3["02-03<br/>Mètodes HTTP<br/><i>el com</i>"]
L3 --> L4["02-04<br/>Codis d'estat<br/><i>el resultat</i>"]
L4 --> L5["02-05<br/>Representacions<br/><i>el cos</i>"]
L5 --> L6["02-06<br/>Col·leccions<br/><i>filtrar i paginar</i>"]
L6 --> L7["02-07<br/>Versionat<br/><i>el temps</i>"]
L7 --> L8["02-08<br/>Documentació<br/><i>el contracte publicat</i>"]
En acabar el mòdul tindràs el contracte complet de l'API de la Botiga Aroma: les seves URIs, els seus mètodes, els seus codis, les seves representacions, les seves col·leccions paginades, la seva política de versions i la seva documentació. El mòdul 3 l'implementa amb Node.js i Express sense inventar-se res de nou.
Errors Comuns i Consells
- Començar pels endpoints. Si el teu primer full de disseny és una llista d'URLs, t'has saltat els consumidors i el domini. Comença per casos d'ús escrits en llenguatge de negoci.
- Dissenyar l'API mirant l'ORM. Els noms de columna, les claus foranes i les banderes internes no són contracte. Projecta, no aboquis.
- Dissenyar l'API mirant la pantalla. L'extrem oposat i també nociu: endpoints que només serveixen per a una vista concreta envelleixen amb aquesta vista. Dissenya recursos i dona al client eines (
camps,expandir) per adaptar-los. - Optimitzar abans de tenir el problema. No afegeixis expansió, filtres exòtics ni memòria cau de negoci "per si de cas". Cada mecanisme del contracte s'ha de documentar, provar i mantenir per sempre.
- Confondre consistència amb rigidesa. Hi haurà excepcions legítimes (la factura en PDF, per exemple). L'important és que siguin poques, conscients i escrites a la guia d'estil, no accidents.
- Consell: escriu primer la resposta. Abans de decidir la URL, escriu a mà el JSON que voldries rebre en el cas d'ús principal. Moltes decisions de disseny s'aclareixen soles en veure'l.
- Consell: la prova del desenvolupador nou. Si algú que no ha participat en el disseny necessita preguntar com es diu el paràmetre de paginació, l'API encara no és previsible.
Exercicis
Exercici 1: separar recursos d'atributs
La Botiga Aroma vol afegir subscripcions: un client rep una bossa de cafè cada mes, amb una periodicitat, un mètode de pagament, una adreça de lliurament i un historial de lliuraments ja fets. A més, cada subscripció es pot pausar.
Decideix, justificant-ho amb els quatre criteris de la secció 5, quins d'aquests substantius són recursos i quins atributs: subscripció, periodicitat, mètode de pagament, adreça de lliurament, lliurament, pausa.
Exercici 2: diagnosticar la granularitat
La pantalla de "les meves comandes" d'Aroma Mòbil fa avui aquestes crides:
GET /v1/clients/cli_842/comandes # 12 comandes
GET /v1/comandes/com_5001 # una per comanda, 12 crides
GET /v1/cafes/caf_001 # una per línia, ~25 cridesI la pantalla només mostra, per comanda: data, estat, total i el nom del primer cafè. Diagnostica el problema i proposa dues solucions de disseny diferents, indicant l'inconvenient de cadascuna.
Exercici 3: ampliar la guia d'estil
Afegeix a la taula de la secció 10 tres files noves que avui no hi són i que saps que faran falta, per a aquests tres assumptes: (a) com s'anomenen les capçaleres pròpies de la Botiga Aroma, (b) quina zona horària es fa servir a les dates d'entrada que envia el client, (c) què passa amb els camps desconeguts que un client enviï al cos d'un POST. Redacta la convenció en una frase per fila.
Solucions
Solució 1
| Substantiu | És recurs? | Justificació |
|---|---|---|
| Subscripció | Sí | Identitat pròpia (sub_310), cicle de vida (activa → pausada → cancel·lada), s'adreça sola. Col·lecció /subscripcions. |
| Periodicitat | No | Atribut de la subscripció (periodicitat: "mensual"). No té identitat ni cicle de vida. |
| Mètode de pagament | Sí, però no com a subrecurs de subscripció | Té identitat i es reutilitza entre comandes i subscripcions: col·lecció pròpia /metodes-pagament, referenciada per id des de la subscripció. |
| Adreça de lliurament | Depèn | Si el client en guarda diverses, és recurs (/clients/{id}/adreces). Si només n'hi ha una per subscripció, és un objecte imbricat en la seva representació. Decideix segons el cas d'ús, no segons la taula. |
| Lliurament | Sí, subrecurs | Cada lliurament té data, estat i seguiment: /subscripcions/{id}/lliuraments. No té sentit fora de la seva subscripció. |
| Pausa | Sí, com a acció modelada com a subrecurs | No és una dada, és una transició: POST /subscripcions/{id}/pausa, coherent amb /aprovacio i /anullacio. Es detalla a 02-02. |
Solució 2
Diagnòstic: API massa fina per a aquest cas d'ús. La pantalla necessita quatre dades per comanda i provoca de l'ordre de 38 crides. És chattiness pura, agreujada perquè Aroma Mòbil pateix latència de xarxa mòbil. A més hi ha over-fetching en l'altre sentit: de cada cafè es descarrega tot per llegir només nom.
Solució A — que la col·lecció retorni ja allò que es pinta. GET /v1/clients/cli_842/comandes retorna cada comanda amb dataCreacio, estat, totalEuros i les línies amb el nom del cafè ja incrustat. Una sola crida.
Inconvenient: es duplica el nom del cafè en moltes respostes i cal mantenir aquesta còpia coherent; a més la resposta creix per a tots els consumidors, inclosos els que no necessiten les línies.
Solució B — expansió i selecció de camps. GET /v1/clients/cli_842/comandes?expandir=linies.cafe&camps=id,dataCreacio,estat,totalEuros,linies. Una crida, i cada consumidor demana el que necessita.
Inconvenient: mecanismes que cal documentar, validar i provar; obren la porta a consultes cares i compliquen la memòria cau, perquè cada combinació de paràmetres és una URL diferent.
(La decisió de la Botiga Aroma combina les dues: incrusta el nom del cafè a les línies —dada estable i sempre necessària— i ofereix expandir/camps com a vàlvula. Es tanca a 02-05.)
Solució 3
| Àmbit | Convenció de la Botiga Aroma | Exemple |
|---|---|---|
| Capçaleres pròpies | Prefix Aroma- en PascalCase amb guions; mai X- (obsolet per RFC 6648) |
Aroma-Esdeveniment-Id, Aroma-Signatura |
| Dates d'entrada | S'accepten només en ISO-8601 amb zona horària explícita; el servidor les normalitza i les emmagatzema en UTC | 2026-03-14T11:32:00+01:00 |
| Camps desconeguts al cos | Es rebutgen amb 400 i codi dades_invalides, indicant el camp a detalls, per detectar errades aviat |
{"nomm": "..."} → error |
Sobre l'última: és una decisió discutible i convé entendre-la. Rebutjar camps desconeguts (strict) detecta errades del client a l'instant; ignorar-los (tolerant) facilita que un client nou parli amb un servidor vell. La Botiga Aroma és estricta a l'entrada i tolerant a la sortida, que és exactament el principi de robustesa de la secció 9.
Conclusió
Dissenyar una API RESTful no comença dibuixant URLs: comença sabent qui la farà servir i per a què, extraient els substantius del domini i decidint amb criteri quins mereixen ser recursos. A partir d'aquí, un grapat de principis rectors —consistència, previsibilitat, orientació a recursos, simetria, contracte estable i errors útils— resolen la majoria de les decisions del dia a dia, mentre que la granularitat i el rebuig a exposar la base de dades eviten els dos errors estructurals més cars. Tot això es materialitza en un artefacte concret: la guia d'estil, que hem obert amb les decisions ja fermes de la Botiga Aroma i que anirem omplint a cada lliçó.
Amb el mètode clar i els consumidors identificats, toca la primera decisió concreta del contracte: quins recursos existeixen i com s'anomenen les seves URIs. A la lliçó següent, 02-02 Recursos i URIs, convertirem la llista de substantius en un mapa complet d'adreces —col·leccions, elements, subrecursos imbricats i singleton—, fixarem les regles d'anomenament, distingirem què va a la ruta i què a la query string, triarem el tipus d'identificador i resoldrem el problema que cap CRUD no resol sol: com es modelen accions com pagar una comanda o moderar una ressenya.
Curs de REST API: Principis de Disseny i Desenvolupament d'APIs RESTful
Mòdul 1: Introducció a les APIs RESTful
- Què és una API?
- Història i evolució de les APIs
- Fonaments d'HTTP per a APIs
- Principis bàsics de REST
- Model de maduresa de Richardson i HATEOAS
- REST vs. SOAP
- REST davant de GraphQL, gRPC i webhooks
Mòdul 2: Disseny d'APIs RESTful
- Principis de disseny d'APIs RESTful
- Recursos i URIs
- Mètodes HTTP
- Codis d'estat HTTP
- Representacions, capçaleres i negociació de contingut
- Filtratge, ordenació, paginació i cerca
- Versionat d'APIs
- Documentació d'APIs
Mòdul 3: Desenvolupament d'APIs RESTful
- Configuració de l'entorn de desenvolupament
- Creació d'un servidor bàsic
- Gestió de peticions i respostes
- Validació de dades d'entrada
- Persistència i capa d'accés a dades
- Autenticació i autorització
- Gestió d'errors
- Proves i validació
Mòdul 4: Bones Pràctiques i Seguretat
- Bones pràctiques en el disseny d'APIs
- Seguretat en APIs RESTful
- OAuth 2.0 i OpenID Connect a la pràctica
- Rate limiting i throttling
- CORS i polítiques de seguretat
- Memòria cau HTTP i rendiment
- Observabilitat: logs, mètriques i traces
Mòdul 5: Eines i Frameworks
- Postman per a proves d'APIs
- Swagger i OpenAPI per a documentació
- Frameworks populars per a APIs RESTful
- Contractes, mocks i proves automatitzades d'API
- Integració contínua i desplegament
- API gateways i portals de desenvolupador
