Rumah > hujung hadapan web > tutorial js > Prinsip SOLID untuk JavaScript

Prinsip SOLID untuk JavaScript

Linda Hamilton
Lepaskan: 2024-12-28 19:34:11
asal
329 orang telah melayarinya

Pengenalan paradigma OOP mempopularkan konsep pengaturcaraan utama seperti Warisan, Polimorfisme, Abstraksi dan Enkapsulasi. OOP dengan cepat menjadi paradigma pengaturcaraan yang diterima secara meluas dengan pelaksanaan dalam beberapa bahasa seperti Java, C , C#, JavaScript dan banyak lagi. Sistem OOP menjadi lebih kompleks dari semasa ke semasa, tetapi perisiannya kekal tahan terhadap perubahan. Untuk meningkatkan kebolehlanjutan perisian dan mengurangkan ketegaran kod, Robert C. Martin (a.k.a Uncle Bob) memperkenalkan prinsip SOLID pada awal 2000-an.

SOLID ialah akronim yang terdiri daripada satu set prinsip — prinsip tanggungjawab tunggal, prinsip tertutup terbuka, prinsip penggantian Liskov, prinsip pengasingan antara muka dan prinsip penyongsangan kebergantungan — yang membantu jurutera perisian mereka bentuk dan menulis boleh diselenggara, berskala dan fleksibel kod. Matlamatnya? Untuk meningkatkan kualiti perisian yang dibangunkan mengikut paradigma Pengaturcaraan Berorientasikan Objek (OOP).

Dalam artikel ini, kami akan menyelidiki semua prinsip SOLID dan menggambarkan cara ia dilaksanakan menggunakan salah satu bahasa pengaturcaraan web yang paling popular, JavaScript.

Prinsip Tanggungjawab Tunggal (SRP)

Huruf pertama dalam SOLID mewakili prinsip tanggungjawab tunggal. Prinsip ini mencadangkan bahawa kelas atau modul harus melaksanakan hanya satu peranan.

Ringkasnya, kelas harus mempunyai satu tanggungjawab atau satu sebab untuk berubah. Jika kelas mengendalikan lebih daripada satu fungsi, mengemas kini satu fungsi tanpa menjejaskan yang lain menjadi rumit. Komplikasi seterusnya boleh mengakibatkan kerosakan dalam prestasi perisian. Untuk mengelakkan masalah seperti ini, kita harus melakukan yang terbaik untuk menulis perisian modular di mana kebimbangan diasingkan.

Jika kelas mempunyai terlalu banyak tanggungjawab atau fungsi, ia menjadi sakit kepala untuk mengubah suai. Dengan menggunakan prinsip tanggungjawab tunggal, kita boleh menulis kod yang modular, lebih mudah diselenggara dan kurang terdedah kepada ralat. Ambil, sebagai contoh, model seseorang:

class Person {
    constructor(name, age, height, country){
      this.name = name
      this.age = age
      this.height = height
      this.country = country
  }
  getPersonCountry(){
    console.log(this.country)    
  }
  greetPerson(){
    console.log("Hi " + this.name)
  }
  static calculateAge(dob) { 
    const today = new Date(); 
    const birthDate = new Date(dob);

    let age = today.getFullYear() - birthDate.getFullYear(); 
    const monthDiff = today.getMonth() - birthDate.getMonth();

    if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) { 
      age--; 
    }
    return age; 
  } 
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Kod di atas nampaknya baik, bukan? Tidak cukup. Kod sampel melanggar prinsip tanggungjawab tunggal. Daripada menjadi satu-satunya model dari mana contoh Orang lain boleh dibuat, kelas Orang juga mempunyai tanggungjawab lain seperti kalkulasiAge, greetPerson dan getPersonCountry.

Tanggungjawab tambahan yang dikendalikan oleh kelas Person ini menyukarkan untuk menukar hanya satu aspek kod. Contohnya, jika anda cuba memfaktorkan semula calculateAge, anda mungkin juga terpaksa memfaktorkan semula model Person. Bergantung pada seberapa padat dan kompleks asas kod kami, mungkin sukar untuk mengkonfigurasi semula kod tanpa menyebabkan ralat.

