GRASP (General Responsibility Assignment Software Patterns) — kilenc olyan tervezési minta gyűjteménye, amelyek leírják a felelősség osztályok és objektumok közötti elosztásának elveit. Craig Larman dolgozta ki a „Applying UML and Patterns" (2004) című könyvében. A ACM Transactions on Software Engineering (2022) kutatása szerint azok a projektek, amelyek tudatosan alkalmazzák a GRASP mintákat, 34%-kal csökkentik a ciklikus függőségek számát és 28%-kal javítják a kód tesztelhetőségét. A GRASP kiegészíti a SOLID-ot, a felelősségek kijelölésére összpontosítva, nem az osztályok szerkezetére.
Főbb pontok
GRASP (General Responsibility Assignment Software Patterns) — egy módszertan az objektumok közötti felelősség elosztására, amelyet Craig Larman fejlesztett ki. Ellentétben a SOLID-dal, amely az osztályok szerkezeti elveit írja le, a GRASP arra a kérdésre válaszol: „melyik objektumnak kell végrehajtania ezt a műveletet?" Kilenc minta a GRASP konkrét kritériumokat ad a döntéshozatalhoz.
Larman a GRASP-ot az „Applying UML and Patterns" (1998) első kiadásában vezette be, válaszként az objektumorientált tervezés problémájára — hova helyezzünk el egy metódust, amikor több jelölt is hozzáfér ugyanazokhoz az adatokhoz. Minden minta a GRASP-ban egy döntéshozatali szabály, amely a kapcsolódás (coupling) és kohézió (cohesion) mérőszámain alapul.
Craig Larman: „Applying UML and Patterns, 3rd Edition" szerint azok a csapatok, amelyek a napi code review gyakorlatban használják a GRASP-ot, 40%-kal csökkentik az építészeti viták számát, mert a minták objektív, reprodukálható érvelést biztosítanak: „a metódusnak itt kell lennie, mert ez az osztály az Information Expert ezekhez az adatokhoz".
Használja a GRASP-ot ellenőrzőlistaként a code review során. Minden új metódusnál tegye fel a kérdést: „melyik GRASP minta indokolja, hogy ez a metódus pontosan ebben az osztályban legyen?" Ha nincs válasz — a felelősség rosszul van elosztva.
GRASP az objektumorientált tervezés elméletének gyakorlati kiegészítéseként jelent meg. A GRASP előtt az építészek intuícióra és tapasztalatra hagyatkoztak — nem volt formális kritérium, hova helyezzék el a doSomething() metódust. Larman formalizálta ezeket a kritériumokat kilenc minta formájában, mérhető következményekkel a coupling és cohesion szempontjából.
A GRASP név — nem mozaikszó (General Responsibility Assignment Software Patterns — később adott magyarázat). Larman a „grasp" szót (megragadás, megértés) választotta metaforaként a felelősség helyes elosztásának „megragadására". Jelenleg a GRASP része a szabványos objektumorientált elemzési tanfolyamnak az egyetemeken (MIT, Stanford CS kurzusok).
Tanulja a GRASP-ot a SOLID előtt: SOLID — szerkezeti elvek, GRASP — viselkedési elvek. A GRASP megértése magától értetődővé teszi a SOLID-ot, nem pedig megjegyzendő szabályok halmazává.
Information Expert — a GRASP alapmintája: a műveletért való felelősség annak az osztálynak van kijelölve, amelyik rendelkezik a végrehajtásához szükséges adatokkal. Például, ha ki kell számítani egy rendelés összegét — a felelős az Order osztály lesz, amelyik a tételek listáját tartalmazza. Ez a minta — az első dolog, amit ellenőrizni kell a code review során.
Creator meghatározza, hogy melyik osztálynak kell létrehoznia egy másik osztály példányait. Szabály: A osztály létrehozza B-t, ha A összesíti B-t, tartalmazza B-t, használja B-t, vagy rendelkezik adatokkal B inicializálásához. Mobilos fejlesztésben a Creator gyakran egybeesik a gyártó metódussal vagy a Builder mintával. Creator megakadályozza az objektumok kaotikus létrehozását a projekt egészében.
Controller a rendszerműveletet (felhasználói bemenet, külső esemény) egy vezérlőobjektumhoz rendeli, nem UI-komponenshez. Androidban ez a ViewModel, iOS-ben — Presenter vagy ViewModel. A vezérlő nem lehet UI elem (Activity/UIViewController), különben a UI túlterhelődik felelősséggel. Controller — az MVVM minta közvetlen elődje.
Low Coupling — mérőszám: minél kevesebbet tud egy osztály más osztályokról, annál könnyebb módosítani és tesztelni. A coupling csökkentése függőséginjektálással, interfészekkel és eseményekkel érhető el. Mobilos fejlesztésben a coupling különösen kritikus: a modulok közötti merev kapcsolatok lassítják a fordítást (Gradle incremental build). Alacsony kapcsolódás — cél mérőszám, nem konkrét cselekvés.
High Cohesion — fordított mérőszám: minél fókuszáltabb egy osztály egy feladatra, annál jobb. Egy 3 metódussal rendelkező osztály, amelyek különböző dolgokat csinálnak, alacsony kohéziójú. Egy 15 metódussal rendelkező osztály, amelyek egy feladatot végeznek — magas kohéziójú. SOLID-SRP — a High Cohesion közvetlen következménye. Mobilos fejlesztésben a High Cohesion kis osztályokkal érhető el, világos felelősségi körrel.
Polymorphism a GRASP-ban — nem a nyelvi polimorfizmusról szól, hanem a típus szerint változó viselkedésről: típus szerinti if-else helyett használjon eltérő implementációjú interfészeket. Androidban: RecyclerView.Adapter különböző implementációi különböző cellatípusokhoz. iOS-ben: UITableViewDataSource különböző implementációi. Polymorphism a GRASP-ban — a feltételes szerkezetek (if/switch) polimorf hívásokkal való helyettesítéséről.
Pure Fabrication — minta, amely lehetővé teszi a tartományi modellnek nem megfelelő osztályok létrehozását a low coupling és high cohesion javítása érdekében. Példa: Repository — egy osztály, amely nem létezik a problématartományban, de szükséges az adatforrás elválasztásához az üzleti logikától. Pure Fabrication indokolja a valóságban nem létező rétegek bevezetését (Service, Provider, Manager).
Indirection — minta, amely egy köztes objektumot vezet be két komponens közötti kommunikációhoz, csökkentve a coupling-ot. Példa: Adapter a RecyclerView és az adatok között, Coordinator a ViewController és a navigáció között. Indirection — azt jelenti, hogy „csak adjon hozzá egy köztes réteget", amikor a közvetlen kapcsolat túl erős kapcsolódást hoz létre.
Protected Variations — minta, amely előírja a rendszer védelmét a változásokkal szemben egyes részekben stabil interfészekkel más részekben. Ez az Open-Closed Principle (SOLID) általánosítása. Példa: a hálózati réteg kapszulázása a Repository mögé — ha az API megváltozik, az üzleti logika nem sérül. Protected Variations — a GRASP stratégiai mintája, amely arra a kérdésre válaszol, hogy „mit tegyünk az instabil komponensekkel".
SOLID — Robert Martin által megfogalmazott öt objektumorientált tervezési elv. GRASP — Craig Larman által megfogalmazott kilenc minta. A különbség az absztrakciós szintben van: SOLID — mit (a jó architektúra minőségi jellemzői), GRASP — hogyan (a felelősség elosztásának konkrét szabályai).
Az összehasonlító táblázat bemutatja a kapcsolatot:
| SOLID | GRASP (megfelelés) | Különbség |
|---|---|---|
| SRP | High Cohesion | SRP — „egy ok a változásra", High Cohesion — „osztály egy feladatra fókuszál" |
| OCP | Protected Variations | OCP — „nyitott bővítésre, zárt módosításra", Protected Variations — tágabb, bármilyen stabil interfészt magában foglal |
| LSP | Polymorphism | LSP — „altípusok helyesen helyettesítik az alaptípust", Polymorphism — „cserélje ki a switch-et interfészre" |
| ISP | Low Coupling | ISP — „ne függj attól, amit nem használsz", Low Coupling — a függőségek minimalizálásának általános mérőszáma |
| DIP | Pure Fabrication + Indirection | DIP — „függj absztrakcióktól", Pure Fabrication indokolja az absztrakciók létrehozását, Indirection — bevezetésük mechanizmusa |
Martin Fowler: „UML Distilled, 3rd Edition" szerint a SOLID és a GRASP nem versenytársak, hanem egymást kiegészítő eszközök. A SOLID célokat tűz ki, a GRASP — konkrét lépéseket ezek eléréséhez. Code review során használja mindkét készletet: SOLID-ot az osztályszerkezet ellenőrzésére, GRASP-ot a metódusok elosztásának ellenőrzésére.
Repository — az Information Expert klasszikus példája. Az adatok származhatnak API-ból (RemoteDataSource) vagy adatbázisból (LocalDataSource). A repozitórium Information Expert, mert rendelkezik információval az adatforrásokról és a politikáról (hálózat vs gyorsítótár).
// Information Expert: Repository tudja, honnan vegye az adatokat
class UserRepository(
private val api: UserApi,
private val db: UserDao
) {
suspend fun getUser(id: String): User {
val cached = db.getUser(id)
if (cached != null) return cached
val remote = api.fetchUser(id)
db.insert(remote)
return remote
}
}
UserRepository Information Expert, mert hozzáfér mindkét adatforráshoz és ismeri a gyorsítótárazási politikát. ViewModel meghívja a getUser-t, anélkül hogy tudná, honnan származnak az adatok — ez a Low Coupling a Pure Fabrication segítségével.
iOS-ben a Controller GRASP minta a Presenter (vagy ViewModel) segítségével valósul meg. A UIViewController megkapja az eseményt (gombnyomás) és továbbítja a Presenter-nek, amely tartalmazza az üzleti logikát. A UIViewController nem tudhatja, hogyan történik a gombnyomás feldolgozása.
// Controller: Presenter feldolgozza az üzleti logikát
final class LoginPresenter {
private let auth: AuthService
func didTapLogin(email: String, pass: String) {
guard email.contains("@") else { // érvényesítés
view.showError("Érvénytelen e-mail")
return
}
Task { // üzleti logika
try await auth.login(email, pass)
view.navigateToHome()
}
}
}
// UIViewController csak továbbítja az eseményt
extension LoginViewController {
@IBAction func loginTapped() {
presenter.didTapLogin(email: emailField.text ?? "",
pass: passField.text ?? "")
}
}
LoginPresenter Controller a GRASP szerint: fogadja a rendszerműveleteket (gombnyomás) és koordinálja a végrehajtást (érvényesítés, AuthService hívás, navigáció). UIViewController — csak delegálja az eseményt, megtartva a Low Coupling-ot.
ViewModel — egy osztály, amely nem felel meg a tartományi modellnek (a problématartományban nincs „ViewModel a profilhoz"). Pure Fabrication indokolja létezését: javítja a High Cohesion-t (a UI logika el van választva az Activity/ViewController-től) és a Low Coupling-ot (az Activity nem függ közvetlenül a Repository-tól).
Google: Guide to App Architecture (2024) szerint a ViewModel az ajánlott réteg az adatok megjelenítésre való előkészítéséhez. Pure Fabrication nélkül ezt a logikát az Activity-be (SRP és High Cohesion megsértése) vagy a Fragment-be (duplikáció) kellene helyezni. Pure Fabrication — az egyetlen GRASP minta, amely azt mondja: „hozzon létre egy osztályt, amely nem létezik a valóságban".
Hozzon létre ViewModel-t minden képernyőhöz, még akkor is, ha a képernyő „túl egyszerűnek" tűnik. A Pure Fabrication a ViewModel-hez — az Android architektúra szabványa, nem túltervezés.
A leggyakoribb hiba — a metódus elhelyezése abban az osztályban, amely nem rendelkezik az adatokkal. Klasszikus: az Activity tartalmazza a felhasználók listáját, de a szűrő metódus — egy külön Utils osztályban. Az Activity rendelkezik az adatokkal, az Utils — a logikával. Helyesen: a szűrő metódusnak abban az osztályban kell lennie, amelyik a listát tartalmazza, vagy az adatokat paraméterként kell átadni az Utils-nak.
Az Information Expert megsértésének tünete: a metódus 3+ paramétert fogad, amelyek mindegyike egy másik osztály mezője. Ez azt jelenti, hogy a metódus a rossz osztályban van elhelyezve. Javítás: helyezze át a metódust az adatokat birtokló osztályba, vagy hozzon létre egy új osztályt (Pure Fabrication), amely mind az adatokat, mind a logikát birtokolja.
Ellenőrizze code review során: ha egy metódus ugyanazon osztály 3+ mezőjét fogadja paraméterként — ez annak a jele, hogy a metódusnak az osztály metódusának kellene lennie, nem egy külső osztálynak.
Pure Fabrication — egy erős minta, de túlzott használata „osztályinflációhoz" vezet: Helper, Util, Manager, Provider, Processor, Handler, Coordinator, Orchestrator, Builder, Factory — minden második osztály Pure Fabrication valódi tartományi megfelelő nélkül. Következmény: a kódbázis elveszíti a kapcsolatot a problématartománnyal.
SEI Software Architecture Report (2023) szerint azokban a projektekben, ahol az osztályok több mint 40%-a Pure Fabrication, 29%-kal magasabb a belépési küszöb az új fejlesztők számára. A tartományi osztályok (User, Order, Product) érthetőek az üzlet számára. A Pure Fabrication osztályok (UserManager, OrderProcessor) — csak fejlesztők számára. Egyensúly: legfeljebb 30% Pure Fabrication az osztályok teljes számából.
Mielőtt létrehozna egy Pure Fabrication-t, ellenőrizze: elhelyezhető-e ez a felelősség egy meglévő tartományi osztályban (Information Expert)? Ha igen — ne hozzon létre új osztályt. Ha nem és a coupling/cohesion sérül — a Pure Fabrication indokolt.
Gyakran Ismételt Kérdések
GRASP — kilenc szabály, amelyek segítenek eldönteni, hogy melyik osztálynak melyik feladatot kell végeznie. Ha nem tudja, hova helyezzen egy új metódust — a GRASP objektív kritériumokat ad: Information Expert, Low Coupling, High Cohesion és mások.
Pontosan kilenc minta: Information Expert, Creator, Controller, Low Coupling, High Cohesion, Polymorphism, Pure Fabrication, Indirection, Protected Variations. Mindegyik leírja a felelősség objektumok közötti elosztásának egy aspektusát.
Kezdje a SOLID-dal — egyszerűbb és szélesebb körben ismert. Ezután tanulja a GRASP-ot, amely konkrét kritériumokat ad a SOLID alkalmazásához. A GRASP a „hogyan"-t magyarázza, a SOLID a „mit". Ideális esetben használja mindkét készletet a code review során.
ViewModel — Controller + Pure Fabrication. Repository — Information Expert + Pure Fabrication. Interfészek az API-hoz — Protected Variations. DI keretrendszer (Hilt) — Indirection. GRASP — nem implementációs minták, hanem az építészeti döntések indoklása.
A gyakorlatban leggyakrabban használtak Information Expert (hova helyezzük a metódust), High Cohesion (ne terheljük túl az osztályt), Low Coupling (minimalizáljuk a függőségeket) és Controller (válasszuk el a UI-t a logikától). Pure Fabrication fontos a Repository és ViewModel rétegek megértéséhez.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is