Latar Belakang
Saya memiliki proyek yang tergantung pada penggunaan jenis perangkat perangkat keras tertentu, sementara itu tidak terlalu penting siapa yang membuat perangkat perangkat keras selama itu melakukan apa yang saya butuhkan. Dengan itu dikatakan, bahkan dua perangkat yang seharusnya melakukan hal yang sama akan memiliki perbedaan ketika mereka tidak dibuat oleh produsen yang sama. Jadi saya berpikir untuk menggunakan antarmuka untuk memisahkan aplikasi dari merek / model perangkat tertentu yang terlibat, dan sebagai gantinya memiliki antarmuka hanya mencakup fungsionalitas tingkat tertinggi. Inilah yang saya pikirkan arsitektur saya akan terlihat seperti:
- Tentukan antarmuka dalam satu proyek C #
IDevice
. - Memiliki beton di perpustakaan yang ditentukan dalam proyek C # lain, yang akan digunakan untuk mewakili perangkat.
- Apakah perangkat konkret mengimplementasikan
IDevice
antarmuka. - The
IDevice
antarmuka mungkin memiliki metode sepertiGetMeasurement
atauSetRange
. - Buat aplikasi memiliki pengetahuan tentang beton, dan meneruskan beton ke kode aplikasi yang memanfaatkan ( bukan mengimplementasikan )
IDevice
perangkat.
Saya cukup yakin bahwa ini adalah cara yang tepat untuk melakukannya, karena dengan begitu saya akan dapat mengganti perangkat apa yang sedang digunakan tanpa mempengaruhi aplikasi (yang sepertinya kadang-kadang terjadi). Dengan kata lain, tidak masalah bagaimana implementasi GetMeasurement
atau SetRange
benar - benar bekerja melalui beton (karena mungkin berbeda di antara produsen perangkat).
Satu-satunya keraguan dalam pikiran saya, adalah bahwa sekarang keduanya aplikasi, dan kelas konkret perangkat keduanya bergantung pada perpustakaan yang berisi IDevice
antarmuka. Tapi, apakah itu hal yang buruk?
Saya juga tidak melihat bagaimana aplikasi tidak perlu tahu tentang perangkat, kecuali perangkat dan IDevice
berada di namespace yang sama.
Pertanyaan
Apakah ini tampak seperti pendekatan yang tepat untuk mengimplementasikan antarmuka untuk memisahkan ketergantungan antara aplikasi saya dan perangkat yang digunakannya?
Jawaban:
Saya pikir Anda sudah memiliki pemahaman yang cukup baik tentang cara kerja perangkat lunak yang dipisahkan :)
Tidak harus!
Anda dapat menangani semua masalah ini dengan Struktur Proyek .
Cara saya biasanya melakukannya:
Common
proyek. Sesuatu sepertiMyBiz.Project.Common
. Proyek lain bebas untuk merujuknya, tetapi mungkin tidak merujuk proyek lain.MyBiz.Project.Devices.TemperatureSensors
. Proyek ini akan merujukCommon
proyek.Client
proyek saya yang merupakan titik masuk ke aplikasi saya (sesuatu sepertiMyBiz.Project.Desktop
). Saat startup, aplikasi melewati proses Bootstrap di mana saya mengkonfigurasi pemetaan abstraksi / implementasi beton. Saya bisa instantiateIDevices
seperti beton sayaWaterTemperatureSensor
dan diIRCameraTemperatureSensor
sini, atau saya bisa mengkonfigurasi layanan seperti Pabrik atau wadah IoC untuk instantiate jenis beton yang tepat untuk saya nanti.Kuncinya di sini adalah hanya
Client
proyek Anda yang perlu mengetahuiCommon
proyek abstrak dan semua proyek implementasi konkret. Dengan membatasi abstrak-> pemetaan konkret ke kode Bootstrap Anda, Anda memungkinkan seluruh aplikasi Anda tidak menyadari jenis-jenis konkret.Kode yang digabungkan dengan longgar :)
sumber
new Foo(new DeviceA());
), daripada memiliki bidang pribadi dalam Foo instantiate DeviceA sendiri (private IDevice idevice = new DeviceA();
) - Anda masih mencapai DI, seperti Foo tidak menyadari DeviceA dalam kasus pertamaYa, itu sepertinya pendekatan yang tepat. Tidak, itu bukan hal buruk bagi aplikasi dan pustaka perangkat untuk bergantung pada antarmuka, terutama jika Anda mengendalikan implementasi.
Jika Anda khawatir perangkat mungkin tidak selalu mengimplementasikan antarmuka, untuk alasan apa pun, Anda dapat memanfaatkan pola adaptor dan menyesuaikan implementasi konkret perangkat ke antarmuka.
EDIT
Dalam menyikapi keprihatinan kelima Anda, pikirkan struktur seperti ini (saya berasumsi Anda mengendalikan mendefinisikan perangkat Anda):
Anda memiliki perpustakaan inti. Di dalamnya ada antarmuka yang disebut IDevice.
Di pustaka perangkat Anda, Anda memiliki referensi ke pustaka inti Anda, dan Anda telah menentukan serangkaian perangkat yang semuanya mengimplementasikan IDevice. Anda juga memiliki pabrik yang tahu cara membuat berbagai jenis layanan.
Dalam aplikasi Anda, Anda menyertakan referensi ke perpustakaan inti dan perpustakaan perangkat. Aplikasi Anda sekarang menggunakan pabrik untuk membuat instance objek yang sesuai dengan antarmuka IDevice.
Ini adalah salah satu dari banyak cara yang mungkin untuk mengatasi masalah Anda.
CONTOH:
sumber
Anda perlu berpikir sebaliknya. Jika Anda tidak melakukannya, aplikasi perlu tahu tentang semua perangkat / implementasi yang berbeda. Yang harus Anda ingat adalah, bahwa mengubah antarmuka itu dapat merusak aplikasi Anda jika sudah keluar dari alam, maka Anda harus merancang antarmuka tersebut dengan cermat.
Cukup ya
Aplikasi ini dapat memuat perakitan beton (dll) saat runtime. Lihat: /programming/465488/can-i-load-a-net-assembly-at-runtime-and-instantiate-a-type-knowing-only-the-na
Jika Anda perlu secara dinamis membongkar / memuat "driver" tersebut, Anda perlu memuatnya ke dalam AppDomain yang terpisah .
sumber
IDevice
antarmuka Anda sehingga perangkatnya dapat digunakan dengan aplikasi Anda, maka tidak akan ada cara lain IMO.