CRUD: az egész több, mint a részek összessége!

A CRUD egy meglehetősen elterjedt fogalom. Egy angol mozaikszó, amely a következő szavak kezdőbetűiből áll össze: Create-Retrieve-Update-Delete. Ezek a szavak az adatok kezelésének négy alapvető módját írják le:

  • Create: létrehoz,
  • Retrieve (vagy Read): lekérdez vagy olvas,
  • Update: módosít,
  • Delete (vagy Destroy): töröl.

ADO.NET

Sok keretrendszer, alkalmazás épül a CRUD köré. A legtipikusabb minta amellyel találkozhatunk, hogy megjelenik egy táblázat, amely adatrekordokat tartalmaz (Retrieve művelet), és ebben kvázi Excel-szerűen, master-detail módon, esetleg egy-egy felugró űrlap segítségével vihetünk fel új rekordokat, esetleg meglévőeket módosíthatunk vagy törölhetünk.

Ezt a mintát támogatja egy az egyben a .NET framework ADO.NET-je (Table Data Gateway minta).

Az ADO.NET lényegét (pongyolán) a következőképpen lehet összefoglalni. Először megtervezünk egy adatbázist, majd abból legeneráljuk a benne lévő táblákat és a közöttük lévő kapcsolatokat reprezentáló C# osztályokat (DataSet, DataTable stb.) A DataTable-ök reprezentálják az egyes táblákat és a benne lévő adatokat, ezeken a már megismert CRUD-műveletekkel kezeljük az adatokat, majd a változtatásokat visszamentjük az adatbázisba. Az ADO.NET képes legenerálni az SQL-szerver számára szükséges adatbázis műveleteket (Insert, Select, Update, Delete), hogy az általunk végrehajtott CRUD-parancsok változtatásai perzisztálódjanak.

Tehát C# kóddal berántjuk az adatokat a memóriába, változtatunk, és mentünk. Mindent az ADO.NET kezel.

Gyors alkalmazásfejlesztés

A CRUD-minta lehetővé teszi bizonyos típusú alkalmazások gyors kifejlesztését, ha valaki ismer egy ezt támogató keretrendszert (pl. az ADO.NET-et). Képzeljünk el pl. egy egyszerű kontaktokat kezelő programot. Megjelenítjük az összes kontaktot, esetleg még szűrhetünk is a benne lévő adatokra (név, telefonszám), majd a kiválasztott nevet módosíthatjuk vagy törölhetjük. Új kontakt felvitele is gyorsan megy.

Sajnos, a CRUD-módszer sem csodafegyver. (“There’s no silver bullet.”)

Sőt, én kifejezetten gyűlölöm.

Egyszerűség

Csak nagyon egyszerű alkalmazások fejleszthetőek ily módon. Kvázi Excel-szerűek, felhasználói felületüket leginkább pár egyszerű táblázat és űrlap jellemzi. Komplexebb rendszerek már a következő jellemzőkkel bírnak (bírhatnak):

  • kifinomult jogosultságkezelés,
  • intelligens validáció,
  • üzleti folyamatok támogatása,
  • összetett fogalmi rendszer és üzleti szabályok támogatása,
  • bonyolult számítások,
  • integráció más rendszerekkel.

A táblázatos reprezentáció és a buta adatmanipulációs eszközök (CRUD) nem képesek hatékonyan rendszerezni azt a rengeteg üzleti logikát, amely egy ilyen komplex rendszer mögött húzódik meg. Számomra akkor hatékony egy rendszerezés, ha a következőket eredményezi:

  • viszonylag gyors implementáció (nem ez feltétlenül a legfőbb szempont),
  • könnyű kód-olvashatóság és karbantarthatóság: mivel komplex rendszerről van szó, az a legritkább esetben lesz elsőre a megrendelő számára megfelelő. Legtöbbször a késznek vélt programkód után is hosszú “reszelgetés” után érjük el a kívánt célt. Elsősorban arra kell törekednünk, hogy kódunk könnyen módosítható legyen.
  • Tesztelhetőség: az “intelligens” framework-ökben a CRUD mintákat sok esetben hozzá lehet kötni a felhasználói felülethez (data binding). Pl. a képernyőn egy adott mezőben történő változtatás azonnal megváltoztatja az aktuális rekord adott mezőjének értékét. Ezekben az esetekben a felhasználói felületben valósul meg az üzleti logika. Ez aztán tényleg rapid alkalmazásfejlesztés, de teljesen kezelhetetlen kódot is eredményez, amelyet képtelenség a felhasználói felület nélkül tesztelni.

