Asumsikan kita memiliki modul perangkat lunak A yang mengimplementasikan fungsi F. Modul B lainnya mengimplementasikan fungsi yang sama dengan F '.
Ada beberapa cara untuk menghilangkan kode duplikat:
- Biarkan A menggunakan F 'dari B.
- Biarkan B menggunakan F dari A.
- Masukkan F ke dalam modul C-nya sendiri dan biarkan A dan B menggunakannya.
Semua opsi ini menghasilkan dependensi tambahan antar modul. Mereka menerapkan prinsip KERING dengan biaya meningkatkan sambungan.
Sejauh yang saya bisa lihat, kopling selalu meningkat atau disewa pindah ke tingkat yang lebih tinggi saat menerapkan KERING. Tampaknya ada konflik antara dua prinsip paling mendasar dari desain perangkat lunak.
(Sebenarnya saya tidak merasa heran bahwa ada konflik seperti itu. Ini mungkin yang membuat desain perangkat lunak yang baik sangat sulit. Saya menemukan mengejutkan bahwa konflik ini biasanya tidak dibahas dalam teks pengantar.)
Sunting (untuk klarifikasi): Saya berasumsi bahwa kesetaraan F dan F 'bukan hanya kebetulan. Jika F harus dimodifikasi, F 'kemungkinan harus dimodifikasi dengan cara yang sama.
sumber
Jawaban:
Kenapa ya mereka lakukan. Tetapi mereka mengurangi kopling antara garis. Apa yang Anda dapatkan adalah kekuatan untuk mengubah kopling. Kopling hadir dalam berbagai bentuk. Mengekstrak kode meningkatkan tipuan dan abstraksi. Peningkatan itu bisa baik atau buruk. Hal nomor satu yang menentukan yang Anda dapatkan adalah nama yang Anda gunakan untuk itu. Jika melihat nama itu membuat saya terkejut ketika saya melihat ke dalam, maka Anda belum melakukan bantuan.
Juga, jangan ikuti KERING dalam ruang hampa. Jika Anda membunuh duplikat Anda bertanggung jawab untuk memprediksi bahwa kedua penggunaan kode itu akan berubah bersama. Jika mereka cenderung berubah secara independen, Anda telah menyebabkan kebingungan dan kerja ekstra untuk sedikit manfaat. Tapi nama yang sangat bagus bisa membuat itu lebih enak. Jika yang dapat Anda pikirkan adalah nama yang buruk maka tolong, berhenti saja sekarang.
Kopling akan selalu ada kecuali sistem Anda sangat terisolasi sehingga tidak ada yang akan tahu jika itu berfungsi. Jadi coupling refactoring adalah permainan memilih racun Anda. Mengikuti KERING dapat memberikan hasil dengan meminimalkan pemasangan yang dibuat dengan mengungkapkan keputusan desain yang sama berulang-ulang di banyak tempat hingga sangat sulit untuk diubah. Tetapi KERING dapat membuatnya mustahil untuk memahami kode Anda. Cara terbaik untuk menyelamatkan situasi itu adalah menemukan nama yang sangat bagus. Jika Anda tidak dapat memikirkan nama yang baik saya harap Anda terampil menghindari nama yang tidak berarti
sumber
Ada cara untuk memutus dependensi eksplisit. Yang populer adalah menyuntikkan dependensi dalam runtime. Dengan cara ini, Anda mendapatkan KERING, menghapus sambungan dengan biaya keamanan statis. Ini sangat populer saat ini, bahwa orang-orang bahkan tidak mengerti, itu adalah tradeoff. Misalnya, wadah aplikasi secara rutin menyediakan manajemen ketergantungan perangkat lunak yang sangat menyulitkan dengan menyembunyikan kompleksitas. Bahkan injeksi konstruktor tua biasa gagal untuk menjamin beberapa kontrak karena kurangnya jenis sistem.
Untuk menjawab judul - ya, itu mungkin, tetapi bersiaplah untuk konsekuensi dari pengiriman runtime.
Dengan cara ini, satu-satunya jenis dependensi yang Anda miliki adalah D tergantung pada masing-masing modul lainnya.
Atau daftarkan C dalam wadah aplikasi dengan injeksi dependensi bawaan dan nikmati keberuntungan autowiring yang perlahan-lahan meningkatkan loop dan deadlock classloading runtime.
sumber
Saya tidak yakin jawaban tanpa konteks lebih lanjut masuk akal.
Apakah
A
sudah tergantungB
atau sebaliknya? - dalam hal ini kita mungkin memiliki pilihan rumah yang jelasF
.Apakah
A
danB
sudah berbagi dependensi umum yang mungkin menjadi rumah yang baikF
?Seberapa besar / kompleksnya
F
? Apa lagiF
tergantung pada?Apakah modul
A
danB
digunakan dalam proyek yang sama?Akankah
A
danB
akhirnya berbagi beberapa ketergantungan bersama?Bahasa / modul sistem apa yang digunakan: Seberapa menyakitkan modul baru, dalam rasa sakit programmer, dalam overhead kinerja? Sebagai contoh, jika Anda menulis dalam C / C ++ dengan sistem modul menjadi COM, yang menyebabkan rasa sakit pada kode sumber, memerlukan tooling alternatif, memiliki implikasi pada debugging, dan memiliki implikasi kinerja (untuk permintaan antar-modul), saya mungkin mengambil jeda yang serius.
Di sisi lain, jika Anda berbicara tentang Java atau C # DLL yang menggabungkan agak mulus dalam lingkungan eksekusi tunggal, itu masalah lain.
Fungsi adalah abstraksi, dan mendukung KERING.
Namun, abstraksi yang baik harus lengkap - abstraksi yang tidak lengkap sangat mungkin menyebabkan klien yang mengkonsumsi (programmer) membuat kekurangan dengan menggunakan pengetahuan tentang implementasi yang mendasarinya: ini menghasilkan kopling yang lebih ketat daripada jika abstraksi yang ditawarkan malah lebih lengkap.
Jadi, saya berpendapat untuk mencari untuk membuat abstraksi yang lebih baik untuk
A
danB
bergantung pada daripada hanya memindahkan satu fungsi tunggal ke modul baruC
.Saya akan mencari satu set fungsi untuk digoda menjadi abstraksi baru, yang bisa dikatakan, saya mungkin menunggu sampai basis kode lebih lanjut untuk mengidentifikasi refactoring abstraksi yang lebih lengkap / lebih lengkap untuk dilakukan daripada berdasarkan pada satu kode fungsi kirim.
sumber
Does A already depend on B or vice versa? — in which case we might have an obvious choice of home for F.
Ini mengasumsikan bahwa A akan selalu bergantung pada B (atau sebaliknya), yang merupakan asumsi yang sangat berbahaya. Fakta bahwa OP melihat F tidak secara inheren bagian dari A (atau B) menunjukkan bahwa F ada tanpa melekat pada salah satu perpustakaan. Jika F milik satu perpustakaan (misalnya metode ekstensi DbContext (F) dan perpustakaan pembungkus Entity Framework (A atau B)), maka pertanyaan OP akan diperdebatkan.Di sini, jawaban yang berfokus pada semua cara Anda dapat "meminimalkan" masalah ini merugikan Anda. Dan "solusi" hanya menawarkan berbagai cara untuk membuat sambungan bukan solusi yang sesungguhnya.
Yang benar adalah bahwa Anda gagal memahami masalah yang Anda buat sendiri. Masalah dengan contoh Anda tidak ada hubungannya dengan KERING, melainkan (lebih luas) dengan desain aplikasi.
Tanyakan pada diri Anda mengapa modul A dan B terpisah jika keduanya bergantung pada fungsi F yang sama? Tentu saja Anda akan memiliki masalah dengan manajemen dependensi / abstraksi / kopling / nama-Anda-jika Anda berkomitmen untuk desain yang buruk.
Pemodelan aplikasi yang tepat dilakukan sesuai dengan perilaku. Dengan demikian, potongan A dan B yang bergantung pada F perlu diekstraksi ke dalam modul mereka sendiri. Jika ini tidak memungkinkan, maka A dan B perlu dikombinasikan. Dalam kedua kasus tersebut, A dan B tidak lagi berguna bagi sistem dan seharusnya tidak ada lagi.
KERING adalah prinsipal yang dapat digunakan untuk mengekspos desain yang buruk, bukan menyebabkannya. Jika Anda tidak dapat mencapai KERING ( ketika itu benar-benar berlaku - mencatat suntingan Anda) karena struktur aplikasi Anda, itu adalah tanda yang jelas bahwa struktur telah menjadi kewajiban. Inilah sebabnya mengapa “refactoring berkelanjutan” juga merupakan prinsip yang harus diikuti.
ABC dari prinsip desain lainnya (SOLID, KERING, dll) di luar sana semua digunakan untuk mengubah (termasuk refactoring) aplikasi lebih tanpa rasa sakit. Fokuslah pada hal itu , dan semua masalah lain mulai menghilang.
sumber
Saya memiliki pendapat yang berbeda, setidaknya untuk opsi ketiga:
Dari uraian Anda:
Menempatkan F dalam modul C tidak meningkatkan kopling karena A dan B sudah membutuhkan fitur C.
sumber