Dependency Injection: Haruskah saya membuat kelas mobil untuk menampung semua bagiannya?


10

Saya memiliki banyak mobil di aplikasi C ++ saya semuanya berisi RaceTrack.

Setiap mobil terdiri dari ratusan bagian. Setiap bagian tergantung pada beberapa bagian lainnya.

Saya telah membaca banyak pertanyaan SO pada buku DI dan Mark Seemann dan sepertinya saya tidak boleh mendefinisikan kelas Mobil hanya untuk memegang bagian mobil karena semua bagian mobil akan saling bergantung dan sup bagian ini adalah mobil. Apakah saya benar?

Jadi ketika saya menempatkan semua mobil balap saya ke dalam RaceTrack tidak akan ada entitas mobil tetapi banyak bagian mobil tergantung pada satu sama lain balap di trek ?? Apakah saya benar?

EDIT:

Untuk waktu yang lama saya memprogram kelas-kelas Mobil karena sudah jelas bagi saya bahwa saya memerlukan kelas mobil jika saya memprogram logika mobil. Tetapi dengan DI tidak begitu jelas bagi saya. Masih bertanya-tanya apakah itu idiom bagi DI untuk tidak membuat kelas Mobil jika saya tidak memiliki peran yang pasti untuknya?

Maksud saya apakah boleh menggunakan SteeringWheel untuk dikendarai, BoltsAndNuts beroda untuk kru pit dan semua jenis antarmuka lucu lainnya tanpa memiliki instance yang mewakili mobil secara keseluruhan?

Jawaban:


24

Apa gunanya sekelompok suku cadang mobil duduk di trek balap lakukan siapa pun?

Jika semua kelas mobil Anda lakukan adalah memegang bagian-bagian mobil itu berguna seperti tas basah bagian.

Pemakaian

Sebagai pengemudi, apa yang saya inginkan adalah sesuatu yang dapat saya kendalikan. Itu merespons ketika saya meminta kecepatan. Pegangan seperti itu di rel. Itu bisa berhenti dengan uang receh.

Yang saya inginkan adalah kelas mobil yang dapat digunakan. Itu bisa saya katakan untuk melakukan sesuatu tanpa harus memikirkan cara kerja karburator. Saya hanya berpikir tentang pedal gas. Bagaimana mereka terhubung bukanlah sesuatu yang saya khawatirkan. Itu abstraksi.

Injeksi Ketergantungan

Ketergantungan injeksi tidak ada hubungannya dengan itu. Ketika saya mengendarai mobil saya tidak berpikir tentang bagaimana itu dibangun. Selama ini berhasil, saya tidak peduli bagaimana mereka menggabungkannya.

Tidak, DI adalah apa yang memungkinkan kru pit saya dengan cepat menukar ban saya dengan yang lebih baik ketika hujan mulai turun di lintasan. Sangat menyenangkan bisa melakukan itu tanpa harus naik ke mobil yang sama sekali berbeda.

DI benar-benar tentang mengikuti prinsip: Pisahkan penggunaan dari konstruksi.

Sebuah mobil yang dapat memasang ban baru dengan kecepatan 90 mil per jam mungkin terdengar keren tapi saya tidak berpikir itu akan memenangkan balapan dengan ban yang memasang alat.

DI adalah tentang memasang komponen Anda dengan cara yang memungkinkan kru pit Anda mendapatkannya. Ketika Anda menggunakan newdi tempat yang sama Anda memprogram perilaku itu seperti Anda mengelas karburator ke tempatnya. Tentu saja obor asetilena dapat menghilangkannya, tetapi harap pertimbangkan untuk menggunakan mur dan baut terlebih dahulu.

Itulah DI. Tentu itu tidak semudah memasukkan newsesuatu segera setelah Anda menyadari bahwa Anda menginginkannya. Sebaliknya Anda harus menulis kode terpisah yang tahu cara membuat mobil Anda. Tapi itu pasti membuatnya lebih mudah untuk mengubah keadaan nanti. Dan itu berarti Anda tidak perlu menyeret pabrik perakitan mobil di sekitar lintasan bersama Anda.

Konstruksi

Sesuatu, di suatu tempat, harus tahu apakah bannya adalah Goodyear. Di mana kemudian untuk meletakkan kode konstruksi mobil? Jika bukan mobil maka kru pit? Tidak, jejaknya? Tidak. Semua itu memiliki kode perilaku. Kode yang harus tampil saat balapan. Membangun mobil harus terjadi sebelum balapan di tempat yang dihapus dari kode perilaku. Mark Seemans menyebut tempat ini Root Komposisi . Kebanyakan orang menyebutnya utama.

Ini pola yang sederhana. Secara utama, buat grafik objek lalu panggil satu metode perilaku pada satu objek dalam grafik objek. Itu dia. Ini adalah tempat konstruksi HANYA dan perilaku harus bersama.

Itu tidak berarti konstruksi harus menjadi tumpukan kode prosedural yang semuanya ditata secara berurutan. Anda bebas menggunakan setiap alat dalam bahasa untuk melakukan konstruksi. Hanya saja jangan mencampurnya dengan perilaku.

