Mengapa KERING penting?

81

Cukup sederhana, mengapa saya ingin menulis kode yang berfungsi untuk semua kasus dan data yang dapat diskalakan ketika yang harus saya lakukan adalah mengulangi proses yang sama beberapa kali dengan beberapa perubahan kecil?

Saya tidak perlu mengedit ini lagi dalam waktu dekat.

Sepertinya banyak pekerjaan yang harus diselesaikan ...

function doStuff1(){/*.a.*/}
function doStuff2(){/*.b.*/}
function doStuff3(){/*.c.*/}

Dan jika saya perlu menambahkan sesuatu ...

function doStuff4(){/*.d.*/}

Dan jika saya perlu menghapusnya, saya menghapusnya.

Lebih sulit untuk mengetahui bagaimana membuat semua itu menjadi satu pola yang lurus ke depan bahwa saya bisa memasukkan data ke dalam dan menangani semua kasus, dan membuat banyak perubahan. Saya tidak merasa seperti akan pernah memiliki melakukan.

Mengapa menjadi KERING ketika terlihat seperti potong cepat + tempel akan menjadi jauh lebih sedikit bekerja?

Penyamaran
sumber
11
karena kering masih lebih cepat ketika Anda melakukannya dengan benar, juga bagaimana jika Anda membuat kesalahan dalam. yang mempengaruhi semua yang lain
Daniel Little
97
"Saya tidak perlu mengedit ini lagi dalam waktu dekat" - Anda mungkin berharap, tetapi kemungkinan besar Anda membuat kesalahan di sini. Dan jika Anda akan bekerja pada kode itu lagi, tetapi tidak begitu cepat, itu hanya akan memperburuk keadaan; Anda akan lupa di mana duplikat berada, dan duplikat akan tumbuh perbedaan yang halus tapi berbahaya. "Tulis seolah-olah orang yang akan menjaga kode Anda adalah orang gila yang tahu di mana Anda tinggal", mengutip kutipan klasik.
9000
14
Saya pikir Anda bisa menyimpulkannya: Satu titik perubahan lebih mudah dipertahankan.
Falcon
17
Jika Anda tidak bisa menjawabnya sendiri, Anda perlu mendapatkan pengalaman pengembangan dan pemeliharaan dunia nyata yang lebih banyak.
David Heffernan
15
@Wayne saya merasakan gangguan besar di sumbernya, seolah-olah jutaan programmer tiba-tiba berteriak ketakutan.
Incognito

Jawaban:

121

Jika Anda mengulangi diri Anda sendiri, Anda dapat membuat masalah pemeliharaan. Jika doStuff1-3 semua memiliki kode terstruktur yang sama dan Anda memperbaiki masalah dalam satu, Anda bisa dengan mudah lupa untuk memperbaiki masalah di tempat lain. Juga, jika Anda harus menambahkan case baru untuk ditangani, Anda dapat dengan mudah memberikan parameter yang berbeda ke dalam satu fungsi daripada menyalin-menempel di semua tempat.

Namun, KERING sering dibawa ke ekstrem oleh programmer yang pintar. Kadang-kadang untuk tidak mengulangi diri sendiri, Anda harus membuat abstraksi, jadi anggap rekan tim Anda tidak bisa mengikutinya. Kadang-kadang struktur dua hal ini hanya samar-samar serupa tetapi cukup berbeda. Jika doStuff1-4 cukup berbeda sehingga refactoring mereka untuk tidak mengulangi diri Anda menyebabkan Anda harus menulis kode yang tidak wajar atau menjalani backflip pengkodean yang pintar yang akan menyebabkan tim Anda memelototi Anda, maka boleh saja mengulangi sendiri. Saya telah membungkuk ke belakang untuk tidak mengulangi diri saya beberapa kali dengan cara yang tidak wajar dan menyesali produk akhirnya.

Saya selalu berbuat salah di sisi KERING, dalam kasus yang jarang terjadi berulang ketika saya berpikir bahwa manfaat dalam keterbacaan sebanding dengan risiko seseorang lupa memperbaiki bug di banyak tempat.

Mempertimbangkan saran itu, sepertinya dalam kasus Anda

ulangi proses yang sama beberapa kali dengan sedikit perubahan kecil

Saya pasti akan bekerja keras untuk tidak mengulangi sendiri dalam kasus Anda. Dengan asumsi "tweak" minimal - mereka dapat ditangani dengan parameter yang berbeda yang mempengaruhi perilaku atau mungkin disuntikkan ketergantungan untuk melakukan subtugas yang berbeda.

Mengapa menjadi KERING ketika terlihat seperti potong cepat + tempel akan menjadi jauh lebih sedikit bekerja?

Kata-kata terakhir yang terkenal. Anda akan menyesal berpikir bahwa ketika seorang insinyur junior melakukan tweak / perbaikan / refaktor, satu doStuff dan bahkan tidak menyadari yang lain ada. Hilaritas terjadi. Sebagian besar tidak terjadi mulas. Setiap baris kode harganya lebih mahal. Berapa banyak jalur kode yang harus Anda uji dengan begitu banyak fungsi yang diulang? Jika satu berfungsi, Anda hanya perlu menguji satu jalur utama dengan beberapa modifikasi perilaku. Jika disalin, Anda harus menguji setiap doStuff secara terpisah. Kemungkinan Anda akan kehilangan satu dan pelanggan mungkin memiliki bug yang tidak disukai dan Anda mungkin memiliki beberapa email yang tidak disukai di kotak masuk Anda.

