Modul yang Memerlukan vs Ketergantungan Injeksi dalam Javascript

24

Saat ini sebuah pertanyaan muncul di benak saya:

Apakah cara kita Javascript melawan hampir semua yang dianggap praktik yang baik dalam Pengembangan Perangkat Lunak tradisional?

Saya memiliki serangkaian pertanyaan / pengamatan terkait dengan pernyataan ini, tetapi untuk menghormati format StackExchange, akan lebih baik jika saya membaginya menjadi pertanyaan yang berbeda.

Modul yang membutuhkan

Kode Javascript standar saat ini terlihat seperti:

const someModule = require('./someModule')

module.exports = function doSomethingWithRequest() {
  // do stuff
  someModule.someFunc()
  // do other stuff
}

Keuntungan

  • Enkapsulasi: modul berfungsi mandiri dan mengetahui segala yang dibutuhkan untuk menjalankan fungsinya.
  • Sebagai colorary, lebih mudah bagi klien untuk menggunakan modul.

Kekurangan

  • Testabilitas yang buruk: ini adalah standar ketika tidak menggunakan DI, tetapi dalam bahasa yang dinamis, seperti Javscript dapat dielakkan * dengan modul seperti mockeryatau rewire.
  • Ini tentu saja melanggar DIP - jangan disamakan dengan Injeksi Ketergantungan. - Karena saya hanya dapat mengimpor modul beton.
  • Mungkin melanggar OCP - misalnya, bayangkan saya memiliki modul log yang menulis ke sistem file (melalui fsmodul). Jika saya ingin memperluas modul log ini untuk mengirimkannya ke jaringan, itu akan sangat sulit.

* Ini mungkin bekerja dengan CommonJS atau bahkan modul AMD karena mereka sebagian besar diimplementasikan di tanah pengguna. Namun, saya tidak yakin bagaimana ini bisa terjadi dengan importsintaks ES6 .

Injeksi Ketergantungan

Menggunakan injeksi ketergantungan, itu akan lebih seperti:

module.exports = function doSomethingWithRequest(someModule) {
  // do stuff
  someModule.someFunc()
  // do other stuff
}

Keuntungan

  • Peningkatan testabilitas: sekarang lebih mudah untuk stub / mock someModule, bahkan menggunakan sintaks ES6.
  • Ini mungkin untuk menghormati DIP: belum tentu juga, karena modul klien masih dapat diprogram untuk implementasi dan tidak antarmuka.

Kekurangan

  • Enkapsulasi rusak: pertanyaan utama yang tersisa adalah:

    Oke, lalu siapa yang akan membuat / membutuhkan dependensi?

  • Melakukan itu di setiap klien modul tampaknya sangat BASAH .
  • Ini mungkin mengharuskan saya untuk menggunakan Container DI agar layak dalam proyek nyata.

Jadi, pertanyaan sebenarnya di sini adalah:

Mengapa pengembang Javascript cenderung condong ke pendekatan pertama?

Apakah ini hanya "cara Javascript"?

Saya sendiri sering menulis kode seperti ini. Saya sudah memiliki bagian yang adil dari pengaturan tes menggunakan perpustakaan mengejek, tetapi selalu merasa agak salah melakukannya.

Apakah saya melewatkan sesuatu?

Henrique Barcelos
sumber
Sebagai seorang. Net yang baru-baru ini menjadi tertarik pada NodeJs, saya telah berjuang dengan ini juga. Saya telah menemukan dependensi monyet dengan Proxyquire (seperti ReWire) tidak apa - apa untuk tujuan pengujian, tetapi kadang-kadang Anda memerlukan beberapa implementasi dependensi ...
RubberDuck

Jawaban:

6

Saya terutama seorang programmer PHP, tetapi telah berhubungan dengan 4 tim JavaScript selama sekitar setahun terakhir.

Sebagai pemrogram berorientasi objek, prinsip injeksi ketergantungan tampaknya merupakan cara terbaik, namun saya telah diberitahu sebaliknya oleh beberapa pengembang JS. JS adalah dunia yang sangat berbeda.

Karena JavaScript memungkinkan Anda untuk menambal segala sesuatu dengan menggunakan teknik yang sangat sederhana, pengembang JavaScript belajar untuk mengadaptasi teknologi berbeda tentang cara membuat aplikasi JavaScript skala lebih besar. Sebagian besar dibangun sebagai set modul mandiri, yang mengekspos fungsionalitas melalui ekspor publik, menyembunyikan internal modul agar tidak memungkinkan orang lain untuk menulis ulang fungsi yang Anda andalkan.

Pendekatan yang biasa biasanya adalah bahkan untuk tidak mengekspos konstruktor apa yang pernah ada tetapi mengekspos konstruksi suatu objek menggunakan pembungkus pabrik - untuk alasan yang sama persis: jika Anda memberi seseorang akses ke suatu objek mereka dapat membuat instantiate secara langsung mereka diizinkan untuk mengubah apa pun.

Dengan mengambil keuntungan dari desain modular, Anda menolak orang lain untuk mengutak-atik fungsi yang Anda harapkan berfungsi, tetapi Anda masih memiliki kemampuan untuk menguji modul Anda - melalui API publik dari file yang diperlukan, API yang Anda buat.

Andy
sumber