Kopling kode diperkenalkan oleh DRY dan OOD

14

Saya mencari panduan tentang KERING vs Kopling kode. Saya tidak suka menduplikasi kode saya dan saya juga tidak suka kode kopling antara modul yang tidak terkait. Jadi saya refactor kode duplikat jika saya menemukan kode duplikat identik setahun setelah duplikasi diperkenalkan. Namun, saya semakin mengalami situasi di mana dunia nyata jauh lebih tidak dapat diprediksi, dan setelah refactoring kode, muncul situasi yang memerlukan forking kode lagi.

Misalnya, jika saya memiliki kode untuk menangani mobil bensin, SUV bensin, mobil listrik dan SUV listrik, katakanlah saya refactored kode duplikat ke dalam hierarki "bensin" dan hierarki "listrik", keduanya turun dari hierarki "kendaraan". Sejauh ini baik. Dan kemudian, perusahaan saya memperkenalkan mobil hybrid dan semi-hybrid yang akan membutuhkan perubahan inti pada hierarki asli saya sendiri. Mungkin itu akan membutuhkan "komposisi" antara bensin dan hierarki listrik.

Jelas duplikasi kode buruk karena meningkatkan waktu yang dibutuhkan untuk mengimplementasikan perubahan yang umum untuk semua produk di atas. Tetapi refactoring kode umum membuat sama sulitnya untuk memperkenalkan variasi spesifik produk, dan mengarah ke banyak "peningkatan kelas" ketika seseorang harus menemukan garis kode untuk memperbaiki bug - satu perubahan dalam kelas induk tingkat yang lebih tinggi dapat memicu bug regresi memicu di antara semua keturunan.

Bagaimana cara mencapai keseimbangan optimal antara KERING vs kopling kode yang tidak diinginkan?

pengguna2549686
sumber
1
Itu selalu baik untuk tidak mengikuti aturan secara membabi buta tetapi melibatkan otak terlebih dahulu.
gnasher729
cukup adil - karenanya pedoman, bukan aturan.
user2549686
Sudahkah Anda membaca halaman Wiki di KERING (atau OAOO, seperti dulu)? wiki.c2.com/?OnceAndOnlyOnce Di situlah banyak diskusi awal tentang hal itu terjadi. (Sebenarnya, Ward menemukan Wiki secara khusus untuk diskusi tentang Pola dan Praktek.)
Jörg W Mittag
Jawaban yang sangat terkait, meskipun pertanyaannya tidak terdengar seperti duplikat: softwareengineering.stackexchange.com/questions/300043/…
Hulk

Jawaban:

8

katakanlah saya refactored kode duplikat ke hierarki "bensin" dan hierarki "listrik", keduanya turun dari hierarki "kendaraan". Sejauh ini baik.

Dan kemudian, perusahaan saya memperkenalkan mobil hybrid dan semi-hybrid yang akan membutuhkan perubahan inti pada hierarki asli saya sendiri. Mungkin itu akan membutuhkan "komposisi" antara bensin dan hierarki listrik

Saya pikir ini adalah salah satu alasan utama orang bergerak menuju komposisi alih-alih warisan.

Warisan memaksa Anda melakukan restrukturisasi besar-besaran ketika Anda memiliki perubahan konseptual seperti yang Anda gambarkan.

Ketika restrukturisasi 'terlalu besar / sulit' maka orang-orang menulis kode duplikat untuk menghindarinya.

Daripada remote duplikat dengan memindahkan kode ke rantai pewarisan Anda dapat memindahkannya ke kelas pembantu atau layanan dan kemudian menyuntikkan kelas itu sebagai bagian dari komposisi di mana diperlukan.

Apakah desain yang dihasilkan adalah OOP terbuka untuk diperdebatkan

Ewan
sumber
1
+1 untuk menunjukkan bahwa warisan adalah masalahnya, bukan KERING. Cara termudah untuk menggunakan kembali kode adalah menghapus dependensi yang tidak perlu, dan terlalu sering orang melewatkan fakta bahwa kelas induk (dan turunannya) adalah semua dependensi saat menggunakan warisan. Hanya ketika Anda mengurangi atau menghilangkan dependensi, Anda benar-benar mendapatkan kode yang dapat digunakan kembali.
Greg Burghardt
3
" Apakah desain yang dihasilkan adalah OOP terbuka untuk diperdebatkan ". Semuanya terbuka untuk diperdebatkan. Pertanyaan yang harus diajukan adalah, apakah ini terbuka untuk debat rasional yang masuk akal? Jawabannya adalah tidak. Saya pikir paragraf terakhir Anda mengurangi jawaban yang sangat baik.
David Arno
@davidarno tidak benar-benar mengikuti Anda, saya membaca OOD di judul sebagai Object Orientated Design? jadi saya menjawab pertanyaan tanpa melalui debat
Ewan
1
@ Ewan: Saya di sini bersama David Arno. Saya pikir sudah terkenal selama lebih dari 2 dekade bahwa kepercayaan "jika tidak ada warisan, maka itu bukan OOP" adalah kekeliruan.
Doc Brown
Memercayai inilah tepatnya jenis diskusi yang saya coba hindari. ada pandangan di kedua sisi, tidak ada jawaban pasti
Ewan
3

Anda benar, mengikuti prinsip KERING, dapat meningkatkan sambungan antara modul yang tidak terkait. Terutama dalam sistem perangkat lunak yang lebih besar, ini dapat menyebabkan situasi di mana tidak mengikuti KERING dapat menjadi alternatif yang lebih baik.

Sayangnya, contoh Anda tidak cocok untuk menunjukkan ini - masalah yang dijelaskan di sana disebabkan oleh kesalahan klasik dalam penggunaan pewarisan suboptimal yang salah . Namun, untuk apa yang telah saya tulis di atas, tidak masalah jika Anda mereformasi kode umum ke kelas dasar umum, atau ke dalam kelas pembantu (komposisi). Dalam kedua kasus, seseorang mungkin terpaksa memasukkan kode umum ke perpustakaan L dan merujuk perpustakaan itu dari dua program yang sebelumnya tidak terkait A dan B.

Mari kita asumsikan A dan B sama sekali tidak terkait sebelumnya, mereka dapat versi, dirilis dan digunakan secara mandiri. Namun, dengan memasukkan kode umum ke lib L bersama, persyaratan baru untuk A dapat menyebabkan perubahan ke L, yang sekarang dapat menyebabkan perubahan ke B. Jadi ini menyebabkan perlunya tes tambahan, dan mungkin rilis baru dan siklus penggunaan untuk B.

Jadi bagaimana Anda bisa menangani situasi ini, jika Anda tidak mau meninggalkan prinsip KERING? Nah, ada beberapa taktik terkenal untuk mendekati ini:

  1. Baik tetap menggunakan A, B, dan L sebagai bagian dari produk yang sama, dengan satu nomor versi umum, proses pembuatan, rilis, dan penyebaran yang sama, dengan otomatisasi tingkat tinggi

  2. atau membuat L produk sendiri, dengan nomor versi kecil (tidak ada perubahan yang tidak kompatibel) dan nomor versi utama (mungkin mengandung perubahan yang melanggar), dan biarkan A dan B memungkinkan masing-masing untuk referensi garis versi L. yang berbeda

  3. Jadikan L SOLID mungkin, dan rawat kompatibilitas ke belakang. Semakin banyak modul dalam L yang dapat digunakan kembali tanpa modifikasi (OCP), semakin kecil kemungkinan terjadinya kerusakan. Dan prinsip-prinsip lain dalam "SOLID" membantu mendukung tujuan itu.

  4. Gunakan tes otomatis terutama untuk L, tetapi juga untuk A dan B.

  5. Hati-hati dengan logika L. Business yang seharusnya hanya ada di satu tempat dalam suatu sistem adalah kandidat yang baik. Hal-hal yang "mirip" dan mungkin berbeda di masa depan adalah kandidat yang buruk.

Perhatikan ketika A dan B dikembangkan, dipelihara, dan dikembangkan oleh tim yang berbeda dan tidak terkait, prinsip KERING menjadi sangat kurang penting - KERING adalah tentang pemeliharaan dan evolusi, tetapi membiarkan dua tim yang berbeda memberikan upaya pemeliharaan individu kadang-kadang lebih efektif daripada mengikat produk mereka bersama karena sedikit penggunaan kembali.

Jadi pada akhirnya, itu adalah tradeoff. Jika Anda ingin mengikuti prinsip KERING dalam sistem yang lebih besar, Anda perlu menginvestasikan lebih banyak upaya untuk menciptakan komponen yang kuat dan dapat digunakan kembali - biasanya lebih dari yang Anda harapkan. Anda harus memercayai penilaian Anda ketika itu layak, dan ketika tidak.

Doc Brown
sumber
1

KERING adalah aturan struktural lainnya. Itu berarti jika Anda mengambilnya secara ekstrem itu sama buruknya dengan jika Anda mengabaikannya. Inilah metafora untuk mengeluarkan Anda dari pola pikir struktural.

Cintai saudara kembar Anda. Bunuh klon.

Saat Anda menyalin dan menempel secara membabi buta untuk menghindari pengetikan keyboard, Anda tanpa sadar membuat klon. Tentu mereka melakukan apa yang Anda inginkan tetapi mereka membebani Anda karena sekarang mengubah perilaku itu sangat mahal.

Ketika Anda mereproduksi perilaku yang identik dengan kode yang identik karena tanggung jawab yang berbeda kebetulan memiliki kebutuhan yang sama sekarang, tetapi itu mungkin memberi Anda perubahan berbeda, Anda memiliki saudara kembar yang harus bebas untuk berubah dan tumbuh sebagai individu seiring berjalannya waktu.

Anda dapat memindai DNA (kode) mereka sesuka Anda. Klon dan kembar sulit dibedakan jika yang Anda lakukan hanyalah melihatnya. Yang Anda butuhkan adalah memahami konteks tempat tinggal mereka. Mengapa mereka dilahirkan. Kemungkinan nasib akhir mereka.

Katakanlah Anda bekerja untuk perusahaan ABC. Dijalankan oleh tiga eksekutif perusahaan, A, B, dan C. Semua dari mereka ingin Anda membuat produk perangkat lunak tetapi mereka masing-masing memiliki departemen sendiri. Mereka semua ingin Anda memulai dari yang kecil. Keluarkan pesan sederhana untuk saat ini. Jadi Anda menulis "Hello World".

A membencinya, ingin kau meletakkan nama perusahaan di sana.

B menyukainya, ingin Anda membiarkannya dan menambahkan nama perusahaan ke layar splash.

C hanya ingin kalkulator dan menganggap pesan itu hanya cara bagi Anda untuk memulai.

Satu hal yang Anda yakini, orang-orang ini memiliki ide yang sangat berbeda tentang proyek ini. Terkadang mereka akan setuju. Terkadang mereka akan menarik Anda ke arah yang berbeda.

Ketika Anda menduplikasi kode karena Anda membuat kemampuan untuk kode itu berbeda secara mandiri, Anda membuat kembar. Ketika Anda menduplikasi kode karena mengetik itu menyakitkan dan menyalin dan menempel dengan mudah Anda membuat klon jahat.

A, B, dan C adalah master berbeda yang harus dilayani oleh kode Anda. Tidak ada satu baris kode yang dapat melayani lebih dari satu master untuk waktu yang lama.

candied_orange
sumber
Pertama-tama, terima kasih banyak untuk semua komentarnya.
user2549686