Kata pengantar
Dalam bab ini, kita akan menjelaskan bab kelima dari implementasi lima prinsip utama bahasa JavaScript yang solid, yang merupakan LSP (prinsip inversi ketergantungan).
Teks Bahasa Inggris Asli: http://freshbrewedcode.com/derekgreeer/2012/01/22/solid-javascript-the-dependency-inversion-principle/
Prinsip Reliance Inversion
Deskripsi prinsip inversi ketergantungan adalah:
A. Modul tingkat tinggi tidak boleh bergantung pada modul tingkat rendah. Keduanya harus bergantung pada abstraksi.
Modul tingkat tinggi tidak boleh bergantung pada modul tingkat rendah, keduanya harus bergantung pada abstraksi
B. Abstraksi tidak boleh bergantung pada detail. Detail harus tergantung pada abstraksi.
Abstrak seharusnya tidak bergantung pada detail, detail harus tergantung pada abstraksi
Masalah yang paling penting dengan prinsip inversi ketergantungan adalah untuk memastikan bahwa komponen utama aplikasi atau kerangka kerja dipisahkan dari rincian implementasi komponen yang mendasari non-penting, yang akan memastikan bahwa bagian terpenting dari program tidak dipengaruhi oleh perubahan dan modifikasi komponen tingkat rendah.
Bagian pertama dari prinsip ini adalah tentang penggabungan antara modul tingkat tinggi dan modul tingkat rendah. Dalam arsitektur divisi tradisional, modul tingkat tinggi (merangkum logika bisnis inti dari program ini) selalu bergantung pada beberapa modul tingkat rendah (beberapa poin dasar). Ketika prinsip inversi ketergantungan diterapkan, hubungan terbalik. Tidak seperti modul tingkat tinggi yang mengandalkan modul tingkat rendah, inversi ketergantungan membuat modul tingkat rendah bergantung pada antarmuka yang didefinisikan dalam modul tingkat tinggi. Misalnya, jika Anda ingin bertahan data untuk suatu program, desain tradisional adalah bahwa modul inti tergantung pada API modul persisten. Setelah rekonstruksi sesuai dengan prinsip inversi ketergantungan, modul inti perlu menentukan antarmuka API yang persisten, dan kemudian instance implementasi persisten perlu mengimplementasikan antarmuka API yang ditentukan oleh modul inti.
Bagian kedua dari prinsip ini menjelaskan hubungan yang benar antara abstraksi dan detail. Memahami bagian ini lebih bermanfaat dengan memahami bahasa C ++ karena penerapannya lebih jelas.
Tidak seperti beberapa bahasa yang diketik secara statis, C ++ tidak memberikan konsep tingkat bahasa untuk mendefinisikan antarmuka. Apa hubungan antara definisi kelas dan implementasi kelas? Dalam C ++, kelas didefinisikan dalam bentuk file header, yang menentukan metode dan variabel anggota kelas yang perlu diimplementasikan oleh file sumber. Karena semua variabel dan metode pribadi didefinisikan dalam file header, mereka dapat digunakan untuk abstrak dan memisahkannya sebelum detail implementasi. Konsep antarmuka diimplementasikan dengan mendefinisikan hanya metode abstrak (kelas dasar abstrak dalam C ++) digunakan untuk mengimplementasikan kelas.
Dip dan JavaScript
Karena JavaScript adalah bahasa yang dinamis, tidak perlu abstrak untuk decoupling. Oleh karena itu, abstraksi tidak boleh bergantung pada detail. Perubahan ini tidak memiliki banyak dampak dalam JavaScript, tetapi modul tingkat tinggi tidak boleh bergantung pada modul tingkat rendah tetapi memiliki dampak besar.
Ketika membahas prinsip inversi ketergantungan dalam konteks bahasa yang diketik secara statis, konsep kopling termasuk semantik dan fisik. Ini berarti bahwa jika modul tingkat tinggi tergantung pada modul tingkat rendah, ia tidak hanya memasangkan antarmuka semantik, tetapi juga antarmuka fisik yang ditentukan dalam modul yang mendasarinya. Dengan kata lain, modul tingkat tinggi tidak hanya harus dipisahkan dari perpustakaan pihak ketiga, tetapi juga dari modul tingkat rendah asli.
Untuk menjelaskan hal ini, bayangkan bahwa program .NET mungkin berisi modul tingkat tinggi yang sangat berguna yang bergantung pada modul persisten tingkat rendah. Ketika penulis perlu menambahkan antarmuka yang sama ke API kegigihan, terlepas dari apakah prinsip inversi ketergantungan digunakan atau tidak, modul tingkat tinggi tidak dapat digunakan kembali dalam program lain sebelum mengimplementasikan kembali antarmuka baru dari modul tingkat rendah ini.
Dalam JavaScript, penerapan prinsip inversi ketergantungan terbatas pada kopling semantik antara modul tingkat tinggi dan modul tingkat rendah. Misalnya, DIP dapat menambahkan antarmuka sesuai kebutuhan alih-alih menggabungkan antarmuka implisit yang ditentukan oleh modul tingkat rendah.
Untuk memahami ini, mari kita lihat contoh berikut:
Salinan kode adalah sebagai berikut:
$ .fn.trackmap = fungsi (opsi) {
var default = {
/ * default */
};
options = $ .ExtEnd ({}, default, opsi);
var mapoptions = {
Pusat: google.maps.latlng baru (option.latitude, options.longitude),
Zoom: 12,
maptypeId: google.maps.maptypeid.roadmap
},
peta = google.maps.map baru (ini [0], mapoptions),
pos = google.maps.latlng baru (options.latitude, options.longitude);
var marker = google.maps.marker baru ({
Posisi: pos,
Judul: Options.Title,
Ikon: Options.icon
});
marker.setMap (peta);
options.feed.update (function (latitude, bujur) {
marker.setMap (null);
var newlatlng = google.maps.latlng baru (latitude, bujur);
marker.position = newlatlng;
marker.setMap (peta);
peta.setCenter (newlatlng);
});
kembalikan ini;
};
var updater = (function () {
// Properti Pribadi
kembali {
UPDATE: function (callback) {
UpdateMap = Callback;
}
};
}) ();
$ ("#MAP_CANVAS"). TrackMap ({
Latitude: 35.044640193770725,
Longitude: -89.98193264007568,
Ikon: 'http://bit.ly/zjngde',
Judul: 'Nomor Pelacakan: 12345',
Feed: Updater
});
Dalam kode di atas, ada perpustakaan kelas JS kecil yang mengubah div menjadi peta untuk menampilkan informasi lokasi yang saat ini dilacak. Fungsi TrackMap memiliki 2 dependensi: API Google Maps pihak ketiga dan umpan lokasi. Tanggung jawab objek pakan adalah memanggil panggilan balik panggilan balik (disediakan pada inisialisasi) ketika posisi ikon diperbarui dan lulus dalam garis lintang lintang dan bujur presisi. API Google Maps digunakan untuk membuat antarmuka.
Antarmuka objek umpan dapat didasarkan pada instalasi atau tidak dirancang sesuai dengan persyaratan fungsi trackmap instalasi. Faktanya, perannya sangat sederhana, berfokus pada implementasi yang berbeda dan tidak perlu mengandalkan banyak pada peta Google. Semantik TrackMap digabungkan ke Google Maps API. Jika Anda perlu beralih ke penyedia peta yang berbeda, Anda harus menulis ulang fungsi trackmap sehingga dapat beradaptasi dengan penyedia yang berbeda.
Untuk membalik kopling semantik dari perpustakaan kelas Google Maps, kita perlu menulis ulang fungsi trackmap desain ke kopling semantik antarmuka implisit (abstrak antarmuka penyedia penyedia peta). Kami juga membutuhkan objek implementasi yang disesuaikan dengan API Google Maps. Berikut ini adalah fungsi trackmap refactored:
Salinan kode adalah sebagai berikut:
$ .fn.trackmap = fungsi (opsi) {
var default = {
/ * default */
};
options = $ .ExtEnd ({}, default, opsi);
options.provider.showmap (
ini [0],
opsi.latitude,
opsi.
opsi.icon,
opsi.title);
options.feed.update (function (latitude, bujur) {
options.provider.updatemap (latitude, bujur);
});
kembalikan ini;
};
$ ("#MAP_CANVAS"). TrackMap ({
Latitude: 35.044640193770725,
Longitude: -89.98193264007568,
Ikon: 'http://bit.ly/zjngde',
Judul: 'Nomor Pelacakan: 12345',
Feed: Updater,
Penyedia: trackmap.googlemapsprovider
});
Dalam versi ini, kami mendesain ulang fungsi TrackMap dan antarmuka penyedia peta yang diperlukan, dan kemudian memindahkan detail implementasi ke komponen GoogleMapsProvider terpisah, yang dapat secara independen dienkapsulasi ke dalam modul JavaScript terpisah. Berikut adalah implementasi googlemapsprovider saya:
Salinan kode adalah sebagai berikut:
trackmap.googlemapsprovider = (function () {
var marker, peta;
kembali {
showmap: function (elemen, lintang, bujur, ikon, judul) {
var mapoptions = {
Pusat: Google.maps.latlng baru (lintang, bujur),
Zoom: 12,
maptypeId: google.maps.maptypeid.roadmap
},
POS = google.maps.latlng (latitude, bujur) baru;
peta = google.maps.map baru (elemen, mapoptions);
marker = google.maps.marker baru ({
Posisi: pos,
Judul: Judul,
Ikon: Ikon
});
marker.setMap (peta);
},
UpdateMap: function (latitude, longitude) {
marker.setMap (null);
var newlatlng = google.maps.latlng baru (latitude, bujur);
marker.position = newlatlng;
marker.setMap (peta);
peta.setCenter (newlatlng);
}
};
}) ();
Setelah melakukan perubahan di atas, fungsi trackmap akan menjadi sangat fleksibel dan tidak harus bergantung pada API Google Maps. Sebaliknya, penyedia peta lainnya dapat diganti sesuka hati, yaitu, penyedia peta apa pun dapat disesuaikan sesuai dengan kebutuhan program.
Kapan suntikan ketergantungan?
Ini agak tidak terkait. Faktanya, konsep injeksi ketergantungan sering dicampur dengan prinsip inversi ketergantungan. Untuk mengklarifikasi perbedaan ini, perlu menjelaskan:
Injeksi ketergantungan adalah bentuk khusus dari inversi kontrol, dan inversi berarti bagaimana komponen memperoleh ketergantungannya. Injeksi ketergantungan berarti: Ketergantungan disediakan ke komponen, daripada komponen untuk mendapatkan ketergantungan, yang berarti membuat instance dari ketergantungan, meminta ketergantungan melalui pabrik, dan meminta ketergantungan melalui pencari lokasi layanan atau komponen itu sendiri. Prinsip inversi ketergantungan dan injeksi ketergantungan keduanya difokuskan pada ketergantungan dan keduanya digunakan untuk inversi. Namun, prinsip inversi ketergantungan tidak fokus pada bagaimana komponen memperoleh ketergantungan, tetapi hanya pada bagaimana modul tingkat tinggi dipisahkan dari modul tingkat rendah. Dalam arti tertentu, prinsip inversi ketergantungan adalah bentuk lain dari inversi kontrol. Di sini, inversi adalah modul mana yang mendefinisikan antarmuka (didefinisikan dari level yang lebih rendah, inversi ke tingkat yang lebih tinggi).
Meringkaskan
Ini adalah artikel terakhir dari lima prinsip utama. Dalam 5 artikel ini, kami melihat seberapa solid diimplementasikan dalam JavaScript. Prinsip yang berbeda dijelaskan dari sudut yang berbeda dalam JavaScript. (Paman Catatan: Faktanya, saya pikir meskipun agak tidak pantas, dari perspektif lain, prinsip -prinsip umum sebenarnya sama dalam berbagai bahasa.)