Perlu diketahui bahwa saya penggemar berat ketergantungan injeksi (DI) dan pengujian otomatis. Saya bisa berbicara sepanjang hari tentang hal itu.
Latar Belakang
Baru-baru ini, tim kami baru saja mendapatkan proyek besar ini yang dibangun dari awal. Ini adalah aplikasi strategis dengan persyaratan bisnis yang kompleks. Tentu saja, saya ingin itu bagus dan bersih, yang bagi saya berarti: dapat dipelihara dan diuji. Jadi saya ingin menggunakan DI.
Perlawanan
Masalahnya ada di tim kami, DI itu tabu. Sudah dibesarkan beberapa kali, tetapi para dewa tidak menyetujui. Tapi itu tidak membuat saya patah semangat.
Kepindahan saya
Ini mungkin terdengar aneh tetapi perpustakaan pihak ketiga biasanya tidak disetujui oleh tim arsitek kami (pikirkan: "Anda tidak boleh berbicara tentang Persatuan , Ninject , NHibernate , Moq atau NUnit , jangan sampai saya memotong jari Anda"). Jadi, alih-alih menggunakan wadah DI yang sudah mapan, saya menulis wadah yang sangat sederhana. Ini pada dasarnya menghubungkan semua dependensi Anda pada startup, menyuntikkan dependensi (konstruktor / properti) dan membuang objek sekali pakai di akhir permintaan web. Itu sangat ringan dan hanya melakukan apa yang kami butuhkan. Dan kemudian saya meminta mereka untuk memeriksanya.
Responnya
Yah, untuk membuatnya singkat. Saya bertemu dengan perlawanan yang berat. Argumen utama adalah, "Kita tidak perlu menambahkan lapisan kompleksitas ini ke proyek yang sudah rumit". Juga, "Ini tidak seperti kita akan memasukkan implementasi komponen yang berbeda". Dan "Kami ingin membuatnya sederhana, jika mungkin memasukkan semuanya ke dalam satu unit. DI adalah kompleksitas yang tidak dibutuhkan tanpa manfaat".
Akhirnya, Pertanyaan Saya
Bagaimana Anda menangani situasi saya? Saya tidak bagus dalam menyajikan ide-ide saya, dan saya ingin tahu bagaimana orang akan mempresentasikan argumen mereka.
Tentu saja, saya berasumsi bahwa seperti saya, Anda lebih suka menggunakan DI. Jika Anda tidak setuju, tolong katakan mengapa saya bisa melihat sisi lain dari koin. Akan sangat menarik untuk melihat sudut pandang seseorang yang tidak setuju.
Memperbarui
Terima kasih atas jawaban semua orang. Itu benar-benar menempatkan segala sesuatu dalam perspektif. Cukup baik untuk memiliki satu set mata untuk memberi Anda umpan balik, lima belas benar-benar hebat! Ini adalah jawaban yang sangat bagus dan membantu saya melihat masalah dari sisi yang berbeda, tetapi saya hanya dapat memilih satu jawaban, jadi saya hanya akan memilih yang teratas. Terima kasih semuanya telah meluangkan waktu untuk menjawab.
Saya telah memutuskan bahwa ini mungkin bukan waktu terbaik untuk menerapkan DI, dan kami belum siap untuk itu. Sebagai gantinya, saya akan memusatkan upaya saya untuk membuat desain dapat diuji dan berusaha menyajikan pengujian unit otomatis. Saya sadar bahwa tes menulis adalah overhead tambahan dan jika pernah diputuskan bahwa overhead tambahan tidak sepadan, secara pribadi saya masih akan melihatnya sebagai situasi menang karena desain masih dapat diuji. Dan jika pernah menguji atau DI adalah pilihan di masa depan, desain dapat dengan mudah mengatasinya.
Jawaban:
Mengambil beberapa argumen balasan:
Apa yang Anda inginkan adalah agar sistem dapat diuji. Agar mudah diuji, Anda perlu melihat mengejek berbagai lapisan proyek (database, komunikasi, dll.) Dan dalam hal ini Anda akan mencolokkan berbagai implementasi komponen.
Jual DI pada manfaat pengujian yang diberikannya kepada Anda. Jika proyek ini rumit, maka Anda akan memerlukan pengujian unit yang bagus dan solid.
Manfaat lain adalah bahwa, ketika Anda mengkode ke antarmuka, jika Anda datang dengan implementasi yang lebih baik (lebih cepat, lebih sedikit memori, apa pun) dari salah satu komponen Anda, menggunakan DI membuatnya jauh lebih mudah untuk menukar implementasi lama untuk baru.
Apa yang saya katakan di sini adalah bahwa Anda perlu membahas manfaat yang DI bawa daripada berdebat untuk DI demi DI. Dengan membuat orang menyetujui pernyataan:
Anda kemudian mengalihkan masalahnya. Anda perlu memastikan bahwa DI adalah jawaban untuk pernyataan ini. Dengan melakukan itu Anda rekan kerja akan memiliki solusinya daripada merasa bahwa itu telah dibebankan pada mereka.
sumber
Dari apa yang Anda tulis, bukan DI itu sendiri adalah tabu, tetapi penggunaan wadah DI, yang merupakan hal yang berbeda. Saya kira Anda tidak akan mendapatkan masalah dengan tim Anda ketika Anda hanya menulis komponen independen yang mendapatkan komponen lain yang mereka perlukan, misalnya, oleh konstruktor. Hanya saja, jangan menyebutnya "DI".
Anda mungkin berpikir untuk komponen seperti itu untuk tidak menggunakan wadah DI itu membosankan, dan Anda benar, tetapi berikan waktu pada tim Anda untuk mencari tahu sendiri.
sumber
Karena Anda bertanya, saya akan memihak tim Anda melawan DI.
Kasus terhadap Injeksi Ketergantungan
Ada aturan yang saya sebut "Konservasi Kompleksitas" yang analog dengan aturan dalam fisika yang disebut "Konservasi Energi." Ini menyatakan bahwa tidak ada jumlah rekayasa yang dapat mengurangi kompleksitas total dari solusi optimal untuk suatu masalah, yang dapat dilakukan hanyalah menggeser kompleksitas tersebut. Produk Apple tidak kalah kompleksnya dengan produk Microsoft, mereka hanya memindahkan kompleksitas dari ruang pengguna ke ruang teknik. (Ini adalah analogi yang cacat, meskipun. Meskipun Anda tidak dapat membuat energi, insinyur memiliki kebiasaan buruk dalam menciptakan kompleksitas di setiap kesempatan. Bahkan, banyak programmer tampaknya menikmati penambahan kompleksitas dan menggunakan sihir, yang menurut kompleksitasnya tidak sepenuhnya dipahami oleh programmer. Kerumitan berlebih ini dapat dikurangi.) Biasanya yang tampak seperti mengurangi kompleksitas hanyalah memindahkan kompleksitas ke tempat lain, biasanya ke perpustakaan.
Demikian pula, DI tidak mengurangi kompleksitas menghubungkan objek klien dengan objek server. Apa yang dilakukannya adalah mengeluarkannya dari Jawa dan memindahkannya ke XML. Itu bagus karena memusatkan segala sesuatu menjadi satu (atau beberapa) file XML di mana mudah untuk melihat semua yang sedang terjadi dan di mana dimungkinkan untuk mengubah hal-hal tanpa mengkompilasi ulang kode. Di sisi lain, itu buruk karena file XML bukan Java dan karenanya tidak tersedia untuk tooling Java. Anda tidak dapat men-debug mereka di debugger, Anda tidak dapat menggunakan analisis statis untuk melacak hierarki panggilan mereka, dan seterusnya. Secara khusus, bug dalam kerangka DI menjadi sangat sulit untuk dideteksi, diidentifikasi, dan diperbaiki.
Oleh karena itu jauh lebih sulit untuk membuktikan suatu program menjadi benar ketika menggunakan DI. Banyak orang berpendapat bahwa program yang menggunakan DI lebih mudah untuk diuji , tetapi pengujian program tidak pernah dapat membuktikan tidak adanya bug . (Perhatikan bahwa makalah yang ditautkan berusia sekitar 40 tahun dan karenanya memiliki beberapa referensi misterius dan mengutip beberapa praktik kedaluwarsa, tetapi banyak pernyataan dasar masih berlaku. Terutama, bahwa P <= p ^ n, di mana P adalah probabilitas bahwa sistem bebas dari bug, p adalah probabilitas bahwa komponen sistem bebas dari bug, dan n adalah jumlah komponen. Tentu saja, persamaan ini terlalu disederhanakan, tetapi menunjuk pada kebenaran penting.) NASDAQ mogok saat IPO Facebook adalah contoh terbaru, di manamereka mengklaim telah menghabiskan 1.000 jam menguji kode dan masih belum menemukan bug yang menyebabkan crash. 1.000 jam adalah setengah tahun orang, jadi itu tidak seperti mereka berhemat pada pengujian.
Benar, hampir tidak ada yang pernah melakukan (apalagi menyelesaikan) tugas membuktikan kode secara formal adalah benar, tetapi bahkan upaya yang lemah pada bukti mengalahkan sebagian besar rezim pengujian untuk menemukan bug. Upaya keras untuk pembuktian, misalnya L4.verified , selalu menemukan sejumlah besar bug yang tidak diuji dan mungkin tidak akan pernah terungkap kecuali penguji sudah mengetahui sifat pasti dari bug tersebut. Apa pun yang membuat kode lebih sulit untuk diverifikasi dengan inspeksi dapat dilihat sebagai mengurangi kemungkinan bug akan terdeteksi , bahkan jika itu meningkatkan kemampuan untuk menguji.
Selanjutnya DI tidak diperlukan untuk pengujian . Saya jarang menggunakannya untuk tujuan itu, karena saya lebih suka menguji sistem terhadap perangkat lunak nyata dalam sistem daripada beberapa versi pengujian alternatif. Segala sesuatu yang saya ubah dalam pengujian (atau mungkin juga) disimpan dalam file properti yang mengarahkan program ke sumber daya di lingkungan pengujian daripada produksi. Saya lebih suka menghabiskan waktu menyiapkan server database pengujian dengan salinan basis data produksi daripada menghabiskan waktu menyusun database tiruan, karena dengan cara ini saya akan dapat melacak masalah dengan data produksi (masalah pengkodean karakter hanyalah salah satu contoh ) dan bug integrasi sistem serta bug dalam sisa kode.
Ketergantungan Injeksi juga tidak diperlukan untuk Ketergantungan Inversi . Anda dapat dengan mudah menggunakan metode pabrik statis untuk mengimplementasikan Pembalikan Ketergantungan. Sebenarnya, itulah yang dilakukan pada 1990-an.
Sebenarnya, meskipun saya telah menggunakan DI selama satu dekade, satu-satunya keuntungan yang saya temukan persuasif adalah kemampuan untuk mengkonfigurasi perpustakaan pihak ketiga untuk menggunakan perpustakaan pihak ketiga lainnya (misalnya mengatur Spring untuk menggunakan Hibernate dan keduanya untuk menggunakan Log4J ) dan mengaktifkan IoC melalui proksi. Jika Anda tidak menggunakan perpustakaan pihak ketiga dan tidak menggunakan IoC, maka tidak ada banyak gunanya dan itu memang menambah kompleksitas yang tidak beralasan.
sumber
Saya minta maaf untuk mengatakan bahwa masalah yang Anda miliki, mengingat apa yang dikatakan rekan kerja Anda dalam pertanyaan Anda, lebih bersifat politis daripada teknis. Ada dua mantra yang harus Anda ingat:
Tentu, Anda dapat memunculkan banyak argumen balasan dengan alasan dan manfaat teknis yang solid, tetapi itu akan menempatkan Anda dalam situasi yang buruk dengan anggota perusahaan lainnya. Mereka sudah memiliki sikap yang tidak mereka inginkan (karena mereka merasa nyaman dengan cara kerja sekarang). Jadi, bahkan mungkin akan merusak hubungan Anda dengan rekan-rekan sejawat Anda jika Anda tetap gigih tentang hal itu. Percayalah pada saya karena ini telah terjadi pada saya dan pada akhirnya membuat saya dipecat beberapa tahun yang lalu (muda dan naif seperti saya); ini adalah situasi yang tidak Anda inginkan.
Masalahnya adalah, Anda perlu mencapai tingkat kepercayaan sebelum orang pergi sejauh mengubah cara kerja mereka saat ini. Kecuali Anda berada dalam posisi di mana Anda memiliki banyak kepercayaan atau Anda dapat memutuskan hal-hal seperti ini, seperti memiliki peran sebagai arsitek atau pemimpin teknologi, ada sangat sedikit yang dapat Anda lakukan untuk mengubah rekan kerja Anda. Dibutuhkan banyak waktu dengan bujukan dan upaya (seperti dalam mengambil langkah-langkah perbaikan kecil) untuk mendapatkan kepercayaan agar budaya perusahaan Anda berubah. Kita berbicara tentang rentang waktu berbulan-bulan atau bertahun-tahun.
Jika Anda menemukan bahwa budaya perusahaan saat ini tidak bekerja dengan Anda maka setidaknya Anda tahu satu hal lagi untuk ditanyakan pada wawancara kerja Anda berikutnya. ;-)
sumber
Jangan gunakan DI. Lupakan.
Buat implementasi dari pola pabrik GoF yang "menciptakan" atau "menemukan" dependensi khusus Anda dan meneruskannya ke objek Anda dan biarkan saja, tetapi jangan menyebutnya DI dan jangan buat kerangka kerja umum yang rumit. Tetap sederhana dan relevan. Pastikan dependensi dan kelas Anda sedemikian rupa sehingga peralihan ke DI dimungkinkan; tetapi jaga agar pabrik tetap menjadi master dan jaga agar lingkupnya sangat terbatas.
Pada waktunya, Anda dapat berharap bahwa itu akan tumbuh dan bahkan satu hari transisi ke DI. Biarkan lead sampai pada kesimpulan pada waktunya sendiri dan jangan mendorong. Sekalipun Anda tidak pernah mencapai hal itu, setidaknya kode Anda memiliki beberapa kelebihan DI, misalnya, kode unit yang dapat diuji.
sumber
Saya telah melihat proyek yang membawa DI ke ekstrem untuk menguji unit dan mengejek objek. Sedemikian rupa sehingga konfigurasi DI menjadi bahasa pemrograman itu sendiri dengan konfigurasi sebanyak yang diperlukan untuk membuat sistem berjalan sebagai kode aktual.
Apakah sistem menderita saat ini karena kurangnya API internal yang sesuai yang tidak dapat diuji? Apakah Anda berharap bahwa beralih sistem ke model DI akan memungkinkan Anda untuk menguji unit lebih baik? Anda tidak perlu wadah untuk menguji unit kode Anda. Menggunakan model DI akan memungkinkan Anda untuk mengujinya dengan lebih mudah dengan benda-benda Mock, tetapi tidak diperlukan.
Anda tidak perlu mengganti seluruh sistem agar menjadi kompatibel DI sekaligus. Anda tidak boleh secara sewenang-wenang menulis tes Unit juga. Kode refactor saat Anda menemukannya di fitur Anda dan bug tiket yang berfungsi. Kemudian pastikan kode yang Anda sentuh mudah diuji.
Pikirkan CodeRot sebagai penyakit. Anda tidak ingin memulai dengan sewenang-wenang meretas sesuatu. Anda memiliki seorang pasien, Anda melihat tempat yang sakit, sehingga Anda mulai memperbaiki tempat itu dan hal-hal di sekitarnya. Setelah area itu bersih, Anda beralih ke yang berikutnya. Cepat atau lambat Anda akan menyentuh sebagian besar kode dan tidak memerlukan perubahan arsitektur "besar" ini.
Saya tidak suka pengujian DI dan Mock saling eksklusif. Dan setelah melihat proyek yang berjalan, karena tidak ada kata yang lebih baik, gila menggunakan DI, saya akan lelah juga tanpa melihat manfaatnya.
Ada beberapa tempat yang masuk akal untuk menggunakan DI:
Memerlukan setiap pengembang untuk mengetahui di mana file konfigurasi DI (Saya menyadari kontainer dapat dibuatkan contoh melalui kode, tetapi mengapa Anda melakukan itu.) Ketika mereka ingin melakukan RegEx frustasi. Oh saya melihat ada IRegExCompiler, DefaultRegExCompiler dan SuperAwesomeRegExCompiler. Namun tidak ada di mana dalam kode saya bisa melakukan analisis untuk melihat di mana Default digunakan dan SuperAwesome digunakan.
Kepribadian saya sendiri akan bereaksi lebih baik jika seseorang menunjukkan kepada saya sesuatu yang lebih baik, kemudian mencoba meyakinkan saya dengan kata-kata mereka. Ada sesuatu yang bisa dikatakan tentang seseorang yang akan meluangkan waktu dan upaya untuk membuat sistem lebih baik. Saya tidak menemukan banyak pengembang yang cukup peduli untuk membuat produk ini benar-benar lebih baik. Jika Anda bisa mendatanginya dengan perubahan nyata dalam sistem dan menunjukkan kepada mereka bagaimana hal itu membuatnya lebih baik dan lebih mudah bagi Anda, itu lebih berharga daripada riset online mana pun.
Singkatnya, cara terbaik untuk melakukan perubahan menjadi suatu sistem adalah dengan perlahan membuat kode yang saat ini Anda sentuh lebih baik setiap kali lewat. Cepat atau lambat Anda akan dapat mengubah sistem menjadi sesuatu yang lebih baik.
sumber
DI tidak memerlukan inversi wadah Kontrol invasif atau kerangka kerja mengejek. Anda dapat memisahkan kode dan mengizinkan DI melalui desain sederhana. Anda dapat melakukan pengujian unit melalui kemampuan Visual Studio bawaan.
Agar adil, rekan kerja Anda ada benarnya. Menggunakan perpustakaan-perpustakaan itu dengan buruk (dan karena mereka tidak terbiasa dengan itu, akan ada rasa sakit belajar) akan menimbulkan masalah. Pada akhirnya, masalah kode. Jangan mengacaukan produk Anda untuk pengujian Anda.
Ingatlah bahwa kompromi diperlukan dalam skenario ini.
sumber
Saya tidak berpikir bahwa Anda dapat menjual DI lagi, karena ini adalah keputusan dogmatis (atau, seperti @Spoike menyebutnya lebih sopan, politis ).
Dalam Situasi ini berdebat dengan praktik terbaik yang diterima secara luas seperti prinsip desain SOLID tidak mungkin lagi.
Seseorang yang memiliki kekuatan politik lebih dari Anda telah membuat (mungkin salah) keputusan untuk tidak menggunakan DI.
Anda di pihak lain telah menentang keputusan ini dengan menerapkan wadah Anda sendiri karena dilarang menggunakan wadah yang sudah ada. Ini kebijakan faits accompli yang Anda mencoba mungkin telah membuat situasi lebih buruk.
Analisis
Menurut pendapat saya, DI tanpa pengembangan testdriven (TDD) dan pengujian unit tidak memiliki manfaat signifikan yang melebihi biaya tambahan awal.
Apakah masalah ini benar-benar tentang
atau ini tentang
[Memperbarui]
Jika Anda melihat proyek Anda dari kesalahan klasik dalam tampilan manajemen proyek , Anda tahu
sementara yang lain melihat
sumber
Jika Anda harus "menjual" prinsip ke tim Anda, maka Anda mungkin sudah beberapa mil di jalan yang salah.
Tidak ada yang ingin melakukan pekerjaan ekstra, jadi jika apa yang Anda coba jual terlihat seperti kerja ekstra, maka Anda tidak akan meyakinkan mereka dengan Invocation of Superior Argument. Mereka perlu tahu bahwa Anda menunjukkan kepada mereka cara untuk mengurangi beban kerja mereka, bukan menambahnya.
DI sering dipandang sebagai kompleksitas ekstra sekarang dengan janji potensi kompleksitas yang berkurang di kemudian hari , yang memiliki nilai, tetapi tidak begitu bagi seseorang yang berusaha mengurangi beban kerja dimuka mereka. Dan dalam banyak kasus, DI hanyalah lapisan YAGNI . Dan biaya kerumitan ini bukan nol, sebenarnya cukup tinggi untuk tim yang tidak terbiasa dengan pola jenis ini. Dan itu adalah uang nyata yang disekop ke dalam ember yang mungkin tidak pernah menghasilkan manfaat apa pun.
Taruh di tempatnya
Taruhan terbaik Anda adalah menggunakan DI di mana itu sangat berguna, bukan hanya di tempat yang biasa. Misalnya, banyak aplikasi menggunakan DI untuk memilih dan mengkonfigurasi basis data. Dan jika aplikasi Anda dikirimkan dengan lapisan basis data maka itu adalah tempat yang menggoda untuk meletakkannya. Tetapi jika aplikasi Anda dikirimkan dengan database yang tidak terlihat oleh pengguna yang terintegrasi dengan kode, maka kemungkinan perlu mengganti DB saat mendekati nol. Dan menjual DI dengan mengatakan, "lihat, kita dapat dengan mudah melakukan hal ini yang tidak akan pernah, ingin kita lakukan," kemungkinan membuat Anda masuk dalam daftar "orang ini punya ide buruk" dengan bos Anda.
Tetapi katakan sebaliknya Anda memiliki hasil debug yang biasanya dikeluarkan IFDEF dalam rilis. Dan setiap kali pengguna memiliki masalah, tim dukungan Anda harus mengirim mereka debug build agar mereka bisa mendapatkan output log. Anda dapat menggunakan DI di sini untuk memungkinkan pelanggan untuk beralih di antara driver log -
LogConsole
untuk pengembang,LogNull
untuk pelanggan, danLogNetwork
untuk pelanggan dengan masalah. Satu bangunan terpadu, runtime dapat dikonfigurasi.Maka Anda bahkan tidak harus menyebutnya DI, sebaliknya itu hanya disebut "ide bagus Mel" dan Anda sekarang berada di daftar ide bagus bukan yang buruk. Orang-orang akan melihat seberapa baik polanya bekerja, dan mulai menggunakannya di tempat yang masuk akal dalam kode mereka.
Ketika Anda menjual ide dengan benar, orang tidak akan tahu bahwa Anda meyakinkan mereka tentang apa pun.
sumber
Tentu saja, Inversion of control (IoC) memiliki sejumlah besar manfaat: ia menyederhanakan kode, menambahkan beberapa keajaiban yang melakukan tugas-tugas khas, dll.
Namun:
Ini menambah banyak dependensi. Aplikasi hello world sederhana yang ditulis dengan Spring dapat memberi bobot selusin MB, dan saya telah melihat Spring ditambahkan hanya untuk menghindari beberapa baris konstruktor dan setter.
Ia menambahkan keajaiban yang disebutkan di atas , yang sulit dipahami oleh orang luar (misalnya, pengembang GUI yang perlu membuat beberapa perubahan di lapisan bisnis). Lihat artikel hebat Pikiran Inovatif Jangan Berpikir Sama - New York Times , yang menggambarkan bagaimana efek ini diremehkan oleh para ahli .
Itu mengeras untuk melacak penggunaan kelas. IDE seperti Eclipse memiliki kemampuan hebat untuk melacak penggunaan kelas atau pemanggilan metode tertentu. Tapi jejak ini hilang ketika ada injeksi ketergantungan dan refleksi dipanggil.
Penggunaan IoC biasanya tidak berakhir dengan ketergantungan injeksi, diakhiri dengan proxy yang tak terhitung jumlahnya, dan Anda mendapatkan tumpukan jejak menghitung ratusan baris, 90% di antaranya adalah proxy dan dipanggil melalui refleksi. Ini sangat menyulitkan menganalisis tumpukan jejak.
Jadi, saya sendiri penggemar berat Spring dan IoC, saya baru-baru ini harus memikirkan kembali pertanyaan di atas. Beberapa kolega saya adalah pengembang web yang diambil di dalam dunia Java dari dunia Web yang dikuasai oleh Python dan PHP dan yang jelas untuk hal-hal java adalah sesuatu yang jelas bagi mereka. Beberapa kolega saya yang lain melakukan trik (tentu saja tidak berdokumen) yang membuat kesalahan sangat sulit ditemukan. Tentu saja penyalahgunaan IoC membuat segalanya lebih ringan untuk mereka;)
Saran saya, jika Anda akan memaksakan penggunaan IoC dalam pekerjaan Anda, Anda akan bertanggung jawab atas penyalahgunaan yang dilakukan orang lain;)
sumber
Saya pikir ChrisF adalah sesuatu yang benar. Jangan menjual DI sendiri. Tetapi jual ide tentang unit yang menguji kode.
Salah satu pendekatan untuk memasukkan wadah DI ke dalam arsitektur bisa dengan perlahan membiarkan tes mendorong implementasi menjadi sesuatu yang cocok dengan arsitektur itu. Misalnya katakanlah Anda sedang mengerjakan pengontrol di aplikasi ASP.NET MVC. Katakanlah Anda menulis kelas seperti ini:
Itu memungkinkan Anda untuk menulis unit test yang dipisahkan dari implementasi sebenarnya dari repositori pengguna. Tetapi kelas masih bekerja tanpa wadah DI untuk membuatnya untuk Anda. Konstruktor tanpa parameter akan membuatnya dengan repositori default.
Jika Anda rekan kerja dapat melihat bahwa ini mengarah pada tes yang lebih bersih, mungkin mereka dapat menyadari bahwa itu adalah cara yang lebih baik. Mungkin Anda bisa membuat mereka mulai mengkode seperti itu.
Setelah mereka menyadari bahwa ini adalah desain yang lebih baik daripada UserController mengetahui tentang implementasi UserRepository tertentu, Anda dapat mengambil langkah selanjutnya, dan menunjukkan kepada mereka bahwa Anda dapat memiliki komponen, wadah DI, yang secara otomatis dapat menyediakan contoh yang Anda butuhkan.
sumber
Mungkin hal terbaik untuk dilakukan adalah mundur dan bertanya pada diri sendiri mengapa Anda ingin memperkenalkan wadah DI? Jika itu untuk meningkatkan testabilitas maka Anda tugas pertama Anda adalah membuat tim untuk membeli ke unit testing. Secara pribadi saya akan jauh lebih khawatir tentang kurangnya unit test daripada kurangnya wadah DI.
Dipersenjatai dengan suite atau suite unit test yang komprehensif, Anda dapat dengan percaya diri mulai mengembangkan desain Anda dari waktu ke waktu. Tanpa mereka, Anda menghadapi perjuangan yang semakin penuh untuk mempertahankan desain Anda selangkah demi selangkah dengan persyaratan yang berkembang, perjuangan yang akhirnya banyak tim kalah.
Jadi saran saya akan menjadi juara pertama pengujian dan refactoring unit kemudian, pada gilirannya memperkenalkan wadah DI dan akhirnya.
sumber
Saya mendengar beberapa no-no besar dari tim Anda di sini:
"Tidak ada perpustakaan pihak ketiga" - AKA "Tidak Diciptakan Di Sini" atau "NIH". Ketakutan adalah bahwa, dengan mengimplementasikan perpustakaan pihak ketiga dan dengan demikian membuat basis kode bergantung padanya, jika perpustakaan memiliki bug, atau lubang keamanan, atau bahkan hanya batasan yang perlu Anda atasi, Anda menjadi tergantung pada ketiga ini pihak untuk memperbaiki perpustakaan mereka agar kode Anda berfungsi. Sementara itu, karena program "Anda" yang gagal spektakuler, atau diretas, atau tidak melakukan apa yang mereka minta, Anda masih memikul tanggung jawab (dan para pengembang pihak ketiga akan mengatakan bahwa alat mereka "apa adanya" ", gunakan dengan resiko Anda sendiri).
Argumen kontra adalah bahwa kode yang memecahkan masalah sudah ada di perpustakaan pihak ketiga. Apakah Anda membangun komputer dari awal? Apakah Anda menulis Visual Studio? Apakah Anda menghindari pustaka bawaan di .NET? Tidak. Anda memiliki tingkat kepercayaan pada Intel / AMD dan Microsoft, dan mereka menemukan bug setiap saat (dan tidak selalu memperbaikinya dengan cepat). Menambahkan perpustakaan pihak ketiga memungkinkan Anda untuk dengan cepat membuat basis kode yang dapat dipertahankan berfungsi, tanpa harus menemukan kembali kemudi. Dan sepasukan pengacara Microsoft akan menertawakan Anda ketika Anda memberi tahu mereka bahwa bug di perpustakaan .NET cryptography membuat mereka bertanggung jawab atas insiden peretasan yang diderita klien Anda saat menggunakan program .NET Anda. Sementara Microsoft pasti akan melompat untuk memperbaiki lubang keamanan "nol-jam" di salah satu produknya,
"Kami ingin memasukkan semuanya menjadi satu perakitan" - sebenarnya, Anda tidak. Di .NET setidaknya, jika Anda membuat perubahan ke satu baris kode seluruh perakitan yang mengandung baris kode itu harus dibangun kembali. Desain kode yang baik didasarkan pada beberapa majelis yang dapat Anda bangun kembali secara mandiri (atau setidaknya hanya harus membangun kembali dependensi, bukan tanggungan). Jika mereka BENAR-BENAR ingin merilis EXE yang hanya EXE (yang memang memiliki nilai dalam keadaan tertentu), ada aplikasi untuk itu; ILMerge.
"DI itu tabu" - WTF? DI adalah praktik terbaik yang diterima dalam bahasa O / O dengan konstruksi kode "antarmuka". Bagaimana tim Anda mematuhi metodologi desain GRASP atau SOLID jika mereka tidak secara longgar menggabungkan ketergantungan antara objek? Jika mereka tidak repot-repot, maka mereka mengabadikan pabrik spageti yang membuat produk itu semakin rumit. Sekarang, DI memang meningkatkan kompleksitas dengan meningkatkan jumlah objek, dan sementara itu membuat penggantian implementasi yang berbeda lebih mudah, itu membuat mengubah antarmuka itu sendiri lebih sulit (dengan menambahkan lapisan tambahan objek kode yang harus diubah).
"Kami tidak perlu menambahkan lapisan kompleksitas ini ke proyek yang sudah rumit" - Mereka mungkin ada benarnya. Suatu hal penting untuk dipertimbangkan dalam pengembangan kode adalah YAGNI; "Kamu Tidak Akan Membutuhkannya". Desain yang direkayasa secara SOLID dari awal adalah desain yang dibuat SOLID "berdasarkan iman"; Anda tidak tahu apakah Anda akan membutuhkan kemudahan perubahan yang disediakan desain SOLID, tetapi Anda punya firasat. Meskipun Anda mungkin benar, Anda juga mungkin sangat salah; desain yang sangat SOLID dapat akhirnya dilihat sebagai "kode lasagna" atau "kode ravioli", memiliki begitu banyak lapisan atau potongan ukuran gigitan yang membuat perubahan yang tampaknya sepele menjadi sulit karena Anda harus menggali melalui begitu banyak lapisan dan / atau melacak melalui tumpukan panggilan yang berbelit-belit.
Saya mendukung aturan tiga pukulan: Buat itu berfungsi, bersihkan, buat SOLID. Saat Anda pertama kali menulis sebaris kode, kode itu harus bekerja, dan Anda tidak mendapatkan poin untuk desain menara gading. Anggap itu hanya satu kali dan lakukan apa yang harus Anda lakukan. Kali kedua Anda melihat kode itu, Anda mungkin ingin memperluas atau menggunakannya kembali, dan bukan itu yang Anda pikir akan terjadi. Pada titik ini, buat lebih elegan dan mudah dipahami dengan refactoring; sederhanakan logika berbelit-belit, ekstrak kode berulang menjadi loop dan / atau panggilan metode, tambahkan beberapa komentar di sana-sini untuk setiap kludge Anda harus meninggalkan di tempat, dll. Ketiga kalinya Anda melihat kode itu mungkin semacam masalah besar. Sekarang Anda harus mematuhi aturan SOLID; menyuntikkan dependensi alih-alih membangunnya, mengekstrak kelas untuk menyimpan metode yang kurang kohesif dengan "daging" kode,
"Ini tidak seperti kita akan melakukan implementasi yang berbeda" - Anda, Pak, memiliki tim yang tidak percaya pada tes unit di tangan Anda. Saya berpendapat bahwa tidak mungkin untuk menulis unit test, yang berjalan dalam isolasi dan tidak memiliki efek samping, tanpa dapat "mengejek" objek yang memiliki efek samping tersebut. Setiap program non-sepele memiliki efek samping; jika program Anda membaca atau menulis ke DB, membuka atau menyimpan file, berkomunikasi melalui jaringan atau soket periferal, meluncurkan program lain, menggambar windows, output ke konsol, atau menggunakan memori atau sumber daya di luar "kotak pasir" prosesnya, ia memiliki efek samping. Jika tidak melakukan hal-hal ini, apa yang DILAKUKAN, dan mengapa saya harus membelinya?
Agar adil, pengujian unit bukan satu-satunya cara untuk membuktikan program bekerja; Anda dapat menulis tes integrasi, kode ke algoritme yang terbukti secara matematis, dll. Namun, pengujian unit menunjukkan, dengan sangat cepat, yang memberikan input A, B dan C, kode ini menghasilkan output X yang diharapkan (atau tidak), dan dengan demikian kode berfungsi dengan baik (atau tidak) dalam kasus yang diberikan. Rangkaian pengujian unit dapat menunjukkan dengan tingkat keyakinan yang tinggi bahwa kode berfungsi seperti yang diharapkan dalam semua kasus, dan mereka juga memberikan sesuatu yang tidak bisa dibuktikan oleh bukti matematis; sebuah demonstrasi bahwa program MASIH bekerja sebagaimana mestinya. Bukti matematis dari algoritma tidak membuktikan itu diterapkan dengan benar, juga tidak membuktikan perubahan yang dibuat diimplementasikan dengan benar dan tidak merusaknya.
Singkatnya adalah bahwa, jika tim ini tidak melihat nilai apa pun yang akan dilakukan DI, maka mereka tidak akan mendukungnya, dan semua orang (setidaknya semua orang senior) harus membeli sesuatu untuk perubahan nyata terjadi. Mereka banyak menekankan pada YAGNI. Anda memberi banyak penekanan pada pengujian SOLID dan otomatis. Di suatu tempat di tengah terletak kebenaran.
sumber
Hati-hati menambahkan fitur tambahan (seperti DI) ke proyek ketika tidak disetujui. Jika Anda memiliki rencana proyek dengan batas waktu, Anda dapat terjebak dalam perangkap karena tidak memiliki cukup waktu untuk menyelesaikan fitur yang disetujui.
Bahkan jika Anda tidak menggunakan DI sekarang, ikut serta dalam pengujian sehingga Anda tahu persis apa harapan untuk pengujian di perusahaan Anda. Akan ada proyek lain dan Anda akan dapat membedakan masalah dengan pengujian proyek saat ini vs DI.
Jika Anda tidak menggunakan DI, Anda bisa berkreasi dan membuat kode Anda DI- "siap". Gunakan konstruktor tanpa parameter untuk memanggil konstruktor lain:
sumber
Saya pikir salah satu kekhawatiran terbesar mereka justru sebaliknya: DI tidak membuat proyek menjadi kompleks. Dalam kebanyakan kasus ini mengurangi banyak kerumitan.
Pikirkan saja tanpa DI, apa yang akan Anda dapatkan dari objek / komponen dependen yang Anda butuhkan? Biasanya itu adalah dengan mencari dari repositori, atau mendapatkan singleton, atau instantiasi diri Anda sendiri.
2 sebelumnya melibatkan kode tambahan dalam menemukan komponen dependen, di dunia DI, Anda tidak melakukan apa pun untuk melakukan pencarian. Kompleksitas komponen Anda sebenarnya berkurang.
Jika Anda membuat contoh sendiri dalam beberapa kasus yang tidak sesuai, itu bahkan menciptakan lebih banyak kompleksitas. Anda perlu tahu cara membuat objek dengan benar, Anda perlu tahu nilai apa untuk menginisialisasi objek ke keadaan bisa diterapkan, semua ini menciptakan kompleksitas tambahan untuk kode Anda.
Jadi, DI tidak membuat kompleks proyek, itu membuatnya lebih sederhana, dengan membuat komponen lebih sederhana.
Argumen besar lainnya adalah, Anda tidak akan mencolokkan implementasi yang berbeda. Ya, memang benar bahwa dalam kode produksi, tidak umum untuk memiliki banyak implementasi yang berbeda dalam kode produksi nyata. Namun ada satu tempat utama yang membutuhkan implementasi yang berbeda: Mock / Stub / Test Doubles dalam Unit Tests. Untuk membuat DI berfungsi, dalam kebanyakan kasus ini bergantung pada model pengembangan yang digerakkan oleh antarmuka, yang pada gilirannya memungkinkan model mengejek / mematikan. Selain mengganti implementasi, "desain berorientasi antarmuka" juga membuat desain lebih bersih dan lebih baik. Tentu saja Anda masih bisa mendesain dengan antarmuka tanpa DI. Namun, tes Unit dan DI mendorong Anda untuk mengadopsi praktik-praktik tersebut.
Kecuali jika "dewa" Anda di perusahaan berpikir bahwa: "kode sederhana", "tes unit", "modularisasi", "tanggung jawab tunggal", dll. Adalah sesuatu yang mereka lawan, seharusnya tidak ada alasan bagi mereka untuk menolak menggunakan DI.
sumber
"Kami ingin tetap sederhana, jika mungkin hanya memasukkan semuanya ke dalam satu perakitan. DI adalah kompleksitas yang tidak dibutuhkan tanpa manfaat".
Manfaatnya adalah desainnya yang dirancang untuk antarmuka dan memungkinkan ejekan yang mudah. Yang akibatnya memfasilitasi pengujian unit. Pengujian unit memastikan kode yang andal, modular, dan mudah dirawat. Jika bos Anda masih mempertahankannya sebagai ide yang buruk, tidak ada yang bisa Anda lakukan - praktik terbaik industri yang diterima yang mereka lawan.
Buat mereka mencoba menulis unit test dengan kerangka kerja DI dan mengejek perpustakaan, mereka akan segera belajar untuk menyukainya.
sumber
new
mana-mana dan menulis kelas pabrik karena Anda memiliki semua komponen ini di tempat.Apakah Anda bekerja dengan orang-orang ini pada proyek yang lebih kecil, atau hanya satu yang besar? Lebih mudah meyakinkan orang untuk mencoba sesuatu yang baru pada proyek sekunder / tersier daripada tim / perusahaan roti dan mentega. Alasan utama adalah bahwa jika gagal biaya untuk menghapus / mengganti itu jauh lebih kecil, dan itu jauh lebih sulit untuk mendapatkannya di mana-mana dalam proyek kecil. Dalam yang sudah ada besar Anda memiliki biaya dimuka yang besar untuk melakukan perubahan di mana saja sekaligus, atau periode yang diperpanjang di mana kode merupakan campuran dari pendekatan lama / baru yang menambah gesekan karena Anda harus mengingat ke arah mana setiap kelas dirancang bekerja.
sumber
Meskipun salah satu hal yang mempromosikan DI adalah pengujian unit, tetapi saya percaya bahwa itu menambah lapisan kompleksitas dalam beberapa kasus.
Lebih baik memiliki mobil yang keras dalam pengujian, tetapi mudah dalam perbaikan daripada mobil yang mudah dalam pengujian dan sulit dalam perbaikan.
Juga nampak bagi saya bahwa kelompok yang mendorong DI hanya mempresentasikan ide-ide mereka melalui pengaruh bahwa beberapa pendekatan desain yang ada buruk.
jika kita memiliki metode melakukan 5 fungsi yang berbeda
DI-People Berkata:
Saya percaya bahwa lebih baik untuk membuat pola desain kita sendiri yang sesuai dengan kebutuhan bisnis daripada dipengaruhi oleh DI.
mendukung DI, mungkin membantu dalam beberapa situasi, misalnya jika Anda memiliki ratusan implementasi untuk Antarmuka yang sama tergantung pada pemilih dan implementasi ini jauh berbeda dalam logika, dalam hal ini saya akan pergi dengan teknik serupa DI atau DI. tetapi jika kita memiliki beberapa implementasi untuk antarmuka yang sama kita tidak perlu DI.
sumber