Ini adalah keputusan desain yang tampaknya muncul cukup banyak: bagaimana melewati konteks melalui metode yang tidak membutuhkannya ke metode yang melakukannya. Apakah ada jawaban yang benar atau tergantung pada konteksnya.
Kode sampel yang membutuhkan solusi
// needs the dependency
function baz(session) {
session('baz');
}
// doesn't care about the dependency
function bar() {
baz();
}
// needs the dependency
function foo(session) {
session('foo')
bar();
}
// creates the dependency
function start() {
let session = new Session();
foo(session);
}
Solusi yang memungkinkan
- threadlocal
- global
- objek konteks
- melewati ketergantungan melalui
- kari baz dan operasikan ke bar dengan dependensi yang ditetapkan sebagai argumen pertama
- injeksi ketergantungan
Contoh di mana muncul
Pemrosesan permintaan HTTP
Objek konteks dalam bentuk atribut permintaan sering digunakan: lihat expressjs, Java Servlets atau .net's owin.
Penebangan
Untuk Java logging rakyat sering menggunakan global / lajang. Lihat pola log4j / commons logging / java logging.
Transaksi
Utas lokal sering digunakan untuk menyimpan transaksi atau sesi yang terkait dengan serangkaian panggilan metode untuk menghindari keharusan meneruskannya sebagai parameter ke semua metode yang tidak membutuhkannya.
design-patterns
Jamie McCrindle
sumber
sumber
Jawaban:
Satu-satunya jawaban yang adil adalah bahwa itu tergantung pada idiom paradigma pemrograman Anda. Jika Anda menggunakan OO, hampir pasti salah untuk meneruskan ketergantungan dari metode ke metode ke metode. Ini bau kode di OO. Bahkan, itulah salah satu masalah yang dipecahkan OO - sebuah objek memperbaiki konteks. Jadi dalam OO, satu pendekatan yang benar (selalu ada cara lain) adalah memberikan ketergantungan melalui kontruktor atau properti. Seorang komentator menyebutkan "Injeksi Ketergantungan" dan itu sah-sah saja, tetapi itu tidak sepenuhnya diperlukan. Berikan saja dependensi sehingga tersedia sebagai anggota untuk
foo
danbaz
.Anda menyebutkan currying, jadi saya akan menganggap pemrograman fungsional tidak keluar dari pertanyaan. Dalam hal itu, ekuivalen filosofis dari konteks objek adalah penutupan. Setiap pendekatan yang, sekali lagi, memperbaiki dependensi sehingga tersedia untuk tanggungan berfungsi dengan baik. Currying adalah salah satu pendekatan semacam itu (dan itu membuat Anda terdengar pintar). Hanya ingat ada cara lain untuk menutup ketergantungan. Beberapa dari mereka elegan dan beberapa dari mereka mengerikan.
Jangan lupa tentang pemrograman berorientasi aspek . Tampaknya telah jatuh dari nikmat dalam beberapa tahun terakhir, tetapi tujuan utamanya adalah memecahkan persis masalah yang Anda gambarkan. Faktanya, contoh Aspect klasik adalah pencatatan. Di AOP, ketergantungan ditambahkan secara otomatis setelah kode lain ditulis. Orang-orang AOP menyebut ini " tenun ". Aspek umum ditenun ke dalam kode di tempat yang sesuai. Ini membuat kode Anda lebih mudah untuk dipikirkan dan sangat keren, tetapi juga menambah beban pengujian baru. Anda akan membutuhkan cara untuk menentukan artefak akhir Anda yang bagus. AOP memiliki jawaban untuk itu juga, jadi jangan merasa terintimidasi.
sumber
Jika
bar
tergantung padabaz
, yang pada gilirannya mengharuskandependency
, makabar
diperlukandependency
juga agar dapat digunakan dengan benarbaz
. Oleh karena itu, pendekatan yang benar akan baik melewati ketergantungan sebagai parameter untukbar
, atau menjelajahbaz
dan meneruskannyabar
.Pendekatan pertama lebih sederhana untuk diimplementasikan dan dibaca, tetapi menciptakan hubungan antara
bar
danbaz
. Pendekatan kedua menghapus kopling itu, tetapi bisa menghasilkan kode yang kurang jelas. Pendekatan mana yang terbaik karena itu kemungkinan akan tergantung pada kompleksitas dan perilaku kedua fungsi. Misalnya, jikabaz
ataudependency
memiliki efek samping, kemudahan pengujian kemungkinan akan menjadi pendorong besar di mana solusi dipilih.Saya menyarankan semua opsi lain yang Anda usulkan bersifat "hacky" dan cenderung menyebabkan masalah baik dengan pengujian maupun dengan sulit untuk melacak bug.
sumber
dependency
berkeliling melalui parameter adalah ketergantungan injeksi?Berbicara secara filosofis
saya setuju dengan keprihatinan David Arno .
Saya membaca OP sebagai mencari solusi implementasi. Namun, jawabannya adalah mengubah desainnya . "Pola"? Desain OO, bisa dikatakan, semuanya tentang konteks. Ini adalah selembar kertas kosong yang mengandung kemungkinan.
Berurusan dengan kode yang ada adalah konteks yang berbeda.
Saya sedang mengerjakan 'masalah yang sama saat ini. Yah, saya sedang memperbaiki ratusan baris kode copy-n-paste yang sudah selesai sehingga nilai bisa disuntikkan.
Modularisasi kode
Saya membuang 600 baris kode duplikat lalu refactored jadi alih-alih "A memanggil B memanggil C memanggil D ..." Saya punya "Panggil A, kembali, Panggil B, kembali, Panggil C ...". Sekarang kita hanya perlu menyuntikkan nilai ke salah satu metode tersebut, katakanlah metode E.
Tambahkan parameter default ke konstruktor. Penelepon yang ada tidak berubah - "opsional" adalah kata yang digunakan di sini. Jika argumen tidak lulus nilai default digunakan. Maka hanya 1 baris yang diubah untuk meneruskan variabel ke dalam struktur modular yang telah direactored; dan perubahan kecil dalam metode E untuk menggunakannya.
Penutupan
Utas Pemrogram - "Mengapa program menggunakan penutupan?"
Pada dasarnya, Anda menyuntikkan nilai ke dalam metode yang mengembalikan metode yang disesuaikan dengan nilai-nilai tersebut. Metode khusus itu kemudian dieksekusi.
Teknik ini memungkinkan Anda untuk memodifikasi metode yang ada tanpa mengubah tanda tangannya.
sumber