Bagaimana Anda membenarkan lebih banyak kode yang ditulis dengan mengikuti praktik kode bersih?

106

Catatan Moderator
Pertanyaan ini sudah diposkan tujuh belas jawaban . Sebelum Anda memposting jawaban baru, harap baca jawaban yang ada dan pastikan sudut pandang Anda belum tercakup secara memadai.

Saya telah mengikuti beberapa praktik yang direkomendasikan dalam buku "Clean Code" Robert Martin, terutama yang berlaku untuk jenis perangkat lunak yang bekerja dengan saya dan yang masuk akal bagi saya (saya tidak mengikutinya sebagai dogma) .

Namun, satu efek samping yang saya perhatikan adalah kode "bersih" yang saya tulis, lebih banyak kode daripada jika saya tidak mengikuti beberapa praktik. Praktik spesifik yang mengarah ke ini adalah:

  • Mengondisikan kondisional

Jadi, bukannya

if(contact.email != null && contact.emails.contains('@')

Saya bisa menulis metode kecil seperti ini

private Boolean isEmailValid(String email){...}
  • Mengganti komentar sebaris dengan metode pribadi lain, sehingga nama metode menggambarkan dirinya sendiri daripada memiliki komentar sebaris di atasnya
  • Kelas seharusnya hanya memiliki satu alasan untuk berubah

Dan beberapa lainnya. Intinya adalah, bahwa apa yang bisa menjadi metode 30 baris, akhirnya menjadi kelas, karena metode kecil yang menggantikan komentar dan merangkum persyaratan, dll. Ketika Anda menyadari bahwa Anda memiliki begitu banyak metode, maka "masuk akal" untuk letakkan semua fungsionalitas ke dalam satu kelas, padahal seharusnya itu adalah metode.

Saya sadar bahwa praktik apa pun yang dilakukan secara ekstrem dapat membahayakan.

Pertanyaan konkret yang saya cari jawabannya adalah:

Apakah ini produk sampingan yang dapat diterima dari penulisan kode bersih? Jika demikian, argumen apa yang dapat saya gunakan untuk membenarkan fakta bahwa lebih banyak LOC telah ditulis?

Organisasi ini tidak peduli secara khusus tentang lebih banyak LOC, tetapi lebih banyak LOC dapat menghasilkan kelas yang sangat besar (yang lagi-lagi, dapat diganti dengan metode yang panjang tanpa banyak fungsi pembantu sekali pakai demi kepentingan keterbacaan).

Ketika Anda melihat kelas yang cukup besar, itu memberi kesan bahwa kelas cukup sibuk, dan bahwa tanggung jawabnya telah selesai. Karenanya, Anda dapat membuat lebih banyak kelas untuk mencapai fungsionalitas lain. Hasilnya kemudian banyak kelas, semua melakukan "satu hal" dengan bantuan banyak metode pembantu kecil.

INI adalah perhatian khusus ... kelas-kelas itu bisa menjadi kelas tunggal yang masih mencapai "satu hal", tanpa bantuan banyak metode kecil. Itu bisa berupa kelas tunggal dengan mungkin 3 atau 4 metode dan beberapa komentar.

CommonCoreTawan
sumber
98
Jika organisasi Anda hanya menggunakan LOC sebagai metrik untuk basis kode Anda, maka membenarkan kode bersih di awal tidak ada harapan.
Kilian Foth
24
Jika pemeliharaan adalah tujuan Anda, LOC bukanlah metrik terbaik untuk menilai - ini salah satunya, tetapi ada banyak hal yang harus dipertimbangkan selain membuatnya singkat.
Zibbobz
29
Bukan jawaban, tetapi hal yang harus dibuat: Ada seluruh subkomunitas tentang penulisan kode dengan sesedikit mungkin baris / simbol. codegolf.stackexchange.com Orang dapat berargumen bahwa sebagian besar jawaban di sana tidak dapat dibaca seperti yang seharusnya.
Antitheos
14
Pelajari alasan di balik setiap praktik terbaik, bukan hanya aturan sendiri. Aturan berikut tanpa alasan adalah Kultus kargo. Setiap aturan memiliki alasannya sendiri.
Gherman
9
Sama seperti kata sampingan, dan menggunakan contoh Anda, kadang-kadang mendorong sesuatu ke metode akan membuat Anda berpikir: "Mungkin ada fungsi perpustakaan yang bisa melakukan ini". Misalnya, untuk memvalidasi alamat email, Anda dapat membuat System.Net.Mail.MailAddress yang akan memvalidasi untuk Anda. Anda kemudian dapat (mudah-mudahan) mempercayai penulis perpustakaan itu untuk memperbaikinya. Ini berarti basis kode Anda akan memiliki lebih banyak abstraksi, dan ukurannya berkurang.
Gregory Currie

Jawaban:

130

... kami adalah tim yang sangat kecil yang mendukung basis kode yang relatif besar dan tidak berdokumen (yang kami warisi), sehingga beberapa pengembang / manajer melihat nilai dalam menulis lebih sedikit kode untuk menyelesaikan sesuatu sehingga kami memiliki lebih sedikit kode untuk dipelihara

Orang-orang ini telah mengidentifikasi sesuatu dengan benar: mereka ingin kode lebih mudah dipelihara. Di mana mereka salah meskipun mengasumsikan bahwa semakin sedikit kode yang ada, semakin mudah untuk mempertahankannya.

Agar kode mudah dipelihara, maka perlu diubah dengan mudah. Sejauh ini cara termudah untuk mencapai kode yang mudah diubah adalah dengan memiliki set lengkap tes otomatis untuk itu yang akan gagal jika perubahan Anda salah satu. Tes adalah kode, jadi menulis tes itu akan membengkak basis kode Anda. Dan itu adalah hal yang baik.

Kedua, untuk mengetahui apa yang perlu diubah, kode Anda harus mudah dibaca dan juga mudah dipikirkan. Kode yang sangat singkat, menyusut hanya untuk menjaga agar garis hitung mundur sangat tidak mudah dibaca. Jelas ada kompromi yang harus dipukul karena kode yang lebih panjang akan lebih lama untuk dibaca. Tetapi jika itu lebih cepat dipahami, maka itu sepadan. Jika tidak menawarkan manfaat itu, maka verbositas itu berhenti menjadi manfaat. Tetapi jika kode yang lebih lama meningkatkan keterbacaan maka sekali lagi ini adalah hal yang baik.

David Arno
sumber
27
"Sejauh ini cara termudah untuk mencapai kode yang mudah diubah adalah dengan memiliki set lengkap tes otomatis untuk itu yang akan gagal jika perubahan Anda adalah salah satu yang melanggar." Ini tidak benar. Tes membutuhkan kerja tambahan untuk setiap perubahan perilaku karena tes juga perlu diubah , ini dirancang dan banyak yang berpendapat bahwa perubahan itu lebih aman, tetapi itu juga membuat perubahan lebih sulit.
Jack Aidley
63
Tentu, tetapi waktu yang hilang dalam mempertahankan tes ini dikerdilkan pada saat Anda akan kehilangan diagnosa dan memperbaiki bug yang mencegah tes.
MetaFight
29
@JackAidley, harus mengubah tes bersama dengan kode dapat memberikan tampilan lebih banyak pekerjaan, tetapi hanya jika seseorang mengabaikan bug yang sulit ditemukan yang akan diubah ke kode yang belum diuji dan yang sering tidak akan ditemukan sampai setelah pengiriman . Yang terakhir hanya menawarkan ilusi kurang kerja.
David Arno
31
@JackAidley, saya benar-benar tidak setuju dengan Anda. Tes membuat kode lebih mudah diubah. Saya akan mengakui bahwa kode yang dirancang dengan buruk yang terlalu erat digabungkan dan dengan demikian digabungkan dengan ketat untuk pengujian bisa sulit untuk diubah, tetapi kode yang terstruktur dan teruji dengan baik mudah untuk diubah dalam pengalaman saya.
David Arno
22
@JackAidley Anda dapat melakukan banyak refactor tanpa mengubah API atau antarmuka apa pun. Ini berarti Anda bisa menjadi gila saat memodifikasi kode tanpa harus mengubah satu baris dalam tes unit atau fungsional. Yaitu, jika tes Anda tidak menguji implementasi tertentu.
Eric Duminil
155

Ya, ini merupakan produk sampingan yang dapat diterima, dan pembenarannya adalah bahwa itu sekarang disusun sedemikian rupa sehingga Anda tidak harus membaca sebagian besar kode sebagian besar waktu. Alih-alih membaca fungsi 30-baris setiap kali Anda membuat perubahan, Anda membaca fungsi 5-baris untuk mendapatkan aliran keseluruhan, dan mungkin beberapa fungsi pembantu jika perubahan Anda menyentuh area itu. Jika kelas "ekstra" baru Anda dipanggil EmailValidatordan Anda tahu masalah Anda bukan dengan validasi email, Anda dapat melewatkan membacanya sama sekali.

Ini juga lebih mudah untuk menggunakan kembali potongan yang lebih kecil, yang cenderung mengurangi jumlah baris Anda untuk keseluruhan program Anda. Sebuah EmailValidatordapat digunakan di semua tempat. Beberapa baris kode yang melakukan validasi email tetapi dikikis bersama dengan kode akses basis data tidak dapat digunakan kembali.

Dan kemudian pertimbangkan apa yang perlu dilakukan jika aturan validasi email perlu diubah — yang Anda inginkan: satu lokasi yang diketahui; atau banyak lokasi, mungkin hilang beberapa?

Karl Bielefeldt
sumber
10
jawaban yang jauh lebih baik daripada "unit testing yang menyelesaikan semua masalah Anda" yang melelahkan
Dirk Boer
13
Jawaban ini mengenai titik kunci yang sepertinya selalu dilewatkan oleh Paman Bob dan teman-temannya - refactoring menjadi metode-metode kecil hanya membantu jika Anda tidak perlu membaca semua metode kecil untuk mengetahui apa yang sedang dilakukan kode Anda. Membuat kelas terpisah untuk memvalidasi alamat email adalah bijaksana. Menarik kode iterations < _maxIterationsmenjadi metode yang disebut ShouldContinueToIterateadalah bodoh .
BJ Myers
4
@DavidArno: "berguna"! = "Menyelesaikan semua masalah Anda"
Christian Hackl
2
@ Davidvido: Ketika seseorang mengeluh tentang orang-orang menyiratkan bahwa pengujian unit "menyelesaikan semua masalah Anda", mereka jelas berarti orang-orang yang menyiratkan bahwa pengujian unit memecahkan, atau setidaknya berkontribusi pada solusi, hampir semua masalah dalam rekayasa perangkat lunak. Saya pikir tidak ada yang menuduh siapa pun menyarankan pengujian unit sebagai cara untuk mengakhiri perang, kemiskinan dan penyakit. Cara lain untuk mengatakannya adalah bahwa pengujian unit yang terlalu ekstrim dalam banyak jawaban, tidak hanya untuk pertanyaan ini tetapi juga pada SE secara umum, dikritik.
Christian Hackl
2
Hai @ DavidArno, komentar saya jelas-jelas hiperbola, bukan strawman;) Bagi saya seperti ini: Saya bertanya bagaimana memperbaiki mobil saya dan orang-orang beragama datang dan memberi tahu saya bahwa saya harus menjalani kehidupan yang tidak terlalu berdosa. Secara teori sesuatu yang layak dibahas, tetapi itu tidak benar-benar membantu saya untuk menjadi lebih baik dalam memperbaiki mobil.
Dirk Boer
34

