CodeGym /Kurslar /C# SELF /Abstraksiyalar və mürəkkəb sistemlərin sadələşdirilməsi

Abstraksiyalar və mürəkkəb sistemlərin sadələşdirilməsi

C# SELF
Səviyyə , Dərs
Mövcuddur

1. Mürəkkəb sistemlərdə sadəliyin açarı

Mürəkkəb proqram sistemləri böyük bir şəhərə bənzəyir: minlərlə sakin, yollar, qaydalar, əlaqələr. Əgər hər obyektə birbaşa nəzarət etməyə çalışsan, tez bir zamanda çaşıb qalarsan və şəhərin (və özünün!) həyatını kabusa çevirərsən. Abstraksiya — bu, şəhərin baş planı kimidir: sən hər taksiyə ayrıca baxmırsan, amma dəqiq bilirsən ki, nəqliyyatın marşrutu, sürücüsü və sərnişinləri var.

Niyə mürəkkəb sistemlər abstraksiyaya ehtiyac duyur

Abstraksiyasız kod "makaron" kimidir — bir yığın detal, hər şey bir-birinə birbaşa bağlıdır, hər xırda dəyişiklik hər şeyi sındırır. Abstraksiya isə reallaşdırma detallarını və ümumi interfeysi ayırır, sistemlə "yuxarıdan" işləməyə imkan verir, hər dəfə detallara girmədən.

Təsəvvür elə bank sistemi var: sən kartdan karta pul köçürmək istəyirsən, amma bank serverlərinin necə işlədiyini və ya verilənlər bazasının necə qurulduğunu bilməyə ehtiyac yoxdur. Sənin üçün sadələşdirilmiş bir interfeys var: "bir hesabdan digər hesaba məbləği köçür" — məhz bu abstraksiya səviyyəsidir.

Bəzən abstraksiya — sadəcə gələcəyini düşünməkdir: dəstəkləmək, genişləndirmək və başa salmaq daha asandır, əgər kod aydın abstraksiyalar üzərindən işləyirsə.

2. Həyatdan gündəlik nümunələr

Kofeaparatla həyat nümunəsi

Kofe bişirəndə sənə pompanın, temperatur sensorlarının və klapanların quruluşunu bilmək lazım deyil. Sadəcə düyməni basırsan — və nəticəni alırsan. Proqramlaşdırmada abstraksiya eyni işi görür: reallaşdırma detallarını sadə interfeys arxasında gizlədir.


// Abstraksiya interfeysi "Kofeaparat"
public abstract class CoffeeMachine
{
    public abstract void MakeEspresso();
    public abstract void MakeCappuccino();
}

// Kofeaparatın konkret modelinin reallaşdırılması
public class FancyCoffeeMachine : CoffeeMachine
{
    public override void MakeEspresso()
    {
        // Espresso hazırlamağın konkret addımları
        Console.WriteLine("Dənələri üyüdürük, presləyirik, espresso bişiririk...");
    }
    
    public override void MakeCappuccino()
    {
        // Kapuçino hazırlamağın konkret addımları
        Console.WriteLine("Dənələri üyüdürük, bişiririk, südü köpükləndiririk kapuçino üçün...");
    }
}

Sən obyektlə CoffeeMachine abstraksiyası vasitəsilə işləyirsən, kofe bişirmənin detalları isə içəridə qalır.

3. Real layihələrdə abstraksiya

Onlayn mağaza hazırlanması

Təsəvvür elə ki, biz onlayn mağaza hazırlayırıq. Çoxlu entitilərimiz var: məhsullar, səbət, istifadəçilər, sifarişlər, ödəniş və çatdırılma. Abstraksiyasız kod asanlıqla monolit və zəif genişlənəbilən olur.