Mari cuba dan semak semula kesilapan itu. Kita boleh memisahkan tanggungjawab ke dalam kelas yang berbeza, seperti:

class Person {
    constructor(name, age, height, country){
      this.name = name
      this.age = age
      this.height = height
      this.country = country
  }
  getPersonCountry(){
    console.log(this.country)    
  }
  greetPerson(){
    console.log("Hi " + this.name)
  }
  static calculateAge(dob) { 
    const today = new Date(); 
    const birthDate = new Date(dob);

    let age = today.getFullYear() - birthDate.getFullYear(); 
    const monthDiff = today.getMonth() - birthDate.getMonth();

    if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) { 
      age--; 
    }
    return age; 
  } 
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Seperti yang anda boleh lihat daripada kod sampel di atas, kami telah mengasingkan tanggungjawab kami. Kelas Orang kini merupakan model yang dengannya kita boleh mencipta objek orang baharu. Dan kelas PersonUtils hanya mempunyai satu tanggungjawab — untuk mengira umur seseorang. Kelas PersonService mengendalikan ucapan dan menunjukkan kepada kita negara setiap orang.

Jika kita mahu, kita masih boleh mengurangkan lagi proses ini. Berikutan SRP, kami ingin memisahkan tanggungjawab kelas ke tahap minimum supaya apabila terdapat isu, pemfaktoran semula dan penyahpepijatan boleh dilakukan tanpa banyak kerumitan.

Dengan membahagikan fungsi kepada kelas yang berasingan, kami mematuhi prinsip tanggungjawab tunggal dan memastikan setiap kelas bertanggungjawab untuk aspek khusus aplikasi.

Sebelum kita beralih ke prinsip seterusnya, perlu diingatkan bahawa mematuhi SRP tidak bermakna setiap kelas harus tegas mengandungi satu kaedah atau fungsi.

Walau bagaimanapun, mematuhi prinsip tanggungjawab tunggal bermakna kita harus bersungguh-sungguh dalam memberikan fungsi kepada kelas. Segala sesuatu yang dijalankan oleh kelas haruslah berkait rapat dalam setiap segi. Kita mesti berhati-hati agar tidak mempunyai beberapa kelas berselerak di merata-rata tempat, dan kita harus, dengan segala cara, mengelakkan kelas yang membuak-buak dalam pangkalan kod kita.

Prinsip Terbuka-Tertutup (OCP)

Prinsip buka-tutup menyatakan bahawa komponen perisian (kelas, fungsi, modul, dll.) harus terbuka kepada sambungan dan tertutup kepada pengubahsuaian. Saya tahu apa yang anda fikirkan — ya, idea ini mungkin kelihatan bercanggah pada mulanya. Tetapi OCP hanya meminta perisian itu direka bentuk dengan cara yang membolehkan sambungan tanpa perlu mengubah suai kod sumber.

OCP adalah penting untuk mengekalkan pangkalan kod yang besar, kerana garis panduan ini membolehkan anda memperkenalkan ciri baharu dengan sedikit atau tiada risiko melanggar kod. Daripada mengubah suai kelas atau modul sedia ada apabila keperluan baharu timbul, anda harus melanjutkan kelas yang berkaitan dengan menambah komponen baharu. Semasa anda melakukan ini, pastikan anda menyemak bahawa komponen baharu tidak memperkenalkan sebarang pepijat kepada sistem.

Prinsip OC boleh dicapai dalam JavaScript menggunakan ciri Warisan kelas ES6.

Coretan kod berikut menggambarkan cara melaksanakan prinsip Terbuka-Tutup dalam JavaScript, menggunakan kata kunci kelas ES6 yang disebutkan di atas:

class Person {
    constructor(name, dateOfBirth, height, country){
      this.name = name
      this.dateOfBirth = dateOfBirth
      this.height = height
      this.country = country
  }
}

class PersonUtils {
  static calculateAge(dob) { 
    const today = new Date(); 
    const birthDate = new Date(dob);

    let age = today.getFullYear() - birthDate.getFullYear(); 
    const monthDiff = today.getMonth() - birthDate.getMonth();

    if(monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) { 
      age--; 
    }
    return age; 
  } 
}