Bill Gates terkenal dikaitkan dengan mengatakan, "Mengukur kemajuan pemrograman dengan garis kode adalah seperti mengukur kemajuan pembangunan pesawat terbang berdasarkan berat."

Dengan rendah hati saya setuju dengan sentimen ini. Ini bukan untuk mengatakan bahwa suatu program harus berusaha untuk lebih atau kurang baris kode, tetapi ini bukanlah yang terpenting untuk menciptakan program yang berfungsi dan berfungsi. Ini membantu untuk mengingat bahwa pada akhirnya alasan di balik penambahan baris kode adalah karena secara teori lebih mudah dibaca.

Ketidaksepakatan dapat terjadi tentang apakah perubahan tertentu lebih atau kurang dapat dibaca, tetapi saya tidak berpikir Anda akan salah untuk membuat perubahan pada program Anda karena Anda berpikir dengan melakukan itu Anda membuatnya lebih mudah dibaca. Misalnya membuat sebuah isEmailValidbisa dianggap berlebihan dan tidak perlu, terutama jika itu disebut tepat sekali oleh kelas yang mendefinisikannya. Namun saya lebih suka melihat isEmailValiddalam kondisi daripada serangkaian kondisi AND di mana saya harus menentukan apa kondisi masing-masing individu memeriksa dan mengapa itu sedang diperiksa.

Di mana Anda mendapat masalah adalah ketika Anda membuat isEmailValidmetode yang memiliki efek samping atau memeriksa hal-hal selain surel, karena ini lebih buruk daripada hanya menuliskan semuanya. Ini lebih buruk karena menyesatkan dan saya mungkin kehilangan bug karena itu.

Meskipun jelas Anda tidak melakukan itu dalam kasus ini, jadi saya akan mendorong Anda untuk melanjutkan apa yang Anda lakukan. Anda harus selalu bertanya pada diri sendiri apakah dengan membuat perubahan, itu lebih mudah dibaca, dan jika itu adalah kasus Anda, maka lakukanlah!

