Bár kétségtelenül a REST a legelterjedtebb kommunikációs mód, akár ugyanolyan
platformon fejlesztett alkalmazások között is, REST API tervezéskor
nekem sok kérdés merül fel, melyre nem kapok megnyugtató választ,
és sok olyan megoldással találkozom, amelyek nem felelnek meg a REST elveknek,
vagy egyszerűen csak nem tetszenek.
Sokáig próbáltam megfogalmazni, hogy mi az alapvető problémám, és talán most
sikerült közelebb kerülni. Vegyünk két microservice-t, melyek mindegyike Javaban készült,
Spring Boot használatával. Mindkét oldalon a programozási nyelv alapeleme az osztályok,
ahol érvényesül az egységbezárás, azaz az attribútumok mellett ott vannak
a metódusok, a megfelelő paraméterekkel és visszatérési értékekkel. Ez
a legtöbb fejlesztőnek triviális.
A REST a kettő között viszont egy teljesen
más absztrakció. Bár a REST nem mondja ki, hogy csak HTTP-vel együtt használható,
más protokollal működni még nem láttam.
A REST alapfogalma az erőforrás, és az azon végzett műveletek, melyeket a HTTP metódusok valósítanak meg, mint a GET
, POST
, PUT
és DELETE
.
Ez nehezen feleltethető meg az objektumorientált világnak.
Egy objektum létrehozására tipikusan konstruktort használunk, ebből nem feltétlen egy van.
Ezen kívül egy objektumnak lehet több metódusa, amik nem feltétlenül feleltethetőek meg a HTTP metódusoknak,
hiszen nem csak ezeket az alapműveleteket használjuk, valamint lehet belőle sokkal több is, mint négy.
Míg a Java nyelv szabvány, addig a REST csak egy ajánlás, és az sincs megfelelően
definiálva, hogy hogyan kéne implementálni, az meg aztán pláne nincs, hogy a kettőt
hogyan feleltessük meg egymásnak. És ennek az az eredménye, hogy minden projekten
teljesen más megoldásokat látok, a legtöbb helyen kompromisszumokkal.
Az RPC alapú kommunikáció esetén igazából nincs ilyen probléma, mert nem szükséges
átfordítás, nincs szükség az absztrakció váltására. Hiszen ott is eljárások vannak,
paraméterekkel és visszatérési értékekkel. A Spring Frameworkben volt is ilyen
lehetőség, hogy egy távoli eljáráshívás történt, azonban a protokollt
kódolás nélkül cserélni lehetett alatta, pl. választhattunk RMI-t,
vagy ki emlékszik még a Hessian és Burlap protokollokra.
Sajnos ez azóta eltűnt.
A SOAP esetén sem volt akkora probléma az átfordítás, hiszen ott is vannak
az operációk (eljárásnak felel meg), és a paraméter, valamint a visszatérési
érték is egy-egy (XML) dokumentum. Vannak modernebb RPC alapú kommunikációs
protokollok is, mint pl. JSON-RPC, vagy az egyre inkább elterjedő
multiplatform gRPC, bináris Protocol Buffers formátummal.
Amennyiben CRUD alkalmazásról van szó, a REST használata talán triviális. De ha
egy olyan alkalmazásról beszélünk, amiben komoly üzleti logika van (és hiszem,
hogy a legtöbb alkalmazásnak ilyennek kéne lennie, csak a fejlesztők “butítják le”
CRUD alkalmazássá, amely végső soron oda is vezethet, hogy borzasztó felhasználói
felületek kerülnek kifejlesztésre), akkor már több kérdés merül fel.
Vegyünk például egy hibajegykezelő alkalmazást (issue tracker), mely rendelkezzen egy minimális
üzleti logikával. Ha hibajegy kerül felvételre, az új (new) állapottal kerül létrehozásra.
Amennyiben valaki elkezd rajta dolgozni, átkerül folyamatban (in_progress) állapotba.
Amennyiben elkészült, átkerül megoldott (resolved) állapotba. Bár a legtöbb hibajegykezelő
alkalmazás lehetővé teszi, hogy egyedi munkafolyamatot lehessen benne létrehozni,
ettől most tekintsünk el, mert akkor megint más problémák merülnek fel.
Ezt egy egyszerű állapotdiagrammal lehet a legegyszerűbben szemléltetni.
Talán egy hibajegy felvételét még el tudom képzelni REST API-n (bár már ott is vannak
kérdéseim), azonban a különböző munkafolyamat lépések implementálásakor már
bizonytalanabb vagyok. Ez a poszt ezt a problémakört járja körbe,
forráskódokkal alátámasztva.