const person = new Person("John", new Date(1994, 11, 23), "6ft", "USA"); 
console.log("Age: " + PersonUtils.calculateAge(person.dateOfBirth));

class PersonService {
  getPersonCountry(){
    console.log(this.country)    
  }
  greetPerson(){
    console.log("Hi " + this.name)
  }
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Kod di atas berfungsi dengan baik, tetapi ia terhad untuk mengira hanya luas segi empat tepat. Sekarang bayangkan bahawa terdapat keperluan baru untuk mengira. Katakan, sebagai contoh, kita perlu mengira luas bulatan. Kami perlu mengubah suai kelas shapeProcessor untuk memenuhinya. Walau bagaimanapun, mengikut piawaian JavaScript ES6, kami boleh melanjutkan fungsi ini untuk mengambil kira kawasan bentuk baharu tanpa perlu mengubah suai kelas shapeProcessor.

Kita boleh melakukannya seperti itu:

class Person {
    constructor(name, age, height, country){
      this.name = name
      this.age = age
      this.height = height
      this.country = country
  }
  getPersonCountry(){
    console.log(this.country)    
  }
  greetPerson(){
    console.log("Hi " + this.name)
  }
  static calculateAge(dob) { 
    const today = new Date(); 
    const birthDate = new Date(dob);

    let age = today.getFullYear() - birthDate.getFullYear(); 
    const monthDiff = today.getMonth() - birthDate.getMonth();

    if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) { 
      age--; 
    }
    return age; 
  } 
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Dalam coretan kod di atas, kami memperluaskan fungsi kelas Shape dengan menggunakan kata kunci extends. Dalam setiap subkelas, kami mengatasi pelaksanaan kaedah kawasan(). Mengikut prinsip ini, kami boleh menambah lebih banyak bentuk dan kawasan proses tanpa perlu mengubah suai kefungsian kelas ShapeProcessor.

Mengapakah OCP Penting?

  • Kurangkan pepijat: OCP membantu mengelakkan pepijat dalam pangkalan kod yang besar dengan mengelakkan pengubahsuaian sistem.
  • Menggalakkan kebolehsuaian perisian: OCP juga menambah baik kemudahan ciri baharu boleh ditambah pada perisian tanpa memecahkan atau mengubah kod sumber.
  • Menguji ciri baharu: OCP mempromosikan sambungan kod berbanding pengubahsuaian, menjadikannya lebih mudah untuk ciri baharu diuji sebagai satu unit tanpa menjejaskan keseluruhan pangkalan kod.

Prinsip Penggantian Liskov

Prinsip penggantian Liskov menyatakan bahawa objek subkelas seharusnya boleh menggantikan objek superclass tanpa melanggar kod. Mari kita pecahkan cara ia berfungsi dengan contoh: jika L ialah subkelas P, maka objek L harus menggantikan objek P tanpa memecahkan sistem. Ini hanya bermakna bahawa subkelas sepatutnya dapat mengatasi kaedah superclass dengan cara yang tidak memecahkan sistem.

Dalam amalan, prinsip penggantian Liskov memastikan syarat berikut dipatuhi:

  • Subkelas harus mengatasi kaedah kelas induk tanpa melanggar kod
  • Subkelas tidak seharusnya menyimpang daripada tingkah laku kelas induk, bermakna subkelas hanya boleh menambah kefungsian tetapi tidak boleh mengubah atau mengalih keluar kefungsian kelas induk
  • Kod yang berfungsi dengan tika kelas induk harus berfungsi dengan tika subkelas tanpa perlu mengetahui bahawa kelas telah berubah

Sudah tiba masanya untuk menggambarkan prinsip penggantian Liskov dengan sampel kod JavaScript. Lihatlah:

class Person {
    constructor(name, dateOfBirth, height, country){
      this.name = name
      this.dateOfBirth = dateOfBirth
      this.height = height
      this.country = country
  }
}

class PersonUtils {
  static calculateAge(dob) { 
    const today = new Date(); 
    const birthDate = new Date(dob);

    let age = today.getFullYear() - birthDate.getFullYear(); 
    const monthDiff = today.getMonth() - birthDate.getMonth();

    if(monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) { 
      age--; 
    }
    return age; 
  } 
}

const person = new Person("John", new Date(1994, 11, 23), "6ft", "USA"); 
console.log("Age: " + PersonUtils.calculateAge(person.dateOfBirth));

class PersonService {
  getPersonCountry(){
    console.log(this.country)    
  }
  greetPerson(){
    console.log("Hi " + this.name)
  }
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Dalam coretan kod di atas, kami mencipta dua subkelas (Basikal dan Kereta) dan satu superclass (Kenderaan). Untuk tujuan artikel ini, kami melaksanakan satu kaedah (OnEngine) untuk superclass.

Salah satu syarat teras untuk LSP ialah subkelas harus mengatasi kefungsian kelas induk tanpa melanggar kod. Dengan mengingati perkara itu, mari kita lihat bagaimana coretan kod yang baru kita lihat melanggar prinsip penggantian Liskov. Pada hakikatnya, Kereta mempunyai enjin dan boleh menghidupkan enjin tetapi basikal secara teknikalnya tidak mempunyai enjin dan oleh itu tidak boleh menghidupkan enjin. Jadi, Basikal tidak boleh mengatasi kaedah OnEngine dalam kelas Kenderaan tanpa melanggar kod.

Kami kini telah mengenal pasti bahagian kod yang melanggar prinsip penggantian Liskov. Kelas Kereta boleh mengatasi fungsi OnEngine dalam superclass dan melaksanakannya dengan cara yang membezakannya daripada kenderaan lain (seperti kapal terbang, contohnya) dan kod itu tidak akan pecah. Kelas Kereta memenuhi prinsip penggantian Liskov.

Dalam coretan kod di bawah, kami akan menggambarkan cara menstruktur kod agar mematuhi prinsip penggantian Liskov:

class Person {
    constructor(name, age, height, country){
      this.name = name
      this.age = age
      this.height = height
      this.country = country
  }
  getPersonCountry(){
    console.log(this.country)    
  }
  greetPerson(){
    console.log("Hi " + this.name)
  }
  static calculateAge(dob) { 
    const today = new Date(); 
    const birthDate = new Date(dob);

    let age = today.getFullYear() - birthDate.getFullYear(); 
    const monthDiff = today.getMonth() - birthDate.getMonth();

    if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) { 
      age--; 
    }
    return age; 
  } 
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Berikut ialah contoh asas kelas Kenderaan dengan fungsi umum, bergerak. Ia adalah kepercayaan umum bahawa semua kenderaan bergerak; mereka hanya bergerak melalui mekanisme yang berbeza. Salah satu cara kita akan menggambarkan LSP adalah untuk mengatasi kaedah move() dan melaksanakannya dengan cara yang menggambarkan cara kenderaan tertentu, contohnya, Kereta akan bergerak.

Untuk berbuat demikian, kami akan mencipta kelas Kereta yang memanjangkan kelas Kenderaan dan mengatasi kaedah pergerakan agar sesuai dengan pergerakan kereta, seperti:

class Person {
    constructor(name, dateOfBirth, height, country){
      this.name = name
      this.dateOfBirth = dateOfBirth
      this.height = height
      this.country = country
  }
}

class PersonUtils {
  static calculateAge(dob) { 
    const today = new Date(); 
    const birthDate = new Date(dob);

    let age = today.getFullYear() - birthDate.getFullYear(); 
    const monthDiff = today.getMonth() - birthDate.getMonth();

    if(monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) { 
      age--; 
    }
    return age; 
  } 
}

const person = new Person("John", new Date(1994, 11, 23), "6ft", "USA"); 
console.log("Age: " + PersonUtils.calculateAge(person.dateOfBirth));

class PersonService {
  getPersonCountry(){
    console.log(this.country)    
  }
  greetPerson(){
    console.log("Hi " + this.name)
  }
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Kami masih boleh melaksanakan kaedah pergerakan dalam kelas sub-kenderaan lain—contohnya—kapal terbang.

Begini cara kami melakukannya:

class Rectangle { 
  constructor(width, height) {
    this.width = width; 
    this.height = height; 
  } 
  area() { 
  return this.width * this.height; 
  } 
} 

class ShapeProcessor { 
    calculateArea(shape) { 
    if (shape instanceof Rectangle) { 
    return shape.area(); 
    } 
  }
}  
const rectangle = new Rectangle(10, 20); const shapeProcessor = new ShapeProcessor(); console.log(shapeProcessor.calculateArea(rectangle)); 
Salin selepas log masuk
Salin selepas log masuk

Dalam dua contoh di atas, kami menggambarkan konsep utama seperti warisan dan kaedah mengatasi.

N.B: Ciri pengaturcaraan yang membenarkan subkelas melaksanakan kaedah yang telah ditakrifkan dalam kelas induk dipanggil kaedah mengatasi.

Mari lakukan pengemasan dan susun semuanya, seperti:

class Shape {
  area() {
    console.log("Override method area in subclass");
  }
}

class Rectangle extends Shape {
  constructor(width, height) {
    super();
    this.width = width;
    this.height = height;
  }