Onlayn mağazada abstraksiya nümunələri

  1. Məhsul (Product):
    Kitab, soyuducu və ya elektron vauçer satmağından asılı olmayaraq, bütün məhsullar ümumi Product sinfi ilə abstraksiya oluna bilər.
  2. Ödəniş (Payment):
    Alıcı kartla, PayPal-la, kriptovalyuta ilə ödəyə bilər — detallar vacib deyil, əsas abstraksiya "ödəniş etmək"dir.
  3. Çatdırılma (Delivery):
    Kuryerlə, poçtla, ya da özün aparmaqla çatdırılma var. Hamısı "Çatdırılma" abstrakt sinifini reallaşdırır, sistem isə bu ümumi tip ilə işləyir.

Kod nümunəsi: çatdırılma üsulunun abstraksiyası


public abstract class Delivery
{
    public string Address { get; set; }

    public abstract void Deliver();
}

public class CourierDelivery : Delivery
{
    public override void Deliver()
    {
        Console.WriteLine($"Kuryerlə çatdırılma ünvanı: {Address}");
    }
}

public class PickupDelivery : Delivery
{
    public override void Deliver()
    {
        Console.WriteLine($"Çıxarış məntəqəsindən özün apar ünvanı: {Address}");
    }
}

Sifariş təsdiqlənəndə, anbar artıq məhsulun necə çatdırılacağını düşünmür — sadəcə order.Delivery.Deliver() çağırır, reallaşdırmanın içinə baxmır. Bu çeviklik verir: yeni çatdırılma növü əlavə etmək asandır, qalan kodu dəyişməyə ehtiyac yoxdur.

4. Abstraksiya nümunə ilə

Bizim tədris proqramımız kiçik bir tətbiq üzərində qurulub — məsələn, "Ferma heyvanlarının uçotu". Keçən dərslərdə Animal, Cow, Dog, Cat və s. sinif iyerarxiyası qurmuşduq. Gəlin, fermada tapşırıqları idarə etmək üçün abstraksiyadan istifadə edək.

Heyvanlar üçün komandaların sadələşdirilməsi kimi abstraksiya

Tutaq ki, indi "Fermer prosesi" reallaşdırmalısan: hər gün bütün heyvanlar yem alır və öz hərəkətini yerinə yetirir (məsələn, süd verir və ya hürür). Biz hər heyvan növü üçün ayrıca prosedur yazmaq istəmirik.


public abstract class Animal
{
    public string Name { get; set; }
    public abstract void Feed();
    public abstract void MakeSound();
}

public class Cow : Animal
{
    public override void Feed()
    {
        Console.WriteLine($"{Name}: ot yeyir.");
    }

    public override void MakeSound()
    {
        Console.WriteLine($"{Name}: Muuuu!");
    }
}

public class Dog : Animal
{
    public override void Feed()
    {
        Console.WriteLine($"{Name}: sümük yeyir.");
    }

    public override void MakeSound()
    {
        Console.WriteLine($"{Name}: Hav-hav!");
    }
}

Niyə bu rahatdır? İndi bütün heyvanları eyni cür işləyə bilərsən, kim olduğunu düşünmədən:


List<Animal> farmAnimals = new List<Animal>
{
    new Cow { Name = "Buryonka" },
    new Dog { Name = "Sharik" }
};

foreach (Animal animal in farmAnimals)
{
    animal.Feed();
    animal.MakeSound();
}

Əgər qaz, qoyun, hətta lama əlavə etmək istəsən — dövrün eyni qalacaq!

5. Abstraksiya bağlılığı necə azaldır

Bağlılıq (coupling) — proqramının müxtəlif hissələrinin bir-birindən nə qədər asılı olduğudur. Yüksək bağlılıq — məktəb yeməkxanası kimidir: çaydan xarab olsa, heç kim çay hazırlaya bilmir, hətta makaron üçün lazım olmasa da. Abstraksiya bağlılığı azaldır: sən interfeyslərlə və ya abstrakt siniflərlə işləyirsən, "kapotun altında" hansı reallaşdırma olduğunu bilmirsən.

