Injeksi ketergantungan: Pada titik apa saya diizinkan membuat objek baru?

13

Saya refactoring aplikasi PHP , dan saya coba lakukan memiliki injeksi ketergantungan (DI) sebanyak mungkin.

Saya merasa memiliki pemahaman yang baik tentang cara kerjanya, dan tentu saja saya bisa melihat kelas saya menjadi jauh lebih ramping dan lebih kuat.

Saya refactoring sehingga saya dapat menyuntikkan ketergantungan daripada membuat objek baru di dalam kelas, tetapi pada titik tertentu saya harus membuat beberapa objek, yaitu, menggunakan newkata kunci yang ditakuti .

Masalah yang saya hadapi sekarang adalah pada titik mana saya bisa benar-benar membuat objek baru? Sepertinya saya akan berakhir di kelas tingkat atas, membuat banyak objek baru karena tidak ada tempat lain untuk pergi. Ini terasa salah.

Saya telah membaca beberapa blog yang menggunakan kelas pabrik untuk membuat semua objek, dan kemudian Anda menyuntikkan pabrik ke kelas lain. Anda kemudian dapat memanggil metode pabrik, dan pabrik membuat objek baru untuk Anda.

Kekhawatiran saya dengan melakukan ini adalah sekarang kelas pabrik saya akan menjadi newgratis-untuk-semua! Saya kira ini mungkin baik-baik saja karena mereka adalah kelas pabrik, tetapi apakah ada beberapa aturan yang harus dipatuhi ketika menggunakan pola pabrik dan DI, atau apakah saya akan jauh dari sasaran di sini?

Gaz_Edge
sumber
Saya merekomendasikan IoC untuk layanan dan kebijakan. Untuk kelas model atau pembantu saya hanya akan menggunakan new. Tentu saja ada beberapa titik masuk di mana Anda perlu memanggil ke wadah IoC, tetapi seharusnya tidak banyak. Biasanya Anda mengkonfigurasi IoC sekali dan kemudian meminta satu kelas untuk diselesaikan per permintaan. Dalam kasus MVC itu biasanya controller.
CodesInChaos
Kelas tingkat atas yang Anda sebutkan adalah bagian dari Root Komposisi. Jauh dari salah.
Rasio Facio

Jawaban:

12

Setelah sedikit googling untuk ini, sepertinya (seperti yang disebutkan dalam komentar di atas) kelas tingkat atas yang saya bicarakan disebut Composition Root .

Tampaknya memang solusi yang diterima untuk menambahkan penciptaan semua objek dalam Komposisi Root ini (atau merujuk wadah IoC dari sini).

Kekhawatiran asli saya dengan ini adalah bahwa kelas atas ini akan berakhir sedikit berantakan. Ini benar sampai batas tertentu, tetapi kelebihan pro menimbang kontra. Sebagai contoh saya dapat melihat keterbacaan, testabilitas dan perawatan semua kelas saya yang lain telah meningkat.

Kelas tingkat atas mungkin agak berantakan, berserakan newdan set_property()tapi saya harus mengatakan saya sebenarnya lebih suka memiliki semua kode ini di satu tempat, daripada tersebar di seluruh kelas lain

Halaman lain yang bermanfaat membahas hit kinerja dari metode ini di sini

Gaz_Edge
sumber
1
+1 karena saya belum pernah mendengar tentang 'Komposisi Root' sebelumnya.
c_maker
2

Kelas Pabrik akan newditaburkan di seluruh kelas. Itu akan menciptakan objek apa pun yang Anda minta dan mungkin dependensi objek itu. Karena pekerjaan pabrik adalah untuk instantiate objek yang benar untuk Anda miliki newdi kelas ini bukanlah hal yang buruk.

DI adalah agar Anda memiliki desain yang digabungkan secara longgar. Anda dapat membuat perubahan pada aplikasi Anda dengan mengubah ketergantungan yang disediakan untuk setiap objek. Membuat aplikasi Anda fleksibel, dapat dikembangkan, dan mudah diuji.

Di tingkat atas, Anda akan memiliki kode yang akan membuat beberapa pabrik, mengatur koneksi ke layanan, dan mengirim respons. Itu akan memiliki cukup banyak newatau panggilan statis untuk instantiate objek yang diperlukan untuk aplikasi Anda. Di situlah tempatnya.

Schleis
sumber
-2

Dua sen saya di sini:

Saya refactoring aplikasi php dan saya coba lakukan memiliki injeksi ketergantungan sebanyak mungkin

Anda tidak menyatakan jika Anda menggunakan kerangka kerja injeksi ketergantungan. Saya pikir Anda pasti harus. Gunakan sesuatu yang memberi Anda fitur yang Anda butuhkan: /programming/9348376/guice-like-dependency-injection-frameworks-in-php .

Masalah yang saya hadapi sekarang adalah pada titik mana saya bisa benar-benar membuat objek baru? Sepertinya saya akan berakhir di kelas tingkat atas, membuat banyak objek baru karena tidak ada tempat lain untuk pergi. Ini terasa salah.

Anda biasanya menggunakan konfigurasi atau titik pusat untuk instantiasi objek awal yang menyusun aplikasi Anda. Wadah akan membuat objek untuk Anda.

Anda kemudian mengakses objek (layanan, penyedia, pengontrol ...) melalui wadah IoC. Ini akan secara transparan membuat objek untuk Anda jika diperlukan, atau memberi Anda referensi ke instance yang ada yang sesuai.

Tentu saja, di dalam implementasi objek khusus Anda, Anda dapat membuat instance objek lain di mana Anda tidak perlu DI (struktur data, tipe kustom, dll), tapi itu pemrograman normal.

Saya telah membaca beberapa blog yang menggunakan kelas pabrik untuk membuat semua objek, dan kemudian Anda menyuntikkan pabrik ke kelas lain. Anda kemudian dapat memanggil metode pabrik, dan pabrik membuat objek baru untuk Anda.

Biasanya, Anda menggunakan Pabrik jika Anda ingin kerangka kerja IoC untuk instantiate beberapa objek IoC melalui pabrik Anda (ini diperlukan saat instantiasi objek tertentu memerlukan kerja ekstra). Jika Anda bisa membuat objek dengan "Objek baru ()", dan mengatur beberapa properti, Anda tidak perlu ingin menggunakan pola Pabrik.

Dengan kata lain, saya akan mengatakan bahwa menggunakan pola Pabrik untuk kelas atau kelompok kelas tergantung pada bagaimana Anda ingin memodelkan kelas-kelas itu, bukan pada apakah Anda menggunakan DI (kecuali jika implementasi DI Anda secara eksplisit membutuhkan pabrik, yang tidak biasa).

Anda juga mengonfigurasi kerangka kerja IoC Anda untuk menggunakan Pabrik saat Anda menggunakan lib pihak ke-3 yang sudah membutuhkan penggunaan Pabrik. Dalam hal ini Anda tidak memiliki kendali tentang ini dan Anda perlu memberi tahu wadah IoC Anda: "Hei, ketika saya meminta salah satu antarmuka ini, Anda harus menggunakan pabrik ini untuk memberi saya contoh yang tepat".

Kekhawatiran saya dengan melakukan ini adalah sekarang kelas pabrik saya akan menjadi gratis-untuk-semua yang baru! Saya kira ini mungkin baik-baik saja karena mereka adalah kelas pabrik, tetapi apakah ada beberapa aturan yang harus dipatuhi ketika menggunakan pola pabrik dan DI, atau apakah saya akan jauh dari sasaran di sini.

Dalam hal ini, sepertinya Anda tidak perlu menggunakan pola Pabrik untuk objek / layanan / pengontrol / apa pun ini, dan Anda dapat mengkonfigurasi IoC Anda untuk membuat instance dengan "baru" kelas yang sesuai dan menyuntikkan yang lainnya.

Saya harap ini membantu.

jjmontes
sumber
terima kasih atas jawaban, tapi pasti wadah IoC adalah 'kelas atas' yang saya maksud. Jika saya hanya bisa membuat objek di sana, itu akan menjadi kekacauan yang tepat.
Gaz_Edge
4
doing DI manually beats the whole purpose of using an Inversion of Control container- Jika maksud Anda "... yang memusatkan dependensi Anda dalam file konfigurasi" maka Anda benar, karena hanya itu yang benar-benar wadah IoC. Tujuan sebenarnya dari DI adalah decoupling, dan Anda dapat melakukannya dengan memasok dependensi Anda dalam metode konstruktor. Anda tidak perlu kerangka DI sama sekali untuk melakukan itu.
Robert Harvey
mmm Anda tidak membuat objek, Anda meminta wadah IoC untuk mereka (dari mana pun Anda perlu), atau Anda menggunakan injeksi bidang / argumen sehingga kelas Anda secara otomatis menyuntikkan kelas yang sesuai, dibuat selalu oleh wadah IoC.
jjmontes
1
Saya setuju bahwa Anda memerlukan kerangka kerja untuk aplikasi yang sangat besar . Banyak aplikasi tidak begitu besar, dan tidak mendapat manfaat dari kompleksitas tambahan menggunakan kerangka kerja DI.
Robert Harvey
2
Saya tidak mengatakan itu. Saya hanya mengatakan bahwa Anda tidak perlu wadah DI untuk melakukannya.
Robert Harvey