Məzmuna keçin
  • Kateqoriyalar
  • Ən yeni
  • Teqlər
  • Populyar
Yığmaq
Brend loqosu

administrators

Şəxsi

Yazı


  • JavaScript-də document və window obyektləri
    codexC codex

    Veb proqramlaşdırmada JavaScript ilə işləyərkən iki əsas obyektə tez-tez rast gəlirik: window və document. Bu obyektlər JavaScript-in brauzer mühitində necə işlədiyini anlamaq mühüm rol oynayır. Gəlin onları yaxından tanıyaq.


    window obyekti nədir?

    window obyekti JavaScript-də qlobal obyekt sayılır. Brauzerdə açılan hər bir səhifə üçün window obyektinin bir nüsxəsi yaradılır. Bu obyekt brauzer pəncərəsini (və ya tabını) təmsil edir və onun daxilində bir çox faydalı metodlar və xüsusiyyətlər mövcuddur.

    Xüsusiyyətləri və metodları:

    • window.alert() – istifadəçiyə xəbərdarlıq mesajı göstərmək
    • window.setTimeout() – müəyyən vaxtdan sonra kodun icrasını planlamaq
    • window.location – cari URL məlumatlarına daxil olmaq və dəyişmək
    • window.innerWidth, window.innerHeight – brauzerin daxili ölçülərini əldə etmək
    • və sairə…

    Əslində, JavaScript-də yazdığınız qlobal dəyişənlər və funksiyalar avtomatik olaraq window obyektinin bir hissəsinə çevrilir:

    var x = 10;
    console.log(window.x); // 10
    

    document obyekti nədir?

    document obyekti window obyektinin bir hissəsidir və HTML sənədini təmsil edir. Yəni, veb səhifənin strukturuna (DOM – Document Object Model) daxil olmaq, onu oxumaq və ya dəyişdirmək üçün istifadə olunur.

    Əsas metodlar və xüsusiyyətlər:

    • document.getElementById() – HTML elementini ID ilə tapmaq
    • document.querySelector() – CSS selektorları ilə element seçmək
    • document.title – səhifənin başlığını oxumaq və ya dəyişmək
    • document.body, document.head – səhifənin əsas struktur hissələrinə çıxış
    • və sairə…
    const title = document.getElementById("my-title");
    title.textContent = "Yeni Başlıq";
    

    window və document arasındakı fərqlər

    Özəllik window document
    Nəyi təmsil edir? Brauzer pəncərəsini HTML sənədini
    Qlobal obyekt Bəli Xeyr, window içindədir
    Əsas istifadə sahəsi Brauzer ilə əlaqəli funksiyalar (alert, setTimeout, location və s.) DOM ilə işləmək, HTML strukturu ilə əlaqə
    Məsuliyyət sahəsi Ümumi pəncərə və interfeys idarəsi Səhifə məzmunu və strukturu

    Bir-birinə necə bağlıdırlar?

    document obyekti əslində window obyektinin daxilində mövcuddur:

    console.log(window.document === document); // true
    

    Bu, o deməkdir ki, document hər zaman window obyektinin içində yerləşir, lakin biz onu birbaşa da çağıraraq istifadə edə bilərik.


    JavaScript-də window və document obyektləri veb səhifənin və brauzer mühitinin idarəsi üçün əsas komponentlərdir.

    • window – ümumi brauzer pəncərəsini,
    • document – səhifənin HTML strukturu və məzmununu təmsil edir.

    Bu iki obyektin fərqini və hansı vəziyyətdə hansından istifadə edilməli olduğunu başa düşmək, daha təmiz və effektiv JavaScript kodu yazmaq üçün vacibdir.

    Front-end document window dom browser

  • ARIA Label nədir və necə istifadə etməliyik?
    codexC codex

    Web saytlarının daha əlçatan və istifadəçi yönümlü olması üçün a11y (accessibility) yanaşması vacib rol oynayır. Bu yanaşmanın əsas hissələrindən biri də aria-label atributudur. Bəs bu atribut nə üçündür və onu hansı hallarda istifadə etməliyik?


    aria-label nə işə yarayır?

    aria-label atributu elementin görmə qabiliyyəti məhdud olan istifadəçilər üçün ekran oxuyucular vasitəsilə səsləndiriləcək mətnini təyin edir. Yəni, bu atribut vizual olaraq istifadəçiyə göstərilməsə də, ekran oxuyucu proqram bu məlumatı səsləndirir.

    Məsələn, təkcə ikonası olan bir düyməni götürək:

    <button aria-label="Sil">
      <TrashIcon />
    </button>
    

    Bu halda ekran oxuyucu “Sil düyməsi” kimi səsləndirəcək. Halbuki istifadəçi ekranda yalnız zibil qutusunu görür.


    Nə zaman istifadə olunmalıdır?

    • Görünən mətn olmayan ikonalı düymələrdə
    • Təkcə simvol və ya şəkil olan linklərdə
    • Özəl dizayn edilmiş (custom) checkbox, switch və ya radio komponentlərində
    • Form elementlərində label etiketi olmayan hallarda
    • Mobil tətbiqlərdəki Floating Action Button (FAB) tipli düymələrdə

    Nə zaman istifadə olunmamalıdır?

    aria-label atributu, əgər həmin elementdə artıq görünən mətn varsa, istifadə edilməməlidir. Çünki bu halda aria-label həmin mətnin əvəzində oxunacaq və istifadəçini çaşdıra bilər.

    Yanlış nümunə:

    <button aria-label="Təsdiqlə">Formu Göndər</button>
    

    Ekran oxuyucu burada “Təsdiqlə” deyəcək, halbuki istifadəçi “Formu Göndər” yazısını görür.

    Əgər artıq mətn varsa, aria-label deyil, ehtiyac olarsa aria-describedby və ya aria-labelledby istifadə etmək daha məqsədəuyğundur.


    aria-* atributlarının fərqləri

    Atribut Təyinatı
    aria-label Görünməyən, lakin ekran oxuyucular üçün vacib qısa ad
    aria-labelledby Başqa elementin ID-sinə əsaslanaraq adı təyin edir
    aria-describedby Əlavə izahat və ya köməkçi mətnləri ekran oxuyucular üçün göstərmək üçündür

    Tövsiyələr və yaxşı təcrübələr (best practices)

    • Dekorativ ikonalar üçün aria-hidden="true" istifadə edin.
    • Əgər komponent daxilində mətn varsa, əlavə aria-label verməyin.
    • İmkan daxilində semantic HTML komponentlərdən istifadə edin (<button>, <label> və s.).
    • Kodunuzu test etmək üçün axe, lighthouse, eslint-plugin-jsx-a11y kimi alətlərdən istifadə edin.
    • Screen reader ilə canlı testlər edin (NVDA, VoiceOver və s.).

    aria-label — sadə görünməsinə baxmayaraq, vəzifəsi kritik olan bir xüsusiyyətdir. Əlçatanlıq məqsədilə istifadə olunan bu atribut, düzgün tətbiq olunduqda saytınızı daha inklüziv və bütün istifadəçilər üçün uyğun hala gətirir.

    Unutmayın:

    Accessibility — sadəcə məhdudiyyətləri olan insanlar üçün deyil, hər kəs üçün daha yaxşı təcrübə yaratmaqdır.

    Front-end aria-label a11y aria-labelledby accessibility

  • Proxy dizayn nümunəsi (Pattern)
    codexC codex

    Proxy Pattern — obyektə birbaşa çıxışı nəzarət altında saxlamaq üçün istifadə olunan dizayn pattern-dir. Bu pattern-in əsas məqsədi, obyektə vasitəçi (proxy) vasitəsilə nəzarət etməkdir. JavaScript-də bu konsept həm real həyatda, həm də proqramlaşdırmada çox faydalıdır.

    Bu yazıda aşağıdakı Proxy Pattern növlərini incələyəcəyik:

    • Property Proxy
    • Protection Proxy
    • Virtual Proxy

    1. valueOf() və toString() ilə xüsusi tip obyektlər

    Aşağıdakı Percentage class-ı valueOf və toString metodları ilə say kimi istifadə edilə bilən obyekt yaradır:

    class Percentage {
      constructor(value) {
        this.value = value;
      }
    
      toString() {
        return `${this.value}%`;
      }
    
      valueOf() {
        return this.value / 100;
      }
    }
    
    let fivePercent = new Percentage(5);
    console.log(fivePercent.toString()); // "5%"
    console.log(`5% of 50 is ${50 * fivePercent}`); // 2.5
    

    ➡️ Bu, JavaScript-in type coercion xüsusiyyətindən yararlanır: valueOf() metodu çağrıldıqda obyektin rəqəmsal dəyəri kimi işlənir.


    2. Property Proxy – Dəyərlərə nəzarət və loglama

    Property classı ilə dəyərlərin dəyişməsinə nəzarət və loglama imkanı yaradılır:

    class Property {
      constructor(value, name = "") {
        this._value = value;
        this.name = name;
      }
    
      get value() {
        return this._value;
      }
    
      set value(newValue) {
        if (this._value === newValue) return;
        
        console.log(`Property ${this.name} changed from ${this._value} to ${newValue}`);
        this._value = newValue;
      }
    }
    
    class Creature {
      constructor() {
        this._agility = new Property(10, "agility");
      }
    
      get agility() {
        return this._agility.value;
      }
    
      set agility(newValue) {
        this._agility.value = newValue;
      }
    }
    
    let creature = new Creature();
    creature.agility = 15; // Property agility changed from 10 to 15
    creature.agility = 15; // No change
    console.log(creature.agility); // 15
    

    ✅ Fayda: Hər dəfə dəyər dəyişəndə loglama aparılır. Lazım olsa, undo sistemi və ya dəyişiklik tarixi də əlavə edilə bilər.


    3. Protection Proxy – Təhlükəsizlik nəzarəti

    Aşağıdakı nümunədə bir maşını yalnız yaşa uyğun olaraq sürməyə icazə verilir:

    class Car {
      drive() {
        console.log("Car is being driven");
      }
    }
    
    class CarProxy {
      constructor(driver) {
        this.driver = driver;
        this._car = new Car();
      }
    
      drive() {
        if (this.driver.age >= 16) {
          this._car.drive();
        } else {
          console.log("Driver is too young to drive");
        }
      }
    }
    
    class Driver {
      constructor(age) {
        this.age = age;
      }
    }
    
    let car1 = new CarProxy(new Driver(15));
    car1.drive(); // Driver is too young to drive
    
    let car2 = new CarProxy(new Driver(22));
    car2.drive(); // Car is being driven
    

    🔐 Protection Proxy sistemə yalnız uyğun istifadəçilərin çıxışını təmin edir. Məsələn, admin panelinə giriş, API endpoint-ə çıxış və s.


    4. Virtual Proxy – Tənbəl yükləmə (Lazy Loading)

    Image obyektinin yaddaşı çox istifadə edə biləcəyini fərz edək. Onu yalnız ilk dəfə lazım olduqda yaratmaq istərik:

    class Image {
      constructor(url) {
        this.url = url;
        console.log(`Image created with URL: ${this.url}`);
      }
    
      draw() {
        console.log(`Drawing image from ${this.url}`);
      }
    }
    
    class LazyImage {
      constructor(url) {
        this.url = url;
      }
    
      draw() {
        if (!this._image) {
          console.log(`Loading image from ${this.url}`);
          this._image = new Image(this.url);
        }
        this._image.draw();
      }
    }
    
    function drawImage(image) {
      console.log("About to draw image...");
      image.draw();
      console.log("Done drawing the image.");
    }
    
    let image = new LazyImage("https://example.com/image.jpg");
    drawImage(image);
    // Yalnız ilk dəfə draw çağırıldıqda Image yaradılır
    

    ⚡ Fayda: Lazım olmayan resursların istifadəsini gecikdirməklə performansı optimallaşdırır.


    Nəticə

    Proxy Pattern JavaScript-də çox güclü bir konseptdir. Bu pattern aşağıdakı hallarda çox faydalıdır:

    Növ Təsvir
    Property Proxy Mülkət dəyişikliklərinə nəzarət, loglama
    Protection Proxy Giriş nəzarəti və hüquq yoxlaması
    Virtual Proxy Resursların tənbəl yüklənməsi (lazy loading)

    Bu nümunələr real həyatda istər UI komponentləri, istərsə də API istəkləri, giriş kontrol sistemləri üçün praktik imkanlar yaradır.

    Dizayn nümunələri design proxy pattern

  • Bridge Pattern – Abstraksiya və İcranın Ayrılması
    codexC codex

    🧪 Tapşırıq

    Aşağıdakı kod nümunəsində Shape adlı əsas class-dan Square və Triangle class-ları yaradılır. Hər forma həm Vector (xəttlərlə) həm də Raster (piksel ilə) şəklində çəkilə bilər. Bu isə hər formanın iki fərqli versiyasının yaradılmasına səbəb olur:

    class Shape {
      constructor(name) {
        this.name = name;
      }
    }
    
    class Triangle extends Shape {
      constructor() {
        super('triangle');
      }
    }
    
    class Square extends Shape {
      constructor() {
        super('square');
      }
    }
    
    class VectorSquare extends Square {
      toString() {
        return 'Drawing square as lines';
      }
    }
    
    class RasterSquare extends Square {
      toString() {
        return 'Drawing square as pixels';
      }
    }
    
    // imagine VectorTriangle and RasterTriangle are here too
    

    Bu yanaşma çox sayda class-ın yaradılmasına səbəb olur və sistemin genişləndirilməsini çətinləşdirir. Hər yeni forma və render üsulu üçün yeni bir class əlavə etmək lazım gəlir. Bu, məhz Dekart hasili problemini yaradır:

    Formalar × Render üsulları = Çox sayda sinif

    Yuxarıdakı kodu elə refactor edin ki, Bridge Pattern-dən istifadə edərək VectorTriangle və RasterTriangle yaradıb kodu new Triangle(new RasterRenderer()); formada çağırdıqda cavabında Drawing Triangle as pixels alınsın.


    🧩 Həlli

    Çalışın ilk öncə özünüz həll edin sonra həllinə baxın


    Bu problemi Bridge Pattern ilə həll edə bilərik. Bu dizayn pattern-in məqsədi abstraksiyanı onun implementasiyasından ayırmaqdır. Bununla da hər iki tərəf müstəqil şəkildə inkişaf etdirilə bilər.

    // Renderer interfeysini təmsil edən baza class
    class Renderer {
      get whatToRenderAs() {
        throw new Error('whatToRenderAs not implemented');
      }
    }
    
    // Konkret Renderer-lər
    class VectorRenderer extends Renderer {
      get whatToRenderAs() {
        return 'lines';
      }
    }
    
    class RasterRenderer extends Renderer {
      get whatToRenderAs() {
        return 'pixels';
      }
    }
    
    // Baz forma classı— artıq rendereri qəbul edir
    class Shape {
      constructor(name, renderer) {
        this.name = name;
        this.renderer = renderer;
      }
    
      toString() {
        return `Drawing ${this.name} as ${this.renderer.whatToRenderAs}`;
      }
    }
    
    // Konkret formalar — yalnız ad və renderer qəbul edir
    class Triangle extends Shape {
      constructor(renderer) {
        super('Triangle', renderer);
      }
    }
    
    class Square extends Shape {
      constructor(renderer) {
        super('Square', renderer);
      }
    }
    

    ⚙️ İstifadə nümunəsi

    const triangle = new Triangle(new RasterRenderer());
    console.log(triangle.toString()); 
    // Output: Drawing Triangle as pixels
    
    const square = new Square(new VectorRenderer());
    console.log(square.toString()); 
    // Output: Drawing Square as lines
    

    Dizayn nümunələri design pattern bridge abstraction

  • Bridge Pattern – Abstraksiya və İcranın Ayrılması
    codexC codex

    c71ae996-8acc-4e98-94b3-ea51c28235f8-image.png

    Bridge Pattern (Körpü nümunəsi) — proqramlaşdırmada abstraksiyanı (istifadəçi səviyyəsində interfeys) onun icrasından (daxili işləmə qaydasından) ayırmaq üçün istifadə olunan dizayn nümunəsidir. Bu, hər iki tərəfin müstəqil şəkildə inkişaf etdirilməsinə imkan yaradır.

    Başqa sözlə, bu pattern “nə edirik” və “necə edirik” anlayışlarını bir-birindən ayırır.


    🧪 JavaScript-də Bridge Pattern nümunəsi

    // Abstraksiya
    class RemoteControl {
      constructor(device) {
        this.device = device;
      }
    
      togglePower() {
        if (this.device.isEnabled()) {
          this.device.disable();
        } else {
          this.device.enable();
        }
      }
    
      volumeUp() {
        this.device.setVolume(this.device.getVolume() + 10);
      }
    
      volumeDown() {
        this.device.setVolume(this.device.getVolume() - 10);
      }
    }
    
    // Genişləndirilmiş Abstraksiya
    class AdvancedRemoteControl extends RemoteControl {
      mute() {
        this.device.setVolume(0);
      }
    }
    
    // İcraçı interfeys
    class Device {
      constructor() {
        this.volume = 50;
        this.enabled = false;
      }
    
      isEnabled() {
        return this.enabled;
      }
    
      enable() {
        this.enabled = true;
      }
    
      disable() {
        this.enabled = false;
      }
    
      getVolume() {
        return this.volume;
      }
    
      setVolume(volume) {
        this.volume = volume;
      }
    }
    
    // Konkret İcraçılar
    class TV extends Device {
      constructor() {
        super();
      }
      // TV-yə xas əlavə metodlar buraya əlavə oluna bilər
    }
    
    class Radio extends Device {
      constructor() {
        super();
      }
      // Radioya xas əlavə metodlar buraya əlavə oluna bilər
    }
    

    🔍 Koda təhlil ilə baxış

    Komponent İzah
    RemoteControl Abstraksiya rolunu oynayır. Obyekti idarə etmək üçün ümumi metodlar təklif edir, lakin icranı device obyektinə ötürür.
    AdvancedRemoteControl Abstraksiyanı genişləndirir və əlavə imkanlar təqdim edir (məsələn, mute).
    Device İcraçı (Implementor) interfeysidir. Konkret cihazların davranışlarını müəyyən edir.
    TV və Radio Konkret icraçılar (Concrete Implementors). Device sinfini miras alaraq öz spesifik funksiyalarını əlavə edə bilərlər.

    ▶️ İstifadə nümunəsi

    const tv = new TV();
    const remote = new RemoteControl(tv);
    
    remote.togglePower();
    console.log(tv.isEnabled()); // true
    
    remote.volumeUp();
    console.log(tv.getVolume()); // 60
    
    const radio = new Radio();
    const advancedRemote = new AdvancedRemoteControl(radio);
    
    advancedRemote.togglePower();
    console.log(radio.isEnabled()); // true
    
    advancedRemote.mute();
    console.log(radio.getVolume()); // 0
    

    Burada RemoteControl istənilən Device tipli obyektlə işləyə bilir. Hər bir yeni cihaz üçün RemoteControl-u dəyişməyə ehtiyac yoxdur.


    🧠 Nəyə görə Bridge Pattern istifadə olunur?

    • Kodun genişləndirilməsi asanlaşır.
    • Yeni Device (məsələn, Projector) və ya yeni RemoteControl variantları əlavə etmək mümkündür.
    • Abstraksiya və implementasiya bir-birindən asılı deyil, bu da çeviklik və test ediləbilərlik verir.

    📊 Ümumi Xülasə

    Bridge Pattern, kodu aşağıdakı şəkildə strukturlaşdırmağa imkan verir:

    • 🔹 RemoteControl — abstraksiya təbəqəsi (istifadəçi interfeysi)
    • 🔸 AdvancedRemoteControl — genişləndirilmiş abstraksiya
    • 🔹 Device — implementasiya interfeysi
    • 🔸 TV, Radio — konkret implementasiyalar

    Bu struktur yeni cihazlar və ya uzaqdan idarəetmə növləri əlavə etdikdə kodun dəyişməsini minimuma endirir.


    ✅ Nəticə

    Bridge Pattern dizayn şablonu kompleks sistemlərdə asan genişləndirmə və idarəetmə üçün idealdır. JavaScript kimi obyekt yönümlü yanaşmanı dəstəkləyən dinamik dillərdə bu şablon real dünyada geniş istifadə olunur.

    Əgər siz komponentləriniz arasında zəif əlaqə (loose coupling) istəyirsinizsə, Bridge Pattern sizin üçün düzgün seçim ola bilər.

    Dizayn nümunələri design pattern bridge abstraction

  • Duck Typing nədir? JavaScript-də tətbiqi və nümunələrlə izah
    codexC codex

    Proqramlaşdırmada 🦆Duck Typing — tip yoxlamasının obyektin davranışına əsasən aparılması prinsipidir. Bu ifadə məşhur bir sitatdan götürülüb:

    “Əgər nəsə ördək kimi gəzir, ördək kimi səs çıxarırsa, deməli bu ördəkdir.”


    🧪 Duck Typing nə deməkdir?

    Duck Typing-də obyektin tipi yox, onun interfeysi və ya xüsusiyyətləri/metodları əsas götürülür. Yəni:

    function printName(entity) {
      if (typeof entity.sayName === "function") {
        entity.sayName();
      } else {
        console.log("Bu obyektin sayName funksiyası yoxdur.");
      }
    }
    

    Burada entity adlı obyektin sayName() funksiyası olub-olmaması yoxlanılır. Onun hansı sinifdən və ya hansı tipdən olması önəmli deyil. Bu, Duck Typing yanaşmasıdır.


    🛠 JavaScript-də Duck Typing nümunələri

    const user = {
      name: "Elvin",
      sayName() {
        console.log(`Mənim adım ${this.name}`);
      },
    };
    
    const robot = {
      id: 42,
      sayName() {
        console.log("Mən bir robotam.");
      },
    };
    
    function greet(entity) {
      entity.sayName(); // Duck Typing prinsipi
    }
    
    greet(user);   // Mənim adım Elvin
    greet(robot);  // Mən bir robotam.
    

    Hər iki obyektin sayName() funksiyası olduğu üçün greet() funksiyası uğurla işləyir. Obyektlərin tipi yox, davranışları ön plandadır.


    💡 Duck Typing ilə tip sistemi arasındakı fərqlər

    Xüsusiyyət Tip əsaslı yanaşma (OOP) Duck Typing (JavaScript)
    Tip yoxlanışı Kompilyasiya zamanı Run-time (işləmə zamanı)
    Tipə əsaslanma Sinif və interfeys Obyektin davranışı
    Quraşdırılmış tiplər Zəruridir Məcburi deyil
    Əsas məqsəd Güvənlik və sabitlik Çeviklik və sadəlik

    ⚠️ Duck Typing-in riskləri

    Duck Typing çox çevik olsa da, müəyyən risklər yarada bilər:

    • Run-time səhvlər: Əgər obyekt gözlənilən funksiyanı ehtiva etmirsə, proqram iş zamanı çökə bilər.
    • Oxunmaz kod: Tip təhlükəsizliyi olmadığından, böyük layihələrdə kodun izlənməsi çətinləşə bilər.
    • IDE köməyi az olur: Tip məlumatı olmadığı üçün kod tamamlaması və səhv yoxlamaları zəif ola bilər.

    Bu səbəblərə görə, TypeScript kimi dillər Duck Typing-in üstünlüklərini qoruyaraq, struktur tip yoxlaması (structural typing) təklif edir.


    ✅ Duck Typing vs Structural Typing (TypeScript)

    TypeScript-də interface vasitəsilə Duck Typing daha formal şəkildə tətbiq edilir:

    interface Nameable {
      sayName(): void;
    }
    
    function greet(entity: Nameable) {
      entity.sayName();
    }
    
    const person = {
      name: "Aysu",
      sayName() {
        console.log("Salam, mən Aysu");
      },
    };
    
    greet(person); // ✅ Keçərli: struktura uyğundur
    

    Burada person Nameable interfeysinə uyğun davranır, çünki sayName metoduna malikdir. Bu, TypeScript-də struktur əsaslı Duck Typing-dir.


    📌 Nəticə

    JavaScript-də Duck Typing proqramçıya obyektin funksionallığına görə davranmaq imkanı verir. Bu yanaşma, daha çevik və rahat kod yazmağa imkan yaratsa da, səhv ehtimallarını artırır. Böyük layihələrdə ya öz tip yoxlamanızı əlavə etməlisiniz, ya da TypeScript kimi həllərə üstünlük verməlisiniz.

    JavaScript types structural 🦆duck

  • Java-da Inheritance və Composition: hansını, nə zaman istifadə etməliyik?
    codexC codex

    Java proqramlaşdırma dilində obyekt yönlü proqramlaşdırmanın (OOP) iki əsas anlayışı olan inheritance və composition proqramın strukturlaşdırılması və kodun təkrar istifadəsi baxımından çox vacib rol oynayır.

    Bu məqalədə hər iki anlayışı dərin təhlil edəcək, onların fərqlərini, üstünlüklərini və real nümunələr əsasında hansı vəziyyətdə hansının seçilməli olduğunu izah edəcəyik.


    🔷 Inheritance nədir?

    Inheritance - bir class-ın başqa bir class-ın xüsusiyyətlərini və metodlarını miras almasına imkan verən OOP prinsiplərindən biridir.

    Sadə nümunə:

    class Animal {
        void sound() {
            System.out.println("Heyvan səsi");
        }
    }
    
    class Dog extends Animal {
        void bark() {
            System.out.println("Hürmək");
        }
    }
    

    Burada Dog class-ı Animal class-ından miras alır və həm sound() metodunu istifadə edə bilir, həm də özünə məxsus bark() metoduna sahibdir.

    Inheritance-ın əsas xüsusiyyətləri:

    • extends açar sözü ilə yazılır.
    • Java-da çoxlu irsilik (multiple inheritance) yalnız interfeyslərlə mümkündür.
    • super açar sözü parent class-a müraciət etmək üçün istifadə olunur.

    ✅ Inheritance-ın üstünlükləri

    • Kod təkrarını azaldır. Eyni funksionallığı müxtəlif class-larda yenidən yazmağa ehtiyac yoxdur.
    • Quruluşlu ierarxiya yaradır. Class-lar arasında əlaqə vizual və konseptual cəhətdən aydın olur.
    • Yenidən istifadə imkanı. Mövcud kod bazasından yeni class-lar yaradıla bilər.

    ⚠️ Inheritance-ın çatışmazlıqları

    • Sıx bağlılıq (tight coupling). Əsas class-dakı dəyişikliklər törəmə class-lara təsir edə bilər.
    • Dizaynın çevikliyi azalır. Törəmə class-lar əsas class-ın strukturu ilə məhdudlaşır.
    • “Fragile base class” problemi. Əsas class-dakı dəyişikliklər bütün sistemə gözlənilməz təsir göstərə bilər.

    🧩 Composition nədir?

    Composition, bir class-ın başqa bir class-ı öz daxilində obyekt kimi saxlaması və onun metodlarından istifadə etməsi prinsipi üzərində qurulub.

    Yəni burada class-lar arasında “has-a” münasibəti olur.

    Sadə nümunə:

    class Engine {
        void start() {
            System.out.println("Mühərrik işə düşdü");
        }
    }
    
    class Car {
        private Engine engine = new Engine();
    
        void drive() {
            engine.start();
            System.out.println("Maşın hərəkət edir");
        }
    }
    

    Bu nümunədə Car class-ı Engine class-ını istifadə edir, lakin ondan irs almır.


    ✅ Composition-nun üstünlükləri

    • Sərbəstlik (loose coupling). Composition olunan class asanlıqla dəyişdirilə və əvəz edilə bilər.
    • Test etmək daha asandır. Mock obyektlər ilə testlər daha effektiv yazılır.
    • Dizayn daha çevik olur. Dinamik davranışlar asanlıqla idarə olunur.

    ⚠️ Composition-nun çatışmazlıqları

    • Dizaynın mürəkkəbləşməsi. Əgər çoxlu class-lar bir-birini compose edirsə, oxumaq və başa düşmək çətinləşə bilər.
    • Əlavə kod yazmaq tələb oluna bilər. Composition inheritance-ə nisbətən bir qədər daha çox konfiqurasiya tələb edir.

    🧠 Hansını nə zaman seçməli?

    Məsələ Inheritance Composition
    Münasibət “is-a” “has-a”
    Kod təkrarını azaltmaq ✔️ ✔️
    Çevik dizayn ❌ ✔️
    Test ediləbilərlik Orta Yüksək
    Valideyn dəyişiklikləri təsiri Yüksək Aşağı

    Sadə qayda:

    Əgər class-lar arasında “is-a” münasibəti varsa — Inheritance,
    “has-a” münasibəti varsa — Composition istifadə edin.


    🎯 Best Practice: “Prefer composition over inheritance”

    Məşhur dizayn prinsiplərindən biri də budur:

    “Composition-u Inheritance-dan üstün tutun”

    Çoxlu məşhur dizayn nümunələri (design patterns) də bu prinsipi əsas götürür:

    • Strategy pattern
    • Decorator pattern
    • Observer pattern və s.

    🔚 Nəticə

    Java proqramlarında Inheritance və Composition hər biri öz yerində çox faydalı vasitələrdir. Əsas məsələ — onları düzgün kontekstdə istifadə etməkdir. Inheritance daha sadə görünsə də, zamanla sistemin çevikliyinə zərər verə bilər. Ona görə də çox vaxt Composition-a üstünlük vermək daha sağlam yanaşmadır.

    Java composition inheritance oop is-a has-a

  • Java-da String və StringBuilder: fərqlər və istifadə qaydaları
    codexC codex

    Java proqramlaşdırma dilində mətnlə işləmək üçün ən çox istifadə olunan iki class var: String və StringBuilder. Bu məqalədə bu iki class-ın fərqlərini, üstünlüklərini və hansı hallarda istifadə olunmalı olduqlarını izah edəcəyik.


    1. String nədir?

    Java-da String — dəyişməz (immutable) bir obyekt növüdür. Yəni, bir dəfə yaradıldıqdan sonra onun məzmunu dəyişdirilə bilməz. Əgər dəyişiklik etsəniz, əslində yeni bir String obyekti yaranacaq.

    Nümunə:

    String ad = "Nilay";
    ad = ad + " Huseynova";
    System.out.println(ad); // Nəticə: Nilay Huseynova
    

    Yuxarıdakı nümunədə ad + " Huseynova" ifadəsi yeni bir String obyekt yaradır və köhnə obyekt dəyişmir. Bu səbəbdən çoxlu string birləşdirmələri performans baxımından zəif ola bilər.


    2. StringBuilder nədir?

    StringBuilder Java-da dəyişə bilən (mutable) string-lər yaratmaq üçün istifadə olunur. Bu class, xüsusilə çoxlu sayda string birləşdirmələri və dəyişikliklər aparıldıqda çox daha sürətli və effektiv işləyir.

    Nümunə:

    StringBuilder ad = new StringBuilder("Nilay");
    ad.append(" Huseynova");
    System.out.println(ad); // Nəticə: Nilay Huseynova
    

    Burada .append() metodu mövcud StringBuilder obyektinə əlavə edir və yeni obyekt yaratmır.


    3. String və StringBuilder arasındakı fərqlər

    Xüsusiyyət String StringBuilder
    Dəyişə bilmə Dəyişməz (immutable) Dəyişə bilən (mutable)
    Performans Aşağı (çoxlu birləşmələrdə) Yüksək
    Thread-safe Bəli (String təhlükəsizdir) Xeyr (lakin daha sürətlidir)
    İstifadə məqsədi Az dəyişiklik olan mətnlər Tez-tez dəyişən mətnlər üçün

    Qeyd: Əgər multithreading istifadə edirsinizsə və StringBuilder lazımdırsa, onun thread-safe versiyası olan StringBuffer istifadə olunmalıdır.


    4. Hansı zaman hansından istifadə etməli?

    Ssenari İstifadə
    Mətni bir neçə dəfə dəyişəcəksiniz StringBuilder
    Mətni nadir hallarda dəyişirsiniz və sadəcə oxuyursunuz String
    Multithreading mühitində təhlükəsizlik vacibdirsə StringBuffer
    == və .equals() ilə müqayisə edirsiniz String

    5. Əlavə faydalı StringBuilder metodları

    • .append(String s) – sonda string əlavə edir
    • .insert(int offset, String s) – müəyyən mövqeyə string əlavə edir
    • .replace(int start, int end, String s) – müəyyən hissəni əvəz edir
    • .delete(int start, int end) – hissəni silir
    • .reverse() – mətni tərsinə çevirir
    • .toString() – StringBuilder obyektini adi String-ə çevirir

    Nümunə:

    StringBuilder sb = new StringBuilder("Salam");
    sb.reverse();
    System.out.println(sb); // Nəticə: malaS
    

    6. String-lərin daxilindəki simvolları gözlənilməz davranışlar

    String a = "Java";
    String b = "Java";
    String c = new String("Java");
    
    System.out.println(a == b); // true (eyni obyektə işarə edir)
    System.out.println(a == c); // false (fərqli obyekt)
    System.out.println(a.equals(c)); // true (məzmun eynidir)
    

    Burada .equals() məzmun müqayisəsi aparır, == isə obyektin ünvanını yoxlayır.


    Nəticə

    Java-da String və StringBuilder hər biri fərqli hallarda istifadə edilməlidir:

    • String: dəyişməzdir, oxunaqlıdır, lakin performansı zəif ola bilər.
    • StringBuilder: dəyişkəndir, sürətlidir və string manipulyasiyası üçün idealdır.

    Sadə və az dəyişən mətni saxlamaq üçün String, lakin çoxlu dəyişiklik edilən mətnlər üçün StringBuilder seçmək daha düzgündür.

    Java string stringbuilder java

  • Shadow DOM və Virtual DOM nədir?
    codexC codex

    Modern veb inkişafında iki vacib anlayış tez-tez qarşımıza çıxır: Shadow DOM və Virtual DOM. Bunlar fərqli məqsədlərə xidmət etsələr də, hər ikisi istifadəçi interfeyslərinin effektiv və strukturlaşdırılmış şəkildə yaradılması üçün istifadə olunur. Bu məqalədə bu iki anlayışı sadə dillə izah edəcəyik və aralarındakı fərqləri göstərəcəyik.


    DOM nədir? (Qısa xatırlatma)

    DOM (Document Object Model) – HTML sənədinin JavaScript ilə idarə olunan obyekt formasında təqdim olunmasıdır. DOM vasitəsilə biz səhifədəki elementləri oxuya və dəyişə bilirik.

    Məsələn:

    document.querySelector("h1").textContent = "Salam, dünya!";
    

    Bu əmrlə h1 başlığının məzmununu dəyişirik.


    1. Shadow DOM nədir?

    Shadow DOM – DOM-un xüsusi bir hissəsidir ki, digər DOM elementlərindən izolyasiya olunmuşdur. Başqa sözlə, bu DOM strukturunda olan stil və ya funksiyalar əsas DOM-a təsir etməz və əsas DOM da ona təsir edə bilməz.

    Harada istifadə olunur?

    Shadow DOM əsasən Web Components texnologiyasının bir hissəsidir. Məsələn, siz öz my-button komponentinizi yaradırsınız və istəmirsiniz ki, başqa CSS qaydaları bu komponentin içini pozsun. O zaman Shadow DOM köməyə gəlir.

    Nümunə:

    <my-button></my-button>
    
    <script>
      class MyButton extends HTMLElement {
        constructor() {
          super();
          const shadow = this.attachShadow({ mode: "open" });
          shadow.innerHTML = `
            <style>
              button { background: red; color: white; }
            </style>
            <button>Click me</button>
          `;
        }
      }
    
      customElements.define("my-button", MyButton);
    </script>
    

    Üstünlükləri:

    • Stil və struktur tam izolyasiyalıdır.
    • Kapsullaşma (encapsulation) verir.
    • Yenidən istifadə edilə bilən komponentlər yaratmaq mümkün olur.

    2. Virtual DOM nədir?

    Virtual DOM – brauzerin real DOM-u ilə birbaşa işləmək əvəzinə, onun yaddaşda olan (virtual) surəti ilə işləmək metodudur. Bu texnika əsasən React, Vue kimi kitabxanalarda istifadə olunur.

    Niyə lazımdır?

    Real DOM ilə birbaşa işləmək çox yavaşdır, çünki hər dəyişiklik brauzerin render prosesini işə salır. Virtual DOM isə dəyişiklikləri əvvəlcə yaddaşda simulyasiya edir, sonra isə ən optimal formada real DOM-u yeniləyir.

    Necə işləyir?

    1. Komponentdə dəyişiklik olur.
    2. Virtual DOM-da yeni vəziyyət yaranır.
    3. Virtual DOM köhnə və yeni halı müqayisə edir (diffing).
    4. Yalnız dəyişən hissələr real DOM-a tətbiq olunur (reconciliation).

    Nümunə (React kontekstində):

    function App() {
      const [count, setCount] = useState(0);
    
      return (
        <div>
          <p>Sayaç: {count}</p>
          <button onClick={() => setCount(count + 1)}>Artır</button>
        </div>
      );
    }
    

    Bu halda React virtual DOM üzərində dəyişiklikləri hesablayır və yalnız p elementinin içini yeniləyir.


    Shadow DOM vs Virtual DOM

    Özəllik Shadow DOM Virtual DOM
    Texnologiya Web Components React, Vue və b. UI kitabxanaları
    Məqsəd Stil və DOM kapsullaşması Performansı artırmaq üçün DOM diffing
    Brauzer dəstəyi Native (birbaşa dəstəklənir) Kitabxana səviyyəsində tətbiq olunur
    Əlaqə Real DOM-un bir hissəsidir Real DOM-un surətidir (yaddaşda)
    Qapsama Bəli (izolyasiya olunmuşdur) Xeyr (ümumi DOM strukturunu təqlid edir)

    Hansı zaman hansından istifadə etməli?

    Ssenari Tövsiyə
    Öz komponentinizi hazırlayırsınız və stil qarışıqlığının qarşısını almaq istəyirsiniz Shadow DOM
    İnteraktiv və tez dəyişən istifadəçi interfeysi qurursunuz Virtual DOM (React, Vue və s.)
    Bütün brauzerlərdə işləməli universal komponentlər istəyirsiniz Shadow DOM-un dəstəyini yoxlayın və ya polyfill istifadə edin

    Nəticə

    Shadow DOM və Virtual DOM – hər ikisi veb inkişafında güclü texnologiyalardır. Shadow DOM daha çox komponent səviyyəsində təhlükəsizliyi və izolyasiyanı təmin edir. Virtual DOM isə performansı artıraraq böyük və interaktiv tətbiqlərin daha səmərəli işləməsinə şərait yaradır.

    Əgər Web Components ilə maraqlanırsınızsa – Shadow DOM öyrənməyə dəyər. Əgər React və ya Vue istifadə edirsinizsə – artıq Virtual DOM ilə işləyirsiniz!

    Front-end

  • package.json faylına ətraflı baxış
    codexC codex

    Node.js layihələri ilə işləyərkən ən önəmli fayllardan biri package.json faylıdır. Bu fayl layihə haqqında bütün əsas məlumatları, istifadə olunan asılılıqları (paketləri), skriptləri və digər konfiqurasiyaları ehtiva edir. Bir sözlə, layihənin idarəetmə mərkəzidir.

    1. Əsas sahələr

    name

    Layihənin adıdır. Kiçik hərflərlə yazılmalı və boşluq əvəzinə - (kəsik xətt) istifadə edilməlidir.

    "name": "my-first-app"
    

    version

    Layihənin versiyası. Bu versiya SemVer (Semantic Versioning) standartına əsaslanır: MAJOR.MINOR.PATCH (məs: 1.2.3)

    "version": "1.0.0"
    

    description

    Layihənin qısa izahı.

    "description": "Node.js ilə hazırlanmış API tətbiqi"
    

    main

    Node.js tərəfindən layihənin əsas giriş faylı kimi istifadə edilən yol.

    "main": "index.js"
    

    scripts

    Terminalda npm run əmri ilə işlədilə bilən skriptlər. Layihənin işə düşməsi, test olunması və s. bu sahədə qeyd olunur.

    "scripts": {
      "start": "node index.js",
      "dev": "nodemon index.js",
      "test": "jest"
    }
    

    keywords

    Layihənin axtarışda tapılması üçün açar sözlər siyahısıdır.

    "keywords": ["nodejs", "api", "express"]
    

    author və contributors

    Layihəni hazırlayan və ya ona töhfə verən şəxslərin siyahısı.

    "author": "Elvin Huseynov",
    "contributors": [
      {
        "name": "Aygün Məmmədova",
        "email": "aygun@example.com"
      }
    ]
    

    license

    Layihənin hüquqi istifadəsini müəyyən edən lisenziya tipi (məs: MIT, ISC, GPL-3.0 və s.)

    "license": "MIT"
    

    2. Asılılıqlar (Dependencies)

    Node.js layihələrində istifadə etdiyimiz kitabxanalar 3 əsas qrupa bölünür:

    dependencies

    Layihənin işləməsi üçün zəruri olan əsas paketlər.

    "dependencies": {
      "express": "^4.18.2",
      "mongoose": "~6.12.1"
    }
    

    devDependencies

    Yalnız inkişaf zamanı lazım olan paketlər – məsələn, test alətləri, linters, bundlers və s.

    "devDependencies": {
      "jest": "^29.7.0",
      "nodemon": "^3.0.1"
    }
    

    peerDependencies

    Bu sahədəki paketlər layihəyə daxil edilmir. Əsasən plugin və ya kitabxananın müəyyən versiya ilə işləməsini tələb edir.

    "peerDependencies": {
      "react": ">=17.0.0"
    }
    

    optionalDependencies

    Quraşdırılsa yaxşı olar, amma olmadan da işləyən paketlər. Quraşdırılarkən səhv olarsa, proses dayanmaz.

    "optionalDependencies": {
      "fsevents": "^2.3.2"
    }
    

    3. Versiya simvollarının mənası

    Versiya nömrələrinin əvvəlində olan bəzi simvollar var ki, onlar versiyanın necə seçildiyini göstərir:

    Simvol Mənası
    ^ Eyni əsas versiya daxilində olan ən son versiyanı qəbul et (default)
    ~ Eyni minor versiya daxilində ən son patch versiyanı qəbul et
    * Hər hansı versiyanı qəbul et
    >= Göstərilən versiyadan daha yuxarı olan versiyaları qəbul et
    <, <= Müvafiq olaraq daha kiçik və ya kiçik bərabər versiyaları göstər
    1.2.x 1.2.0 – 1.2.99 aralığında olan versiyalar

    Nümunə:

    "lodash": "^4.17.0"
    

    Bu halda, 4.17.0-dan başlayaraq 4.x.x aralığında olan ən son versiya quraşdırıla bilər, lakin 5.x.x yox.


    4. Digər faydalı sahələr

    engines

    Layihənin işləməsi üçün lazım olan Node.js və npm versiyasını göstərir.

    "engines": {
      "node": ">=16.0.0",
      "npm": ">=8.0.0"
    }
    

    type

    Modul sistemini təyin edir: "module" (ESM) və ya "commonjs".

    "type": "module"
    

    files

    Layihə npm publish ilə paylaşılarkən daxil ediləcək faylları göstərir.

    "files": ["dist/", "index.js"]
    

    private

    Layihənin səhvən npm publish ilə yayımlanmasının qarşısını alır.

    "private": true
    

    5. Tam package.json nümunəsi

    {
      "name": "codex-api",
      "version": "1.0.0",
      "description": "CodeX üçün REST API backend tətbiqi",
      "main": "server.js",
      "scripts": {
        "start": "node server.js",
        "dev": "nodemon server.js",
        "test": "jest"
      },
      "keywords": ["nodejs", "api", "backend"],
      "author": "Elvin Huseynov",
      "license": "MIT",
      "dependencies": {
        "express": "^4.18.2",
        "mongoose": "~6.12.1"
      },
      "devDependencies": {
        "jest": "^29.7.0",
        "nodemon": "^3.0.1"
      },
      "engines": {
        "node": ">=16.0.0"
      },
      "private": true
    }
    

    Nəticə

    package.json – yalnız texniki fayl deyil, sizin layihənizin struktur kitabçasıdır. Onu düzgün qurmaq, həm layihənin idarə olunmasını asanlaşdırır, həm də digərlərinin onu rahat şəkildə başa düşməsini təmin edir. Versiya simvollarının mənasını anlamaq isə asılılıqların stabil və təhlükəsiz olmasında mühüm rol oynayır.

    Qarışıq mövzular npm package nodejs

Üzv siyahısı

codexC codex
  • Daxil ol

  • Sizin hesabınız yoxdur? Qeydiyyatdan keç

  • Axtarış etmək üçün daxil olun və ya qeydiyyatdan keçin.
  • İlk yazı
    Son yazı
0
  • Kateqoriyalar
  • Ən yeni
  • Teqlər
  • Populyar