GRASP (General Responsibility Assignment Software Patterns) — скуп од девет образаца пројектовања који описују принципе расподјеле одговорности између класа и објеката. Развио их је Крејг Ларман у књизи „Applying UML and Patterns" (2004). Према истраживању ACM Transactions on Software Engineering (2022), пројекти који свјесно примјењују GRASP обрасце смањују број цикличких зависности за 34% и побољшавају тестирабилност кода за 28%. GRASP допуњује SOLID, фокусирајући се на додјељивање одговорности, а не на структуру класа.
Главне тачке
GRASP (General Responsibility Assignment Software Patterns) — методологија расподјеле одговорности између објеката коју је развио Крејг Ларман. За разлику од SOLID-а, који описује структурне принципе класа, GRASP одговара на питање: „који објекат треба да изврши ову операцију?" Девет образаца GRASP-а даје конкретне критеријуме за доношење одлука.
Ларман је увео GRASP у првом издању „Applying UML and Patterns" (1998) као одговор на проблем објектно-оријентисаног пројектовања — гдје смјестити метод када више кандидата има приступ истим подацима. Сваки образац GRASP-а је правило одлучивања засновано на метрикама повезаности (coupling) и кохезије (cohesion).
Према Craig Larman: „Applying UML and Patterns, 3rd Edition", тимови који користе GRASP у свакодневној пракси code review-а смањују број архитектонских спорова за 40%, јер обрасци пружају објективну, поновљиву аргументацију: „метод треба да буде овдје, јер је ова класа Information Expert за ове податке".
Користите GRASP као контролну листу на code review-у. За сваки нови метод поставите питање: „који GRASP образац оправдава смјештање овог метода управо у овој класи?" Ако нема одговора — одговорност је погрешно распоређена.
GRASP је настао као практична допуна теорији објектно-оријентисаног пројектовања. Прије GRASP-а, архитекте су се ослањали на интуицију и искуство — није постојао формални критеријум гдје смјестити метод doSomething(). Ларман је формализовао ове критеријуме у виду девет образаца са мјерљивим посљедицама за coupling и cohesion.
Назив GRASP — није акроним (General Responsibility Assignment Software Patterns — накнадно објашњење). Ларман је изабрао ријеч „grasp" (хватање, разумијевање) као метафору за „хватање" правилне расподјеле одговорности. Тренутно GRASP улази у састав стандардног курса објектно-оријентисане анализе на универзитетима (MIT, Stanford CS курсеви).
Учите GRASP прије SOLID-а: SOLID — структурни принципи, GRASP — бихевиорални. Разумијевање GRASP-а чини SOLID очигледним, а не скупом правила за памћење.
Information Expert — основни GRASP образац: одговорност за операцију се додјељује класи која има податке за њено извршење. На примјер, ако треба израчунати суму поруџбине — одговорна ће бити класа Order која посједује листу ставки. Овај образац — прва ствар коју треба провјерити на code review-у.
Creator одређује која класа треба да креира инстанце друге класе. Правило: класа А креира Б ако А агрегира Б, садржи Б, користи Б или има податке за иницијализацију Б. У мобилном развоју, Creator се често поклапа са фабричким методом или Builder обрасцем. Creator спречава хаотично креирање објеката широм пројекта.
Controller додјељује системску операцију (кориснички унос, спољашњи догађај) објекту-контролеру, а не UI компоненти. У Android-у је то ViewModel, у iOS-у — Presenter или ViewModel. Контролер не би требало да буде UI елемент (Activity/UIViewController), иначе UI постаје преоптерећен одговорношћу. Controller — директни претходник MVVM обрасца.
Low Coupling — метрика: што класа мање зна о другим класама, лакше је мијењати и тестирати. Смањење coupling-а се постиже кроз убризгавање зависности, интерфејсе и догађаје. У мобилном развоју, coupling је посебно критичан: чврсте везе између модула успоравају компилацију (Gradle incremental build). Ниска повезаност — циљна метрика, а не конкретна радња.
High Cohesion — обрнута метрика: што је класа фокусиранија на један задатак, то боље. Класа са 3 метода који раде различите ствари има ниску кохезију. Класа са 15 метода који раде један задатак — високу. SOLID-SRP — директна посљедица High Cohesion-а. У мобилном развоју, High Cohesion се постиже кроз мале класе са јасном зоном одговорности.
Polymorphism у GRASP-у — не ради се о језичком полиморфизму, већ о понашању које варира по типовима: умјесто if-else по типу користите интерфејсе са различитим имплементацијама. У Android-у: различите имплементације RecyclerView.Adapter-а за различите типове ћелија. У iOS-у: различите имплементације UITableViewDataSource-а. Polymorphism у GRASP-у — о замјени условних конструкција (if/switch) полиморфним позивима.
Pure Fabrication — образац који дозвољава креирање класа које не одговарају доменском моделу ради побољшања low coupling и high cohesion-а. Примјер: Repository — класа која не постоји у предметној области, али је потребна за одвајање извора података од пословне логике. Pure Fabrication оправдава увођење слојева који не постоје у стварности (Service, Provider, Manager).
Indirection — образац који уводи посредни објекат за комуникацију између двије компоненте, смањујући coupling. Примјер: Adapter између RecyclerView-а и података, Coordinator између ViewController-а и навигације. Indirection — значи „само додајте посредни слој" када директна веза ствара прејаку повезаност.
Protected Variations — образац који прописује заштиту система од промјена у једним дијеловима кроз стабилне интерфејсе у другим. Ово је генерализација Open-Closed Principle (SOLID). Примјер: инкапсулација мрежног слоја иза Repository-а — ако се API промијени, пословна логика неће страдати. Protected Variations — стратешки GRASP образац који одговара на питање „шта радити са нестабилним компонентама".
SOLID — пет принципа објектно-оријентисаног пројектовања које је формулисао Роберт Мартин. GRASP — девет образаца које је формулисао Крејг Ларман. Разлика је у нивоу апстракције: SOLID — шта (квалитативне карактеристике добре архитектуре), GRASP — како (конкретна правила расподјеле одговорности).
Табела поређења приказује међусобну повезаност:
| SOLID | GRASP (подударност) | Разлика |
|---|---|---|
| SRP | High Cohesion | SRP — „један разлог за промјену", High Cohesion — „класа се фокусира на један задатак" |
| OCP | Protected Variations | OCP — „отворен за проширење, затворен за промјену", Protected Variations — шире, укључује било које стабилне интерфејсе |
| LSP | Polymorphism | LSP — „подтипови замјењују базни тип исправно", Polymorphism — „замијените switch интерфејсом" |
| ISP | Low Coupling | ISP — „не зависи од онога што не користиш", Low Coupling — општа метрика минимизације зависности |
| DIP | Pure Fabrication + Indirection | DIP — „зависи од апстракција", Pure Fabrication оправдава креирање апстракција, Indirection — механизам њиховог увођења |
Према Martin Fowler: „UML Distilled, 3rd Edition", SOLID и GRASP нису конкуренти, већ комплементарни алати. SOLID поставља циљеве, GRASP — конкретне кораке за њихово постизање. На code review-у користите оба скупа: SOLID за провјеру структуре класа, GRASP за провјеру расподјеле метода.
Repository — класичан примјер Information Expert-а. Подаци могу долазити из API-ја (RemoteDataSource) или из базе података (LocalDataSource). Репозиторијум је Information Expert, јер посједује информације о изворима података и политици (мрежа наспрам кеша).
// Information Expert: Repository зна одакле да преузме податке
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, јер има приступ оба извора података и зна политику кеширања. ViewModel позива getUser, не знајући одакле су подаци дошли — ово је Low Coupling кроз Pure Fabrication.
У iOS-у образац Controller GRASP се имплементира кроз Presenter (или ViewModel). UIViewController прима догађај (притисак дугмета) и просљеђује га Presenter-у који садржи пословну логику. UIViewController не би требало да зна како се обрађује притисак.
// Controller: Presenter обрађује пословну логику
final class LoginPresenter {
private let auth: AuthService
func didTapLogin(email: String, pass: String) {
guard email.contains("@") else { // валидација
view.showError("Неисправан email")
return
}
Task { // пословна логика
try await auth.login(email, pass)
view.navigateToHome()
}
}
}
// UIViewController само просљеђује догађај
extension LoginViewController {
@IBAction func loginTapped() {
presenter.didTapLogin(email: emailField.text ?? "",
pass: passField.text ?? "")
}
}
LoginPresenter је Controller по GRASP-у: прима системске операције (притисак дугмета) и координира извршење (валидација, позив AuthService-а, навигација). UIViewController — само делегира догађај, поштујући Low Coupling.
ViewModel — класа која не одговара доменском моделу (у предметној области не постоји „ViewModel за профил"). Pure Fabrication оправдава њено постојање: побољшава High Cohesion (UI логика је одвојена од Activity/ViewController-а) и Low Coupling (Activity не зависи директно од Repository-а).
Према Google: Guide to App Architecture (2024), ViewModel је препоручени слој за припрему података за приказ. Без Pure Fabrication-а, ову логику би требало смјестити у Activity (кршење SRP и High Cohesion-а) или у Fragment (дуплирање). Pure Fabrication — једини GRASP образац који каже „направите класу која не постоји у стварности".
Креирајте ViewModel за сваки екран, чак и ако изгледа да је екран „превише једноставан". Pure Fabrication за ViewModel — стандард Android архитектуре, а не overengineering.
Најчешћа грешка — смјештање метода у класи која не посједује податке. Класика: Activity садржи листу корисника, а метод филтрирања — у засебној Utils класи. Activity посједује податке, Utils — логику. Исправно: метод филтрирања треба да буде у класи која посједује листу или податке треба пренијети у Utils као параметар.
Симптом кршења Information Expert-а: метод прима 3+ параметра, од којих су сви поља друге класе. То значи да је метод смјештен у погрешној класи. Исправка: премјестите метод у класу-власника података или креирајте нову класу (Pure Fabrication) која ће посједовати и податке и логику.
Провјеравајте на code review-у: ако метод прима 3+ поља исте класе као параметре — то је знак да метод треба да буде метод те класе, а не спољашњи.
Pure Fabrication — моћан образац, али његова злоупотреба води до „класне инфлације": Helper, Util, Manager, Provider, Processor, Handler, Coordinator, Orchestrator, Builder, Factory — свака друга класа је Pure Fabrication без стварног доменског еквивалента. Посљедица: база кода губи везу са предметном облашћу.
Према SEI Software Architecture Report (2023), пројекти у којима је преко 40% класа Pure Fabrication имају 29% виши праг уласка за нове програмере. Доменске класе (User, Order, Product) су разумљиве бизнису. Pure Fabrication класе (UserManager, OrderProcessor) — само програмерима. Равнотежа: не више од 30% Pure Fabrication-а од укупног броја класа.
Прије креирања Pure Fabrication-а провјерите: може ли се ова одговорност смјестити у постојећу доменску класу (Information Expert)? Ако може — не креирајте нову класу. Ако не може и coupling/cohesion пате — Pure Fabrication је оправдан.
Често постављана питања
GRASP — девет правила која помажу да одлучите која класа треба да ради који посао. Ако не знате гдје да смјестите нови метод — GRASP даје објективне критеријуме: Information Expert, Low Coupling, High Cohesion и друге.
Тачно девет образаца: Information Expert, Creator, Controller, Low Coupling, High Cohesion, Polymorphism, Pure Fabrication, Indirection, Protected Variations. Сваки описује један аспект расподјеле одговорности између објеката.
Почните са SOLID-ом — једноставнији је и шире познат. Затим учите GRASP, који даје конкретне критеријуме за примјену SOLID-а. GRASP објашњава „како", SOLID објашњава „шта". Идеално је користити оба скупа на code review-у.
ViewModel — Controller + Pure Fabrication. Repository — Information Expert + Pure Fabrication. Интерфејси за API — Protected Variations. DI оквир (Hilt) — Indirection. GRASP — нису обрасци имплементације, већ образложење за архитектонске одлуке.
У пракси најчешће се користе Information Expert (гдје смјестити метод), High Cohesion (не преоптерећуј класу), Low Coupling (минимизирај зависности) и Controller (одвоји UI од логике). Pure Fabrication је важан за разумијевање Repository и ViewModel слојева.
Закључци
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође