IlmHamroh
Python kursi/Arxitektura2/12-dars18 daqiqa
Mundarija (22)

27.2-dars: SOLID tamoyillari

27-QISM — ARXITEKTURA · 2-dars


1. Kirish va motivatsiya

Obyektga yo'naltirilgan kod (16-qism) yozish oson, lekin yaxshi yozish qiyin: sinflar shishib ketadi (hammasini qiladi), o'zgartirish bir joyni tuzatib boshqasini buzadi, yangi imkoniyat butun kodni qayta yozishni talab qiladi. SOLID — obyektga yo'naltirilgan dizaynning besh asosiy tamoyili: sinflarni moslashuvchan, kengaytiriladigan, sinaladigan qiladi. Har harf bir tamoyil: SRP, OCP, LSP, ISP, DIP. SOLID — toza kod 27.1-bob ni sinf/tizim darajasiga ko'taradi.

SOLID — Robert Martin umumlashtirgan besh tamoyil: S (Single Responsibility — bir mas'uliyat: sinf bir sababga o'zgaradi), O (Open/Closed — ochiq/yopiq: kengaytirishga ochiq, o'zgartirishga yopiq), L (Liskov Substitution — Liskov almashinuvi: quyi sinf yuqorini almashtira oladi), I (Interface Segregation — interfeys ajratish: kichik, maxsus interfeyslar), D (Dependency Inversion — bog'liqlik teskariligi: abstraksiyaga bog'lan, aniqga emas). Bu tamoyillar o'zgartirishni oson qiladi (yaxshi dizaynning maqsadi — o'zgarishga tayyorlik). SOLID — moslashuvchan dizayn qoidalari.

Real vaziyat. Bir loyihada Order sinfi hammasini qilar edi: hisoblash, saqlash, email yuborish, PDF chiqarish. Email tizimi o'zgarganda — Order o'zgardi (nega buyurtma email uchun o'zgaradi?). Sinf bo'lindi: Order (mantiq), OrderRepository (saqlash), EmailService (email) — har biri bir mas'uliyat (SRP). Endi email o'zgarsa — faqat EmailService. Yangi to'lov turi — yangi sinf (OCP, Order tegilmaydi). SOLID — o'zgartirish xavfsizligi.

Bu darsda SOLID tamoyillarini o'rganamiz.

Bu darsda:

  • SOLID nima
  • S — Single Responsibility (bir mas'uliyat)
  • O — Open/Closed (ochiq/yopiq)
  • L — Liskov Substitution (almashinuv)
  • I — Interface Segregation (interfeys ajratish)
  • D — Dependency Inversion (bog'liqlik teskarisi)
  • SOLID birgalikda
  • Amaliy: SOLID qo'llash

ℹ Misollarda SOLID sof Python (sinflar, Protocol, ABC) bilan ko'rsatiladi — deterministik.


2. Nazariya — chuqur tushuntirish

2.1. SOLID nima

Besh dizayn tamoyili:

S — Single Responsibility (bir mas'uliyat)
O — Open/Closed (ochiq/yopiq)
L — Liskov Substitution (almashinuv)
I — Interface Segregation (interfeys ajratish)
D — Dependency Inversion (bog'liqlik teskarisi)

SOLID — obyektga yo'naltirilgan dizaynning besh tamoyili (Robert Martin): sinflarni moslashuvchan (o'zgartirish oson), kengaytiriladigan (yangi imkoniyat qo'shish oson), sinaladigan qiladi. Har tamoyil — bir muammoga qarshi (shishgan sinf, mo'rt kengaytirish, noto'g'ri meros). Maqsad: o'zgartirishga tayyorlik (kod o'zgaradi — yaxshi dizayn o'zgarishni yengillashtiradi). SOLID — tamoyil (qat'iy qonun emas — kontekstda qo'llanadi). SOLID — yaxshi OOP dizayni.

2.2. S — Single Responsibility (bir mas'uliyat)

Sinf bir sababga o'zgaradi:

python
# yomon: Order hammasini qiladi
class Order:
    def hisobla(self): ...
    def saqla(self): ...       # baza
    def email_yubor(self): ... # email

# yaxshi: har biri bir mas'uliyat
class Order: def hisobla(self): ...
class OrderRepository: def saqla(self): ...
class EmailService: def yubor(self): ...

SRP (Single Responsibility Principle) — sinf bir mas'uliyatga (bir o'zgarish sababiga) ega bo'lishi kerak: Order faqat buyurtma mantigi (hisoblash), saqlash — OrderRepository, email — EmailService. Sabab: sinf ko'p ish qilsa — bir o'zgarish (email formati) boshqasini (buyurtma) xavf ostiga qo'yadi; ajratilgan — har o'zgarish alohida. Belgi: sinf tavsifi "va" bilan (hisoblaydi va saqlaydi) — bo'lish kerak. SRP — 27.1 (kichik funksiya) ning sinf darajasi. Bir sinf — bir sabab.

2.3. O — Open/Closed (ochiq/yopiq)

Kengaytirishga ochiq, o'zgartirishga yopiq:

python
# yomon: yangi shakl → if qo'shish (o'zgartirish)
def yuza(shakl):
    if shakl.turi == "doira": ...
    elif shakl.turi == "kvadrat": ...   # yangi → shu yerni o'zgartir

# yaxshi: yangi shakl → yangi sinf (o'zgartirishsiz)
class Shakl: def yuza(self): ...
class Doira(Shakl): def yuza(self): ...

OCP (Open/Closed Principle) — kod kengaytirishga ochiq (yangi xulq qo'shish mumkin), lekin o'zgartirishga yopiq (mavjud kod tegilmaydi): yangi shakl qo'shish — yangi sinf (mavjud if/elif ni o'zgartirmasdan). Sabab: mavjud, sinalgan kodni o'zgartirish — xato xavfi (ishlayotgan narsani buzish); yangi kod qo'shish — xavfsiz. Yechim: abstraksiya (asosiy sinf/interfeys) + polimorfizm (16-qism). OCP — o'zgarishni qo'shimcha bilan (o'zgartirish emas). Ochiq kengaytirishga, yopiq buzishga.

2.4. L — Liskov Substitution (almashinuv)

Quyi sinf yuqorini almashtira oladi:

python
# quyi sinf yuqori turgan joyda ishlashi kerak
class Qush: def uch(self): ...
class Burgut(Qush): def uch(self): ...   # ✅ ucha oladi
class Tuyaqush(Qush): def uch(self):     # ⚠️ ucholmaydi — LSP buziladi
    raise Error("ucholmaydi")

LSP (Liskov Substitution Principle) — quyi sinf (voris) yuqori sinf o'rniga ishlashi kerak (dasturni buzmasdan): Qush kutilgan joyga Burgut (ucha oladi) mos, Tuyaqush (ucholmaydi) — LSP buzadi (kutilgan xulqni bajarmaydi). Sabab: agar voris ota-sinf va'dasini bajarmasa (xato tashlaydi, boshqacha ishlaydi) — polimorfizm ishonchsiz (voris qo'yilsa — buziladi). Belgi: voris metodi NotImplementedError yoki cheklov qo'shadi — meros noto'g'ri. LSP — merosda va'daga sodiqlik. Voris — otani almashtira olishi kerak.

2.5. I — Interface Segregation (interfeys ajratish)

Kichik, maxsus interfeyslar:

python
# yomon: katta interfeys (hamma majbur)
class Ishchi:
    def ishla(self): ...
    def ovqatlan(self): ...   # robot ovqatlanmaydi!

# yaxshi: ajratilgan
class Ishlaydigan: def ishla(self): ...
class Ovqatlanadigan: def ovqatlan(self): ...

ISP (Interface Segregation Principle) — kichik, maxsus interfeyslar (bitta katta emas): mijoz faqat kerak metodlarga bog'lanishi kerak (ishlatmaydiganga emas). Masalan katta Ishchi interfeysi (ishla, ovqatlan) — Robot uchun ovqatlan keraksiz (majbur qiladi). Yechim: kichik interfeyslar (Ishlaydigan, Ovqatlanadigan) — har kim keragini oladi. Sabab: katta interfeys — keraksiz bog'liqlik (o'zgarsa — bog'langanlar ta'sirlanadi). ISP — SRP interfeys darajasida. Kichik interfeys — kam bog'liqlik.

2.6. D — Dependency Inversion (bog'liqlik teskarisi)

Abstraksiyaga bog'lan, aniqga emas:

python
# yomon: yuqori sinf aniq quyiga bog'liq
class Xabarchi:
    def __init__(self): self.email = EmailYuboruvchi()  # aniq

# yaxshi: abstraksiyaga (interfeys)
class Xabarchi:
    def __init__(self, yuboruvchi: Yuboruvchi):  # abstraksiya
        self.yuboruvchi = yuboruvchi

DIP (Dependency Inversion Principle) — yuqori daraja moduli quyiga aniq bog'lanmasligi kerak; ikkalasi abstraksiyaga bog'lanishi kerak: Xabarchi aniq EmailYuboruvchi ga emas, Yuboruvchi interfeysiga bog'lanadi (email, SMS — almashtiriladi). Sabab: aniqga bog'liqlik — qattiq (email o'zgarsa — Xabarchi o'zgaradi, sinash qiyin); abstraksiya — moslashuvchan (istalgan yuboruvchi beriladi — DI, dependency injection). DIP — bog'liqlik yo'nalishini teskari (aniqga emas, abstraksiyaga). Abstraksiyaga bog'lan.

2.7. SOLID birgalikda

SOLID tamoyillari birga ishlaydi: SRP (bir mas'uliyat) sinflarni bo'ladi, OCP (kengaytirish) va DIP (abstraksiya) yangi imkoniyatni oson qiladi, LSP (almashinuv) polimorfizni ishonchli qiladi, ISP (kichik interfeys) bog'liqlikni kamaytiradi. Umumiy g'oya: o'zgartirishga tayyorlik — sinflar kichik, aniq, abstraksiya orqali bog'langan (o'zgarish bir joyda, kengaytirish qo'shimcha bilan). Lekin SOLID — tamoyil, qonun emas: haddan oshirish (har narsaga interfeys) — murakkablik (KISS — 27.1). Muvozanat: SOLID o'zgarish kutilgan joyda. SOLID — moslashuvchan, lekin ortiqcha emas.

2.8. SOLID — dizaynning maqsadi

SOLID — obyektga yo'naltirilgan dizaynning maqsadini ochadi: kod o'zgaradi (talab o'zgaradi, yangi imkoniyat) — yaxshi dizayn o'zgarishni oson va xavfsiz qiladi. SOLID buni ta'minlaydi: o'zgarish cheklangan (bir sinf — SRP), qo'shimcha bilan (yangi sinf — OCP), almashinuvchan (abstraksiya — DIP). Bu naqshlar (27.3–27.5 — SOLID ni amalga oshiradigan yechimlar), qatlamlar 27.6-bob, Clean Architecture 27.7-bob uchun asos. SOLID toza kod 27.1-bob ustiga quriladi (nomlash, kichik funksiya + sinf dizayni). SOLID — o'zgarishni boshqarish. Yaxshi dizayn — o'zgarishga tayyor dizayn.


3. Tez ma'lumotnoma

python
# S — Single Responsibility (bir sabab)
class Order: hisobla()          # mantiq
class OrderRepo: saqla()        # saqlash
class Email: yubor()            # email

# O — Open/Closed (yangi = yangi sinf)
class Shakl(ABC): def yuza(self): ...
class Doira(Shakl): ...         # yangi, mavjud tegilmaydi

# L — Liskov (voris otani almashtira oladi)
def chiz(sh: Shakl): sh.yuza()  # har voris ishlashi kerak

# I — Interface Segregation (kichik interfeys)
class Ishlaydigan(Protocol): def ishla(self): ...
class Ovqatlanadigan(Protocol): def ovqatlan(self): ...

# D — Dependency Inversion (abstraksiyaga)
class X:
    def __init__(self, y: Yuboruvchi):  # interfeys, aniq emas
        self.y = y

SOLID xulosasi

S — bir mas'uliyat (bir o'zgarish sababi)
O — kengaytirishga ochiq, o'zgartirishga yopiq
L — voris otani almashtira oladi (va'daga sodiq)
I — kichik, maxsus interfeys (keraksizga bog'lanma)
D — abstraksiyaga bog'lan (aniqga emas — DI)
Maqsad: o'zgarishga tayyorlik (oson, xavfsiz)

4. Batafsil misollar

Misollarda SOLID sof Python (sinflar, ABC, Protocol) bilan ko'rsatiladi.

Misol 1 — SRP: mas'uliyatlarni ajratish

python
"""SRP: bir sinf bir mas'uliyat (mantiq, saqlash, xabar alohida)."""


class Buyurtma:
    """Faqat buyurtma mantigi (bir mas'uliyat)."""

    def __init__(self, mahsulot: str, narx: float, soni: int) -> None:
        self.mahsulot = mahsulot
        self.narx = narx
        self.soni = soni

    def jami(self) -> float:
        return self.narx * self.soni


class BuyurtmaOmbori:
    """Faqat saqlash (baza mock)."""

    def __init__(self) -> None:
        self.saqlangan: list = []

    def saqla(self, b: Buyurtma) -> None:
        self.saqlangan.append(b.mahsulot)


class XabarXizmati:
    """Faqat xabar."""

    def yubor(self, b: Buyurtma) -> str:
        return f"'{b.mahsulot}' buyurtma qabul qilindi ({b.jami()})"


def main() -> None:
    buyurtma = Buyurtma("Python kursi", 100, 2)

    print("=== 1. Buyurtma mantigi (Buyurtma) ===")
    print(f"  jami: {buyurtma.jami()}")

    print("\n=== 2. Saqlash (BuyurtmaOmbori) ===")
    ombor = BuyurtmaOmbori()
    ombor.saqla(buyurtma)
    print(f"  saqlangan: {ombor.saqlangan}")

    print("\n=== 3. Xabar (XabarXizmati) ===")
    xabar = XabarXizmati()
    print(f"  {xabar.yubor(buyurtma)}")

    print("\n=== 4. Har biri bir sababga o'zgaradi ===")
    print("  Buyurtma → narx mantigi o'zgarsa")
    print("  Ombor → baza o'zgarsa")
    print("  Xabar → email formati o'zgarsa")
    print("  ⭐ SRP — bir sinf, bir mas'uliyat")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Buyurtma mantigi (Buyurtma) ===
  jami: 200

=== 2. Saqlash (BuyurtmaOmbori) ===
  saqlangan: ['Python kursi']

=== 3. Xabar (XabarXizmati) ===
  'Python kursi' buyurtma qabul qilindi (200)

=== 4. Har biri bir sababga o'zgaradi ===
  Buyurtma → narx mantigi o'zgarsa
  Ombor → baza o'zgarsa
  Xabar → email formati o'zgarsa
  ⭐ SRP — bir sinf, bir mas'uliyat

Nima ko'rsatdi: 2.2-bo'lim.

Misol 2 — OCP: kengaytirishga ochiq

python
"""OCP: yangi shakl = yangi sinf (mavjud kod o'zgartirilmaydi)."""
from abc import ABC, abstractmethod


class Shakl(ABC):
    @abstractmethod
    def yuza(self) -> float: ...


class Doira(Shakl):
    def __init__(self, radius: float) -> None:
        self.radius = radius

    def yuza(self) -> float:
        return 3.14 * self.radius ** 2


class Kvadrat(Shakl):
    def __init__(self, tomon: float) -> None:
        self.tomon = tomon

    def yuza(self) -> float:
        return self.tomon ** 2


# yangi shakl qo'shish — mavjud kod tegilmaydi
class Uchburchak(Shakl):
    def __init__(self, asos: float, balandlik: float) -> None:
        self.asos = asos
        self.balandlik = balandlik

    def yuza(self) -> float:
        return 0.5 * self.asos * self.balandlik


def umumiy_yuza(shakllar: list) -> float:
    # bu funksiya yangi shakl qo'shilsa ham o'zgarmaydi (OCP)
    return sum(sh.yuza() for sh in shakllar)


def main() -> None:
    shakllar = [Doira(2), Kvadrat(3), Uchburchak(4, 5)]

    print("=== 1. Har shakl yuzasi ===")
    for sh in shakllar:
        print(f"  {type(sh).__name__}: {sh.yuza()}")

    print("\n=== 2. Umumiy yuza (o'zgarmas funksiya) ===")
    print(f"  jami: {umumiy_yuza(shakllar)}")

    print("\n=== 3. Yangi shakl qo'shish ===")
    print("  Uchburchak qo'shildi — umumiy_yuza tegilmadi")
    print("  if/elif yo'q (polimorfizm)")

    print("\n=== 4. Ochiq/yopiq ===")
    print("  ochiq: yangi sinf qo'shiladi")
    print("  yopiq: mavjud kod o'zgartirilmaydi")
    print("  ⭐ OCP — kengaytir (o'zgartirma)")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Har shakl yuzasi ===
  Doira: 12.56
  Kvadrat: 9
  Uchburchak: 10.0

=== 2. Umumiy yuza (o'zgarmas funksiya) ===
  jami: 31.560000000000002

=== 3. Yangi shakl qo'shish ===
  Uchburchak qo'shildi — umumiy_yuza tegilmadi
  if/elif yo'q (polimorfizm)

=== 4. Ochiq/yopiq ===
  ochiq: yangi sinf qo'shiladi
  yopiq: mavjud kod o'zgartirilmaydi
  ⭐ OCP — kengaytir (o'zgartirma)

Nima ko'rsatdi: 2.3-bo'lim.

Misol 3 — LSP: almashinuvchan vorislar

python
"""LSP: har voris ota o'rnida ishlashi kerak (va'daga sodiq)."""
from abc import ABC, abstractmethod


class Toluv(ABC):
    @abstractmethod
    def tola(self, summa: float) -> str: ...


class KartaToluv(Toluv):
    def tola(self, summa: float) -> str:
        return f"Karta: {summa} to'landi"


class NaqdToluv(Toluv):
    def tola(self, summa: float) -> str:
        return f"Naqd: {summa} to'landi"


class UmsToluv(Toluv):
    def tola(self, summa: float) -> str:
        return f"UMS: {summa} to'landi"


def toluvni_amalga_oshir(toluv: Toluv, summa: float) -> str:
    # har voris bu yerda ishlashi kerak (LSP)
    return toluv.tola(summa)


def main() -> None:
    toluvlar = [KartaToluv(), NaqdToluv(), UmsToluv()]

    print("=== 1. Har to'lov turi ishlaydi ===")
    for t in toluvlar:
        print(f"  {toluvni_amalga_oshir(t, 100)}")

    print("\n=== 2. Almashinuvchanlik ===")
    print("  har voris Toluv o'rnida ishlaydi")
    print("  toluvni_amalga_oshir — turni bilmaydi")

    print("\n=== 3. LSP sharti ===")
    print("  voris ota va'dasini bajaradi (tola)")
    print("  xato tashlamaydi, cheklov qo'shmaydi")

    print("\n=== 4. Sanoq ===")
    print(f"  to'lov turlari: {[type(t).__name__ for t in toluvlar]}")
    print("  ⭐ LSP — voris otani almashtira oladi")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Har to'lov turi ishlaydi ===
  Karta: 100 to'landi
  Naqd: 100 to'landi
  UMS: 100 to'landi

=== 2. Almashinuvchanlik ===
  har voris Toluv o'rnida ishlaydi
  toluvni_amalga_oshir — turni bilmaydi

=== 3. LSP sharti ===
  voris ota va'dasini bajaradi (tola)
  xato tashlamaydi, cheklov qo'shmaydi

=== 4. Sanoq ===
  to'lov turlari: ['KartaToluv', 'NaqdToluv', 'UmsToluv']
  ⭐ LSP — voris otani almashtira oladi

Nima ko'rsatdi: 2.4-bo'lim.

Misol 4 — DIP: abstraksiyaga bog'lanish

python
"""DIP: yuqori sinf abstraksiyaga bog'lanadi (aniq emas — almashtiriladi)."""
from abc import ABC, abstractmethod


class Yuboruvchi(ABC):
    """Abstraksiya (interfeys)."""

    @abstractmethod
    def yubor(self, xabar: str) -> str: ...


class EmailYuboruvchi(Yuboruvchi):
    def yubor(self, xabar: str) -> str:
        return f"[EMAIL] {xabar}"


class SmsYuboruvchi(Yuboruvchi):
    def yubor(self, xabar: str) -> str:
        return f"[SMS] {xabar}"


class Xabarchi:
    """Yuqori sinf — abstraksiyaga bog'liq (aniq yuboruvchiga emas)."""

    def __init__(self, yuboruvchi: Yuboruvchi) -> None:
        self.yuboruvchi = yuboruvchi   # DI (tashqaridan beriladi)

    def ogohlantir(self, kim: str) -> str:
        return self.yuboruvchi.yubor(f"Salom {kim}!")


def main() -> None:
    print("=== 1. Email bilan ===")
    x1 = Xabarchi(EmailYuboruvchi())
    print(f"  {x1.ogohlantir('Ali')}")

    print("\n=== 2. SMS bilan (almashtirildi) ===")
    x2 = Xabarchi(SmsYuboruvchi())
    print(f"  {x2.ogohlantir('Ali')}")

    print("\n=== 3. Xabarchi o'zgarmadi ===")
    print("  bir xil Xabarchi, turli yuboruvchi")
    print("  aniq turga bog'liq emas (abstraksiyaga)")

    print("\n=== 4. Sinash oson (mock beriladi) ===")
    class MockYuboruvchi(Yuboruvchi):
        def yubor(self, xabar: str) -> str:
            return "[MOCK]"
    print(f"  test: {Xabarchi(MockYuboruvchi()).ogohlantir('X')}")
    print("  ⭐ DIP — abstraksiyaga bog'lan (moslashuvchan)")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Email bilan ===
  [EMAIL] Salom Ali!

=== 2. SMS bilan (almashtirildi) ===
  [SMS] Salom Ali!

=== 3. Xabarchi o'zgarmadi ===
  bir xil Xabarchi, turli yuboruvchi
  aniq turga bog'liq emas (abstraksiyaga)

=== 4. Sinash oson (mock beriladi) ===
  test: [MOCK]
  ⭐ DIP — abstraksiyaga bog'lan (moslashuvchan)

Nima ko'rsatdi: 2.6-bo'lim.


5. To'g'ri va noto'g'ri tushunishlar

Noto'g'ri fikr To'g'risi
"SOLID — qat'iy qonun" Tamoyil (kontekstda)
"Sinf ko'p ish qilsa bo'ladi" SRP (bir mas'uliyat)
"Yangi = if qo'shish" OCP (yangi sinf)
"Meros erkin" LSP (va'daga sodiq)
"Katta interfeys qulay" ISP (kichik)
"Aniq turga bog'lan" DIP (abstraksiya)
"SOLID = ko'p sinf" O'zgarishga tayyorlik
"Har narsaga interfeys" Muvozanat (KISS)

6. Keng tarqalgan xatolar va yechimlari

1. Xudo sinfi (hammasini qiladi)

python
class Order: hisobla(); saqla(); email()   # ⚠️ SRP buziladi
# ajrat: Order, Repository, Email          # ✅

2. if/elif tur bo'yicha

python
if shakl.turi == "doira": ...              # ⚠️ OCP buziladi
class Doira(Shakl): def yuza(self)         # ✅ polimorfizm

3. Voris va'dani buzadi

python
class Tuyaqush(Qush): def uch(self): raise # ⚠️ LSP buziladi
# to'g'ri ierarxiya (Ucholadigan alohida)  # ✅

4. Semiz interfeys

python
class Ishchi: ishla(); ovqatlan()  # robot? # ⚠️ ISP buziladi
# Ishlaydigan, Ovqatlanadigan (ajrat)       # ✅

5. Aniqga bog'liqlik

python
self.db = PostgresDB()   # aniq            # ⚠️ DIP buziladi
def __init__(self, db: Database): ...      # ✅ abstraksiya

6. Haddan SOLID (murakkablik)

python
# har oddiy narsaga interfeys, factory     # ⚠️ ortiqcha
# SOLID o'zgarish kutilgan joyda            # ✅ muvozanat

7. DI qo'lda (har joyda yaratish)

python
Xabarchi(EmailYuboruvchi())  # har joyda    # ⚠️
# DI konteyner yoki bir joyda sozlash       # ✅

7. Integratsiya — bu bilim qayerda kerak bo'ladi

  • 27.1-dars (o'tilgan): Toza kod — SOLID asosi
  • 27.3–27.5-dars: Naqshlar — SOLID ni amalga oshiradi
  • 27.6-dars: Qatlamlar — DIP bilan
  • 16-qism (o'tilgan): OOP — meros, polimorfizm
  • 20-qism (o'tilgan): FastAPI — DI (Depends)

8. Eng yaxshi amaliyotlar

  1. SRP — sinf bir sababga o'zgarsin.

  2. OCP — yangi xulq yangi sinf bilan.

  3. LSP — voris otani to'liq almashtirsin.

  4. ISP — kichik, maxsus interfeys.

  5. DIP — abstraksiyaga bog'lan (DI).

  6. Muvozanat — SOLID o'zgarish kutilganda.

  7. KISS bilan (haddan SOLID emas).

  8. Protocol/ABC — abstraksiya uchun.


9. Amaliy topshiriq

Vazifa 1: Bashorat qiling

python
1.  # SOLID nima?
2.  # S nima?
3.  # SRP: sinf necha sababga o'zgaradi?
4.  # O nima?
5.  # OCP: yangi xulq qanday?
6.  # L nima?
7.  # LSP sharti?
8.  # I nima?
9.  # ISP: interfeys qanday?
10. # D nima?
11. # DIP: nimaga bog'lanadi?
12. # DI nima?
Javoblar
  1. Besh OOP dizayn tamoyili
  2. Single Responsibility
  3. Bir sababga
  4. Open/Closed
  5. Yangi sinf (o'zgartirishsiz)
  6. Liskov Substitution
  7. Voris otani almashtira oladi
  8. Interface Segregation
  9. Kichik, maxsus
  10. Dependency Inversion
  11. Abstraksiyaga (aniq emas)
  12. Dependency Injection (tashqaridan berish)

Vazifa 2: Xatolarni tuzating

python
1.  class Order: hisobla; saqla; email     # SRP

2.  if shakl.turi == "doira"               # OCP

3.  class Tuyaqush: uch → raise            # LSP

4.  class Ishchi: ishla; ovqatlan          # ISP

5.  self.db = PostgresDB()                 # DIP
Javoblar
python
1.  Order, Repository, Email (ajrat)

2.  class Doira(Shakl): yuza (polimorfizm)

3.  Ucholadigan alohida (to'g'ri ierarxiya)

4.  Ishlaydigan, Ovqatlanadigan (ajrat)

5.  def __init__(self, db: Database)

Vazifa 3: SRP

Ajrating:

  1. Xudo sinfi
  2. Mas'uliyatlar
  3. Sinflar
  4. Bir sabab

Vazifa 4: OCP

Kengaytiring:

  1. Abstraksiya
  2. Voris
  3. Polimorfizm
  4. O'zgartirishsiz

Vazifa 5: LSP

Tekshiring:

  1. Voris
  2. Va'da
  3. Almashinuv
  4. Buzilish

Vazifa 6: DIP

Bog'lang:

  1. Abstraksiya
  2. Voris
  3. DI
  4. Sinash

Vazifa 7: O'ylash

SOLID tamoyillarining umumiy maqsadi — o'zgarishga tayyorlik (kod o'zgaradi — yaxshi dizayn buni oson qiladi). Lekin SOLID ni haddan qo'llash (har narsaga interfeys, factory, abstraksiya) — murakkablik (KISS buziladi). Nima uchun "o'zgarish kutilgan joy" ni oldindan bilish qiyin (va shuning uchun SOLID ni qachon qo'llash — mahorat), va nega "ortiqcha dizayn" (haddan SOLID) "kam dizayn" (SOLID yo'q) kabi xatarli?

Javob

Qisqa javob: "O'zgarish kutilgan joy"ni oldindan bilish qiyin, chunki: kelajakni aniq bilmaymiz (qaysi qism o'zgaradi — talab, texnologiya?). SOLID o'zgarishni oson qiladi, lekin har joyga SOLID — narx (murakkablik, ko'p sinf, abstraksiya). Muvozanat: SOLID ni o'zgarish ehtimoli yuqori joyga (to'lov turlari ko'payadi — OCP; ma'lumot manbai o'zgaradi — DIP), oddiy/barqaror joyga — sodda (KISS). Buni bilish tajriba (domenni tushunish — nima o'zgaradi) va mahorat (qachon abstraksiya, qachon sodda). "Ortiqcha dizayn" (haddan SOLID) xatarli, chunki: murakkablik (ko'p sinf, interfeys — o'qish, tushunish qiyin), erta abstraksiya (noto'g'ri — kelajakni taxmin qildik, xato chiqdi — abstraksiya mos kelmaydi, qayta yozish), YAGNI buzilishi (You Aren't Gonna Need It — kerak bo'lmas narsani qurdik). "Kam dizayn" (SOLID yo'q) ham xatarli: qattiq (o'zgartirish qiyin), mo'rt (bir o'zgarish boshqasini buzadi), shishgan (xudo sinflar). Ikkalasi — muvozanatsizlik (biri kam, biri ko'p). Yechim: "amaliy SOLID" — o'zgarish ko'ringanda refactoring (avval sodda, o'zgarish talab qilganda SOLID qo'sh) — "uch marta qoidasi" (bir marta yoz, ikki marta chida, uchinchida abstraksiya). Muhandis saboqi: dizayn — muvozanat (o'zgarish moslashuvi vs oddiylik); tajriba qachon qaysini tanlashni o'rgatadi.

1. Nega kelajak noaniq

Qaysi qism o'zgaradi — bilmaymiz (talab, texnologiya). SOLID har joyga — narx (murakkablik).

2. Muvozanat (qayerga SOLID)

Joy Yondashuv
O'zgarish ehtimoli yuqori SOLID (moslashuvchan)
Barqaror, oddiy Sodda (KISS)

3. Ortiqcha dizayn xatari

  • Murakkablik (ko'p sinf — o'qish qiyin)
  • Erta abstraksiya (noto'g'ri taxmin — qayta yozish)
  • YAGNI (kerak bo'lmas narsa)

4. Kam dizayn xatari

  • Qattiq (o'zgartirish qiyin)
  • Mo'rt (bir o'zgarish boshqasini buzadi)
  • Shishgan (xudo sinflar)

5. Amaliy yechim

"Uch marta qoidasi": avval sodda, o'zgarish talab qilganda SOLID qo'sh (refactoring). Erta emas, kech emas.

6. Xulosa

  1. Kelajak noaniq — o'zgarish joyini taxmin qiyin
  2. Muvozanat: SOLID o'zgarishga, sodda barqarorga
  3. Ortiqcha (murakkab) va kam (qattiq) — ikki xato
  4. Amaliy SOLID: o'zgarish ko'ringanda qo'sh (mahorat)

Nimani mustahkamlaydi: 2.7, 2.8-bo'limlar.


Xulosa

Bu darsda SOLID tamoyillarini o'rgandik.

Eng muhim uch fikr:

  1. SOLID va SRP, OCP. SOLID — obyektga yo'naltirilgan dizaynning besh tamoyili (sinflarni moslashuvchan, kengaytiriladigan, sinaladigan qiladi — maqsad: o'zgarishga tayyorlik). S — SRP (Single Responsibility): sinf bir mas'uliyatga (bir o'zgarish sababiga) ega — Order (mantiq), OrderRepository (saqlash), EmailService (email) alohida (belgi: tavsif "va" bilan — bo'lish). O — OCP (Open/Closed): kod kengaytirishga ochiq, o'zgartirishga yopiq — yangi shakl = yangi sinf (mavjud if/elif ni o'zgartirmasdan), abstraksiya + polimorfizm bilan.

  2. LSP, ISP, DIP. L — LSP (Liskov Substitution): quyi sinf (voris) yuqori o'rnida ishlashi kerak (dasturni buzmasdan) — Tuyaqush (ucholmaydi) Qush o'rniga mos emas (LSP buzadi — voris ota va'dasini bajarmaydi). I — ISP (Interface Segregation): kichik, maxsus interfeyslar — mijoz faqat kerak metodlarga bog'lansin (Robot uchun ovqatlan keraksiz — Ishlaydigan/Ovqatlanadigan ajrat). D — DIP (Dependency Inversion): yuqori daraja quyiga aniq emas, ikkalasi abstraksiyaga bog'lansin — Xabarchi aniq EmailYuboruvchi ga emas, Yuboruvchi interfeysiga (DI — dependency injection, tashqaridan berish; email/SMS almashtiriladi, sinash oson).

  3. SOLID birgalikda va muvozanat. SOLID tamoyillari birga: SRP bo'ladi, OCP+DIP kengaytiradi, LSP polimorfizni ishonchli qiladi, ISP bog'liqlikni kamaytiradi — umumiy g'oya o'zgarishni oson va xavfsiz qilish. Lekin SOLID — tamoyil, qonun emas: haddan qo'llash (har narsaga interfeys) — murakkablik (KISS buziladi); "ortiqcha dizayn" (erta abstraksiya, YAGNI) va "kam dizayn" (qattiq, mo'rt, xudo sinf) — ikki xato. Amaliy yechim: "uch marta qoidasi" (o'zgarish talab qilganda SOLID qo'sh — refactoring, erta emas). SOLID — toza kod 27.1-bob ustiga quriladi va naqshlar (27.3–27.5), qatlamlar 27.6-bob, Clean Architecture 27.7-bob uchun asos. Yaxshi dizayn — o'zgarishga tayyor dizayn (muvozanat bilan).

Keyingi darsda dizayn naqshlari: yaratuvchi (creational) ni o'rganamiz: obyekt yaratishning takrorlanuvchi yechimlari (Factory, Singleton, Builder, Prototype) — SOLID ni amalda qo'llaydigan tayyor andozalar.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
27.2-dars: SOLID tamoyillari — IlmHamroh