SOLID — Robert C. Martin (Uncle Bob) tomonidan 2000-yillarning boshida ishlab chiqilgan beshta ob'ektga yo'naltirilgan dasturlash tamoyili. DigitalOcean, 2024 ma'lumotlariga ko'ra, SOLID Single Responsibility, Open-Closed, Liskov Substitution, Interface Segregation va Dependency Inversion deb ochiladi. Bu tamoyillar Clean Architecture asosini tashkil etadi va Android (MVP, MVVM, Clean Architecture) va iOS (VIPER, TCA) ishlanmasida qo'llaniladi.
Asosiy
SOLID — beshta ob'ektga yo'naltirilgan dizayn tamoyilini bildiruvchi mnemonic akronim. Atama Robert C. Martin tomonidan “Design Principles and Design Patterns” (2000) maqolasida kiritilgan va keyinchalik “Agile Software Development: Principles, Patterns, and Practices” (2002) kitobida ommalashtirilgan. SOLID framework yoki kutubxona emas — kodni kamroq bog'liq, ko'proq test qilinadigan va o'zgartirish uchun qulayroq qiladigan amaliyotlar to'plami.
Clean Coder Blog, 2014 ma'lumotlariga ko'ra, har bir SOLID tamoyili ma'lum bir dizayn muammosini hal qiladi: SRP God-sinflar bilan kurashadi, OCP — kaskad o'zgarishlar bilan, LSP — noto'g'ri meros bilan, ISP — semiz interfeyslar bilan, DIP — qattiq bog'lanish bilan. Birgalikda ular MVP, MVVM va MVI bilan Android loyihalarida ishlatiladigan Clean Architecture asosini tashkil qiladi.
Single Responsibility Principle (SRP) — yagona mas'uliyat tamoyili. Formula: “Sinf o'zgartirish uchun faqat bitta sababga ega bo'lishi kerak.” Bu har bir modul yoki sinf aniq bir funksionallik yoki domen obyekti uchun javobgar degani. Agar sinf ham foydalanuvchilarni, ham email jo'natishni boshqarsa — uning o'zgartirish uchun ikkita sababi bor, bu SRPni buzadi.
Robert C. Martin, 2002 ga ko'ra, SRP eng muhim va shu bilan birga eng ko'p buziladigan tamoyildir. Mobil ishlanmada SRP ko'pincha Activity/Fragment da UI mantig'i, navigatsiya, tarmoq ishi va biznes mantig'ini birlashtirib buziladi. Yechim — har bir qatlamni alohida sinfga ajratish: UI mantig'i uchun ViewModel, ma'lumotlar uchun Repository, navigatsiya uchun NavController.
UserManager sinfini ko'rib chiqaylik, u profilni yuklaydi, sozlamalarni saqlaydi va email jo'natadi. Bu uch xil mas'uliyat, har biri alohida sinfga ajratilishi kerak: UserProfileRepository (yuklash), UserSettingsStorage (saqlash) va EmailService (jo'natish). Mijoz kodi (ViewModel) uchalasini Dependency Injection orqali ishlatadi va har bir sinf alohida osonlik bilan test qilinadi va boshqalarga ta'sir qilmasdan o'zgartiriladi.
// ❌ SRP buzilishi: Activity tarmoq, BD va UI haqida biladi
class ProfileActivity : AppCompatActivity() {
fun loadProfile() {
api.getUser() // Tarmoq chaqiruvi
db.saveUser() // BD bilan ishlash
updateUI() // UI yangilanishi
}
}
// ✅ SRP bajarilgan: qatlamlar ajratilgan
class ProfileViewModel : ViewModel() {
private val repo = UserRepository()
fun loadProfile() { repo.getUser() }
}
SRP buzilish belgilari: sinf 200 dan ortiq satrni o'z ichiga oladi, turli sohalardan metodlari bor, tez-tez turli sabablarga ko'ra o'zgaradi. Android ishlanmasi uchun qoida oddiy: Activity faqat ekranning hayot aylanishi uchun javobgar, ViewModel — UI holati uchun, Repository — ma'lumot manbalari uchun.
SRP tamoyili nafaqat sinflarga, balki xizmat darajasidagi arxitekturaga ham tegishli. Har bir mikroservis bir domen obyekti uchun javobgar: UserService — faqat foydalanuvchilar, PaymentService — faqat to'lovlar, NotificationService — faqat bildirishnomalar. Bu xizmatlarni mustaqil ravishda masshtablash, joylashtirish va test qilish imkonini beradi. Mobil ilovada mikroservis darajasida SRP API mijozlarining domenlar bo'yicha bo'linishida namoyon bo'ladi.
Open-Closed Principle (OCP) — ochiqlik/yopiqlik tamoyili. Sinflar kengaytirish uchun ochiq (yangi xatti-harakat qo'shilishi mumkin) va o'zgartirish uchun yopiq (mavjud kod o'zgarmaydi) bo'lishi kerak. Bunga polimorfizm, abstrakt sinflar va interfeyslar orqali erishiladi. Mavjud metodga if-else qo'shish o'rniga, interfeysning yangi implementatsiyasi yaratiladi.
Clean Coder Blog, 2014 ga ko'ra, OCP Strategy naqshi bilan birgalikda eng samarali hisoblanadi. Masalan, ilova turli to'lov usullarini (Google Pay, Apple Pay, PayPal) qo'llab-quvvatlasa, to'lov protsessoriga switch-case qo'shish shart emas. Har bir to'lov usuli umumiy PaymentGateway interfeysini implementatsiya qiladi va yangi to'lov tizimi mavjud kodni o'zgartirmasdan yangi sinf sifatida qo'shiladi.
// ✅ OCP: kengaytirishga ochiq, o'zgartirishga yopiq
interface PaymentGateway {
fun processPayment(amount: Double): Boolean
}
class GooglePayGateway : PaymentGateway {
override fun processPayment(amount: Double) = true
}
// Yangi to'lov tizimi — mavjud kodni o'zgartirmasdan
class ApplePayGateway : PaymentGateway {
override fun processPayment(amount: Double) = true
}
Liskov Substitution Principle (LSP) — Barbara Liskovning almashtirish tamoyili. Agar S T ning kichik turi bo'lsa, T obyektlarini dastur xususiyatlarini o'zgartirmasdan S obyektlari bilan almashtirish mumkin. Rasmiy ravishda: asosiy sinfdan foydalanadigan funksiya uning istalgan kichik sinfi bilan to'g'ri ishlashi kerak. Agar kichik sinf asosiy sinf tashlamaydigan joyda exception tashlasa — LSP buzilgan.
Robert C. Martin, 2002 ga ko'ra, LSP SOLIDning tushunish eng qiyin tamoyilidir. Buzilishning klassik misoli — Rectangle (to'rtburchak) dan meros olgan Square sinfi (kvadrat). Agar Square uchun setWidth ham enini, ham balandligini o'rnatsa, Rectangle xatti-harakatini kutayotgan mijoz kodi kutilmagan natija oladi. Mobil ishlanmada LSP ko'pincha ViewModel meros olishda buziladi, bunda bola ViewModel majburiy bog'liqliklarni qo'shadi.
// ❌ LSP buzilishi: Square Rectangle xatti-harakatini buzadi
open class Rectangle(open var width: Int, open var height: Int)
class Square(side: Int) : Rectangle(side, side) {
override var width
get() = super.width
set(value) { super.setBoth(value, value) }
}
Interface Segregation Principle (ISP) — interfeyslarni ajratish tamoyili. Mijozlar foydalanmaydigan interfeyslarga bog'liq bo'lmasligi kerak. Bitta “semiz” interfeys o'rniga bir nechta tor, ixtisoslashtirilgan interfeyslar yaratiladi. Agar sinf interfeysni implementatsiya qilsa, lekin metodlarning bir qismi UnsupportedOperationException tashlasa yoki bo'sh qolsa — bu ISP buzilishining aniq belgisidir.
DigitalOcean, 2024 ga ko'ra, ISP mobil ishlanmada ViewModel va Repository dizaynida ayniqsa dolzarbdir. Barcha CRUD metodlari bilan bitta UserRepository interfeysi o'rniga QueryUserRepository (faqat o'qish) va CommandUserRepository (yozish) yaratish yaxshiroq. U holda o'quvchi mijoz (UI elementi) faqat Query interfeysiga bog'liq va yozish metodlari haqida bilmaydi.
// ❌ Semiz interfeys — mijoz keraksiz metodlarni implementatsiya qilishga majbur
interface UserOperations {
fun getUser(id: String): User
fun saveUser(user: User)
fun deleteUser(id: String)
fun exportUsers(): File
}
// ✅ ISP: ajratilgan interfeyslar
interface UserReader { fun getUser(id: String): User }
interface UserWriter { fun saveUser(user: User) }
interface UserDeleter { fun deleteUser(id: String) }
Dependency Inversion Principle (DIP) — bog'liqliklarni teskari qilish tamoyili. Yuqori darajadagi modullar pastki darajadagi modullarga bog'liq bo'lmasligi kerak. Ikkala daraja ham abstraksiyalarga (interfeyslarga) bog'liq bo'lishi kerak. Abstraksiyalar tafsilotlarga bog'liq bo'lmasligi kerak — tafsilotlar abstraksiyalarga bog'liq. Bu “Dependency Injection” (bog'liqliklarni kiritish) bilan bir xil emas, garchi DI DIPni implementatsiya qilishning keng tarqalgan usuli bo'lsa ham.
Robert C. Martin, 2019 ga ko'ra, DIP Clean Architecture asosidir. ViewModel (yuqori daraja) to'g'ridan-to'g'ri RetrofitApi (tafsilot) namunasini yaratmasligi kerak. Buning o'rniga ViewModel UserRepository interfeysiga bog'liq va Retrofit bilan aniq UserRepositoryImpl implementatsiyasi konstruktor orqali uzatiladi. Android-da DIP Hilt/Dagger yoki Koin orqali implementatsiya qilinadi: barcha bog'liqliklar DI konteyneri orqali ta'minlanadi.
// ✅ DIP: Modul abstraksiyaga bog'liq, tafsilotga emas
class UserRepositoryImpl(
private val api: UserApi, // Interfeysga bog'liq
private val db: UserDao // Interfeysga bog'liq
) : UserRepository {
override suspend fun getUser(id: String): User {
return api.fetchUser(id)
}
}
// Hilt DI: tafsilotlar DI moduli orqali bog'lanadi
@Module
object NetworkModule {
@Provides
fun provideUserApi(retrofit: Retrofit): UserApi =
retrofit.create(UserApi::class.java)
}
Mobil ishlanmada SOLID barcha darajalarda qo'llaniladi: ilova arxitekturasidan tortib alohida sinflargacha. Android loyihalarida Clean Architecture kodni uch qatlamga ajratadi: domain (biznes mantig'i — frameworklardan mustaqil), data (repositorylar, API, BD) va presentation (UI, ViewModel). Domain qatlami SOLID tamoyillaridan foydalanadi: use case (SRP), repository interfeyslari (DIP), entity sinflari (OCP + LSP).
Android Developers Guide, 2025 ga ko'ra, SRP Android-da ViewModel, Repository va Mapper bo'linishida namoyon bo'ladi. OCP — DataSource interfeysi orqali yangi ma'lumot manbalari qo'shganda. LSP — turli repositorylardan Result ni bir xil ishlashda. ISP — CQRS yondashuvida (Read/Write repositorylarini ajratish). DIP — bog'liqliklarni kiritish uchun Hilt/Koin orqali.
| Tamoyil | Usiz muammo | Mobil loyihada yechim |
|---|---|---|
| SRP | 1000+ sartr Activity | ViewModel + UseCase + Repository |
| OCP | To'lov turiga qarab switch-case | Strategy: PaymentGateway interfeysi |
| LSP | BaseViewModel almashtirishda xato | Kichik sinflar shartnomasini tekshirish |
| ISP | UnsupportedOperationException | Reader / Writer ajratish |
| DIP | ViewModel qo'lda Retrofit yaratadi | Hilt / Koin DI konteyneri |
SOLID xatolari ko'pincha kodni haddan tashqari murakkablashtirish bilan bog'liq. Birinchisi — kontekstni hisobga olmasdan tamoyillarga so'zma-so'z amal qilish. Bitta UserService sinfini “toza” ISP uchun 10 interfeys va 15 sinfga bo'lish overengineering. SOLID vosita, maqsad emas. Ikkinchi xato — SRPni “bitta metod = bitta mas'uliyat” bilan aralashtirish. Sinf bir nechta metodga ega bo'lishi mumkin, agar ularning barchasi bitta mas'uliyat sohasiga tegishli bo'lsa.
Simple Thread, 2024 ga ko'ra, uchinchi xato — Android-da ViewModel meros olishda LSPni e'tiborsiz qoldirish. Agar asosiy ViewModel LiveData kutsa, bola esa StateFlow ishlatsa — LiveData-ga obuna bo'lgan mijoz kodi yangilanishlarni olmaydi. To'rtinchi — testlash uchun DIPni buzish: RepositoryImpl to'g'ridan-to'g'ri OkHttpClient namunasini yaratadi, bu birlik testlarini imkonsiz qiladi.
Oltin o'rta qoidasi: SOLIDni real muammoni hal qilganda qo'llang (tez-tez o'zgarishlar, testlash qiyinligi, takrorlanish). Oddiy CRUD ekranlari uchun barcha besh tamoyilga qat'iy rioya qilish ortiqcha. Biznes mantig'i, moliyaviy hisob-kitoblar va API o'zaro aloqalari uchun SOLID majburiydir.
Clean Architecture (Robert C. Martin, 2012) — SOLIDni ilova qatlamlari darajasida to'g'ridan-to'g'ri qo'llash. SRP use case chegaralarini belgilaydi (har bir use case — bitta sinf). OCP repository interfeyslari orqali amalga oshiriladi (Data qatlami Domainni o'zgartirmasdan o'zgarishi mumkin). ISP Use Case ni kirish/chiqish boundary ga bo'lishni ta'minlaydi. DIP — bog'liqliklarning Domain qatlami ichkarisiga yo'nalishi. LSP repositoryning har qanday implementatsiyasi use case ni buzmasdan almashtirilishini kafolatlaydi.
Ko'p beriladigan savollar
SOLID — kodni o'zgartirish, testlash va tushunish oson bo'lishi uchun beshta yozish qoidasi. Har bir harf bitta tamoyil: katta sinflar yozmang (SRP), mavjud kodni o'zgartirmang — yangisini qo'shing (OCP), merosxo'rlarning xatti-harakatini buzmang (LSP) va boshqalar.
SRP (Single Responsibility) eng muhim hisoblanadi, chunki uning buzilishi God-sinflarga — testlash va o'zgartirish qiyin bo'lgan ulkan sinflarga olib keladi. Biroq DIP (Dependency Inversion) bo'lmasa, kod qattiq bog'liq bo'lib qoladi, bu ham juda muhim.
Majburiy emas, lekin uzoq hayot aylanishiga ega tijorat loyihalari uchun juda tavsiya etiladi. Oddiy ilovalar (bitta ekran, biznes mantig'i yo'q) uchun SOLID ortiqcha bo'lishi mumkin. 50+ ekran va 3+ dasturchi bo'lgan loyihalar uchun SOLID zaruriy minimumdir.
Natijalar: sinflar “semiz” bo'ladi (1000+ satr), bir joydagi o'zgarish uchta boshqa joyni buzadi, birlik testlarini yozish imkonsiz bo'ladi, yangi funksiya qo'shish kunlar o'rniga haftalar oladi. Vaqt o'tishi bilan kod “Big Ball of Mud” — chalkash va mo'rt narsaga aylanadi.
Rioya qilish belgilari: har bir sinf 200 satrdan kam, funksiya o'zgarishi 5+ faylga ta'sir qilmaydi, testlar 10 bog'liqlikni mock qilmasdan yoziladi, yangi dasturchi strukturani bir kunda tushunadi. SonarQube va detekt kabi vositalar SRP va DIP buzilishlarini aniqlashga yordam beradi.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.
Shuningdek o'qing