Doug T.
sumber
2
Eh, hanya untuk memperjelas, saya tidak mengusulkan kering itu buruk, pertanyaan ini lebih merupakan advokasi setan. Saya benar-benar mencari respons logis yang dapat saya tautkan ke orang-orang yang berpikir cut + paste + kode tweak baik-baik saja.
Incognito
2
Yang sedang berkata, saya paling suka jawaban Anda karena itu mencakup kedua kegagalan di KERING: tidak mengganggu, dan pergi berlebihan, serta menjelaskan dampak. - Pada satu titik tentang mengorbankan keterbacaan untuk bug, saya berpendapat bahwa kode berulang kurang dapat dibaca karena alasan yang sama dengan yang Anda tunjukkan, di mana mudah untuk kehilangan jejak.
Incognito
16
Saya akan menggarisbawahi satu perangkap mudah KERING: kode serupa digabungkan. Jika Anda memiliki dua kasus penggunaan yang secara fungsional tidak terkait tetapi kebetulan memiliki kode yang sangat mirip, mudah untuk menggabungkan keduanya karena KERING baik . Sayangnya, ketika seseorang perlu berevolusi, Anda kemudian sering menemukan diri Anda dengan tugas yang tidak menyenangkan karena harus memecah fungsi sekali lagi, dan kemudian pergi melalui semua situs panggilan dan dengan hati-hati mempertimbangkan yang mana yang harus dipanggil di sini ... Contoh: LLVM struktural mengetik (semua tipe serupa digabung menjadi satu) membuatnya hampir tidak mungkin untuk memetakan IR kembali ke kode asli.
Matthieu M.
1
Bingo. Jika dua atau lebih potongan kode akan diubah, dan perubahan akan selalu sama untuk semua bagian, maka mereka harus digabung. Setiap bagian yang perlu diubah dengan cara yang berbeda dari yang lain tidak boleh digabungkan. Jika kode tidak akan pernah berubah sama sekali, tidak masalah apakah itu digabung atau tidak. Pertanyaan apakah perubahan harus dikunci atau dilepaskan jauh lebih penting daripada ukuran kode yang dimaksud.
supercat
1
@ MatthieuM itu sedikit contoh yang tidak adil. LLVM menerapkan pengetikan struktural sebagai pengoptimalan ; yaitu, orang-orang LLVM memutuskan untuk membayar harga IR yang sulit dipahami untuk manfaat kinerja. KERING biasanya merupakan masalah rawatan, tetapi dalam kasus ini jelas merupakan keputusan yang disengaja untuk mengurangi rawatan.
Benjamin Hodgson
47

Karena KERING akan kurang bekerja nantinya.


KERING: (Jangan Ulangi Diri Sendiri)

Satu fungsi mengambil argumen.

def log(arg):
    print(arg)

C&P: (Salin & Tempel)

26 trilyun fungsi pada dasarnya melakukan hal yang sama, tetapi dengan perbedaan 2 karakter.

def logA():
    print('a')

def logB():
    print('b')

...ad infinitum...

Bagaimana kalau kita memperbarui pencetakan kita untuk menentukan apa yang sebenarnya dicetak?

KERING:

def log(arg):
    print(arg + "Printed from process foo")

Selesai.

C&P:

Anda harus kembali dan mengubah setiap fungsi .


Menurut Anda, mana yang lebih mudah di-debug?

John
sumber
10
Selain itu, Anda perlu menulis suite tes serupa karena Anda memiliki fungsi ganda.
9000
Anda telah mengilustrasikan konsep tersebut secara memadai, tetapi dalam praktiknya tidak ada yang akan melakukan apa yang Anda gambarkan dengan fungsi trilyun, tidak dengan cara itu.
Robert Harvey
@ Robert Saya harap tidak! Saya memilih tugas yang sangat sederhana untuk mencoba mengilustrasikan konsep dengan lebih baik dan mengapa itu bisa menjadi hal yang baik.
John
11
@Robert - sudahkah Anda membaca artikel di thedailywtf.com ;) - ada beberapa di luar sana yang akan melakukan hal itu
HorusKol
1
@ 9000 Tidak jika Anda tidak memiliki suite tes: p (yang sebenarnya sering terjadi di beberapa proyek ... sayangnya ...)
Svish
16

Karena , terapkan pada contoh Anda:

  • + keterbacaan

    Lebih sedikit kode sering diterjemahkan menjadi lebih sedikit noise . (tidak selalu...)

  • + fleksibilitas

    Jika Anda harus mengubah perilaku doStuffX, Anda pasti ingin bunuh diri atau siapa pun yang menulisnya,

  • + diperpanjang

    Jika Anda telah mengekstraksi bagian-bagian yang berbeda ke struktur data pilihan Anda dan kemudian hanya mengulanginya dengan memanggil generik doStuff, Anda bisa menambahkan satu baris dalam struktur data Anda di mana Anda ingin entri baru, atau menghapus satu, dan mengubah perilaku hanya akan berarti mengedit doStuff. Lebih mudah dirawat .

  • + efisiensi biaya

    lebih sedikit kode di sini berarti:

    • => lebih sedikit pengembangan => pengurangan biaya
    • => lebih sedikit probabilitas untuk bug => lebih sedikit waktu dukungan => pengurangan biaya
  • + (mungkin) optimisasi terkelola

    Bergantung pada bahasanya, kompiler / juru bahasa mungkin memiliki peluang lebih besar untuk menentukan bahwa generik doStuffselalu melakukan hal-hal yang hampir identik sering satu panggilan bergantian, dan dapat menyambungkannya atau berupaya mengoptimalkannya . Mungkin tidak akan untuk variasi X dari doStuffX.

  • + pengujian dan kualitas

    Pengujian lebih mudah: doStuffperlu pengujian, dan hanya itu. Yah, tidak persis, tapi itu sudah mencakup lebih . Hanya harapan IO-nya yang bervariasi dan perlu diuji dalam kondisi yang berbeda, tetapi masih jauh lebih mudah untuk diuji dan lebih dapat dipertahankan daripada semua variasi doStuffX.

Secara keseluruhan, ini menyumbang kode yang lebih dapat dipelihara dan peningkatan efisiensi pengembangan untuk tim Anda, dan ini adalah salah satu dari banyak praktik bagus untuk membantu Anda menghasilkan perangkat lunak yang lebih kuat dan dapat diandalkan.

haylem
sumber
13

Karena semua orang telah melakukan pekerjaan yang hebat dalam menjelaskan masalah pemeliharaan dengan kode duplikat, saya hanya akan mengatakan ini:

Banyak pemrograman mengharuskan Anda untuk memikirkan masa depan, bukan hanya saat ini saja. Anda benar bahwa salin & tempel lebih mudah sekarang, tetapi pernyataannya, saya tidak perlu mengedit ini lagi dalam waktu dekat " menunjukkan Anda tidak berpikir dengan benar. Ya, Anda mungkin membeli sedikit waktu dengan salin / tempel yang cepat dan kotor, tetapi dengan melakukannya Anda menunjukkan bahwa Anda tidak dapat melihat di luar masalah langsung Anda dan berpikir tentang hari esok. Apakah Anda yakin Anda tidak akan pernah perlu mengunjungi kembali kode ini? Apakah Anda tahu pasti ada tidak ada bug di dalamnya? Bisakah Anda 100% menjamin Anda tidak perlu mengunjungi lagi ketika set fitur berikutnya perlu diimplementasikan? Itu adalah masalah untuk besok, dan perlu dipertimbangkan ketika Anda merancang hari ini.

Tentu saja, ada kalanya copy / paste diperlukan. Sebagai pengembang UI, saya menemukan ada saatnya saya harus melanggar prinsip KERING. Itu menyebalkan, saya ngeri setiap kali itu terjadi, dan untungnya, itu jarang terjadi. Tapi itu memang terjadi.

Perbedaannya adalah bahwa ketika melanggar KERING, Anda harus memiliki alasan yang sangat kuat untuk melakukannya, dan pernyataan itu, Lebih sulit untuk mengetahui bagaimana menjadikan semua itu menjadi satu pola yang lurus ke depan bukan benar-benar salah satunya. Kecuali jika Anda berada dalam masa krisis besar-besaran dan bos Anda berteriak untuk mendapatkan sesuatu dalam beberapa jam ke depan atau Anda akan kehilangan pekerjaan Anda, saya tidak berpikir ini adalah alasan yang valid.

Jangan salah paham: Saya tidak mencoba menghukum atau menghukum Anda, tetapi mencoba dan membuat Anda melihat di mana mentalitas Anda salah. Programer berinvestasi dalam kemalasan masa depan; KERING adalah cara untuk mencapai itu. Pekerjaan yang Anda lakukan hari ini memecahkan masalah desain yang sulit akan memberi hasil besok.

bedwyr
sumber
Saya tidak yakin bahwa saya setuju dengan bos yang memberi tahu Anda "selesaikan atau Anda dipecat" adalah alasan bagus untuk melanggar KERING. Utang teknis, kapan Anda punya waktu untuk melakukannya dengan benar, apakah itu benar-benar menghemat waktu, dll?
Incognito
1
@Incognito, saya mencoba untuk menjadi sedikit ironis :)
bedwyr
7

Saya tidak perlu mengedit ini lagi dalam waktu dekat.

Jika ini benar-benar terjadi, maka Anda mungkin bisa lolos begitu saja, tetapi lebih sering daripada tidak Anda akan bekerja pada kode yang perlu dipertahankan. Itu berarti memperluas fungsionalitas, memperbaiki bug, dan peningkatan lainnya. Jika Anda memiliki variasi kecil dari kode yang sama di 10 tempat berbeda, dan suatu hari Anda kembali ke kode itu dan perlu melakukan perubahan, Anda sekarang memiliki tugas rawan kesalahan untuk membuat perubahan yang sama di 10 tempat berbeda (Maaf, ada ada 11 tempat, Anda lupa satu dan sekarang Anda memiliki bug).

Jika Anda dapat menggeneralisasi masalah apa yang ingin Anda selesaikan, Anda dapat membuat kode lebih mudah diperluas dan diperbaiki jika bug muncul.

Alex
sumber
Jawaban keren, tetapi bahkan jika saya bisa lolos begitu saja, bagaimana dengan getah miskin yang dapat mempertahankannya setelah saya? ;).
Incognito
Lihat: "lebih sering daripada tidak Anda akan bekerja pada kode yang perlu dipertahankan" :)
Alex
Meskipun begitu, hanya masalahnya jika apa yang Anda salin dan tempelkan 100% sempurna bebas bug. Dan tidak, dan berhenti berpikir itu mungkin.
Dan Ray
Saya akui saya sudah menyalin dan menempelkan barang-barang di masa lalu, tetapi tidak pernah untuk apa pun yang akan saya pertahankan selama lebih dari satu hari. Terkadang Anda hanya memerlukan skrip dibuang yang cepat dan kotor.
Alex
6

Seperti yang saya nyatakan dalam jawaban untuk pertanyaan lain, pendekatan saya adalah sebagai berikut:

  1. Pertama kali saya memecahkan masalah tertentu, saya baru saja menyelesaikannya.
  2. Kedua kalinya (yaitu ketika saya memecahkan masalah yang sama) saya pikir: hm, mungkin saya mengulangi diri saya sendiri, tetapi saya akan pergi untuk salin dan tempel cepat untuk saat ini.
  3. Ketiga kalinya saya berpikir: hm, saya mengulangi sendiri -> buatlah itu menjadi umum!

Yaitu hingga 2, prinsip lain (YAGNI) menang atas KERING. Tetapi mulai dari 3 (atau 4 jika saya benar-benar malas!) Sepertinya saya akan membutuhkannya dan saya mengikuti KERING.

Memperbarui

Beberapa ide lebih lanjut dari pengalaman saya baru-baru ini. Saya harus mengadaptasi / mengintegrasikan dua komponen A dan B yang dikembangkan oleh tim lain ke dalam produk kami. Pertama: dua komponen A dan B sangat mirip satu sama lain, jadi saya sudah terganggu oleh kenyataan bahwa mereka memiliki arsitektur yang agak berbeda. Kedua: Saya harus mengadaptasinya sehingga saya akan senang menggunakan subclass dan hanya mengesampingkan apa yang benar-benar saya butuhkan.

Jadi saya mulai refactoring dua komponen ini (masing-masing terdiri dari sekitar 8 kelas C ++): Saya ingin memiliki arsitektur yang sama untuk A dan B, dan kemudian menambahkan fitur yang kita butuhkan dengan mendefinisikan subclass. Dengan cara ini, dua komponen baru kami A 'dan B' akan diturunkan dari yang sudah ada.

Setelah dua minggu mencoba mengeluarkan struktur yang umum dan jelas dari kode yang ada dan harus menjelaskan selama pertemuan harian kami bahwa saya membuat sedikit kemajuan karena kode aslinya terlalu berantakan, saya berbicara dengan bos saya. Kami mengamati bahwa kami tidak akan memerlukan apa-apa selain dua komponen baru ini A 'dan B' (tidak akan ada empat atau enam dari mereka, hanya dua).

Ok, jadi itu: Saya melakukan copy besar-besaran dan mengubah nama kelas dari A dan B dan mulai mengadaptasi salinan kode. Saya mulai berfungsi dalam dua minggu lagi (masih melakukan beberapa perbaikan bug sekarang).

Keuntungan: Kami memiliki fungsi yang hampir selesai sekarang dan ketika kami telah memperbaiki semua bug kami selesai. Kami telah menyimpan semua refactoring dan pengujian A dan B.

Kekurangan: Dua minggu lalu tim lain mengubah komponen C lain, yang digunakan oleh A dan B. Mereka mengadaptasi A dan B tetapi A 'dan B' juga rusak dan kami harus mengubahnya sendiri. Ini memperkenalkan bug baru yang harus kami perbaiki. Pekerjaan tambahan ini mungkin tidak perlu jika A 'dan B' telah membagikan sebagian besar kode mereka dengan A dan B.

Jadi: duplikasi kode selalu berbahaya. Saya pikir itu selalu masalah mencari timbal balik dan seringkali itu tidak mudah.

Giorgio
sumber
5

Hanya untuk memperjelas, karena saya tidak menemukan ini di salah satu jawaban lain:

KERING adalah prinsip pengembangan perangkat lunak yang bertujuan mengurangi pengulangan semua jenis informasi .

Setiap pengetahuan harus memiliki representasi tunggal, tidak ambigu, otoritatif dalam suatu sistem.

Prinsip KERING seperti yang disebutkan oleh Andy Hunt dan Dave Thomas tidak terbatas untuk mencegah duplikasi kode. Ini juga mengadvokasi pembuatan kode dan setiap proses otomasi. Ironisnya, hasil pembuatan kode bahkan bisa menjadi kode duplikat ...

Alasan mengapa telah dijelaskan secara menyeluruh dalam jawaban lain, tetapi komentar Falcon meringkasnya dengan cukup baik IMHO:

Satu titik perubahan lebih mudah dipertahankan.

Steven Jeuris
sumber
Oh wow, saya pikir tag memiliki beberapa data di dalamnya. Saya akan menaruh beberapa info di sana.
Incognito
3

Ada yang namanya KERING terlalu banyak. Ketika ini terjadi, dua konsep yang muncul pada titik tertentu cukup mirip untuk menjamin kode anjak (1) kemudian menjadi cukup berbeda sehingga mereka layak untuk implementasi yang terpisah.

Dengan kata lain, KERING dan sambungan longgar terkadang bertentangan. Jika Anda berharap doStuff1 dan teman-teman menyimpang dengan setiap rilis baru perangkat lunak, tidak apa-apa untuk menggandakan kode mereka.

Dalam pengalaman saya, mungkin sulit untuk menilai kemana perangkat lunak Anda pergi di masa depan, dan untuk alasan ini, KERING sering merupakan pilihan yang aman.

Kode yang terlalu "kering" biasanya memiliki aliran kontrol yang kompleks dan terlalu banyak parameter. Apa yang awalnya merupakan fungsi sederhana kemudian diperluas untuk mendukung fungsionalitas baru yang dikendalikan oleh parameter tambahan. Setelah dua atau tiga iterasi, fungsi tidak lagi dapat dipertahankan. Perbaiki bug yang terjadi di pengaturan, dan Anda memperkenalkan bug baru di pengaturan lain.

Dapat dimengerti bahwa kualitas kode sering turun ketika kode berevolusi, tetapi saya telah melihat kasus di mana fungsi multi-parameter dengan spaghetti if-then-else di dalam tubuh adalah hasil dari upaya refactoring yang bermaksud baik tetapi tidak dilakukan dengan baik.

(1) Saya menggunakan kata "kode", tetapi ini juga berlaku untuk desain.

Joh
sumber
Ini akan membantu untuk memberikan contoh "terlalu banyak kering" karena itu adalah ujung spektrum yang kurang terlihat.
Incognito
@Incognito: Saya telah mengedit jawaban saya. Tidak ada contoh nyata, tapi mudah-mudahan yang saya maksud sudah cukup jelas.
Joh
2

Saya harus menyebutkan masalah dengan KERING di dunia basis data relasional. Basis data dirancang untuk berkinerja cepat dan baik menggunakan set-based logic dan melalui query yang besar. Prinsip KERING sering menyebabkan pengembang untuk menulis pertanyaan non-Sargable atau menggunakan logika Row-by-agonizing-Row untuk meningkatkan kode yang ada dalam berbagai situasi. KERING dan optimalisasi kinerja sering bertentangan dan di dunia basis data, kinerja biasanya jauh lebih penting daripada rawatan. Ini tidak berarti bahwa Anda tidak boleh menggunakan prinsip KERING sama sekali, hanya saja Anda harus menyadari bagaimana hal itu akan memengaruhi kegunaan keseluruhan basis data. Pengembang aplikasi penting terlebih dahulu dan kinerja kedua, pengembang basis data berpikir integritas data pertama, kinerja kedua, keamanan data ketiga (kinerja dan keamanan mungkin bertukar tempat di beberapa sistem).

Saya telah memperhatikan secara umum, bahwa semakin banyak lapisan abstraksi yang Anda masukkan ke dalam database, semakin lama semakin lambat permintaannya. Saya tidak mengatakan saya tidak berharap orang-orang yang merancang program basis data sendiri tidak melakukan pekerjaan yang lebih baik untuk memungkinkan pengembang untuk menggunakan KERING tanpa mempengaruhi seberapa baik kinerja database, tapi saya tidak merancang perangkat lunak database pada tingkat itu , jadi mungkin konflik antara abstraksi dan kinerja dalam database lebih sulit untuk diperbaiki daripada yang saya kira. Namun, kami harus bekerja dengan sistem karena mereka sedang dibangun. Kami dapat meminta implementasi yang lebih baik dari prinsip-prinsip KERING dalam rilis mendatang yang tidak juga akan membunuh kinerja (dan telah menjadi lebih baik selama bertahun-tahun tetapi masih bermasalah), tetapi sementara itu kita harus mempertimbangkan jika KERING adalah langkah yang tepat untuk database ini pada saat ini.

Tetapi seringkali fitur yang ingin Anda gunakan untuk memastikan prinsip KERING terpenuhi adalah orang-orang yang menyebabkan masalah luar biasa untuk basis data. Saya tidak mengatakan tidak pernah menggunakan KERING tetapi jangan berlebihan dengan itu.

Contoh dari apa yang saya bicarakan. Anda perlu melakukan impor data sejuta catatan sebulan sekali. Rekaman sudah bisa ditambahkan secara manual melalui antarmuka pengguna yang memanggil proc tersimpan. Proc ini, karena dirancang untuk impor rekaman tunggal, hanya menambahkan satu rekaman pada satu waktu. Menggunakan KERING untuk menghindari memasukkan kode di dua tempat, Anda menulis kursor untuk memanggil proc berulang kali daripada menulis impor berbasis set yang Anda butuhkan. Waktu untuk impor berlangsung dari 30 menit yang dibutuhkan menggunakan logika berbasis set ke 18 jam. Sekarang cara yang tepat untuk mematuhi KERING dalam hal ini adalah dengan memperbaiki proc untuk menangani impor rekaman mulitple. Sayangnya, sering kali tidak mungkin atau sangat sulit untuk mengirim array ke proc (tergantung pada ujung belakang db) dan dengan mengubah proc, Anda akhirnya melanggar aplikasi.

Fungsi skalar dan fungsi bernilai tabel juga digunakan untuk menerapkan prinsip KERING dan sekali lagi mereka dapat secara serius mempengaruhi kinerja terutama jika Anda perlu menggunakannya dengan cara yang mencegah indeks agar tidak berguna.

Tampilan juga bagus untuk mengimplementasikan KERING. Namun, jika Anda menerapkan KERING melalui penggunaan tampilan yang memanggil tampilan yang memanggil tampilan lain, Anda akan dengan cepat sampai ke titik di mana kueri akan habis waktu habis di bawah beban. Bahkan Anda mungkin akhirnya perlu menghasilkan set data jutaan catatan saat Anda hanya membutuhkan tiga di akhir. Jadi pandangan satu tingkat dari serangkaian gabungan kompleks untuk mengimplementasikan KERING bisa menjadi sangat baik (saya punya satu sendiri yang kami gunakan untuk memastikan semua pelaporan keuangan menggunakan kumpulan dasar tabel yang sama dan perhitungan hal-hal tertentu), lebih dari dua tingkat dan Anda perlu mempertimbangkan jika Anda membuat kekacauan kinerja.

HLGEM
sumber
1

Saya tidak melihat poin kunci dari jawaban saya di atas, jadi begini. Jangan memandang KERING sebanyak aturan melawanmelakukan sesuatu. Mungkin diutarakan seperti itu tetapi itu benar-benar dapat melayani tujuan yang sangat berbeda dan positif. Ini adalah sinyal untuk berhenti, berpikir, dan menemukan jawaban yang lebih baik. Ini menantang saya untuk mencari peluang untuk merancang solusi yang lebih baik. Ini adalah sisi baik dari bau busuk dalam kode saya yang mendorong saya untuk memikirkan kembali desain saya dan membuat saya melakukannya jauh lebih baik. KERING bukan hanya tentang pelanggaran sintaksis. Itu menantang saya untuk memodulasi. Ini menantang saya untuk membuat komponen. Ini menandakan pengulangan yang mengingatkan saya untuk berpikir tentang menggunakan templat dan pembuatan kode, bukannya kekerasan dan ketidaktahuan. Ini membantu saya mengetahui bahwa saya harus mencari waktu untuk mengotomatisasi otomasi saya. Ini membawa Anda ke gaya hidup pelit! Ini membantu Anda untuk menghabiskan lebih banyak waktu Anda melakukan hal-hal baru yang lebih keren daripada detail membosankan tua nitpicky. Dan itu memberi Anda sopan santun, napas yang baik, dan gaya hidup sehat! Yah, mungkin aku agak tersesat ....

John Tobler
sumber
KERING memiliki efek yang sangat berbeda pada saya, namun, jika ini adalah efeknya pada Anda, saya lebih suka filosofi sesuatu menjadi "sinyal untuk berhenti, berpikir, dan menemukan jawaban yang lebih baik", dan tantangannya.
n611x007
1

Saya memiliki proyek lawas lama, di mana beberapa mantan pengembang tidak peduli sama sekali KERING. Jadi seluruh basis kode itu berantakan dengan metode pembantu seperti GetSystemTimeAsString (), LogToFile () dan banyak hal lainnya. Beberapa metode sedikit disesuaikan dengan kebutuhan khusus, tetapi kebanyakan hanya menyalin dan menempel.

Sayangnya beberapa metode memiliki bug halus seperti array char tidak cukup lama dalam beberapa kasus, menggunakan hal-hal tidak aman seperti strcpy (), dll.

Jadi itu adalah PITA nyata untuk menemukan semua fragmen kode, menyelaraskannya dan memperbaiki bug. Dan kami masih menyelaraskan dan memperbaiki hal-hal.

Anda tidak pernah tahu, jika Anda membuat kesalahan dalam metode pertama Anda dan kemudian harus memperbaikinya beberapa kali, karena Anda baru saja menyalinnya. Dan jika Anda ingin menggunakan beberapa metode nanti, bagaimana Anda tahu, yang mana dari 5 metode dalam basis kode yang satu untuk kasus Anda sekarang? Jadi Anda tinggal menyalin satu, menyesuaikannya dan ini dimulai lagi ...

Simon
sumber
1

Ya, jangan repot-repot KERING jika Anda menulis Kode Throwaway .

Tapi KERING tentu saja penting, jika Anda berencana untuk menyimpan kode.

Pacerier
sumber
1

Ungkapan "jangan ulangi dirimu" sedikit berlebihan. Yang penting adalah "hindari memiliki satu informasi yang berpotensi berubah yang dikemas di dua tempat independen ."

Jika suatu program seharusnya memproses widget, masing-masing dengan tiga woozles, dan banyak loop formulir

for (i=0; i<3; i++)
  thisWidget.processWoozle(i);

maka harapan bahwa widget diharapkan mengandung tiga woozles akan diringkas dalam masing-masing loop, dan memperbarui kode untuk mengakomodasi jumlah woozles lain per widget bisa sulit. Sebaliknya, jika orang mengatakannya

#define WOOZLES_PER_WIDGET 3

dan setiap loop ditulis ulang

for (i=0; i<WOOZLES_PER_WIDGET; i++) ...

desain seperti itu mungkin membuatnya sangat mudah untuk mengubah jumlah woozles per widget.

Penting untuk dicatat, bahwa meskipun diinginkan untuk mengkonsolidasikan informasi seperti jumlah woozles per widget ke satu titik, itu tidak selalu praktis. Kadang-kadang mungkin perlu untuk logika kode keras yang hanya akan berfungsi jika ukurannya tertentu. Misalnya, jika setiap woozle memiliki nilai dan seseorang ingin menemukan median yang terkait dengan widget tertentu, dimungkinkan untuk mengurutkan nilai-nilai dan mengambil yang tengah, dan pendekatan seperti itu akan bekerja dengan sejumlah woozles, tetapi logika yang ditulis tangan secara khusus untuk menemukan median tiga item bisa secara signifikan lebih cepat.

Walaupun memiliki konstanta WOOZLES_PER_WIDGET dapat membuat kode lebih mudah dibaca, harus dikomentari untuk memperjelas bahwa nilainya tidak dapat diubah tanpa membuat penyesuaian lain pada logika program. Dalam hal ini, logika yang dikodekan keras untuk tiga item dan WOOZLES_PER_WIDGET konstan keduanya akan menduplikasi informasi "setiap widget memiliki tiga woozles", tetapi manfaat dari duplikasi tersebut (kecepatan eksekusi yang lebih besar) dapat melebihi biaya.

supercat
sumber
0

Sementara saya benar-benar setuju dengan komentar poster lain tentang rawatan dll yang semuanya valid.

Saya ingin menambahkan suara kecil yang berbeda dalam debat.

  • Ini hanya penting bagi programmer. Orang-orang yang membayar upah Anda tidak akan peduli selama perangkat lunaknya lulus UAT.
  • Dalam hal kepentingan, peringkatnya jauh di bawah item seperti mendapatkan persyaratan yang benar, mendengarkan sponsor proyek dan memberikan tepat waktu.
James Anderson
sumber
karena situs ini adalah untuk "Programmer" Saya pikir aman untuk mengatakan pertanyaannya diarahkan pada "sudut pandang programmer". Pernyataan Anda tentang pembayar upah, UAT, dan peringkat kepentingan tentu saja valid, tetapi tidak relevan dengan pertanyaan khusus ini.
ozz
1
Saya sangat tidak setuju. Manajemen yang baik akan memahami prinsip-prinsip dan mengapa itu dilakukan jika dijelaskan secara rinci. Ini harus menjadi pembicaraan mendalam yang serius, bukan 5 menit mampir.
Michael Durrant
2
Poin kedua Anda sepenuhnya benar.
Jim G.
1
@Ozz, kebanggaan pada keahlian Anda adalah penting, bahkan penting bagi seorang programmer yang baik, tetapi, mungkin "sudut pandang programmer" harus menyertakan sedikit perhatian terhadap "kepuasan pelanggan".
James Anderson
0

<tl;dr>

Saya tidak bisa membaca semua jawaban berulang sehingga saya mungkin telah melewatkan sesuatu (dan akan mengulanginya sendiri <= lihat apa yang saya lakukan di sini?).

Berikut adalah daftar hal-hal yang mengagumkan tentang mencegah duplikasi kode!

  1. Lebih mudah untuk diuji: Anda hanya perlu menguji satu 'salinan' dari kode tersebut.
  2. Lebih mudah diperbaiki: Anda hanya perlu menemukan bug dalam satu 'salinan' kode dan memperbaikinya sekali.
  3. Lebih mudah untuk memperbarui (sama seperti di atas): perubahan yang diperlukan, seringkali dapat ditangani dengan memodifikasi kode di beberapa tempat karena Anda meluangkan waktu untuk menggunakan kembali kode dengan benar dan tidak menyalin baris yang sama ke ratusan atau ribuan tempat berbeda di sumber.
  4. Lebih mudah digunakan kembali: ketika (tidak diduplikasi di beberapa tempat) dan disimpan dalam metode generik yang diberi nama, mudah untuk menemukannya dan menggunakannya alih-alih menulis sendiri.
  5. Lebih mudah dibaca: kode duplikat sulit dibaca karena tidak perlu bertele-tele; itu berisi banyak baris yang bukan bagian dari logika dan fungsionalitas yang dimaksudkan khusus (misalnya perintah generik yang digunakan untuk mengatur tahap untuk tindakan berlangsung atau tugas-tugas umum yang diulang-ulang sederhana yang diperlukan di banyak tempat). Kode bersih membuat logika dan fungsionalitas muncul karena tidak ada pengulangan yang mengotori ruang kode.
  6. Lebih mudah di-debug karena (1) dan (5).
  7. Menghemat waktu & uang Anda dan melakukan lebih banyak hal menyenangkan di masa depan; secara khusus membuat kode yang lebih baik lebih kuat. Ini adalah intinya dan ini adalah penjumlahan dari hampir semua hal di atas. Jika banyak orang menggunakan fungsi yang sama doFoo1(a, b), ada kemungkinan lebih besar bahwa banyak kesalahan menjengkelkan & tepi kasus akan terungkap dan diselesaikan. Jika semua orang menyalin kode dan membuat doFoo2(specialA)... doFuu2^n(a, b, c)maka mereka menduplikasi masalah doFoo1dan secara konkret menciptakan lebih banyak pekerjaan.

</tl;dr>

Versi panjang:

Masalah dengan duplikasi kode adalah bahwa itu "tumbuh secara eksponensial" (dengan kata lain, itu berkembang dengan cepat) karena ketika Anda menduplikasi kode Anda secara tidak sadar memberikan izin kepada orang lain (untuk satu, Anda tidak lagi dalam posisi untuk menilai mereka) dan Anda mendorong mereka untuk melakukan hal yang sama. Anda juga membuatnya lebih sulit untuk tidak melakukannya karena lebih sulit untuk menemukan dan menggunakan kembali kode yang berguna ketika ada banyak pengulangan berlebihan yang membingungkan dalam sumber. Terutama jika kode tersebut belum diekstraksi menjadi fungsi yang dinamai dengan tepat. Jadi, jika Anda menghadapi masalah umum yang biasa untuk menyelesaikan masalah, Anda kemungkinan akan menulis sepotong kode sendiri yang menyelesaikannya… Dan Anda mungkin akan gagal memeriksa beberapa kasus tepi, menambahkan lebih banyak kode yang belum diuji.

Hal lain adalah bahwa bagi seorang pemula hal ini mungkin terdengar seperti masalah yang hanya akan memengaruhi perusahaan-perusahaan besar, tetapi saya mendapati hal itu hanya mempengaruhi startup kecil saja (seperti dalam 10.000 baris kode sisi server yang digandakan). Ini adalah kondisi pikiran. Anda tidak hanya harus menguasai KERING tetapi berusaha mendorong orang lain untuk melakukan hal yang sama; karena jika tidak, Anda akan menghukum diri Anda sendiri dengan sebagian besar kode duplikat. Ketika alat KERING sudah dekat dan ditegakkan, akan lebih mudah untuk menerapkannya. Ketika ada banyak kode duplikat, jauh lebih mudah untuk menerapkan solusi salin tempel.

Hal-hal yang saya temukan berbahaya dalam duplikasi kode:

  1. Apakah fungsi ini dapat digunakan? Katakanlah Anda menemukan fungsi yang berfungsi (atau tampaknya melakukan apa yang Anda butuhkan), bagaimana Anda tahu apakah itu seharusnya berfungsi dengan benar atau apakah itu hanya kode yang telah digandakan dan ditinggalkan.
  2. Kode berlebihan Terkadang orang menduplikasi kode, menggunakannya dan melupakannya (mereka selalu dapat menduplikasinya lagi di masa mendatang). Pada titik tertentu seseorang menghapus panggilan ke fungsi yang digandakan di beberapa tempat dalam upaya untuk memperbaiki tetapi fungsi yang tidak digunakan tetap bahkan jika tidak sedang digunakan secara aktif.
  3. Sulit menemukan apa yang Anda cari. Kode duplikat mengambil ruang dan membuat menemukan hal-hal yang berguna dan dibutuhkan (menggunakan alat seperti grep) menjadi tugas yang lebih sulit daripada ketika Anda mendapatkan puluhan atau ribuan hasil di mana Anda seharusnya hanya mendapatkan segelintir.
  4. (Telah disebutkan sebelumnya): Sulit untuk mempertahankan tetapi juga sulit digunakan untuk tujuan pemeliharaan dan regresi. Jika kode pengujian diduplikasi dan tidak diekstraksi dengan benar ke dalam fungsi, yang lain akan menduplikatnya. Adakah yang akan repot-repot menulis API yang mudah digunakan, mudah dibaca untuk membuat kualitas hidup menjadi lebih baik? Dalam pengalaman saya, tidak, sering ada sesuatu yang orang anggap lebih mendesak sampai tidak terkendali.
  5. Duplikasi kode lebih sulit dibaca karena membuat kode bertele-tele di tempat yang tidak harus, di tempat-tempat di mana verbositas tidak menambahkan informasi tentang fungsionalitas yang dimaksud: misalnya panggilan metode umum yang digunakan [berulang-ulang] untuk menetapkan dasar untuk beberapa jenis fungsionalitas yang dimaksudkan, membuatnya lebih sulit untuk fungsionalitas aktual ini muncul.
  6. Ini telah banyak disebutkan. Jika kodenya salah, beberapa gadis atau lelaki miskin perlu mencari dan mengubah setiap penggunaan kode itu. Misalnya, jika seseorang menggunakan panggilan injeksi SQL tidak aman ke mysql_query di sangat sedikit tempat dalam Kelas terorganisir di mana itu diperlukan, akan lebih mudah untuk memperbaikinya dan menggunakan PHP PDO sebagai gantinya, tetapi jika mereka menggunakannya di lebih dari seribu tempat menyalin panggilan melalui dan lebih dari itu, memperbaikinya secara praktis perlu outsourcing atau kadangkala lebih berbahaya, kode perlu ditulis ulang dari awal.
  7. Kode duplikat adalah kebiasaan buruk. Jika Anda berlatih sesuatu secara perlahan menjadi sifat kedua dan itu mempengaruhi orang-orang di sekitar Anda. Junior devs melihat Anda melakukannya dan melakukannya juga. Anda harus mempraktekkan apa yang Anda khotbahkan dan biasakan melakukan hal yang benar. Anda belajar lebih banyak. Menulis kode non-duplikat lebih sulit dan lebih menantang. Itu adalah kebiasaan yang menyenangkan.

Catatan terakhir tentang pencegahan duplikasi kode yang terlalu bersemangat & menyimpulkan:

Ini juga telah dikatakan sebelumnya tetapi kadang-kadang menghindari duplikasi menyebabkan Anda "membungkuk ke belakang" dan melakukan hal-hal yang terlalu canggih (atau tidak penting) untuk dipahami orang lain. Menulis kode yang tidak dapat dibaca (atau secara bercanda kita menyebutnya kode "pelestarian pekerjaan") adalah masalah tersendiri bahkan ketika mencegah duplikasi kode tidak terlibat. Namun, saya menemukan bahwa jika infrastruktur yang tepat dan praktik terbaik ditanamkan sejak awal, akan lebih mudah untuk mencegah duplikasi kode dan orang sering dapat menghindari melakukan hal-hal yang tidak intuitif sehingga dapat mencegah tumpukan pekerjaan yang tidak perlu dan tidak terbaca di masa depan yang dilakukan untuk pencegahan duplikasi kode jika Anda melakukan hal yang benar dari awal itu.

Apa yang dilakukan dengan benar? Yah itu adalah pertanyaan yang sulit dijawab tetapi satu hal adalah untuk menentukan metode mana yang diperlukan untuk proyek dan melihat apa yang telah dilaksanakan oleh orang lain (di luar dan) di dalam perusahaan dan menggunakannya kembali jika memungkinkan; mendokumentasikan semua yang Anda lakukan menambah basis kode dan berusaha menjadikannya satu tingkat lebih generik daripada yang seharusnya, tetapi hanya itu. Jangan berlebihan pola desain hanya untuk membuat kode fleksibel di tempat yang tidak perlu.

serigala
sumber