Melakukan ini dalam bahasa dan tidak menggunakan beberapa kerangka DI atau wadah IoC disebut DI murni . Ini bekerja dengan sangat baik. Sudah sejak lama. Kami biasa menyebutnya referensi lewat .

Alat DI

Apa alat DI membeli Anda adalah rincian konstruksi dipindahkan ke bahasa yang berbeda (xml, json, apa pun) yang menegakkan pemisahan antara konstruksi dan perilaku. Jika Anda tidak memercayai sesama programmer Anda untuk tidak menggunakan newsaat mereka seharusnya tidak menarik.

Yang menarik adalah tergoda untuk membiarkan detail alat DI menyebar ke seluruh basis kode. Terkadang menginfeksi basis kode dengan anotasi eksklusif. Contoh-contoh yang mereka berikan tentu mendorong ini. Alat ini cenderung pindah ke ruang bahasa sampai Anda tidak bisa hanya mengiklankan pekerjaan sebagai pekerjaan pemrograman Java tetapi sebagai pekerjaan pemrograman Java / Spring.

Prinsip desain

Untuk waktu yang lama saya memprogram kelas-kelas Mobil karena sudah jelas bagi saya bahwa saya memerlukan kelas mobil jika saya memprogram logika mobil. Tetapi dengan DI tidak begitu jelas bagi saya. Masih bertanya-tanya apakah itu idiom bagi DI untuk tidak membuat kelas Mobil jika saya tidak memiliki peran yang pasti untuknya?

Saya pikir Anda belajar tentang abstraksi dan mengubah cara Anda memutuskan kelas diperlukan. Itu bagus. Tapi itu bukan tentang DI. DI tidak membantu Anda memutuskan apakah Anda membutuhkan kelas mobil. DI membantu Anda menjaga agar mobil tidak tahu, dan karenanya peduli, jika bannya adalah ban Goodyear. DI membantu Anda menjaga jalur agar tidak mengetahui apakah mobil tersebut dibuat di Jepang.

Salah satu pertanyaan paling mendasar dalam desain perangkat lunak adalah "apa yang tahu tentang apa?" Itulah hal utama yang ditunjukkan diagram UML kepada Anda. Ketika Anda menemukan sesuatu yang Anda capai melewati itu antarmuka ke hal konkret yang sekarang Anda terikat. Mobil sekarang harus tahu bahwa bannya adalah Goodyear. Yang agak menyebalkan jika Michelin ingin mensponsori Anda.

Menghindari melakukan itu disebut mengikuti prinsip inversi ketergantungan . Secara formal, modul tingkat tinggi (seperti kelas mobil) tidak boleh langsung bergantung pada modul tingkat rendah (seperti kelas GoodyearTire). Itu harus bergantung pada abstraksi (seperti antarmuka Tyre).

Cara untuk menghindari hal itu disebut Pembalikan kontrol . Di sini penekanannya adalah pada mengubah aliran kontrol. Apakah ban menggerakkan mobil atau mobil menggerakkan ban? Memikirkan hal ini dengan cara yang benar memungkinkan kita untuk tidak memasangkan mobil dan ban secara statis. DI adalah salah satu cara khusus untuk mengikuti Inversion of Control.

Tidak ada yang memberi tahu Anda jika Anda membutuhkan kelas mobil. Jika Anda memprogram "logika mobil" itu bagus jika ada satu tempat untuk menyimpannya daripada menyebarkannya di mana saja. Hanya saja jangan tertipu dengan berpikir logika konstruksi mobil sama dengan logika perilaku mobil sehingga semuanya harus hidup di tempat yang sama. Tetapi jika Anda tidak memiliki roll yang ditentukan untuk mobil maka Anda juga tidak perlu. Balap motor di trek jika Anda suka.

Maksud saya apakah boleh menggunakan SteeringWheel untuk dikendarai, BoltsAndNuts beroda untuk kru pit dan semua jenis antarmuka lucu lainnya tanpa memiliki instance yang mewakili mobil secara keseluruhan?

DI atau tidak DI, boleh saja memiliki instance yang mewakili mobil secara keseluruhan, tetapi instance itu bukan sesuatu yang ingin saya ketahui secara langsung jika saya tidak perlu. Berikan saya abstraksi mobil jadi saya tidak perlu peduli apakah itu berjalan pada gas, diesel, atau listrik ketika saya menggunakannya. Itu hanya sesuatu yang harus saya pedulikan ketika saya membangun atau memeliharanya. Sangat menyenangkan jika kode yang menggunakan mobil tidak harus tahu atau peduli bagaimana cara kerjanya. "Aku tidak tahu. Aku tidak ingin tahu."


Akan lebih keren jika Anda tidak menggunakan metafora mobil dan kru pit untuk pertanyaan yang menggunakannya untuk mewakili kode. Tapi tetap saja, jawaban yang bagus.
S. Tarık Çetin

6
Dan saya selalu berpikir Inversion of Control adalah ketika Anda mengarahkan kiri tetapi mobil berbelok ke kanan ...
mkrieger1

CandiedOrange, jadi tidak ada kelas Mobil jika tidak memiliki antarmuka yang berarti dan tanggung jawab yang jelas? Dan tidak ada Car.h di proyek saya. Dan kolega melihat ke kode saya dan bertanya-tanya apakah itu e-shop mobil atau aplikasi pengelola garasi? :)
Anton Petrov

@AntonPetrov "jika terlihat seperti bebek dan dukun seperti bebek, tetapi membutuhkan baterai Anda mungkin memiliki abstraksi yang salah". Nama yang baik sangat penting dan sulit dipikirkan tetapi harus diubah untuk mencerminkan tanggung jawab yang jelas dan antarmuka yang bermakna sehingga tidak mengejutkan. Jika saya membaca nama lalu melihat antarmuka dan berpikir "itu yang saya harapkan" maka Anda memiliki nama baik.
candied_orange

15

sepertinya saya tidak boleh mendefinisikan kelas Mobil hanya untuk memegang bagian mobil karena semua bagian mobil akan saling bergantung dan sup bagian ini adalah mobil. Apakah saya benar?

Tidak.

Titik injeksi ketergantungan sama sekali tidak untuk mencegah ketergantungan. Justru sebaliknya.

Ketergantungan injeksi adalah tentang pertanyaan: mana mobil mendapatkan bagian-bagiannya dari ? Di mana dan bagaimana mereka dibuat, dan bagaimana mobil mendapatkan referensi kepada mereka?

Secara naif, mobil akan membuat bagian-bagiannya sendiri dengan memanggil new. Ini mudah dan langsung, tetapi sangat tidak fleksibel. Mobil harus mengetahui semua yang diperlukan untuk membuat bagian-bagiannya, dan jika Anda ingin memiliki dua mobil dengan bagian yang berbeda, logika itu harus masuk ke mobil juga.

Dengan injeksi ketergantungan, semua logika dikeluarkan dari mobil dan dimasukkan ke dalam komponen konfigurasi, yang menciptakan semua bagian dan menghubungkan referensi. Ketergantungan yang dikonfigurasi sepenuhnya disuntikkan ke dalam mobil - dan satu sama lain.


1
Akhirnya, penjelasan dependency injectionkonsep yang waras .
anatoly techtonik

1
Saya akan mengatakan sistem yang lebih umum untuk pendekatan "naif" bukanlah bahwa mobil itu akan memanggil baru, tetapi bahwa pengguna kelas mobil akan menetapkan bagian-bagiannya ke propertinya, dan sementara itu kelas mobil akan berada di keadaan tak tentu. DI menyediakan cara untuk memastikan validitas kelas secara mekanis.
whatsisname

2
@whatsisname Saya dapat dengan mudah menggunakan DI untuk membuat objek yang tidak valid dan setengah diinisialisasi. Validasi bukan tanggung jawab DI. Juga tidak berubah. DI dapat mengambil pekerjaan membangun objek yang valid dan tidak berubah. DI tidak memiliki cara untuk menegakkan bahwa itu adalah satu-satunya cara benda-benda itu dibangun dan digunakan. Objek harus menegakkan ini.
candied_orange

@CandiedOrange: jadi Anda bisa dengan mudah menggunakan teknik apa saja untuk membuat sesuatu yang setengah-setengah, jadi apa? Membutuhkan dependensi pada konstruktor, dan membuatnya tidak berubah, bukan peluru perak, tapi tetap saja cara yang sangat berguna untuk mencegah banyak situasi buruk umum.
whatsisname

0

Jadi ketika saya menempatkan semua mobil balap saya ke dalam RaceTrack tidak akan ada entitas mobil tetapi banyak bagian mobil tergantung pada satu sama lain balap di trek ?? Apakah saya benar?

Baik. Iya dan tidak. Entitas mobil masih berlaku untuk dimiliki. Dan mobil lebih dari jumlah bagian-bagiannya. Anda memerlukan driver juga (untuk saat ini). Banyak kali mobil balap memiliki nama juga, belum lagi Merek dan Model mobil.

Ya, mobil pada dasarnya adalah sebuah wadah suku cadang, tetapi pengemasan dan kerja sama suku cadang inilah yang membentuk sesuatu yang lebih besar: sebuah mobil.

Jadi sungguh tidak. Mobil bukan hanya kantong logam dan plastik yang acak. Ini sebuah mesin.

Injeksi ketergantungan tidak berlebihan dalam kasus ini. Sesuatu yang lain harus membangun mobil, yang akan menjadi kelas pabrik atau objek Builder. Mobil itu seharusnya tidak tahu bagaimana membangunnya sendiri.


2
Anda dapat memiliki DI tanpa objek pabrik atau pembangun. Parameter konstruktor sederhana adalah metode valid yang berfungsi untuk banyak keadaan.
whatsisname
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.