Neil
sumber
1
Berat pesawat adalah metrik yang penting. Dan selama desain berat yang diharapkan dipantau dengan cermat. Bukan sebagai tanda kemajuan, tetapi sebagai kendala. Memantau garis kode menyarankan lebih banyak lebih baik, sedangkan dalam desain pesawat lebih sedikit berat lebih baik. Jadi saya pikir Tuan Gates bisa memilih ilustrasi yang lebih baik untuk maksudnya.
jos
21
@ jo di OP tim tertentu bekerja, tampaknya lebih sedikit LOC dianggap 'lebih baik'. Maksud yang dibuat Bill Gates adalah bahwa LOC tidak terkait dengan kemajuan dengan cara apa pun yang berarti, seperti halnya dalam konstruksi pesawat, bobot tidak terkait dengan kemajuan dengan cara yang bermakna. Sebuah pesawat terbang yang sedang dalam pembangunan mungkin memiliki 95% dari bobot akhirnya relatif cepat, tetapi itu hanya akan menjadi cangkang kosong tanpa sistem kontrol itu, itu tidak 95% lengkap. Sama dalam perangkat lunak, jika suatu program memiliki 100 ribu baris kode, itu tidak berarti setiap 1000 baris menyediakan 1% fungsionalitas.
Mr.Mindor
7
Memantau kemajuan adalah pekerjaan yang sulit, bukan? Manajer yang buruk.
jos
@ jo: dalam kode juga lebih baik memiliki lebih sedikit baris untuk fungsi yang sama, jika semuanya sama.
RemcoGerlich
@ jo Baca dengan cermat. Gates tidak mengatakan apa-apa tentang apakah berat merupakan ukuran penting bagi pesawat itu sendiri. Dia mengatakan bahwa berat badan adalah ukuran yang mengerikan untuk kemajuan membangun pesawat terbang. Lagi pula, dengan ukuran itu segera setelah seluruh lambung dilemparkan ke tanah, Anda pada dasarnya sudah selesai karena itu mungkin berjumlah 9x% dari berat seluruh pesawat.
Voo
23

jadi beberapa pengembang / manajer melihat nilai dalam menulis lebih sedikit kode untuk menyelesaikan sesuatu sehingga kita memiliki lebih sedikit kode untuk dipelihara

Ini adalah masalah kehilangan pandangan pada tujuan yang sebenarnya.

Yang penting adalah menurunkan jam yang dihabiskan untuk pembangunan . Itu diukur dalam waktu (atau upaya yang setara), bukan dalam baris kode.
Ini seperti mengatakan bahwa pabrikan mobil harus membuat mobil mereka dengan sekrup yang lebih sedikit, karena dibutuhkan jumlah waktu yang tidak nol untuk memasukkan setiap sekrup. Walaupun itu benar benar, nilai pasar mobil tidak ditentukan oleh berapa banyak sekrup yang dibuatnya. atau tidak punya. Di atas segalanya, mobil harus performan, aman, dan mudah dirawat.

Sisa dari jawabannya adalah contoh bagaimana kode bersih dapat menyebabkan perolehan waktu.


Penebangan

Ambil aplikasi (A) yang tidak memiliki pendataan. Sekarang buat aplikasi B, yang merupakan aplikasi yang sama tetapi dengan logging. B akan selalu memiliki lebih banyak baris kode, dan dengan demikian Anda perlu menulis lebih banyak kode.

Tetapi banyak waktu akan menyelidiki masalah dan bug, dan mencari tahu apa yang salah.

Untuk aplikasi A, pengembang akan terjebak membaca kode, dan harus terus-menerus mereproduksi masalah dan melangkah melalui kode untuk menemukan sumber masalah. Ini berarti bahwa pengembang harus menguji dari awal eksekusi hingga akhir, di setiap lapisan yang digunakan, dan perlu mengamati setiap bagian logika yang digunakan.
Mungkin dia beruntung menemukannya segera, tetapi mungkin jawabannya ada di tempat terakhir yang dia pikirkan.

Untuk aplikasi B, dengan asumsi logging sempurna, pengembang mengamati log, dapat segera mengidentifikasi komponen yang salah, dan sekarang tahu ke mana harus mencari.

Ini bisa berupa hitungan menit, jam atau hari yang disimpan; tergantung pada ukuran dan kompleksitas basis kode.


Regresi

Ambil aplikasi A, yang tidak ramah sama sekali.
Ambil aplikasi B, yang KERING, tetapi akhirnya membutuhkan lebih banyak garis karena abstraksi tambahan.

Permintaan perubahan diajukan, yang membutuhkan perubahan logika.

Untuk aplikasi B, pengembang mengubah logika (unik, dibagi) sesuai dengan permintaan perubahan.

Untuk aplikasi A, pengembang harus mengubah semua instance dari logika ini di mana ia mengingatnya sedang digunakan.

  • Jika dia berhasil mengingat semua kejadian, dia masih harus menerapkan perubahan yang sama beberapa kali.
  • Jika dia tidak berhasil mengingat semua kejadian, Anda sekarang berurusan dengan basis kode tidak konsisten yang bertentangan dengan dirinya sendiri. Jika pengembang lupa sepotong kode yang jarang digunakan, bug ini mungkin tidak menjadi jelas bagi pengguna akhir sampai jauh di masa depan. Pada saat itu, apakah pengguna akhir akan mengidentifikasi apa sumber masalahnya? Bahkan jika demikian, pengembang mungkin tidak ingat apa perubahan yang terjadi, dan harus mencari cara untuk mengubah potongan logika yang terlupakan ini. Mungkin pengembang bahkan tidak bekerja di perusahaan saat itu, dan kemudian orang lain sekarang harus mencari tahu semuanya dari awal.

Ini dapat menyebabkan pemborosan waktu yang sangat besar. Tidak hanya dalam pengembangan, tetapi dalam berburu dan menemukan bug. Aplikasi dapat mulai berperilaku tidak menentu dengan cara yang tidak mudah dipahami pengembang. Dan itu akan menyebabkan sesi debugging yang panjang.


Pertukaran pengembang

Pengembang Aplikasi yang dibuat A. Kode tidak bersih atau dapat dibaca, tetapi berfungsi seperti pesona dan telah berjalan dalam produksi. Tidak mengherankan, tidak ada dokumentasi juga.

Pengembang A tidak ada selama sebulan karena liburan. Permintaan perubahan darurat diajukan. Tidak bisa menunggu tiga minggu lagi untuk Dev A kembali.

Pengembang B harus melakukan perubahan ini. Dia sekarang perlu membaca seluruh basis kode, memahami bagaimana segala sesuatu bekerja, mengapa itu bekerja, dan apa yang ingin dicapai. Ini membutuhkan waktu lama, tetapi katakanlah dia bisa melakukannya dalam waktu tiga minggu.

Pada saat yang sama, aplikasi B (yang dev B buat) memiliki keadaan darurat. Dev B ditempati, tetapi Dev C tersedia, meskipun ia tidak tahu basis kode. Apa yang kita lakukan?

  • Jika kita terus B bekerja di A, dan menempatkan C untuk bekerja di B, maka kita memiliki dua pengembang yang tidak tahu apa yang mereka lakukan, dan pekerjaan itu dilakukan secara optimal.
  • Jika kita menarik B menjauh dari A dan membuatnya melakukan B, dan sekarang kita menempatkan C pada A, maka semua pekerjaan pengembang B (atau sebagian besar darinya) mungkin akan dibuang. Ini berpotensi sia-sia beberapa hari / minggu.

Dev A kembali dari liburannya, dan melihat bahwa B tidak memahami kode itu, dan karenanya menerapkannya dengan buruk. Itu bukan kesalahan B, karena ia menggunakan semua sumber daya yang tersedia, kode sumber tidak cukup dapat dibaca. Apakah A sekarang harus menghabiskan waktu memperbaiki pembacaan kode?


Semua masalah ini, dan banyak lagi, akhirnya membuang - buang waktu . Ya, dalam jangka pendek, kode bersih membutuhkan lebih banyak upaya sekarang , tetapi akan membayar dividen di kemudian hari ketika bug / perubahan yang tak terhindarkan perlu ditangani.

Manajemen perlu memahami bahwa tugas singkat sekarang akan menyelamatkan Anda beberapa tugas panjang di masa depan. Gagal merencanakan adalah rencana untuk gagal.

Jika demikian, argumen apa yang dapat saya gunakan untuk membenarkan fakta bahwa lebih banyak LOC telah ditulis?

Penjelasan goto saya bertanya kepada manajemen apa yang mereka inginkan: aplikasi dengan basis kode 100KLOC yang dapat dikembangkan dalam tiga bulan, atau basis kode 50KLOC yang dapat dikembangkan dalam enam bulan.

Mereka jelas akan memilih waktu pengembangan yang lebih pendek, karena manajemen tidak peduli dengan KLOC . Manajer yang fokus pada KLOC mengelola mikro sementara tidak mendapat informasi tentang apa yang mereka coba kelola.

Flater
sumber
23

Saya pikir Anda harus sangat berhati-hati dalam menerapkan praktik "kode bersih" jika mereka mengarah pada kompleksitas yang lebih menyeluruh. Refactoring prematur adalah akar dari banyak hal buruk.

Mengekstrak kondisional ke fungsi mengarah ke kode yang lebih sederhana pada titik di mana kondisional diekstraksi , tetapi mengarah ke kompleksitas yang lebih menyeluruh karena Anda sekarang memiliki fungsi yang terlihat dari lebih banyak titik dalam program. Anda menambahkan sedikit kompleksitas ke semua fungsi lain di mana fungsi baru ini sekarang terlihat.

Saya tidak mengatakan Anda tidak harus mengekstrak kondisional, hanya saja Anda harus mempertimbangkan dengan hati-hati jika perlu.

  • Jika Anda ingin secara khusus menguji logika validasi email. Maka Anda perlu mengekstrak logika itu ke fungsi yang terpisah - bahkan mungkin kelas.
  • Jika logika yang sama digunakan dari beberapa tempat dalam kode maka Anda jelas harus mengekstraknya ke satu fungsi. Jangan ulangi dirimu sendiri!
  • Jika logika jelas merupakan tanggung jawab terpisah, mis. Validasi email terjadi di tengah algoritma pengurutan. Validasi email akan berubah secara independen dari algoritma pengurutan, sehingga harus berada di kelas yang terpisah.

Dalam semua hal di atas adalah alasan untuk ekstraksi di luar itu hanya menjadi "kode bersih". Selain itu, Anda mungkin tidak akan ragu apakah itu hal yang benar untuk dilakukan.

Saya akan mengatakan, jika ragu, selalu memilih kode yang paling sederhana dan paling mudah.

JacquesB
sumber
7
Saya harus setuju, mengubah setiap persyaratan menjadi metode validasi dapat memperkenalkan kompleksitas yang tidak diinginkan ketika datang ke pemeliharaan dan tinjauan kode. Anda sekarang harus beralih bolak-balik dalam kode hanya untuk memastikan metode kondisional Anda benar. Dan apa yang terjadi ketika Anda memiliki kondisi berbeda untuk nilai yang sama? Sekarang Anda mungkin memiliki mimpi buruk penamaan dengan beberapa metode kecil yang hanya dipanggil sekali dan sebagian besar terlihat sama.
pboss3010
7
Mudah jawaban terbaik di sini. Terutama pengamatan (dalam paragraf ketiga) bahwa kompleksitas bukan hanya properti dari seluruh kode sebagai keseluruhan tetapi sesuatu yang ada, dan berbeda, pada beberapa level abstraksi secara bersamaan.
Christian Hackl
2
Saya pikir salah satu cara untuk mengatakan ini adalah bahwa, secara umum, mengekstraksi suatu kondisi harus dilakukan hanya jika ada nama yang bermakna dan tidak dikaburkan untuk kondisi itu. Ini adalah kondisi yang diperlukan tetapi tidak cukup.
JimmyJames
Re "... karena Anda sekarang memiliki fungsi yang terlihat dari lebih banyak titik dalam program" : di Pascal dimungkinkan untuk memiliki fungsi lokal - "... Setiap prosedur atau fungsi dapat memiliki deklarasi label goto sendiri, konstanta , jenis, variabel, dan prosedur dan fungsi lainnya, ... "
Peter Mortensen
2
@PeterMortensen: Dimungkinkan juga dalam C # dan JavaScript. Dan itu luar biasa! Tetapi intinya tetap, fungsi, bahkan fungsi lokal, terlihat dalam lingkup yang lebih besar daripada fragmen kode inline.
JacquesB
9

Saya akan menunjukkan tidak ada yang salah dengan ini:

if(contact.email != null && contact.email.contains('@')

Setidaknya dengan asumsi itu digunakan sekali ini.

Saya bisa mengalami masalah dengan ini dengan sangat mudah:

private Boolean isEmailValid(String email){
   return email != null && email.contains('@');
}

Beberapa hal yang saya perhatikan:

  1. Mengapa ini pribadi? Sepertinya rintisan yang berpotensi bermanfaat. Apakah cukup bermanfaat untuk menjadi metode pribadi dan tidak ada peluang digunakan secara lebih luas?
  2. Saya tidak akan menyebutkan nama metode IsValidEmail secara pribadi, mungkin ContainsAtSign atau LooksVaguelyLikeEmailAddress karena hampir tidak ada validasi nyata, yang mungkin baik, mungkin bukan apa yang ditampilkan.
  3. Apakah ini digunakan lebih dari satu kali?

Jika sedang digunakan sekali, mudah diurai, dan membutuhkan kurang dari satu baris saya akan menebak keputusan kedua. Itu mungkin bukan sesuatu yang saya sebut jika bukan masalah khusus dari tim.

Di sisi lain saya telah melihat metode melakukan sesuatu seperti ini:

if (contact.email != null && contact.email.contains('@')) { ... }
else if (contact.email != null && contact.email.contains('@') && contact.email.contains("@mydomain.com")) { //headquarters email }
else if (contact.email != null && contact.email.contains('@') && (contact.email.contains("@news.mydomain.com") || contact.email.contains("@design.mydomain.com") ) { //internal contract teams }

Contoh itu jelas bukan KERING.

Atau bahkan pernyataan terakhir itu bisa memberikan contoh lain:

if (contact.email != null && contact.email.contains('@') && (contact.email.contains("@news.mydomain.com") || contact.email.contains("@design.mydomain.com") )

Tujuannya adalah membuat kode lebih mudah dibaca:

if (LooksSortaLikeAnEmail(contact.Email)) { ... }
else if (LooksLikeFromHeadquarters(contact.Email)) { ... }
else if (LooksLikeInternalEmail(contact.Email)) { ... }

Skenario lain:

Anda mungkin memiliki metode seperti:

public void SaveContact(Contact contact){
   if (contact.email != null && contact.email.contains('@'))
   {
       contacts.Add(contact);
       contacts.Save();
   }
}

Jika ini sesuai dengan logika bisnis Anda dan tidak digunakan kembali, tidak ada masalah di sini.

Tetapi ketika seseorang bertanya "Mengapa '@' diselamatkan, karena itu tidak benar!" dan Anda memutuskan untuk menambahkan validasi yang sebenarnya, lalu ekstrak!

Anda akan senang Anda lakukan ketika Anda juga perlu akun untuk akun email kedua presiden Pr3 $ sid3nt @ h0m3! @ Mydomain.com dan memutuskan untuk pergi keluar semua dan mencoba dan mendukung RFC 2822.

Keterbacaan:

// If there is an email property and it contains an @ sign then process
if (contact.email != null && contact.email.contains('@'))

Jika kode Anda jelas, Anda tidak perlu komentar di sini. Sebenarnya, Anda tidak perlu komentar untuk mengatakan apa yang paling sering dilakukan oleh kode, tetapi mengapa melakukannya:

// The UI passes '@' by default, the DBA's made this column non-nullable but 
// marketing is currently more concerned with other fields and '@' default is OK
if (contact.email != null && contact.email.contains('@'))

Apakah komentar di atas pernyataan if atau di dalam metode kecil bagi saya, sangat bagus. Saya bahkan mungkin berpendapat sebaliknya berguna dengan komentar baik di dalam metode lain karena sekarang Anda harus menavigasi ke metode lain untuk melihat bagaimana dan mengapa ia melakukan apa yang dilakukannya.

Singkatnya: Jangan mengukur hal-hal ini; Berfokuslah pada prinsip-prinsip dari mana teks itu dibuat (KERING, SOLID, KISS).

// A valid class that does nothing
public class Nothing 
{

}
AthomSfere
sumber
3
Whether the comments above an if statement or inside a tiny method is to me, pedantic.Ini adalah masalah "jerami yang mematahkan punggung unta". Anda benar bahwa hal yang satu ini tidak terlalu sulit untuk dibaca secara langsung. Tapi jika Anda memiliki metode besar (misalnya impor besar) yang memiliki puluhan ini evaluasi kecil, memiliki ini dikemas dalam nama metode yang dapat dibaca ( IsUserActive, GetAverageIncome, MustBeDeleted, ...) akan menjadi peningkatan yang nyata pada membaca kode. Masalah dengan contohnya adalah ia hanya mengamati satu jerami, bukan seluruh buntalan yang mematahkan punggung unta.
Flater
@Flater dan saya berharap ini adalah semangat yang diambil pembaca dari itu.
AthomSfere
1
"Enkapsulasi" ini adalah anti-pola, dan jawabannya benar-benar menunjukkan ini. Kami kembali untuk membaca kode untuk keperluan debugging dan untuk tujuan memperluas kode. Dalam kedua kasus, memahami apa yang sebenarnya dilakukan kode sangat penting. Awal blok kode if (contact.email != null && contact.email.contains('@'))bermasalah. Jika if salah, tidak ada yang lain jika baris bisa benar. Ini sama sekali tidak terlihat di LooksSortaLikeAnEmailblok. Fungsi yang berisi satu baris kode tidak jauh lebih baik daripada komentar yang menjelaskan cara kerja baris.
Quirk
1
Paling-paling, lapisan tipuan lainnya mengaburkan mekanisme yang sebenarnya dan membuat debugging lebih sulit. Paling buruk, nama fungsi telah menjadi kebohongan dengan cara yang sama dengan komentar menjadi kebohongan - isinya diperbarui tetapi namanya tidak. Ini bukan serangan terhadap enkapsulasi secara umum, tetapi idiom khusus ini merupakan gejala dari masalah besar modern dengan rekayasa perangkat lunak "perusahaan" - lapisan dan lapisan abstraksi dan lem mengubur logika yang relevan.
Quirk
@ tanya saya pikir Anda setuju dengan poin saya secara keseluruhan? Dan dengan lemnya, masalah yang Anda hadapi berbeda. Saya benar-benar menggunakan peta kode ketika melihat kode tim baru. Sangat menakutkan apa yang saya lihat dilakukan untuk beberapa metode besar memanggil serangkaian metode besar bahkan pada tingkat pola mvc.
AthomSfere
6

Clean Code adalah buku yang sangat bagus, dan layak dibaca, tetapi bukan merupakan otoritas final dalam hal-hal tersebut.

Memecah kode menjadi fungsi-fungsi logis biasanya merupakan ide yang baik, tetapi beberapa programmer melakukannya sejauh Martin melakukannya - pada titik tertentu Anda mendapatkan hasil yang semakin berkurang dari mengubah segala sesuatu menjadi fungsi dan itu bisa sulit untuk diikuti ketika semua kode berada dalam ukuran kecil. potongan.

Salah satu opsi saat tidak layak membuat fungsi baru adalah dengan menggunakan variabel perantara:

boolean isEmailValid = (contact.email != null && contact.emails.contains('@');

if (isEmailValid) {
...

Ini membantu menjaga kode mudah diikuti tanpa harus sering melompati file.

Masalah lain adalah bahwa Kode Bersih sudah cukup tua sebagai buku sekarang. Banyak rekayasa perangkat lunak telah bergerak ke arah pemrograman fungsional, sedangkan Martin berusaha keras untuk menambah keadaan ke berbagai hal dan membuat objek. Saya curiga dia akan menulis buku yang sangat berbeda jika dia menulisnya hari ini.

Rich Smith
sumber
Beberapa khawatir tentang baris kode tambahan di dekat kondisi (saya tidak, sama sekali), tetapi mungkin mengatasi itu dalam jawaban Anda.
Peter Mortensen
5

Mempertimbangkan fakta bahwa "adalah email yang valid" kondisi yang Anda miliki saat ini akan menerima alamat email yang sangat tidak valid " @", saya pikir Anda memiliki alasan untuk mencabut kelas EmailValidator. Lebih baik lagi, gunakan perpustakaan yang baik, teruji dengan baik untuk memvalidasi alamat email.

Baris kode sebagai metrik tidak ada artinya. Pertanyaan penting dalam rekayasa perangkat lunak bukanlah:

  • Apakah Anda memiliki terlalu banyak kode?
  • Apakah kode Anda terlalu sedikit?

Pertanyaan penting adalah:

  • Apakah aplikasi secara keseluruhan dirancang dengan benar?
  • Apakah kode diterapkan dengan benar?
  • Apakah kode dapat dipelihara?
  • Apakah kode dapat diuji?
  • Apakah kode diuji secara memadai?

Saya tidak pernah memikirkan LoC saat menulis kode untuk tujuan apa pun selain Code Golf. Saya bertanya pada diri sendiri, "Bisakah saya menulis ini dengan lebih ringkas?", Tetapi untuk tujuan keterbacaan, pemeliharaan, dan efisiensi, tidak hanya panjang.

Tentu, mungkin saya bisa menggunakan rantai panjang operasi boolean bukan metode utilitas, tetapi haruskah saya?

Pertanyaan Anda benar-benar membuat saya berpikir kembali pada rantai panjang boolean yang telah saya tulis dan sadari bahwa saya mungkin seharusnya menulis satu atau lebih metode utilitas.

Clement Cherlin
sumber
3

Pada satu tingkat, mereka benar - kode kurang lebih baik. Jawaban lain yang dikutip Gate, saya lebih suka:

“Jika debugging adalah proses menghilangkan bug perangkat lunak, maka pemrograman harus menjadi proses memasukkannya.” - Edsger Dijkstra

“Saat debugging, para pemula memasukkan kode korektif; para ahli menghapus kode yang rusak. "- Richard Pattis

Komponen termurah, tercepat, dan paling dapat diandalkan adalah komponen yang tidak ada. - Gordon Bell

Singkatnya, semakin sedikit kode yang Anda miliki, semakin sedikit yang bisa salah. Jika sesuatu tidak perlu, potong saja.
Jika ada kode yang terlalu rumit, maka sederhanakan sampai semua elemen fungsional yang sebenarnya tetap ada.

Yang penting di sini, adalah bahwa semua ini merujuk pada fungsionalitas, dan hanya memiliki minimum yang diperlukan untuk melakukannya. Itu tidak mengatakan apa-apa tentang bagaimana itu diungkapkan.

Apa yang Anda lakukan dengan mencoba memiliki kode bersih tidak bertentangan dengan hal di atas. Anda menambahkan ke LOC Anda tetapi tidak menambahkan fungsionalitas yang tidak digunakan.

Tujuan akhirnya adalah memiliki kode yang dapat dibaca tetapi tidak ada tambahan yang berlebihan. Kedua prinsip tersebut seharusnya tidak saling bertentangan.

Metafora akan membangun mobil. Bagian fungsional dari kode adalah sasis, mesin, roda ... apa yang membuat mobil berjalan. Bagaimana Anda memecahnya lebih seperti suspensi, power steering dan sebagainya, itu membuatnya lebih mudah untuk ditangani. Anda ingin mekanik Anda sesederhana mungkin sambil tetap melakukan pekerjaan mereka, untuk meminimalkan kemungkinan terjadi kesalahan, tetapi itu tidak mencegah Anda dari memiliki kursi yang bagus.

Baldrickk
sumber
2

Ada banyak kebijaksanaan dalam jawaban yang ada, tetapi saya ingin menambahkan satu faktor lagi: bahasa .

Beberapa bahasa mengambil lebih banyak kode daripada yang lain untuk mendapatkan efek yang sama. Secara khusus, sementara Java (yang saya duga adalah bahasa dalam pertanyaan) sangat terkenal dan umumnya sangat solid dan jelas dan langsung, beberapa bahasa yang lebih modern jauh lebih ringkas dan ekspresif.

Sebagai contoh, di Jawa dapat dengan mudah mengambil 50 baris untuk menulis kelas baru dengan tiga properti, masing-masing dengan pengambil dan penyetel, dan satu atau lebih konstruktor - sementara Anda dapat mencapai hal yang persis sama dalam satu baris Kotlin * atau Scala. (Tabungan Bahkan lebih besar jika Anda juga ingin cocok equals(), hashCode()dan toString()metode.)

Hasilnya adalah bahwa di Jawa, pekerjaan tambahan berarti Anda lebih mungkin untuk menggunakan kembali objek umum yang tidak benar-benar cocok, untuk memeras properti menjadi objek yang ada, atau untuk melewati sekelompok properti 'telanjang' di sekitar secara individual; sementara dalam bahasa yang singkat dan ekspresif, Anda lebih cenderung menulis kode yang lebih baik.

(Ini menyoroti perbedaan antara kompleksitas 'permukaan' dari kode, dan kompleksitas dari ide / model / pemrosesan yang diterapkannya. Garis-garis kode bukanlah ukuran yang buruk dari yang pertama, tetapi lebih sedikit hubungannya dengan yang kedua .)

Jadi 'biaya' untuk melakukan sesuatu dengan benar tergantung pada bahasanya. Mungkin satu tanda bahasa yang baik adalah yang tidak membuat Anda memilih antara melakukan sesuatu dengan baik, dan melakukannya dengan mudah!

(* Ini bukan tempat yang tepat untuk plug, tapi Kotlin layak untuk dicoba.)

gidds
sumber
1

Mari kita asumsikan bahwa Anda sedang bekerja dengan kelas Contactsaat ini. Fakta bahwa Anda menulis metode lain untuk validasi alamat email adalah bukti fakta bahwa kelas Contacttidak menangani satu tanggung jawab tunggal.

Itu juga menangani beberapa tanggung jawab email, yang idealnya, harus kelas tersendiri.


Bukti lebih lanjut bahwa kode Anda adalah perpaduan Contactdan Emailkelas adalah bahwa Anda tidak akan dapat dengan mudah menguji kode validasi email. Dibutuhkan banyak manuver untuk mencapai kode validasi email dalam metode besar dengan nilai yang benar. Lihat metode yaitu di bawah ini.

private void LargeMethod() {
    //A lot of code which modifies a lot of values. You do all sorts of tricks here.
    //Code.
    //Code..
    //Code...

    //Email validation code becoming very difficult to test as it will be difficult to ensure 
    //that you have the right data till you reach here in the method
    ValidateEmail();

    //Another whole lot of code that modifies all sorts of values.
    //Extra work to preserve the result of ValidateEmail() for your asserts later.
}

Di sisi lain, jika Anda memiliki kelas Email terpisah dengan metode untuk validasi email, maka untuk menguji unit kode validasi Anda, Anda hanya akan membuat satu panggilan sederhana Email.Validation()dengan data pengujian Anda.


Konten Bonus: Pembicaraan MFeather tentang sinergi yang mendalam antara testabilitas dan desain yang baik.

nama tampilan
sumber
1

Pengurangan LOC telah ditemukan berkorelasi dengan berkurangnya cacat, tidak ada yang lain. Dengan asumsi kemudian bahwa setiap kali Anda mengurangi LOC, Anda telah mengurangi kemungkinan cacat pada dasarnya jatuh ke dalam perangkap percaya bahwa korelasi sama dengan sebab-akibat. Pengurangan LOC adalah hasil dari praktik pengembangan yang baik dan bukan apa yang membuat kode baik.

Dalam pengalaman saya, orang yang dapat memecahkan masalah dengan kode lebih sedikit (pada level makro) cenderung lebih terampil daripada mereka yang menulis lebih banyak kode untuk melakukan hal yang sama. Apa yang dilakukan oleh pengembang yang terampil ini untuk mengurangi baris kode adalah menggunakan / membuat abstraksi dan solusi yang dapat digunakan kembali untuk memecahkan masalah umum. Mereka tidak menghabiskan waktu menghitung baris kode dan merasa tersiksa apakah mereka dapat memotong garis di sini atau di sana. Seringkali kode yang mereka tulis lebih bertele-tele daripada yang diperlukan, mereka hanya menulis lebih sedikit.

Biarkan saya memberi Anda sebuah contoh. Saya harus berurusan dengan logika di sekitar periode waktu dan bagaimana mereka tumpang tindih, apakah mereka berdekatan, dan kesenjangan apa yang ada di antara mereka. Ketika saya pertama kali mulai mengerjakan masalah ini, saya akan memiliki blok kode melakukan perhitungan di mana-mana. Akhirnya, saya membangun kelas untuk mewakili periode waktu dan operasi yang menghitung tumpang tindih, komplemen, dll. Ini segera menghapus sejumlah besar kode dan mengubahnya menjadi beberapa metode panggilan. Tetapi kelas-kelas itu sendiri tidak ditulis dengan singkat sama sekali.

Secara jelas menyatakan: jika Anda mencoba mengurangi LOC dengan mencoba memotong garis kode di sini atau di sana dengan lebih singkat, Anda salah melakukannya. Ini seperti mencoba menurunkan berat badan dengan mengurangi jumlah sayuran yang Anda makan. Tulis kode yang mudah dimengerti, dipelihara, dan didebug dan kurangi LOC melalui penggunaan kembali dan abstraksi.

JimmyJames
sumber
1

Anda telah mengidentifikasi trade-off yang valid

Jadi memang ada trade-off di sini dan itu melekat pada abstraksi secara keseluruhan. Setiap kali ada orang yang mencoba menarik N baris kode ke dalam fungsinya sendiri untuk memberi nama dan mengisolasinya, mereka secara bersamaan membuat membaca situs panggilan lebih mudah (dengan merujuk pada nama daripada semua detail berdarah yang mendasari nama itu) dan lebih kompleks (Anda sekarang memiliki makna yang terjerat di dua bagian berbeda dari basis kode). "Mudah" adalah kebalikan dari "keras," tetapi itu bukan sinonim untuk "sederhana" yang merupakan kebalikan dari "kompleks." Keduanya tidak bertolak belakang, dan abstraksi selalu meningkatkan kompleksitas untuk memasukkan beberapa bentuk dengan mudah.

Kita dapat melihat kompleksitas yang ditambahkan secara langsung ketika beberapa perubahan dalam persyaratan bisnis membuat abstraksi mulai bocor. Mungkin beberapa logika baru akan berjalan paling alami di tengah kode pra-abstrak, katakan misalnya jika kode abstrak melintasi beberapa pohon dan Anda benar-benar ingin mengumpulkan (dan mungkin bertindak berdasarkan) semacam informasi saat Anda berada melintasi pohon itu. Sementara itu, jika Anda telah mengabstraksikan kode ini, maka mungkin ada situs panggilan lain, dan menambahkan logika yang diperlukan ke tengah metode ini dapat merusak situs panggilan lain tersebut. Lihat, setiap kali kita mengubah satu baris kode, kita hanya perlu melihat konteks langsung dari baris kode itu; ketika kita mengubah metode, kita harus Cmd-F seluruh kode sumber kita mencari apa pun yang mungkin rusak sebagai akibat dari mengubah kontrak metode itu,

Algoritma serakah bisa gagal dalam kasus ini

Kompleksitasnya juga membuat kode dalam arti tertentu lebih mudah dibaca daripada lebih banyak. Dalam pekerjaan sebelumnya saya berurusan dengan API HTTP yang sangat hati-hati dan tepat terstruktur menjadi beberapa lapisan, setiap titik akhir ditentukan oleh pengontrol yang memvalidasi bentuk pesan yang masuk dan kemudian menyerahkannya ke manajer "business-logic-layer" , yang kemudian membuat beberapa permintaan "lapisan data" yang bertanggung jawab untuk membuat beberapa pertanyaan ke lapisan "objek akses data", yang bertanggung jawab untuk membuat beberapa Delegasi SQL yang sebenarnya akan menjawab pertanyaan Anda. Hal pertama yang bisa saya katakan tentang hal itu adalah, sekitar 90% dari kode itu adalah copy-and-paste boilerplate, dengan kata lain itu adalah no-ops. Jadi dalam banyak kasus membaca setiap bagian kode yang diberikan sangat "mudah", karena "oh manajer ini hanya meneruskan permintaan ke objek akses data itu."banyak pengalihan konteks dan menemukan file dan mencoba melacak informasi yang seharusnya tidak pernah Anda lacak, "ini disebut X pada layer ini, ia disebut X 'pada layer lain ini, kemudian disebut X' 'pada layer lain ini lapisan lain. "

Saya pikir ketika saya tinggalkan, CRUD API sederhana ini berada pada tahap di mana jika Anda mencetaknya pada 30 baris per halaman, itu akan memakan 10-20 lima ratus halaman buku teks di rak: itu adalah seluruh ensiklopedia repetitif kode. Dalam hal kompleksitas esensial, saya tidak yakin bahwa ada bahkan setengah dari buku teks kompleksitas esensial di sana; kami hanya memiliki 5-6 diagram database untuk mengatasinya. Membuat sedikit perubahan pada itu adalah usaha yang sangat besar, belajar itu adalah usaha yang sangat besar, menambahkan fungsionalitas baru menjadi sangat menyakitkan sehingga kami benar-benar memiliki file templat boilerplate yang akan kami gunakan untuk menambahkan fungsionalitas baru.

Jadi saya telah melihat sendiri bagaimana membuat setiap bagian sangat mudah dibaca dan jelas dapat membuat keseluruhannya sangat tidak dapat dibaca dan tidak jelas. Ini berarti bahwa algoritma serakah dapat gagal. Anda tahu algoritma serakah, ya? "Saya akan melakukan langkah apa pun yang paling meningkatkan situasi lokal, dan kemudian saya akan percaya bahwa saya menemukan diri saya dalam situasi yang meningkat secara global." Ini sering merupakan upaya pertama yang indah tetapi juga bisa gagal dalam konteks yang kompleks. Sebagai contoh di bidang manufaktur, Anda mungkin mencoba meningkatkan efisiensi setiap langkah tertentu dalam proses pembuatan yang kompleks - lakukan batch yang lebih besar, berteriak pada orang-orang di lantai yang tampaknya tidak melakukan apa pun untuk membuat tangan mereka sibuk dengan hal lain - dan ini seringkali dapat menghancurkan efisiensi global sistem.

Praktik terbaik: gunakan KERING dan panjang untuk melakukan panggilan

(Catatan: Judul bagian ini agak bercanda; Saya sering memberi tahu teman-teman saya bahwa ketika seseorang mengatakan "kita harus melakukan X karena praktik terbaik mengatakan demikian " mereka 90% dari waktu tidak berbicara tentang sesuatu seperti injeksi SQL atau kata sandi hashing atau apa pun - praktik terbaik unilateral - dan dengan demikian pernyataan tersebut dapat diterjemahkan dalam 90% waktu untuk "kita harus melakukan X karena saya mengatakan demikian ." Seperti mereka mungkin memiliki beberapa artikel blog dari beberapa bisnis yang melakukan pekerjaan yang lebih baik dengan X daripada X 'tetapi umumnya tidak ada jaminan bahwa bisnis Anda menyerupai bisnis itu, dan umumnya ada beberapa artikel lain dari beberapa bisnis lain yang melakukan pekerjaan yang lebih baik dengan X' daripada X. Jadi tolong jangan mengambil judul juga serius.)

Apa yang saya sarankan didasarkan pada ceramah oleh Jack Diederich yang disebut Stop Writing Classes (youtube.com) . Dia membuat beberapa poin bagus dalam pembicaraan itu: misalnya, bahwa Anda dapat mengetahui kelas benar-benar hanya berfungsi ketika hanya memiliki dua metode publik, dan salah satunya adalah konstruktor / initializer. Tetapi dalam satu kasus dia berbicara tentang bagaimana perpustakaan hipotetis yang dia ganti string untuk pembicaraan sebagai "Muffin" menyatakan kelasnya sendiri "MuffinHash" yang merupakan subkelas dari dicttipe builtin yang dimiliki oleh Python. Implementasinya benar-benar kosong — seseorang baru saja berpikir, "kita mungkin perlu menambahkan fungsionalitas khusus ke kamus Python nanti, mari kita perkenalkan abstraksi sekarang untuk berjaga-jaga."

Dan jawabannya adalah, "kita selalu bisa melakukannya nanti, jika perlu."

Saya pikir kita kadang-kadang berpura-pura seperti kita akan menjadi programmer yang lebih buruk di masa depan daripada kita sekarang, jadi kita mungkin ingin memasukkan semacam hal kecil yang mungkin membuat kita bahagia di masa depan. Kami mengantisipasi kebutuhan masa depan-kita. "Jika lalu lintas 100 kali lebih besar dari yang kami kira, pendekatan itu tidak akan berkembang, jadi kami harus menempatkan investasi di muka ke dalam pendekatan yang lebih sulit ini yang akan ditingkatkan." Sangat mencurigakan.

Jika kita menanggapi saran itu dengan serius maka kita perlu mengidentifikasi kapan "nanti" telah datang. Mungkin hal yang paling jelas adalah menetapkan batas atas panjangnya barang untuk alasan gaya. Dan saya pikir saran terbaik yang tersisa adalah menggunakan KERING — jangan ulangi diri Anda sendiri — dengan heuristik ini tentang panjang garis untuk menambal lubang dalam prinsip-prinsip SOLID. Berdasarkan heuristik 30 baris menjadi "halaman" teks dan analogi dengan prosa,

  1. Ubah tanda centang pada fungsi / metode ketika Anda ingin menyalin-menempelkannya. Seperti ada beberapa alasan sah untuk menyalin-tempel tetapi Anda harus selalu merasa kotor karenanya. Penulis sejati tidak membuat Anda membaca ulang kalimat panjang yang besar 50 kali sepanjang narasi kecuali mereka benar-benar mencoba menyoroti tema.
  2. Fungsi / metode idealnya adalah "paragraf". Sebagian besar fungsi harus panjangnya sekitar setengah halaman, atau 1-15 baris kode, dan mungkin hanya 10% dari fungsi Anda yang diizinkan berkisar hingga satu setengah halaman, 45 baris atau lebih. Setelah Anda berada di 120+ baris kode dan komentar hal itu perlu dipecah menjadi beberapa bagian.
  3. Sebuah file idealnya menjadi "bab". Sebagian besar file harus sepanjang 12 halaman atau kurang, jadi 360 baris kode dan komentar. Hanya mungkin 10% dari file Anda yang boleh memiliki rentang hingga 50 halaman, atau 1500 baris kode dan komentar.
  4. Idealnya, sebagian besar kode Anda harus diindentasi dengan garis dasar fungsi atau sedalam satu level. Berdasarkan beberapa heuristik tentang pohon sumber Linux, jika Anda religius tentang hal itu, hanya mungkin 10% dari kode Anda harus diindentasi 2 level atau lebih dalam baseline, kurang dari 5% indentasi 3 level atau lebih. Ini berarti khususnya bahwa hal-hal yang perlu "membungkus" beberapa masalah lain, seperti penanganan kesalahan dalam percobaan / penangkapan besar, harus ditarik keluar dari logika aktual.

Seperti yang saya sebutkan di sana, saya menguji statistik ini terhadap pohon sumber Linux saat ini untuk menemukan perkiraan persentase itu, tetapi mereka juga semacam alasan dalam analogi sastra.

CR Drost
sumber