Asosiy kontentga o‘tish
Innovialabs

SOLID tamoyillari: amaliy misollar bilan tushuntirish

Amaliyot4 daq

Qisqacha

SOLID — kodni o‘zgartirishni oson qiladigan beshta qoida: klassni o‘zgartirish uchun bitta sabab, tahrirsiz kengaytirish, xavfsiz almashtirish, kichik interfeyslar va aniq klasslarga emas, abstraksiyalarga bog‘liqlik.

SOLID amalda nima beradi

SOLID — obyektga yo‘naltirilgan kodni loyihalashning beshta tamoyili. Umumiy maqsad oddiy: bir joydagi o‘zgarish boshqa joylarni buzmasligi yoki u yerda tahrir talab qilmasligi kerak. Quyida har bir tamoyil uchun TypeScript’da «oldin» va «keyin» misoli hamda aniq foydasi berilgan.

S: yagona mas’uliyat tamoyili

Klassni o‘zgartirish uchun bitta sabab bo‘lishi kerak.

// Oldin: hisobot hisobi, formatlash va pochta bitta klassda
class Report {
  build(data: Order[]) { /* jami summalarni hisoblash */ }
  toPdf() { /* PDF yaratish */ }
  sendByEmail(to: string) { /* SMTP */ }
}
// Keyin: har bir klass o‘z sababi bilan o‘zgaradi
class ReportBuilder { build(data: Order[]): ReportData { /* ... */ } }
class PdfRenderer { render(r: ReportData): Buffer { /* ... */ } }
class Mailer { send(to: string, file: Buffer) { /* ... */ } }

Foydasi: PDF maketini o‘zgartirish endi jami summalar hisobini buzmaydi, har bir qismni alohida test qilish mumkin.

O: ochiqlik/yopiqlik tamoyili

Kod kengaytirish uchun ochiq, o‘zgartirish uchun yopiq: yangi xatti-harakat ishlayotgan kodni tahrirlash bilan emas, yangi kod bilan qo‘shiladi.

// Oldin: har bir yangi yetkazish usuli — shu funksiyani tahrirlash
function deliveryCost(type: string, weight: number) {
  if (type === "courier") return 20 + weight * 2;
  if (type === "pickup") return 0;
  throw new Error("unknown type");
}
// Keyin: yangi yetkazish turi — yangi klass
interface Delivery { cost(weight: number): number }
class Courier implements Delivery { cost(w: number) { return 20 + w * 2; } }
class Pickup implements Delivery { cost() { return 0; } }

Foydasi: yangi yetkazish turi test qilingan kodga tegmaydi, shuning uchun regressiyalar kamroq.

L: Liskov almashtirish tamoyili

Quyi klass ota klass kutilgan har qanday joyda kutilmagan holatlarsiz ishlashi kerak.

// Oldin: ReadOnlyFile File kontraktini buzadi
class File { write(text: string) { /* ... */ } }
class ReadOnlyFile extends File {
  write() { throw new Error("read-only"); }
}
// Keyin: imkoniyatlar ajratilgan, va’dalar buzilmaydi
interface Readable { read(): string }
interface Writable { write(text: string): void }
class ReadOnlyFile implements Readable { read() { return "..."; } }

Foydasi: ota turini qabul qiladigan kodga «maxsus» quyi klasslar uchun instanceof tekshiruvlari va try/catch kerak bo‘lmaydi.

I: interfeyslarni ajratish tamoyili

Mijozlar foydalanmaydigan metodlarga bog‘liq bo‘lmasligi kerak.

// Oldin: bitta «semiz» interfeys
interface Worker { code(): void; test(): void; manageBudget(): void }
// Keyin: kichik, aniq interfeyslar
interface Coder { code(): void }
interface Tester { test(): void }
interface BudgetOwner { manageBudget(): void }

Foydasi: klasslar faqat o‘zlariga kerakli narsani amalga oshiradi, bitta interfeysning o‘zgarishi kamroq faylga ta’sir qiladi.

D: bog‘liqliklarni teskari aylantirish tamoyili

Biznes mantiq aniq implementatsiyalarga emas, abstraksiyalarga bog‘liq bo‘lishi kerak.

// Oldin: servis bitta bazaga qattiq bog‘langan
class OrderService {
  private db = new PostgresClient();
  save(o: Order) { this.db.insert("orders", o); }
}
// Keyin: bog‘liqlik interfeys orqali uzatiladi
interface OrderRepository { save(o: Order): Promise<void> }
class OrderService {
  constructor(private repo: OrderRepository) {}
  place(o: Order) { return this.repo.save(o); }
}

Foydasi: testlarda xotiradagi repozitoriy uzatiladi, omborni almashtirish esa biznes mantiqqa tegmaydi.

Qisqa qo‘llanma

TamoyilOgohlantiruvchi belgiOdatiy yechim
SRPKlass bir-biriga bog‘liq bo‘lmagan bir nechta sabab bilan o‘zgaradiMas’uliyat bo‘yicha ajratish
OCPTur bo‘yicha o‘sib borayotgan if/switchPolimorfizm yoki strategiyalar xaritasi
LSPQuyi klass «qo‘llab-quvvatlanmaydi» xatosini tashlaydiIerarxiyani qayta ko‘rib chiqish
ISPBo‘sh yoki zaglushka metodlarInterfeysni ajratish
DIPBiznes mantiq ichida infratuzilmani new qilishInterfeys orqali uzatish

Ko‘p uchraydigan xatolar

  • SOLID’ni juda erta qo‘llash: bitta implementatsiyasi bor va o‘zgarish rejasi yo‘q funksiya uchun uchta interfeys faqat shovqin qo‘shadi.
  • Uni qonun deb hisoblash: bu tez-tez o‘zgaradigan kod uchun yo‘l-yo‘riq, har bir fayl uchun nazorat ro‘yxati emas.
  • Juda mayda bo‘lish: bir qatorli o‘nlab klasslarni o‘qish bitta ulkan klassni o‘qishdek qiyin.

Amaliy qoida: SOLID tomon refaktoringni o‘zgarish og‘riq keltirganda qiling — bir joyni ikkinchi-uchinchi marta tahrirlaganda.

Ko‘p beriladigan savollar

G‘oyalari — ha. Funksional kodda yagona mas’uliyat kichik, aniq funksiyalarni, bog‘liqliklarni teskari aylantirish esa bog‘liqliklarni to‘g‘ridan-to‘g‘ri import qilish o‘rniga argument sifatida uzatishni anglatadi.

Bunda yordam beramiz

O‘zingiz shug‘ullanmasdan natija olishni istasangiz — biz har kuni shu bilan shug‘ullanamiz.

Loyihani muhokama qilish

Yana o‘qing

G‘oya yoki vazifangiz bormi? Bizga aytib bering

Ish kuni davomida javob beramiz va yechim taklif qilamiz. Konsultatsiya bepul.