  area() {
    return this.width * this.height;
  }
}

class Circle extends Shape {
  constructor(radius) {
    super();
    this.radius = radius;
  }

  area() {
    return Math.PI * this.radius * this.radius;
  }
}

class ShapeProcessor {
  calculateArea(shape) {
    return shape.area();
  }
}

const rectangle = new Rectangle(20, 10);
const circle = new Circle(2);
const shapeProcessor = new ShapeProcessor();

console.log(shapeProcessor.calculateArea(rectangle));
console.log(shapeProcessor.calculateArea(circle));
Salin selepas log masuk
Salin selepas log masuk

Kini, kami mempunyai 2 subkelas yang mewarisi dan mengatasi satu fungsi daripada kelas induk dan melaksanakannya mengikut keperluan mereka. Pelaksanaan baharu ini tidak melanggar kod.

Prinsip Pengasingan Antara Muka (ISP)

Prinsip pengasingan antara muka menyatakan bahawa tiada pelanggan harus dipaksa untuk bergantung pada antara muka yang tidak digunakannya. Ia mahu kami mencipta antara muka yang lebih kecil dan lebih khusus yang berkaitan dengan pelanggan tertentu, dan bukannya mempunyai antara muka monolitik yang besar yang memaksa pelanggan melaksanakan kaedah yang mereka tidak perlukan.

Memastikan antara muka kami padat menjadikan asas kod lebih mudah untuk dinyahpepijat, diselenggara, diuji dan dilanjutkan. Tanpa ISP, perubahan dalam satu bahagian antara muka yang besar boleh memaksa perubahan pada bahagian pangkalan kod yang tidak berkaitan, menyebabkan kami menjalankan pemfaktoran semula kod yang dalam kebanyakan kes bergantung pada saiz pangkalan kod boleh menjadi tugas yang sukar.

JavaScript, tidak seperti bahasa pengaturcaraan berasaskan C seperti Java, tidak mempunyai sokongan terbina dalam untuk antara muka. Walau bagaimanapun, terdapat teknik yang antara muka dilaksanakan dalam JavaScript.

Antara muka ialah satu set tandatangan kaedah yang mesti dilaksanakan oleh kelas.

Dalam JavaScript, anda mentakrifkan antara muka sebagai objek dengan nama kaedah dan tandatangan fungsi, seperti:

class Person {
    constructor(name, age, height, country){
      this.name = name
      this.age = age
      this.height = height
      this.country = country
  }
  getPersonCountry(){
    console.log(this.country)    
  }
  greetPerson(){
    console.log("Hi " + this.name)
  }
  static calculateAge(dob) { 
    const today = new Date(); 
    const birthDate = new Date(dob);

    let age = today.getFullYear() - birthDate.getFullYear(); 
    const monthDiff = today.getMonth() - birthDate.getMonth();

    if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) { 
      age--; 
    }
    return age; 
  } 
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Untuk melaksanakan antara muka dalam JavaScript, cipta kelas dan pastikan ia mengandungi kaedah dengan nama dan tandatangan yang sama yang dinyatakan dalam antara muka:

class Person {
    constructor(name, dateOfBirth, height, country){
      this.name = name
      this.dateOfBirth = dateOfBirth
      this.height = height
      this.country = country
  }
}

class PersonUtils {
  static calculateAge(dob) { 
    const today = new Date(); 
    const birthDate = new Date(dob);

    let age = today.getFullYear() - birthDate.getFullYear(); 
    const monthDiff = today.getMonth() - birthDate.getMonth();

    if(monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) { 
      age--; 
    }
    return age; 
  } 
}

const person = new Person("John", new Date(1994, 11, 23), "6ft", "USA"); 
console.log("Age: " + PersonUtils.calculateAge(person.dateOfBirth));

class PersonService {
  getPersonCountry(){
    console.log(this.country)    
  }
  greetPerson(){
    console.log("Hi " + this.name)
  }
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Sekarang kami telah mengetahui cara membuat dan menggunakan antara muka dalam JavaScript. Perkara seterusnya yang perlu kita lakukan ialah menggambarkan cara mengasingkan antara muka dalam JavaScript supaya kita dapat melihat bagaimana semuanya sesuai dan menjadikan kod lebih mudah untuk diselenggara.

Dalam contoh berikut, kami akan menggunakan pencetak untuk menggambarkan prinsip pengasingan antara muka.

Dengan mengandaikan kita mempunyai pencetak, pengimbas dan faks, mari buat antara muka yang mentakrifkan fungsi objek ini:

class Rectangle { 
  constructor(width, height) {
    this.width = width; 
    this.height = height; 
  } 
  area() { 
  return this.width * this.height; 
  } 
} 

class ShapeProcessor { 
    calculateArea(shape) { 
    if (shape instanceof Rectangle) { 
    return shape.area(); 
    } 
  }
}  
const rectangle = new Rectangle(10, 20); const shapeProcessor = new ShapeProcessor(); console.log(shapeProcessor.calculateArea(rectangle)); 
Salin selepas log masuk
Salin selepas log masuk

Dalam kod di atas, kami mencipta senarai antara muka yang diasingkan atau diasingkan daripada mempunyai satu antara muka besar yang mentakrifkan semua fungsi ini. Dengan memecahkan fungsi ini kepada bit yang lebih kecil dan antara muka yang lebih khusus, kami membenarkan pelanggan yang berbeza untuk melaksanakan hanya kaedah yang mereka perlukan dan mengekalkan semua bit lain.

Dalam langkah seterusnya, kami akan mencipta kelas yang melaksanakan antara muka ini. Mengikut prinsip pengasingan antara muka, setiap kelas hanya akan melaksanakan kaedah yang diperlukan.

Jika kita ingin melaksanakan pencetak asas yang hanya boleh mencetak dokumen, kita hanya boleh melaksanakan kaedah print() melalui printerInterface, seperti:

class Shape {
  area() {
    console.log("Override method area in subclass");
  }
}

class Rectangle extends Shape {
  constructor(width, height) {
    super();
    this.width = width;
    this.height = height;
  }

