Haruskah kode saya KERING atau dapat dibaca jika tidak bisa keduanya?

14

Saya sedang menulis kode Ruby untuk latihan enkripsi sederhana dan sering mengalami dilema ini (latihan ini adalah sandi solitaire jika Anda harus tahu). Ini adalah pertanyaan apakah saya harus menggunakan logika saya dengan variabel deskriptif dan pernyataan satu langkah yang membuat fungsi lebih mudah dibaca daripada pernyataan singkat, bahkan padat yang menghilangkan pengulangan dan / atau meminimalkan peluang kesalahan.

Contoh saya yang terbaru: Program saya mengambil input, dan karena pedoman format yang kaku, ia dapat dengan mudah menentukan apakah input harus dienkripsi atau didekripsi. Untuk menyederhanakan, setelah kunci enkripsi dan pesan dikonversi / dihasilkan agar kompatibel, itu adalah masalah mengurangi kunci dari pesan terenkripsi atau menambahkan kunci ke pesan yang tidak dienkripsi, untuk mendapatkan output yang diinginkan (anggap kunci sebagai enkripsi, message + enkripsi = kode; kode - enkripsi = pesan). Posisi KERING mengatakan kepada saya bahwa saya harus mengubah pesan terenkripsi saya berbeda dari pesan tidak terenkripsi sehingga fungsi yang mengambil kunci enkripsi dan menerapkannya pada pesan tidak perlu dibedakan. Saya telah menemukan bahwa ini berarti saya perlu beberapa pernyataan bersarang jika fungsi tetapi logika tampaknya solid. Namun, kode ini tidak mudah dibaca.

Saya bisa, di sisi lain, menulis dua fungsi berbeda yang dipanggil berdasarkan flag yang diset ketika aplikasi menentukan enkripsi atau dekripsi. Ini akan lebih mudah dibaca tetapi akan menduplikasi fungsi tingkat tinggi menerapkan kunci enkripsi ke pesan (menyebabkannya dienkripsi atau didekripsi).

Haruskah saya condong ke arah kode yang mudah dibaca, atau kode ringkas? Atau apakah saya melewatkan cara lain untuk mendapatkan fungsi ini dan memenuhi kedua prinsip? Apakah itu posisi sepanjang skala di mana seseorang harus mempertimbangkan tujuan proyek dan membuat keputusan terbaik untuk melayani tujuan itu?

Sejauh ini, saya cenderung menekankan kode DRY yang ringkas dan lebih mudah dibaca.

lutze
sumber
2
Dapat digunakan pertama, KERING kedua, Dapat dibaca ketiga. Kode yang sangat bermanfaat menghasilkan kode konsumsi yang sangat mudah dibaca yang lebih mudah memenuhi KERING dan mudah dibaca. Inilah sebabnya mengapa Anda ingin mengambil kompleksitas yang tidak menyenangkan dan menaruhnya di suatu tempat dengan API yang bagus, jika mereka tidak dapat dibuat lebih baik; setidaknya kode yang berinteraksi dengan mereka akan terhindar dari menjadi buruk juga dengan pendekatan ini.
Jimmy Hoffa
4
beberapa contoh kode aktual dapat membantu, saya curiga Anda kehilangan beberapa cara ke-3 seperti fungsi tingkat tinggi untuk memiliki kode kering dan dapat dibaca
jk.
2
Bukan duplikat. Ringkas v. Dapat dibaca dan KERING v. Dapat dibaca adalah dua perbandingan yang sangat berbeda. Tidak KERING jauh lebih berbahaya daripada tidak ringkas.
djechlin
Hanya saja, jangan jatuh ke dalam perangkap yang menganggap kode duplikasi lebih mudah dibaca karena jatuh ke dalam pola yang dapat diprediksi. Saya menduga mudah untuk berpikir seperti itu, sampai Anda telah memelihara sebuah sistem yang menduplikasi begitu banyak sehingga Anda menemukan bug-bug halus di satu cabang yang tidak ada di cabang lain, cabang-cabang yang hampir identik.
KChaloux
Saya tidak mengerti apa yang Anda maksud dengan "fungsi tingkat tinggi menerapkan kunci enkripsi untuk pesan". Jika Anda bermaksud bahwa ada tumpang tindih antara mengenkripsi dan mendekripsi, pertimbangkan menggunakan metode ekstrak refactoring untuk memfaktorkan bagian-bagian umum.
Aaron Kurtzhals

