SoC (Separation of Concerns) este abrevierea principiului conform căruia un sistem software este împărțit în domenii izolate de responsabilitate. Potrivit lui Martin Fowler, separarea responsabilităților este un element cheie al codului ușor de întreținut. Principiul SoC permite dezvoltatorilor să schimbe un strat al aplicației fără a afecta celelalte, ceea ce este deosebit de important în dezvoltarea mobilă în echipă.
Puncte cheie
SoC înseamnă Separation of Concerns — «separarea responsabilităților» sau «separarea domeniilor de interes». În contextul programării, termenul concern desemnează orice funcționalitate separabilă: afișarea interfeței utilizator, procesarea clicurilor, validarea datelor, comunicarea în rețea sau lucrul cu baza de date. Principiul SoC prescrie gruparea codului în jurul acestor domenii astfel încât modificările într-unul să nu le afecteze pe celelalte.
Abrevierea SoC este utilizată pe scară largă în literatura tehnică, discuțiile arhitecturale și documentația framework-urilor. De exemplu, în documentația Android Architecture Components se menționează în repetate rânduri SoC ca motivație pentru separarea ViewModel și View. În comunitatea iOS, termenul este folosit când se discută problema Massive View Controller — consecința directă a lipsei SoC.
Este important să înțelegem că SoC nu este o acțiune unică, ci un proces continuu. Pe măsură ce aplicația crește, apar noi domenii de responsabilitate și arhitectura trebuie revizuită. O bază de cod bună trece prin mai multe iterații de separare înainte de a atinge o stare stabilă în care fiecare concern este izolat și gestionabil.
Separation of Concerns și abrevierea sa SoC desemnează același principiu. Diferența constă doar în contextul de utilizare: denumirea completă se folosește în documente formale, materiale educaționale și la explicarea conceptului pentru dezvoltatorii noi. SoC este convenabil în discuțiile tehnice, code review și documentația unde concizia este importantă.
În mediul profesional ambii termeni sunt interschimbabili. Un dezvoltator poate spune «aici SoC este încălcat» sau «acest lucru încalcă Separation of Concerns» — sensul nu se schimbă. Totuși, în anunțurile de angajare și cerințele arhitecturale apare mai des denumirea completă, în timp ce în chat-uri și code review — abrevierea. Cunoașterea ambelor variante este necesară pentru o intrare confortabilă în industrie.
Există confuzie terminologică: abrevierea SoC este, de asemenea, utilizată în context hardware pentru System-on-a-Chip (sistem pe un cip). În dezvoltarea mobilă, contextul este întotdeauna clar din mediu — dacă discuția vizează arhitectura codului, este vorba despre Separation of Concerns. În acest articol, SoC se referă întotdeauna la principiul separării responsabilităților.
Arhitectura pe trei straturi — cel mai răspândit mod de implementare a SoC în aplicațiile mobile. Împarte codul în Presentation (UI), Domain (logica de business) și Data (lucrul cu sursele). Fiecare strat conține tipuri strict definite de clase și este izolat de vecini prin interfețe. Această abordare este la fel de eficientă pentru proiectele iOS, Android și Flutter.
View și ViewModel formează stratul de prezentare. View se ocupă de redarea interfeței și transmiterea evenimentelor utilizatorului. ViewModel stochează starea ecranului și transformă datele din stratul Domain într-un format gata de afișare. ViewModel nu are referințe la Activity, Fragment sau UIViewController — aceasta asigură SoC între UI și logică.
De exemplu, în Android Jetpack ViewModel supraviețuiește rotației ecranului, iar UI este recreat. Fără SoC ar trebui să salvăm starea în Activity, amestecând gestionarea ciclului de viață cu datele. ViewModel rezolvă această sarcină în mod izolat, demonstrând o implementare pură a principiului separării responsabilităților.
Use Cases conțin reguli de business independente de platformă. Acest strat nu importă Android SDK, iOS UIKit sau Flutter framework. Use Case primește date din Repository, le aplică logica de business și returnează rezultatul. Datorită SoC, un Use Case poate fi reutilizat pe diferite ecrane și platforme.
Un exemplu clasic — ValidateAndSaveUseCase pentru formularul de înregistrare. Acesta verifică corectitudinea email-ului și parolei, cheamă UserRepository pentru salvare și returnează ValidationResult. Nici UI, nici baza de date nu cunosc regulile de validare — ele sunt concentrate într-un singur loc, ceea ce simplifică modificarea lor.
Repository abstractizează sursele de date de restul aplicației. ViewModel nu știe de unde provin datele — din REST API, GraphQL, baza de date locală sau cache. Repository decide ce sursă să utilizeze și ascunde această logică în spatele unei interfețe. Aceasta este SoC între obținerea datelor și consumul lor.
DataSource asigură o separare și mai profundă: RemoteDataSource răspunde doar pentru cererile HTTP, LocalDataSource — pentru lucrul cu Room, CoreData sau SharedPreferences. Repository le combină, aplicând strategii de cache. Fiecare DataSource poate fi înlocuit independent, ceea ce este critic la migrarea între servere sau baze de date.
Un astfel de sistem multi-nivel DataSource implementează SoC la nivel de infrastructură: comunicarea în rețea, stocarea locală și cache-ul — concerns separate, fiecare cu propria logică și ciclu de viață. La schimbarea clientului HTTP, se modifică doar RemoteDataSource, iar Repository și straturile superioare rămân intacte, ceea ce confirmă valoarea practică a separării responsabilităților.
MVP (Model-View-Presenter) — unul dintre primele pattern-uri care implementează explicit SoC în dezvoltarea mobilă. Presenter conține logica și gestionează View prin intermediul unei interfețe. View este pasiv — afișează doar ceea ce spune Presenter. Separarea simplifică testarea: Presenter se testează fără emulator, iar View rămâne atât de simplu încât nu are ce să se strice.
MVVM a adăugat legarea reactivă: View se abonează la modificările ViewModel prin Observable sau StateFlow. ViewModel nu păstrează referința la View, ceea ce elimină riscul de scurgere de memorie și separă și mai puternic concerns. În Android, MVVM a devenit standard datorită Jetpack ViewModel și LiveData, în iOS — datorită Combine și RxSwift.
Clean Architecture a lui Robert Martin duce SoC la o separare radicală în inele. Inelul exterior (framework-uri și drivere) depinde de cel interior (entități), dar nu invers. În practică, proiectele mobile rareori implementează toate cele patru inele — straturile Domain și Data în jurul Presentation sunt suficiente. Dar însuși principiul dependenței «spre interior» oferă avantaje semnificative la schimbarea framework-urilor.
// View — doar afișare, fără logică
final class LoginViewController: UIViewController {
let viewModel: LoginViewModel
func loginTapped() {
viewModel.login(emailField.text, passwordField.text)
}
}
// ViewModel — conține logica ecranului, nu cunoaște UIKit
final class LoginViewModel {
private let loginUseCase: LoginUseCase
func login(email: String?, password: String?) {
loginUseCase.execute(email, password)
}
}
// Use Case — logică de business, independentă de platformă
final class LoginUseCase {
private let repo: AuthRepository
func execute(email: String?, password: String?) {
guard let e = email, let p = password else { return }
repo.authenticate(e, p)
}
}
Exemplul arată trei niveluri de SoC: LoginViewController doar transmite evenimente, LoginViewModel gestionează starea, LoginUseCase conține regulile de business. Fiecare clasă se testează independent, iar schimbarea framework-ului UI nu afectează Use Case.
Massive View Controller — cea mai frecventă încălcare a SoC în iOS. O clasă care gestionează UI, procesează cereri de rețea, parsează JSON și salvează date încalcă principiul la toate nivelurile. Soluția — extrageți fiecare responsabilitate într-o componentă separată: NetworkingService, JSONParser, CoreDataStack, lăsând ViewController doar gestionarea View.
În Android există o problemă analogă — God Activity sau God Fragment. O singură activitate care încarcă date, validează formulare, afișează dialoguri și actualizează UI. Se tratează prin introducerea ViewModel și Repository, care preiau gestionarea stării și datelor. ViewModel protejează, de asemenea, împotriva pierderii datelor la rotirea ecranului.
A treia încălcare — amestecarea codului de platformă cu cel de business. De exemplu, plasarea unei cereri HTTP direct într-o SwiftUI View sau Android Composable. Acest lucru face codul neportabil și dificil de testat. Abordarea corectă — extrageți cererea în Repository, care este apelat prin Use Case, iar View doar se abonează la rezultat. Fiecare element al sistemului își rezolvă sarcina și nu depășește granițele sale.
Întrebări frecvente
Nu. SoC este un principiu mai general de împărțire a sistemului în domenii de responsabilitate. SOLID este un set de cinci reguli specifice pentru proiectarea orientată pe obiecte. Primul principiu SOLID (Single Responsibility) este un caz particular al SoC la nivelul unei singure clase.
Folosiți regula unui singur motiv pentru schimbare (Single Responsibility). Dacă o clasă se modifică din cauza schimbării UI, formatului datelor și regulilor de business — SoC este încălcat. Instrumente precum ArchTest (Android) și StrictConcurrency (iOS) ajută la detectarea automată a unor astfel de încălcări.
În teorie, straturile suplimentare adaugă apeluri indirecte, dar în practică impactul asupra performanței aplicației mobile este neglijabil. Compilatorul inline-izează multe apeluri, iar optimizările JIT și AOT elimină overhead-ul. Mentenabilitatea codului câștigă mult mai mult decât se pierde prin abstracții.
Începeți cu extragerea cererilor de rețea din UI în Repository. Apoi separați logica de business în Use Cases. Folosiți injectarea dependențelor pentru conectarea straturilor. Faceți modificările iterativ, acoperind noul cod cu teste — aceasta garantează că refactorizarea nu va strica funcționalitatea existentă.
În prototipuri puteți încălca SoC de dragul vitezei. Dar dacă prototipul trece în dezvoltarea de producție, costurile de refactorizare pot depăși beneficiul pornirii rapide. Optim — păstrați o separare minimă (UI și date) chiar și în prototip, pentru a nu rescrie totul de la zero la lansare.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și