Saya sudah banyak membaca tentang pola tunggal dan bagaimana itu "buruk" karena membuat kelas-kelas menggunakannya sulit untuk diuji sehingga harus dihindari. Saya telah membaca beberapa artikel yang menjelaskan bagaimana singleton dapat diganti dengan suntikan ketergantungan, tetapi tampaknya tidak perlu bagi saya.
Inilah masalah saya sedikit lebih detail. Saya sedang membangun aplikasi seluler menggunakan React Native dan saya ingin membuat klien REST yang akan berkomunikasi dengan server, mendapatkan data, memposting data, dan menangani login (menyimpan token login dan mengirimkannya dengan setiap permintaan setelah login).
Rencana awal saya adalah membuat objek tunggal (RESTClient) yang akan digunakan aplikasi saya pada awalnya untuk masuk dan kemudian membuat permintaan mengirim kredensial jika diperlukan. Pendekatan DI tampaknya sangat rumit bagi saya (mungkin karena saya tidak pernah menggunakan DI sebelumnya) tetapi saya menggunakan proyek ini untuk belajar sebanyak mungkin sehingga saya ingin melakukan yang terbaik di sini. Setiap saran dan komentar sangat dihargai.
Sunting: Saya sekarang sadar saya telah menjawab pertanyaan saya dengan buruk. Saya ingin beberapa panduan tentang cara menghindari pola tunggal di RN dan haruskah saya melakukannya. Untungnya Samuel memberi saya jawaban yang saya inginkan. Masalah saya adalah saya ingin menghindari pola tunggal dan menggunakan DI, tetapi tampaknya sangat rumit untuk mengimplementasikannya dalam React Native. Saya melakukan riset lebih lanjut dan mengimplementasikannya menggunakan sistem konteks Reacts.
Bagi siapa pun yang tertarik, inilah cara saya melakukannya. Seperti saya katakan, saya menggunakan konteks di RN yang merupakan sesuatu seperti alat peraga tetapi itu disebarkan ke setiap komponen.
Di komponen root saya memberikan dependensi yang diperlukan seperti ini:
export default class Root extends Component {
getChildContext() {
restClient: new MyRestClient();
}
render() {...}
}
Root.childContextTypes = {restClient: PropTypes.object};
Sekarang restClient tersedia di semua komponen di bawah Root. Saya dapat mengaksesnya seperti ini.
export default class Child extends Component {
useRestClient() {
this.context.restClient.getData(...);
}
render() {...}
}
Child.contextTypes = {restClient: PropTypes.object}
Ini secara efektif memindahkan pembuatan objek dari logika dan memisahkan implementasi klien REST dari komponen saya.
sumber
Jawaban:
Injeksi ketergantungan tidak perlu rumit sama sekali, dan itu benar-benar layak untuk dipelajari dan digunakan. Biasanya rumit dengan penggunaan kerangka kerja injeksi ketergantungan, tetapi mereka tidak perlu.
Dalam bentuk yang paling sederhana, injeksi dependensi melewati dependensi alih-alih mengimpor atau membangunnya. Ini bisa dipuji dengan hanya menggunakan parameter untuk apa yang akan diimpor. Katakanlah Anda memiliki komponen bernama
MyList
yang perlu digunakanRESTClient
untuk mengambil beberapa data dan menampilkannya kepada pengguna. Pendekatan "tunggal" akan terlihat seperti ini:Ini sangat cocok
MyList
untuk pasanganrestClient
, dan tidak mungkin Anda bisa menguji unitMyList
tanpa pengujianrestClient
. Pendekatan DI akan terlihat seperti ini:Hanya itu yang diperlukan untuk menggunakan DI. Ini menambah paling banyak dua baris kode dan Anda bisa menghilangkan impor. Alasan mengapa saya memperkenalkan fungsi baru "pabrik" adalah karena AFAIK Anda tidak dapat melewatkan parameter konstruktor tambahan di Bereaksi, dan saya lebih suka untuk tidak meneruskan hal-hal ini melalui properti Bereaksi karena itu tidak portabel dan semua komponen induk harus tahu untuk melewati semua alat peraga untuk anak-anak.
Jadi sekarang Anda memiliki fungsi untuk membangun
MyList
komponen, tetapi bagaimana Anda menggunakannya? Pola DI memunculkan rantai ketergantungan. Katakanlah Anda memiliki komponenMyApp
yang digunakanMyList
. Pendekatan "tunggal" adalah:Pendekatan DI adalah:
Sekarang kita dapat menguji
MyApp
tanpa mengujiMyList
secara langsung. Kami bahkan dapat menggunakan kembaliMyApp
dengan daftar yang sangat berbeda. Pola ini menggelembung hingga ke akar komposisi . Di sinilah Anda memanggil pabrik Anda dan mengirimkan semua komponen.Sekarang sistem kami menggunakan instance tunggal
RESTClient
, tetapi kami telah mendesainnya sedemikian rupa sehingga komponen dapat digabungkan secara longgar dan mudah diuji.sumber
MyAppFactory
mengembalikanMyApp
kelas?Menurut tempat Anda (belajar), jawaban paling sederhana adalah tidak, lajang bukan alternatif terbaik untuk Dependency Injection .
Jika belajar adalah tujuannya, Anda akan menemukan DI menjadi sumber daya yang lebih berharga di kotak alat Anda daripada Singleton. Ini mungkin terlihat rumit, tetapi kurva belajarnya hampir pada semua yang Anda harus pelajari dari awal. Jangan berbaring di zona nyaman Anda atau tidak akan ada belajar sama sekali.
Secara teknis, ada sedikit perbedaan antara singleton dan single instance (apa yang saya pikir Anda coba lakukan). Belajar DI Anda akan menyadari bahwa Anda dapat menyuntikkan satu contoh di seluruh kode. Anda akan menemukan kode Anda lebih mudah untuk diuji dan digabungkan secara longgar. ( Untuk lebih jelasnya lihat jawaban Samuel )
Tapi jangan berhenti di sini. Apakah menerapkan kode yang sama dengan Singleton. Kemudian bandingkan kedua pendekatan tersebut.
Memahami dan membiasakan diri dengan kedua implementasi akan memungkinkan Anda untuk mengetahui kapan mereka cocok dan mungkin Anda akan berada dalam posisi untuk menjawab sendiri pertanyaan itu.
Sekarang, selama pelatihan, ketika Anda memalsukan Golden Hammers Anda , jadi jika Anda memutuskan untuk menghindari belajar DI, kemungkinan besar Anda akan akhirnya menerapkan lajang setiap kali Anda membutuhkan DI.
sumber
Saya setuju dengan jawaban lain bahwa mempelajari apa itu DI dan bagaimana menggunakannya adalah ide yang bagus.
Yang mengatakan, peringatan bahwa lajang membuat pengujian terlalu keras biasanya dibuat oleh orang yang menggunakan bahasa yang diketik secara statis (C ++, C #, Java, dll . ) .
Berbeda dengan bahasa yang dinamis (Javascript, PHP, Python, Ruby, dll.) , Biasanya sulit untuk mengganti singleton dengan implementasi tes khusus daripada jika Anda menggunakan DI.
Dalam hal ini, saya sarankan menggunakan desain yang terasa lebih alami untuk Anda dan co-developer Anda, karena itu akan cenderung menghindari kesalahan. Jika itu menghasilkan lajang, jadilah itu.
(Tapi sekali lagi: Pelajari DI sebelum Anda membuat keputusan itu.)
sumber