Vizual sxem: abstraksiya səviyyəsi və asılılıqlar


+--------------------+     +------------------------+
|   Yüksəksəviyyəli  | --> |      Abstraksiya       |
|      kod           |     |  (abstrakt sinif /     |
|  (məsələn, Order)  |     |      interfeys)        |
+--------------------+     +------------------------+
                                     /      \
                                    /        \
                   +------------------+    +-----------------+
                   | Reallaşdırma 1   |    | Reallaşdırma 2  |
                   | (CourierDelivery)|    | (PickupDelivery)|
                   +------------------+    +-----------------+
Yüksəksəviyyəli kod yalnız abstraksiya ilə işləyir, konkret reallaşdırma ilə yox

Abstraksiyanın üstünlüklərinə başqa baxış

  • Çeviklik: yeni obyekt tipləri əlavə etmək, davranışı dəyişmək tez olur, qalan kodu toxunmadan.
  • Genişlənəbilənlik: sistem asanlıqla böyüyür. Onlayn mağazamızda yeni çatdırılma üsulu əlavə etmək üçün sadəcə yeni alt sinif yazırsan.
  • Testlənəbilənlik: abstraksiya sistemi modul testlər üçün rahat edir (reallaşdırmaları "əvəz etmək" olur).
  • "Açıq/qapalı prinsipi" (Open/Closed Principle, OCP): kod genişlənməyə açıqdır (yeni reallaşdırma əlavə etmək olar), amma dəyişməyə qapalıdır (mövcud kodu dəyişmək lazım deyil).

6. Abstraksiyasız problemlər

Abstraksiyasız kod tez bir zamanda tip yoxlamaları, təkrarlanan kod və şərtlərdən ibarət makarona çevrilir. Məsələn, belə etmək olmaz:


// Antipattern: heç bir abstraksiya yoxdur, sadəcə ağrı
if (animal is Cow)
{
    ((Cow)animal).Feed();
}
else if (animal is Dog)
{
    ((Dog)animal).Feed();
}
else if (animal is Cat)
{
    ((Cat)animal).Feed();
}
// və s...

Belə kodu saxlamaq çətindir: qoyun əlavə etsən, hər yerdə yeni şərtlər yazmalısan. Əgər heyvan rəqs etməyi öyrənsə, böyük kod bloklarını bütün layihə boyu kopyalamaq lazım olacaq.

7. Abstraksiyalarla layihələndirmədə tipik səhvlər

Səhv №1: həddindən artıq irsiyyət istifadə etmək.
Yeni başlayanlar tez-tez mürəkkəb sinif iyerarxiyaları qurmağa çalışır, halbuki bəzən kompozisiya daha sadə və etibarlıdır. Hər şey irsiyyət olmalı deyil. Bəzən obyekti içəridə saxlamaq, onun davranışını irsən almaqdan daha asandır.

Səhv №2: abstrakt sinif heç nəyi abstraksiya etmir.
Bəzən abstrakt sinifə elə xüsusiyyət və metodlar qoyurlar ki, heç bir varisdə istifadə olunmur. Bu, vahid məsuliyyət prinsipini pozur və kodun dəstəyini çətinləşdirir. Abstrakt sinif əsas davranışı müəyyən etməlidir, təsadüfi metodlar üçün anbar olmamalıdır.

Səhv №3: kod təkrarı zamanı abstraksiyanın olmaması.
Əgər bir neçə sinifdə eyni məntiq təkrarlanırsa, bu, artıq ümumi abstrakt ata sinif yaratmaq vaxtıdır. Bu səhv çox vaxt bilməməkdən yox, tələsik və ya pis planlaşdırmadan yaranır.

1
Sorğu/viktorina
, səviyyə, dərs
Əlçatan deyil
Abstrakt siniflər
Abstraksiya və abstrakt siniflər
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION