Prinsip SOLID untuk JavaScript
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; } }
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; } }
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) } }
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; } }
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) } }
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; } }
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) } }
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));
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));
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; } }
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) } }
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));
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));
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; } }
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.
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!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas











JavaScript adalah asas kepada pembangunan web moden, dan fungsi utamanya termasuk pengaturcaraan yang didorong oleh peristiwa, penjanaan kandungan dinamik dan pengaturcaraan tak segerak. 1) Pengaturcaraan yang didorong oleh peristiwa membolehkan laman web berubah secara dinamik mengikut operasi pengguna. 2) Penjanaan kandungan dinamik membolehkan kandungan halaman diselaraskan mengikut syarat. 3) Pengaturcaraan Asynchronous memastikan bahawa antara muka pengguna tidak disekat. JavaScript digunakan secara meluas dalam interaksi web, aplikasi satu halaman dan pembangunan sisi pelayan, sangat meningkatkan fleksibiliti pengalaman pengguna dan pembangunan silang platform.

Trend terkini dalam JavaScript termasuk kebangkitan TypeScript, populariti kerangka dan perpustakaan moden, dan penerapan webassembly. Prospek masa depan meliputi sistem jenis yang lebih berkuasa, pembangunan JavaScript, pengembangan kecerdasan buatan dan pembelajaran mesin, dan potensi pengkomputeran IoT dan kelebihan.

Enjin JavaScript yang berbeza mempunyai kesan yang berbeza apabila menguraikan dan melaksanakan kod JavaScript, kerana prinsip pelaksanaan dan strategi pengoptimuman setiap enjin berbeza. 1. Analisis leksikal: Menukar kod sumber ke dalam unit leksikal. 2. Analisis Tatabahasa: Menjana pokok sintaks abstrak. 3. Pengoptimuman dan Penyusunan: Menjana kod mesin melalui pengkompil JIT. 4. Jalankan: Jalankan kod mesin. Enjin V8 mengoptimumkan melalui kompilasi segera dan kelas tersembunyi, Spidermonkey menggunakan sistem kesimpulan jenis, menghasilkan prestasi prestasi yang berbeza pada kod yang sama.

Python lebih sesuai untuk pemula, dengan lengkung pembelajaran yang lancar dan sintaks ringkas; JavaScript sesuai untuk pembangunan front-end, dengan lengkung pembelajaran yang curam dan sintaks yang fleksibel. 1. Sintaks Python adalah intuitif dan sesuai untuk sains data dan pembangunan back-end. 2. JavaScript adalah fleksibel dan digunakan secara meluas dalam pengaturcaraan depan dan pelayan.

JavaScript adalah bahasa utama pembangunan web moden dan digunakan secara meluas untuk kepelbagaian dan fleksibiliti. 1) Pembangunan front-end: Membina laman web dinamik dan aplikasi satu halaman melalui operasi DOM dan kerangka moden (seperti React, Vue.js, sudut). 2) Pembangunan sisi pelayan: Node.js menggunakan model I/O yang tidak menyekat untuk mengendalikan aplikasi konkurensi tinggi dan masa nyata. 3) Pembangunan aplikasi mudah alih dan desktop: Pembangunan silang platform direalisasikan melalui reaktnatif dan elektron untuk meningkatkan kecekapan pembangunan.

Artikel ini menunjukkan integrasi frontend dengan backend yang dijamin oleh permit, membina aplikasi edtech SaaS yang berfungsi menggunakan Next.Js. Frontend mengambil kebenaran pengguna untuk mengawal penglihatan UI dan memastikan permintaan API mematuhi dasar peranan

Saya membina aplikasi SaaS multi-penyewa berfungsi (aplikasi edTech) dengan alat teknologi harian anda dan anda boleh melakukan perkara yang sama. Pertama, apakah aplikasi SaaS multi-penyewa? Aplikasi SaaS Multi-penyewa membolehkan anda melayani beberapa pelanggan dari Sing

Peralihan dari C/C ke JavaScript memerlukan menyesuaikan diri dengan menaip dinamik, pengumpulan sampah dan pengaturcaraan asynchronous. 1) C/C adalah bahasa yang ditaip secara statik yang memerlukan pengurusan memori manual, manakala JavaScript ditaip secara dinamik dan pengumpulan sampah diproses secara automatik. 2) C/C perlu dikumpulkan ke dalam kod mesin, manakala JavaScript adalah bahasa yang ditafsirkan. 3) JavaScript memperkenalkan konsep seperti penutupan, rantaian prototaip dan janji, yang meningkatkan keupayaan pengaturcaraan fleksibiliti dan asynchronous.