Jawaban:

20

KERING adalah pedoman, bukan agama. Mereka yang membawanya ke titik KERING di atas segalanya, telah mengambilnya terlalu jauh.

Pertama dan terpenting, kode yang dapat digunakan adalah yang terpenting. Jika kode tidak berguna dan tidak dapat digunakan, itu tidak ... dan tidak ada gunanya menulisnya di tempat pertama.

Kedua, suatu hari, seseorang harus menjaga kode Anda. Jika kode Anda tidak dapat dipertahankan, mereka akan merusak desain Anda yang padat, ringkas, KERING sambil mengutuk nama Anda. Jangan lakukan ini. Saya telah menjadi orang itu dan setiap kali saya melihat nama tertentu dalam anotasi kode, saya bergidik.

Membuat kode yang padat yang tidak memiliki "variabel deskriptif" dan memasukkan semuanya ke dalam ekspresi ternary bersarang dengan lambdas tanpa dokumentasi apa pun adalah cerdas. Sangat menyenangkan mengetahui bahwa Anda dapat melakukannya - tetapi tidak. Kode pintar sangat sulit untuk di-debug. Hindari menulis kode pintar .

Sebagian besar waktu yang dihabiskan dalam perangkat lunak dihabiskan untuk pemeliharaan perangkat lunak - bukan menulisnya pertama kali. Tulis kode sehingga Anda (atau orang lain) dapat dengan cepat dan mudah memperbaiki bug dan menambahkan fitur yang diperlukan dengan sedikit perubahan desain yang ideal.

Komunitas
sumber
Secara intuitif atau tidak, Anda telah menemukan masalah yang saya abaikan. Saya telah menulis kode 'pintar' sebanyak yang saya bisa untuk latihan ini, hanya untuk mengetahui saya bisa melakukannya, yang saya setuju itu baik untuk diketahui, tetapi saya setuju dengan Anda di sini bahwa ini adalah praktik yang buruk. Sekarang, saya harus melakukan banyak refactoring.
lutze
1
@ Lutze Saya seorang perl dan terkadang ruby ​​coder dan tentu saja dapat memahami godaan untuk menulis kode pintar di sana. Versi sebelum posting dari jawaban ini termasuk kutipan dari Larry Wall tentang keangkuhan - saya percaya bahwa ini adalah kebajikan yang sangat penting ketika bekerja dengan kode yang suatu hari nanti akan dipertahankan. Karena kemungkinan tersingkatnya bahasa, kadang-kadang sulit untuk mendapatkan keuntungan dari menulis lebih banyak kode daripada mencoba untuk kode padat yang pandai ... sampai Anda harus memeliharanya.
17

Saya tidak yakin berdasarkan pertanyaan yang Anda mengerti KERING. Kode KERING tidak sama dengan ringkas. Cukup sering justru sebaliknya.

Di sini, saya tidak yakin apa masalahnya untuk contoh ini. Buat fungsi untuk mengenkripsi, fungsi untuk mendekripsi, pembantu fungsi umum (mix bytes), dan front end sederhana untuk mengambil input dan menentukan enkripsi / dekripsi ... Tidak perlu mengulangi sendiri.

Secara umum, baik KERING dan mudah dibaca ada untuk membantu menjaga dan memperluas kode. Tidak semua skenario sama, hit yang mudah dibaca untuk menghapus sedikit pengulangan tidak baik, dan begitu pula banyak duplikasi untuk menambah sedikit keterbacaan.

Jika ditekan, saya lebih suka keterbacaan. Kode duplikat masih dapat diuji - kode yang tidak dapat dibaca mengarah ke Anda melakukan (dan menguji) hal yang salah.

Telastyn
sumber
Poin bagus, saya memang sedikit menggabungkan prinsip KERING dengan tujuan kode ringkas.
lutze
12

Saya tidak terbiasa dengan kasus spesifik Anda, tetapi dapat memberikan beberapa panduan umum.

Tujuan dari keterbacaan dan KERING adalah kemampuan pemeliharaan .

Maintainability penting dalam kebanyakan situasi Anda akan menghabiskan lebih banyak waktu mempertahankan kode daripada menulisnya. Ini terutama benar jika Anda menganggap menulis kode sebagai jenis perawatan khusus.

Sayangnya, KERING sering disalahpahami. Ini sebagian karena tampaknya sangat sederhana, tetapi seperti banyak hal sederhana itu bisa, yah ... rumit.

Tujuannya KERING adalah bahwa setiap unit fungsi hanya ada di satu tempat. Jika prinsip ini diikuti, pengelola kode yang ditugaskan untuk mengubah atau memverifikasi fungsionalitas dapat menangani kode sekaligus. Jika KERING tidak diikuti maka ada bahaya yang sangat nyata bahwa beberapa salinan fungsi tidak akan dikelola dengan baik.

Pelanggaran DRY yang paling mencolok adalah copy-paste coding, di mana seluruh blok kode diulang-ulang dalam basis kode. Ini secara mengejutkan umum dalam pengalaman saya, dan tidak ada cara yang menambah keterbacaan. Oleh karena itu, refactoring kode untuk memperkenalkan metode umum selalu meningkatkan kesesuaian dan keterbacaan KERING.

Pelanggaran kedua yang paling mencolok adalah "salin dan tempel sedikit". Sekali lagi, refactoriing untuk memperkenalkan metode umum dengan parameter, atau memecah fungsi menjadi langkah-langkah dan mengabstraksi kesamaan hampir selalu meningkatkan keterbacaan.

Lalu ada pelanggaran yang lebih halus, di mana fungsionalitas digandakan tetapi kodenya berbeda. Ini selalu tidak mudah dikenali, tetapi ketika Anda melihatnya dan refactor untuk menarik kode umum ke dalam satu metode / kelas / fungsi maka kode tersebut secara umum lebih mudah dibaca daripada sebelumnya.

Akhirnya, ada kasus pengulangan desain. Misalnya, Anda mungkin telah menggunakan pola keadaan beberapa kali dalam basis kode Anda, dan Anda sedang mempertimbangkan refactoring untuk menghilangkan pengulangan ini. Dalam hal ini, lanjutkan dengan hati-hati. Anda mungkin mengurangi keterbacaan dengan memperkenalkan lebih banyak level abstraksi. Pada saat yang sama, Anda tidak benar-benar berurusan dengan duplikasi fungsi tetapi dengan duplikasi abstraksi. Terkadang itu sepadan ... tetapi seringkali tidak. Prinsip panduan Anda adalah bertanya, "yang mana yang lebih bisa dipertahankan".

Setiap kali saya membuat panggilan penilaian ini, saya mencoba mempertimbangkan jumlah waktu yang dihabiskan orang untuk mempertahankan kode. Jika kode adalah fungsionalitas inti bisnis maka mungkin perlu lebih banyak pemeliharaan. Dalam hal ini saya bertujuan untuk membuat kode dapat dikelola untuk orang-orang yang akrab dengan basis kode dan abstraksi yang terlibat. Saya akan lebih senang memperkenalkan sedikit abstraksi untuk mengurangi pengulangan. Sebaliknya, naskah yang jarang digunakan dan jarang dipelihara mungkin kurang mudah dipahami oleh pengelola jika melibatkan terlalu banyak abstraksi. Dalam hal ini saya akan melakukan kesalahan di sisi pengulangan.

Saya juga mempertimbangkan tingkat pengalaman anggota tim saya yang lain. Saya menghindari abstraksi "mewah" dengan pengembang yang tidak berpengalaman, tetapi memanfaatkan pola desain yang diakui industri dengan kelompok yang lebih matang.

Dalam kesimpulan, jawaban atas pertanyaan Anda adalah melakukan apa pun yang membuat kode Anda paling bisa dipertahankan. Apa artinya itu dalam skenario Anda tergantung pada Anda untuk memutuskan.

Kramii
sumber
Saya pikir Anda telah memecahkan salah satu masalah saya dengan tepat. Contoh yang saya berikan tentang fungsionalitas yang saya coba untuk tidak duplikat lebih mungkin merupakan duplikasi abstraksi.
lutze
+1. Saat ini saya sedang berurusan dengan sistem yang menyalahgunakan copy dan paste ke tingkat yang konyol. Memperhitungkan satu metode dari copy / paste kode dihapus lebih dari 400 baris dari salah satu kelas saya hari ini. Sayangnya, saya menemukannya dalam metode garis 900 ...
KChaloux
1
Jika dua konstruksi kode saat ini melakukan hal yang sama, tetapi perubahan ke satu umumnya tidak berarti perubahan ke yang lain, salin / tempel mungkin lebih baik daripada fungsi umum yang difaktorkan. Jika kode menggunakan dua metode identik karakter-untuk-karakter melakukan hal yang sama untuk tujuan yang berbeda, dan secara konsisten mendasarkan pilihan metode pada tujuan yang diperlukan, maka jika hal-hal kemudian perlu dilakukan sedikit untuk salah satu tujuan tersebut, mengubah hanya sesuai Metode hanya akan mempengaruhi perilaku yang harus dipengaruhi. Menggunakan satu metode umum bisa membuat perubahan lebih sulit.
supercat
7

Jika fungsi Anda menjadi lebih rumit dan lebih lama (sehingga kurang dapat dibaca) ketika Anda mencoba membuatnya KERING, maka Anda salah melakukannya. Anda mencoba untuk menempatkan terlalu banyak fungsi dalam satu fungsi karena Anda berpikir bahwa ini adalah satu-satunya cara untuk menghindari mengulangi potongan kode yang sama dalam fungsi kedua.

Membuat kode KERING hampir selalu berarti mengembalikan fungsi umum ke fungsi yang lebih kecil. Masing-masing fungsi itu harus lebih sederhana (dan dengan demikian lebih mudah dibaca) daripada yang asli. Untuk menjaga segala sesuatu dalam fungsi asli pada tingkat abstraksi yang sama, ini juga dapat berarti untuk memperbaiki bagian tambahan yang tidak digunakan di tempat lain. Fungsi asli Anda kemudian menjadi "fungsi tingkat tinggi", memanggil yang lebih kecil, dan menjadi lebih kecil dan lebih sederhana juga.

Dengan melakukan hal ini, sebagian besar mengarah ke berbagai level abstraksi dalam kode Anda - dan beberapa orang percaya kode semacam itu kurang dapat dibaca. Menurut pengalaman saya, ini adalah kekeliruan. Poin kunci di sini adalah untuk memberi fungsi yang lebih kecil nama yang baik, memperkenalkan tipe data yang bagus dan abstraksi yang dapat dengan mudah dipahami oleh orang kedua. Dengan cara itu "KERING" dan "keterbacaan" seharusnya hanya sangat, sangat jarang menimbulkan konflik.

Doc Brown
sumber
2

Meskipun saya tidak yakin persis apa yang menyebabkan masalah di sini, pengalaman saya adalah ketika Anda menemukan KERING dan keterbacaan yang bertentangan yang mengatakan ini saatnya untuk memperbaiki sesuatu.

Loren Pechtel
sumber
0

Saya akan memilih yang dapat dibaca (= dapat dipelihara) daripada KERING setiap hari dalam seminggu. Pada kenyataannya keduanya sering disejajarkan, seseorang yang mendapat konsep KERING umumnya akan menghasilkan (kebanyakan) kode yang dapat dibaca.

Zdravko Danev
sumber
2
tanpa penjelasan, jawaban ini dapat menjadi sia-sia jika ada orang yang memposting pendapat yang berbeda. Misalnya, jika seseorang memposting klaim seperti "Saya akan memilih KERING (= dapat dipertahankan) alih-alih dapat dibaca setiap hari dalam seminggu", bagaimana jawaban ini membantu pembaca untuk memilih dua pendapat yang bertentangan? Pertimbangkan untuk mengeditnya menjadi bentuk yang lebih baik
agas
0

Sangat sangat sangat sangat sangat sedikit dalam karir saya, saya menemukan kasus yang sah bahwa pitt mudah dibaca terhadap KERING. Jadikan itu mudah dibaca dulu. Sebutkan hal-hal dengan baik. Salin dan tempel jika perlu.

Sekarang mundur dan lihat totalitas yang telah Anda buat, seperti seorang seniman melangkah mundur untuk melihat lukisan mereka. Sekarang Anda dapat mengidentifikasi pengulangan dengan benar.

Kode yang berulang harus di refactored ke dalam metodenya sendiri, atau ditarik keluar ke kelasnya sendiri.

Kode berulang harus menjadi pilihan terakhir. Dapat dibaca DAN KERING terlebih dahulu, gagal terbaca jika Anda membatasi ruang lingkup kode berulang.

Greg Burghardt
sumber