Rossz gondolkozás

Úgy vehetjük észre, hogy CRUD-ra jár az agyunk, ha munka közben ilyen gondolatok merülnek fel:

“Ezen a képernyőn a Szerződés tábla rekordjait kell megjeleníteni. Majd lesz egy nagy táblázat, amelyet a user görget.” Az a megfigyelésem, hogy általában nincs olyan, hogy egy táblázatban vegytisztán kell megjeleníteni egy adott táblázat oszlopait. Mindig vannak kapcsolatok más táblákra, és egyes oszlopok értékei egy másik tábla bizonyos mezőinek aggregált értékét is tartalmazhatják. Az is előfordul, hogy szakítanunk kell a táblázatszerű adatmegjelenítéssel: a felhasználó számára megfelelő prezentációs modell különbözhet az adatreprezentálási modelltől. (Példa: egy hibakövető rendszerben rögzítik, hogy egy adott bejelentés milyen prioritású. A prioritásoknak különféle szintjei vannak: normál, sürgős, azonnali stb. A felhasználói felületen elegendő lehet egy piros felkiáltójellel jelölni, ha egy bejelentés nem normál prioritású. Ez egyből feltűnik a felhasználónak, és az ilyen jellegű bejelentések igényelnek általában is különböző bánásmódot.) Ki kell lépnünk a megszokott gondolkozásból, és inkább a felhasználói igényeket kell megvizsgálnunk: az adott feladat elvégzéséhez milyen felületet adjunk a felhasználónak? Mi az a minimális információ, amit megjelenítsünk a számára? Hogyan tudom a legmegfelelőbben megjeleníteni?

“Ha egy új hitelt visznek fel, akkor kell egy új mező a táblába, amely jelzi, hogy a hitelt jóváhagyták-e.” Sajnos, sokszor kiderül, hogy bonyolultabb üzleti szabályok húzódnak meg a háttérben. Célszerűbb egy objektum-orientált megközelítés, amelyben minden hitelhez tartozik egy jóváhagyás entitás, amely felöleli mindazon logikákat (workflow, jogosultság), amely ennek a funkciónak a megvalósításához szükséges. Még az is lehet, hogy a különböző hiteltípusokhoz más és más jóváhagyási szabályok tartoznak. Esetleg itt jól jöhet az öröklés is: az egyes származtatott osztályok a különféle típusú hitelekhez tartalmazzák a jóváhagyást leíró üzleti szabályokat. A módszer előnye a rugalmasság. Nem kell, hogy fájjon a fejünk attól, ha a későbbiekben kiderül, mégsem csak egy boolean-flag a jóváhagyás.

“Ha törölnek egy megrendelést, törölhetem-e a rekordot az adatbázisból, mert nincs rá mutató kapcsolat, vagy csináljak inkább egy törölt flag-et, amit 1-re állítok be?” Ez szintén egy tipikus rossz hozzáállás. Ahelyett, hogy flag-eket buzerálnánk, érdemesebb azon elgondolkoznunk, vajon mit jelent az, hogy törölnek egy megrendelést. Ha pl. a megrendelés abban a fázisban van, hogy épp a küldemény összeállításánál tartanak, akkor a felhasználói kezdeményezés, a megrendelés visszavonása extra folyamatot is generálhat (pl. a már beszerzésre került termékek után nem térítik vissza a teljes vételárat). Az is lehet, hogy egy árut nem tudtak beszerezni, ilyenkor a szállító a megrendelést lemondja, és értesíteni kell az ügyfelet a lemondás tényéről. Ha megfigyeljuk, az említett két eset (visszavonás és lemondás) már kézzelfogható üzleti folyamatokat eredményez szemben az egyszerű megrendelés törlése, adatközpontú megközelítéssel.

A CRUD-dal a legnagyobb baj, hogy arra késztet, adat szinten gondolkozzunk. A lényeg az üzleti probléma megértése és hatékony leképezése a kódba.

A kód nem csak adatok lekérdezése, megjelenítése és változtatása. A kód magának az üzleti területnek, az üzleti tudásnak a hatékony, működő leképezése.

…és így az egész már több is, mint a részek összessége.

Share
This entry was posted in Programozás, Technológia and tagged , , . Bookmark the permalink. Follow any comments here with the RSS feed for this post. Trackbacks are closed, but you can post a comment.

There are no comments yet, add one below.

Leave a Comment