Apa tujuan dari Kontainer IOC? Alasan gabungan untuk itu dapat disederhanakan sebagai berikut:
Saat menggunakan prinsip-prinsip Pengembangan OOP / SOLID, Injeksi Ketergantungan menjadi berantakan. Entah Anda memiliki titik masuk level atas yang mengelola dependensi untuk beberapa level di bawahnya dan melewati dependensi secara rekursif melalui konstruksi, atau Anda memiliki kode duplikat dalam pola pabrik / pembangun dan antarmuka yang membangun dependensi sesuai kebutuhan Anda.
Tidak ada OOP / SOLID cara untuk melakukan ini DAN memiliki kode yang sangat cantik.
Jika pernyataan sebelumnya itu benar, lalu bagaimana IOC Containers melakukannya? Sejauh yang saya tahu, mereka tidak menggunakan beberapa teknik yang tidak diketahui yang tidak dapat dilakukan dengan manual DI Jadi satu-satunya eksplorasi adalah bahwa IOC Containers melanggar Prinsip OOP / SOLID dengan menggunakan objek statis accessors pribadi.
Apakah IOC Containers melanggar prinsip-prinsip berikut di belakang layar? Ini adalah pertanyaan sebenarnya karena saya memiliki pemahaman yang baik, tetapi memiliki perasaan orang lain memiliki pemahaman yang lebih baik:
- Kontrol ruang lingkup . Lingkup adalah alasan untuk hampir setiap keputusan yang saya buat pada desain kode saya. Blok, Lokal, Modul, Statis / Global. Lingkup harus sangat eksplisit, sebanyak di level blok dan sesedikit mungkin di Statis. Anda harus melihat deklarasi, contoh, dan akhir siklus hidup. Saya mempercayai bahasa dan GC untuk mengelola ruang lingkup selama saya eksplisit dengannya. Dalam penelitian saya, saya menemukan bahwa Kontainer IOC mengatur sebagian besar atau semua dependensi sebagai Statis dan mengendalikannya melalui beberapa implementasi AOP di belakang layar. Jadi tidak ada yang transparan.
- Enkapsulasi . Apa tujuan enkapsulasi? Mengapa kita harus menjaga anggota pribadi begitu? Untuk alasan praktis, implementor API kami tidak dapat menghentikan implementasi dengan mengubah status (yang harus dikelola oleh kelas pemilik). Tetapi juga, karena alasan keamanan, suntikan tidak dapat terjadi yang mengambil alih negara anggota kami dan memintas validasi dan kontrol kelas. Jadi apa pun (kerangka kerja mengejek atau kerangka kerja IOC) yang entah bagaimana menyuntikkan kode sebelum mengkompilasi waktu untuk memungkinkan akses eksternal ke anggota pribadi sangat besar.
- Prinsip Tanggung Jawab Tunggal . Di permukaan, IOC Containers tampaknya membuat segalanya lebih bersih. Tetapi bayangkan bagaimana Anda akan mencapai hal yang sama tanpa kerangka kerja pembantu. Anda akan memiliki konstruktor dengan selusin dependensi yang dilewati. Itu tidak berarti menutupinya dengan Kontainer IOC, itu adalah hal yang baik! Ini adalah tanda untuk memfaktorkan ulang kode Anda dan mengikuti SRP.
Buka / Tutup . Sama seperti SRP bukan Kelas-Saja (saya menerapkan SRP ke jalur tanggung jawab tunggal, apalagi metode). Open / Closed bukan hanya teori tingkat tinggi untuk tidak mengubah kode kelas. Ini adalah praktik memahami konfigurasi program Anda dan memiliki kendali atas apa yang diubah dan apa yang diperluas. Kontainer IOC dapat mengubah cara kerja kelas Anda sebagian karena:
Sebuah. Kode utama tidak membuat penentuan ketergantungan keluar, konfigurasi kerangka adalah.
b. Ruang lingkup dapat diubah pada waktu yang tidak dikontrol oleh anggota pemanggil, melainkan ditentukan secara eksternal oleh kerangka kerja statis.
Jadi konfigurasi kelas tidak benar-benar tertutup, itu mengubah sendiri berdasarkan konfigurasi alat pihak ketiga.
Alasan mengapa ini menjadi pertanyaan adalah karena saya belum tentu menguasai semua Kontainer IOC. Dan meskipun gagasan tentang IOC Container bagus, mereka tampaknya hanya façade yang menutupi implementasi yang buruk. Tetapi untuk mencapai kontrol Lingkup eksternal, akses anggota Privat, dan pemuatan Malas, banyak hal yang tidak sepele yang dipertanyakan harus terus berjalan. AOP itu hebat, tetapi cara itu dicapai melalui IOC Containers juga dipertanyakan.
Saya bisa mempercayai C # dan .NET GC untuk melakukan apa yang saya harapkan. Tapi saya tidak bisa menaruh kepercayaan yang sama pada alat pihak ketiga yang mengubah kode kompilasi saya untuk melakukan solusi untuk hal-hal yang saya tidak akan bisa lakukan secara manual.
EG: Kerangka Entitas dan ORM lainnya menciptakan objek yang sangat diketik dan memetakannya ke entitas basis data, serta menyediakan fungsionalitas dasar boiler-plate untuk melakukan CRUD. Siapa saja dapat membangun ORM mereka sendiri dan terus mengikuti Prinsip OOP / SOLID secara manual. Tapi kerangka itu membantu kita sehingga kita tidak perlu menemukan kembali roda setiap saat. Sedangkan Kontainer IOC, tampaknya, membantu kami dengan sengaja bekerja di sekitar Prinsip OOP / SOLID dan menutupinya.
IOC
danExplicitness of code
persis hal yang saya miliki masalah dengan. Manual DI dapat dengan mudah menjadi tugas, tetapi setidaknya menempatkan alur program eksplisit mandiri di satu tempat - "Anda mendapatkan apa yang Anda lihat, Anda melihat apa yang Anda dapatkan". Sementara binding dan deklarasi kontainer IOC dapat dengan mudah menjadi program paralel tersembunyi sendiri.Jawaban:
Saya akan membahas poin-poin Anda secara numerik, tetapi pertama-tama, ada sesuatu yang harus Anda sangat berhati-hati: jangan mengacaukan bagaimana konsumen menggunakan perpustakaan dengan bagaimana perpustakaan diimplementasikan . Contoh bagus dari ini adalah Kerangka Entitas (yang Anda kutip sendiri sebagai perpustakaan yang baik) dan MVC ASP.NET. Keduanya melakukan banyak hal di bawah tenda dengan, misalnya, refleksi, yang sama sekali tidak dianggap desain yang baik jika Anda menyebarkannya melalui kode sehari-hari.
Perpustakaan ini sama sekali tidak "transparan" dalam cara kerjanya, atau apa yang mereka lakukan di belakang layar. Tapi itu bukan kerugian, karena mereka mendukung prinsip pemrograman yang baik di konsumen mereka . Jadi, setiap kali Anda berbicara tentang perpustakaan seperti ini, ingatlah bahwa sebagai konsumen perpustakaan, bukan tugas Anda untuk mengkhawatirkan implementasi atau pemeliharaannya. Anda hanya perlu khawatir tentang bagaimana ini membantu atau menghalangi kode yang Anda tulis yang menggunakan perpustakaan. Jangan mengacaukan konsep-konsep ini!
Jadi, untuk melewati poin:
Segera kami mencapai apa yang hanya bisa saya asumsikan adalah contoh di atas. Anda mengatakan bahwa wadah IOC mengatur sebagian besar dependensi sebagai statis. Yah, mungkin beberapa detail implementasi tentang cara kerjanya termasuk penyimpanan statis (meskipun mengingat bahwa mereka cenderung memiliki instance objek seperti Ninject
IKernel
sebagai penyimpanan inti mereka, saya ragu bahkan itu). Tapi ini bukan urusanmu!Sebenarnya, wadah IoC sama eksplisitnya dengan ruang lingkup seperti injeksi ketergantungan orang miskin. (Aku akan terus membandingkan kontainer IoC dengan DI orang miskin karena membandingkannya dengan tidak ada DI sama sekali tidak adil dan membingungkan. Dan, untuk lebih jelasnya, aku tidak menggunakan "DI orang miskin" sebagai penghinaan.)
Di DI orang miskin, Anda akan instantiate ketergantungan secara manual, lalu menyuntikkannya ke kelas yang membutuhkannya. Pada titik di mana Anda membangun ketergantungan, Anda akan memilih apa yang akan dilakukan dengan itu- menyimpannya dalam variabel cakupan lokal, variabel kelas, variabel statis, tidak menyimpannya sama sekali, apa pun. Anda bisa memberikan contoh yang sama ke banyak kelas, atau Anda bisa membuat yang baru untuk setiap kelas. Masa bodo. Intinya adalah, untuk melihat mana yang terjadi, Anda melihat ke titik - mungkin di dekat root aplikasi - tempat ketergantungan dibuat.
Sekarang bagaimana dengan wadah IOC? Nah, Anda melakukan hal yang persis sama! Sekali lagi, akan dengan terminologi Ninject, Anda melihat di mana mengikat diatur, dan mencari apakah itu mengatakan sesuatu seperti
InTransientScope
,InSingletonScope
, atau apa pun. Jika ada hal ini berpotensi lebih jelas, karena Anda memiliki kode di sana yang menyatakan ruang lingkupnya, daripada harus melihat melalui metode untuk melacak apa yang terjadi pada beberapa objek (objek dapat dicakup ke blok, tetapi apakah itu digunakan beberapa kali dalam hal itu blok atau hanya sekali, misalnya). Jadi mungkin Anda ditolak oleh gagasan harus menggunakan fitur pada wadah IoC daripada fitur bahasa mentah untuk menentukan ruang lingkup, tetapi selama Anda mempercayai perpustakaan IoC Anda - yang Anda harus! - tidak ada kerugian nyata untuk itu .Saya masih tidak benar-benar tahu apa yang Anda bicarakan di sini. Apakah wadah IoC melihat properti pribadi sebagai bagian dari implementasi internal mereka? Saya tidak tahu mengapa mereka melakukannya, tetapi sekali lagi, jika mereka melakukannya, bukan urusan Anda bagaimana perpustakaan yang Anda gunakan diimplementasikan.
Atau, mungkin, mereka mengekspos kemampuan seperti menyuntikkan ke setter pribadi? Jujur saya belum pernah menemukan ini, dan saya ragu apakah ini benar-benar fitur umum. Tetapi bahkan jika itu ada, itu adalah kasus sederhana dari alat yang dapat disalahgunakan. Ingat, bahkan tanpa wadah IoC, hanya beberapa baris kode Refleksi untuk mengakses dan memodifikasi properti pribadi. Ini adalah sesuatu yang hampir tidak boleh Anda lakukan, tetapi itu tidak berarti. NET buruk untuk mengekspos kemampuan. Jika seseorang dengan jelas dan liar menyalahgunakan alat, itu kesalahan orang itu, bukan alat itu.
Poin pamungkas di sini mirip dengan 2. Sebagian besar waktu, kontainer IOC menggunakan konstruktor! Injeksi setter ditawarkan untuk keadaan yang sangat spesifik di mana, karena alasan tertentu, injeksi konstruktor tidak dapat digunakan. Siapa pun yang menggunakan injeksi setter sepanjang waktu untuk menutupi berapa banyak dependensi yang dilewatkan secara masif meninggalkan alat. Itu BUKAN kesalahan alat, itu milik mereka.
Sekarang, jika ini adalah kesalahan yang sangat mudah untuk dibuat dengan tidak bersalah, dan salah satu yang didorong oleh wadah IoC, maka oke, mungkin Anda akan ada benarnya. Itu seperti membuat setiap anggota kelas saya menjadi publik lalu menyalahkan orang lain ketika mereka memodifikasi hal-hal yang seharusnya tidak mereka lakukan, bukan? Tetapi siapa pun yang menggunakan injeksi setter untuk menutupi pelanggaran SRP dengan sengaja mengabaikan atau sama sekali tidak mengetahui prinsip-prinsip desain dasar. Tidak masuk akal untuk menyalahkan ini di wadah IoC.
Itu terutama benar karena itu juga sesuatu yang dapat Anda lakukan dengan mudah dengan DI orang miskin:
Jadi sungguh, kekhawatiran ini tampaknya benar-benar ortogonal apakah wadah IOC digunakan atau tidak.
Mengubah cara kerja kelas Anda bukanlah pelanggaran OCP. Jika ya, maka semua inversi ketergantungan akan mendorong pelanggaran OCP. Jika ini masalahnya, keduanya tidak akan berada dalam akronim SOLID yang sama!
Lebih lanjut, baik poin a) maupun b) hampir tidak ada hubungannya dengan OCP. Saya bahkan tidak tahu bagaimana menjawabnya sehubungan dengan OCP.
Satu-satunya hal yang bisa saya tebak adalah bahwa Anda pikir OCP ada hubungannya dengan perilaku yang tidak diubah saat runtime, atau tentang di mana dalam kode siklus hidup dependensi dikendalikan. Ini bukan. OCP adalah tentang tidak harus mengubah kode yang ada ketika persyaratan ditambahkan atau diubah. Ini semua tentang menulis kode, bukan tentang bagaimana kode yang sudah Anda tulis direkatkan (meskipun, tentu saja, kopling longgar adalah bagian penting untuk mencapai OCP).
Dan satu hal terakhir yang Anda katakan:
Ya kamu bisa . Sama sekali tidak ada alasan bagi Anda untuk berpikir bahwa alat-alat ini - yang diandalkan oleh sejumlah besar proyek - lebih buggy atau rentan terhadap perilaku yang tidak terduga daripada perpustakaan pihak ketiga lainnya.
Tambahan
Saya hanya melihat paragraf intro Anda bisa menggunakan beberapa pengalamatan juga. Anda dengan sinis mengatakan bahwa wadah IoC "tidak menggunakan beberapa teknik rahasia yang belum pernah kami dengar" untuk menghindari kode yang berantakan dan rawan duplikasi untuk membuat grafik ketergantungan. Dan Anda benar, apa yang mereka lakukan sebenarnya menangani hal-hal ini dengan teknik dasar yang sama seperti yang selalu dilakukan oleh para programmer.
Biarkan saya berbicara dengan Anda melalui skenario hipotetis. Anda, sebagai programmer, membuat aplikasi besar, dan pada titik masuk, tempat Anda membuat grafik objek, Anda melihat ada kode yang cukup berantakan. Ada beberapa kelas yang digunakan berulang kali, dan setiap kali Anda membangun salah satu dari itu Anda harus membangun seluruh rantai ketergantungan di bawahnya lagi. Selain itu, Anda tidak memiliki cara ekspresif untuk mendeklarasikan atau mengendalikan siklus hidup dependensi, kecuali dengan kode khusus untuk masing-masingnya. Kode Anda tidak terstruktur dan penuh pengulangan. Ini adalah kekacauan yang Anda bicarakan di paragraf intro Anda.
Jadi pertama, Anda mulai sedikit refactor - di mana beberapa kode berulang cukup terstruktur Anda menariknya ke dalam metode pembantu, dan seterusnya. Tapi kemudian Anda mulai berpikir- ini masalah yang saya mungkin bisa mengatasi dalam umum akal, salah satu yang tidak spesifik untuk proyek tertentu tetapi bisa membantu Anda dalam semua proyek masa depan Anda?
Jadi Anda duduk, dan memikirkannya, dan memutuskan bahwa harus ada kelas yang dapat menyelesaikan dependensi. Dan Anda membuat sketsa metode publik apa yang dibutuhkan:
Bind
mengatakan "di mana Anda melihat argumen konstruktor tipeinterfaceType
, berikan contohconcreteType
".singleton
Parameter tambahan mengatakan apakah akan menggunakan instance yang samaconcreteType
setiap kali, atau selalu membuat yang baru.Resolve
hanya akan mencoba untuk membangunT
dengan konstruktor apa pun yang dapat ditemukan argumen siapa semua jenis yang sebelumnya terikat. Itu juga bisa menyebut dirinya secara rekursif untuk menyelesaikan dependensi sepenuhnya. Jika itu tidak dapat menyelesaikan sebuah instance karena tidak semuanya telah diikat, ia mengeluarkan pengecualian.Anda dapat mencoba menerapkan ini sendiri, dan Anda akan menemukan Anda perlu sedikit refleksi, dan beberapa caching untuk binding mana
singleton
benar, tetapi tentu saja tidak ada yang drastis atau mengerikan. Dan begitu Anda selesai - voila , Anda memiliki inti dari wadah IoC Anda sendiri! Apakah itu benar-benar menakutkan? Satu-satunya perbedaan nyata antara ini dan Ninject atau StructureMap atau Castle Windsor atau apa pun yang Anda inginkan adalah bahwa mereka memiliki lebih banyak fungsi untuk menutupi kasus penggunaan (banyak!) Di mana versi dasar ini tidak akan cukup. Tetapi pada intinya, apa yang Anda miliki adalah esensi dari wadah IoC.sumber
Dalam teori? Tidak. Wadah IoC hanyalah alat. Anda dapat memiliki objek yang memiliki tanggung jawab tunggal, antarmuka yang terpisah, tidak dapat mengubah perilakunya setelah ditulis, dll.
Dalam praktek? Benar.
Maksudku, saya pernah mendengar tidak sedikit programmer mengatakan bahwa mereka menggunakan wadah IoC khusus untuk memungkinkan Anda menggunakan beberapa konfigurasi untuk mengubah perilaku sistem - melanggar Prinsip Terbuka / Tertutup. Dulu ada lelucon yang dibuat tentang pengkodean dalam XML karena 90% dari pekerjaan mereka memperbaiki konfigurasi Spring. Dan Anda tentu benar bahwa menyembunyikan dependensi (yang memang diakui, tidak semua wadah IOC melakukannya) adalah cara cepat dan mudah untuk membuat kode yang sangat berpasangan dan sangat rapuh.
Mari kita melihatnya dengan cara yang berbeda. Mari kita pertimbangkan kelas yang sangat mendasar yang memiliki ketergantungan tunggal, dasar. Itu tergantung pada
Action
, delegasi atau functor yang tidak mengambil parameter dan mengembalikanvoid
. Apa tanggung jawab kelas ini? Anda tidak tahu. Saya dapat menyebutkan ketergantungan itu dengan sesuatu yang jelas sepertiCleanUpAction
yang membuat Anda berpikir itu melakukan apa yang Anda inginkan. Begitu IoC mulai berperan, ia menjadi apa saja . Siapa pun dapat masuk ke konfigurasi dan memodifikasi perangkat lunak Anda untuk melakukan banyak hal sewenang-wenang."Apa bedanya dengan memberikan
Action
kepada konstruktor?" Anda bertanya. Ini berbeda karena Anda tidak dapat mengubah apa yang diteruskan ke konstruktor setelah perangkat lunak digunakan (atau saat runtime!). Ini berbeda karena tes unit Anda (atau tes unit konsumen Anda) telah membahas skenario di mana delegasi dilewatkan ke konstruktor."Tapi itu contoh palsu! Barang-barangku tidak memungkinkan perubahan perilaku!" Anda berseru. Maaf untuk memberitahumu, tetapi itu benar. Kecuali jika antarmuka yang Anda suntikkan hanya data. Dan antarmuka Anda bukan hanya data, karena jika itu hanya data, Anda akan membangun objek sederhana dan menggunakannya. Segera setelah Anda memiliki metode virtual di titik injeksi Anda, kontrak kelas Anda menggunakan IoC adalah "Saya bisa melakukan apa saja ".
"Apa bedanya dengan menggunakan skrip untuk mengendalikan sesuatu? Itu tidak apa-apa untuk dilakukan." beberapa dari Anda bertanya. Itu tidak berbeda. Dari perspektif desain program, tidak ada perbedaan. Anda memanggil program Anda untuk menjalankan kode arbitrer. Dan tentu saja, itu sudah dilakukan dalam game sejak lama. Ini dilakukan dalam banyak alat administrasi sistem. Apakah itu OOP? Tidak juga.
Tidak ada alasan untuk keberadaan mereka saat ini. Kontainer IoC memiliki satu tujuan yang kuat - untuk merekatkan ketergantungan Anda ketika Anda memiliki begitu banyak kombinasi, atau mereka bergerak begitu cepat sehingga tidak praktis untuk membuat dependensi itu eksplisit. Jadi sangat sedikit bisnis yang benar-benar sesuai dengan skenario itu.
sumber
Apakah menggunakan wadah IOC harus melanggar prinsip OOP / SOLID? Tidak ada .
Bisakah Anda menggunakan wadah IoC sedemikian rupa sehingga melanggar prinsip OOP / SOLID? Ya .
Kontainer IoC hanyalah kerangka kerja untuk mengelola dependensi dalam aplikasi Anda.
Anda menyatakan injeksi Malas, setter properti, dan beberapa fitur lain yang belum saya rasa perlu digunakan, yang saya setujui dapat memberi Anda desain yang kurang optimal. Namun, penggunaan fitur-fitur spesifik ini disebabkan oleh keterbatasan dalam teknologi tempat Anda menerapkan wadah IoC.
Misalnya, ASP.NET WebForms, Anda diharuskan untuk menggunakan injeksi properti karena tidak mungkin untuk instantiate a
Page
. Ini dapat dimengerti karena WebForms tidak pernah dirancang dengan paradigma OOP yang ketat dalam pikiran.ASP.NET MVC di sisi lain, sangat mungkin untuk menggunakan wadah IoC menggunakan injeksi konstruktor ramah yang sangat OOP / SOLID.
Dalam skenario ini (menggunakan injeksi konstruktor), saya percaya ini mempromosikan prinsip SOLID karena alasan berikut:
Prinsip Tanggung Jawab Tunggal - Memiliki banyak kelas yang lebih kecil memungkinkan kelas-kelas ini menjadi sangat spesifik dan memiliki satu alasan untuk keberadaannya. Menggunakan wadah IoC membuat mengaturnya lebih mudah.
Buka / Tutup - Di sinilah menggunakan wadah IoC benar-benar bersinar, Anda dapat memperluas fungsionalitas kelas dengan cara menyuntikkan dependensi yang berbeda. Memiliki dependensi yang Anda suntikkan memungkinkan Anda mengubah perilaku kelas itu. Contoh yang baik adalah mengubah kelas yang Anda suntikkan dengan menulis dekorator untuk mengatakan menambahkan caching atau masuk. Anda benar-benar dapat mengubah implementasi dependensi Anda jika ditulis dalam tingkat abstraksi yang sesuai.
Prinsip Pergantian Liskov - Tidak terlalu relevan
Prinsip Segregasi Antarmuka - Anda dapat menetapkan banyak antarmuka ke waktu konkret tunggal jika Anda mau, setiap wadah IoC seharga sebutir garam akan dengan mudah melakukan ini.
Dependency Inversion - Container IoC memungkinkan Anda melakukan inversi ketergantungan dengan mudah.
Baik eksplisit dan transparan, Anda perlu memberi tahu wadah IoC Anda cara memasang dependensi dan cara mengelola objek seumur hidup. Ini bisa dengan konvensi, dengan file konfigurasi, atau dengan kode yang ditulis dalam aplikasi utama sistem Anda.
Ini adalah alasan utama OOP / SOLID, untuk membuat sistem dapat dikelola. Menggunakan wadah IoC sejalan dengan tujuan itu.
Kelas dengan 12 dependensi mungkin merupakan pelanggaran SRP apa pun konteksnya Anda menggunakannya.
sumber
Kata
static
kunci dalam C # memungkinkan pengembang untuk melanggar banyak prinsip OOP / SOLID tetapi masih merupakan alat yang valid dalam keadaan yang tepat.Kontainer IoC memungkinkan kode terstruktur dengan baik dan mengurangi beban kognitif pada pengembang. Sebuah wadah IoC dapat digunakan untuk membuat prinsip-prinsip SOLID berikut jauh lebih mudah. Ini bisa disalahgunakan, tentu saja, tetapi jika kita mengecualikan penggunaan alat apa pun yang dapat disalahgunakan, kita harus menyerah pemrograman sama sekali.
Jadi, sementara kata-kata kasar ini memunculkan beberapa poin valid tentang kode yang ditulis dengan buruk, itu bukan pertanyaan dan tidak terlalu berguna.
sumber
Saya melihat banyak kesalahan dan kesalahpahaman dalam pertanyaan Anda. Yang utama pertama adalah bahwa Anda kehilangan perbedaan antara injeksi properti / bidang, injeksi konstruktor, dan pencari layanan. Ada banyak diskusi (mis. Flamewars) tentang cara yang tepat untuk melakukan sesuatu. Dalam pertanyaan Anda, Anda tampaknya menganggap hanya injeksi properti dan mengabaikan injeksi konstruktor.
Hal kedua adalah Anda berasumsi bahwa wadah IoC mempengaruhi desain kode Anda. Mereka tidak, atau setidaknya, seharusnya tidak perlu mengubah desain kode Anda jika Anda menggunakan IOC. Masalah Anda dengan kelas dengan banyak konstruktor adalah kasus IoC menyembunyikan masalah nyata dengan kode Anda (kemungkinan besar kelas yang melanggar SRP) dan dependensi tersembunyi adalah salah satu alasan mengapa orang tidak menyarankan penggunaan injeksi properti dan pencari lokasi.
Saya tidak mengerti dari mana masalah dengan prinsip buka-tutup ini, jadi saya tidak akan mengomentarinya. Tetapi Anda kehilangan satu bagian dari SOLID, yang memiliki pengaruh besar pada ini: Prinsip Ketergantungan Pembalikan. Jika Anda mengikuti DIP, Anda akan menemukan, bahwa membalik dependensi memperkenalkan abstraksi, yang implementasinya perlu diselesaikan ketika instance kelas dibuat. Dengan pendekatan ini, Anda akan berakhir dengan banyak kelas, yang membutuhkan beberapa antarmuka untuk direalisasikan dan disediakan pada konstruksi agar berfungsi dengan baik. Jika Anda kemudian memberikan dependensi itu dengan tangan, Anda harus melakukan banyak pekerjaan tambahan. Kontainer IoC memudahkan untuk melakukan pekerjaan ini dan bahkan memungkinkan Anda untuk mengubahnya tanpa harus mengkompilasi ulang program.
Jadi, jawaban untuk pertanyaan Anda adalah tidak. Kontainer IoC tidak melanggar prinsip-prinsip desain OOP. Sebaliknya, mereka memecahkan masalah yang disebabkan oleh mengikuti prinsip-prinsip SOLID (terutama prinsip Ketergantungan-Inversi).
sumber