  area() {
    return this.width * this.height;
  }
}

class Circle extends Shape {
  constructor(radius) {
    super();
    this.radius = radius;
  }

  area() {
    return Math.PI * this.radius * this.radius;
  }
}

class ShapeProcessor {
  calculateArea(shape) {
    return shape.area();
  }
}

const rectangle = new Rectangle(20, 10);
const circle = new Circle(2);
const shapeProcessor = new ShapeProcessor();

console.log(shapeProcessor.calculateArea(rectangle));
console.log(shapeProcessor.calculateArea(circle));
Salin selepas log masuk
Salin selepas log masuk

Kelas ini hanya melaksanakan PrinterInterface. Ia tidak melaksanakan kaedah imbasan atau faks. Dengan mengikut prinsip pengasingan antara muka, pelanggan — dalam kes ini, kelas Pencetak — telah mengurangkan kerumitannya dan meningkatkan prestasi perisian.

Prinsip Penyongsangan Ketergantungan (DIP)

Sekarang untuk prinsip terakhir kami: prinsip penyongsangan kebergantungan. Prinsip ini mengatakan bahawa modul peringkat tinggi (logik perniagaan) harus bergantung pada abstraksi dan bukannya bergantung secara langsung pada modul peringkat rendah (konkrit). Ia membantu kami mengurangkan kebergantungan kod dan menawarkan fleksibiliti pembangun untuk mengubah suai dan mengembangkan aplikasi pada tahap yang lebih tinggi tanpa menghadapi komplikasi.

Mengapakah prinsip penyongsangan kebergantungan mengutamakan pengabstrakan berbanding kebergantungan langsung? Ini kerana pengenalan abstraksi mengurangkan potensi kesan perubahan, meningkatkan kebolehujian (mengejek abstraksi dan bukannya pelaksanaan konkrit) dan mencapai tahap fleksibiliti yang lebih tinggi dalam kod anda. Peraturan ini memudahkan untuk melanjutkan komponen perisian melalui pendekatan modular dan juga membantu kami mengubah suai komponen peringkat rendah tanpa menjejaskan logik peringkat tinggi.

Mematuhi DIP menjadikan kod lebih mudah untuk diselenggara, dilanjutkan dan skala, dengan itu menghentikan pepijat yang mungkin berlaku kerana perubahan dalam kod. Ia mengesyorkan agar pembangun menggunakan gandingan longgar dan bukannya gandingan ketat antara kelas. Secara amnya, dengan mengamalkan pemikiran yang mengutamakan abstraksi berbanding kebergantungan langsung, pasukan akan memperoleh ketangkasan untuk menyesuaikan diri dan menambah fungsi baharu atau menukar komponen lama tanpa menyebabkan gangguan riak. Dalam JavaScript, kami dapat melaksanakan DIP menggunakan pendekatan suntikan kebergantungan, seperti:

class Person {
    constructor(name, age, height, country){
      this.name = name
      this.age = age
      this.height = height
      this.country = country
  }
  getPersonCountry(){
    console.log(this.country)    
  }
  greetPerson(){
    console.log("Hi " + this.name)
  }
  static calculateAge(dob) { 
    const today = new Date(); 
    const birthDate = new Date(dob);

    let age = today.getFullYear() - birthDate.getFullYear(); 
    const monthDiff = today.getMonth() - birthDate.getMonth();

    if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) { 
      age--; 
    }
    return age; 
  } 
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Dalam contoh asas di atas, kelas Aplikasi ialah modul peringkat tinggi yang bergantung pada abstraksi pangkalan data. Kami mencipta dua kelas pangkalan data: MySQLDatabase, dan MongoDBDatabase. Pangkalan data ialah modul peringkat rendah dan kejadiannya disuntik ke dalam masa jalan Aplikasi tanpa mengubah suai Aplikasi itu sendiri.

Kesimpulan

Prinsip SOLID ialah blok binaan asas untuk reka bentuk perisian berskala, boleh diselenggara dan teguh. Set prinsip ini membantu pembangun menulis kod yang bersih, modular dan boleh disesuaikan.

Prinsip SOLID menggalakkan kefungsian padu, kebolehlanjutan tanpa pengubahsuaian, penggantian objek, pemisahan antara muka dan pengabstrakan ke atas kebergantungan konkrit. Pastikan anda menyepadukan prinsip SOLID ke dalam kod anda untuk mengelakkan pepijat mendapat semua faedahnya.


LogRocket: Nyahpepijat ralat JavaScript dengan lebih mudah dengan memahami konteks

Kod nyahpepijat sentiasa menjadi tugas yang membosankan. Tetapi semakin anda memahami kesilapan anda, semakin mudah untuk membetulkannya.

LogRocket membolehkan anda memahami ralat ini dengan cara baharu dan unik. Penyelesaian pemantauan bahagian hadapan kami menjejaki penglibatan pengguna dengan bahagian hadapan JavaScript anda untuk memberi anda keupayaan untuk melihat dengan tepat perkara yang dilakukan pengguna yang membawa kepada ralat.

SOLID principles for JavaScript

LogRocket merekodkan log konsol, masa muat halaman, surih tindanan, permintaan/tindak balas rangkaian perlahan dengan badan pengepala, metadata penyemak imbas dan log tersuai. Memahami kesan kod JavaScript anda tidak akan menjadi lebih mudah!

Cuba secara percuma.

Atas ialah kandungan terperinci Prinsip SOLID untuk JavaScript. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan