One-liners vs keterbacaan: kapan harus berhenti mengurangi kode? [Tutup]

14

Konteks

Saya baru-baru ini tertarik untuk menghasilkan kode yang diformat lebih baik. Dan yang lebih baik saya maksudkan "mengikuti aturan yang didukung oleh cukup banyak orang untuk menganggapnya sebagai praktik yang baik" (karena tentu saja tidak akan ada satu cara "terbaik" yang unik untuk kode, tentu saja).

Hari-hari ini, aku kebanyakan kode Ruby jadi aku mulai menggunakan linter (Rubocop) untuk memberikan saya beberapa info tentang "kualitas" dari kode saya (ini "kualitas" yang didefinisikan oleh proyek berbasis masyarakat ruby-style-panduan ).

Perhatikan bahwa saya akan menggunakan "kualitas" seperti dalam "kualitas Formating", tidak begitu banyak tentang efisiensi kode, bahkan jika dalam beberapa kasus, efisiensi kode sebenarnya adalah dipengaruhi oleh bagaimana kode ditulis.

Bagaimanapun, melakukan semua itu, saya menyadari (atau setidaknya, ingat) beberapa hal:

  • Beberapa bahasa (terutama Python, Ruby, dan semacamnya) memungkinkan untuk membuat satu baris kode yang hebat
  • Mengikuti beberapa pedoman untuk kode Anda dapat membuatnya secara signifikan lebih pendek dan masih sangat jelas
  • Namun, mengikuti pedoman ini terlalu ketat dapat membuat kode menjadi kurang jelas / mudah dibaca
  • Kode dapat menghormati beberapa pedoman hampir dengan sempurna dan masih berkualitas buruk
  • Keterbacaan kode sebagian besar subyektif (seperti dalam "apa yang saya temukan jelas benar-benar tidak jelas bagi sesama pengembang")

Itu hanya pengamatan, bukan aturan mutlak tentu saja. Anda juga akan mencatat bahwa keterbacaan kode dan pedoman berikut mungkin tampak tidak berhubungan pada titik ini, tetapi di sini pedoman adalah cara untuk mempersempit jumlah cara untuk menulis ulang satu potong kode.

Sekarang, beberapa contoh, untuk membuatnya lebih jelas.

Contohnya

Mari kita ambil contoh penggunaan sederhana: kami memiliki aplikasi dengan Usermodel " ". Seorang pengguna memiliki opsional firstnamedan surnamedan wajibemail .

Saya ingin menulis metode " name" yang akan mengembalikan lalu memberi nama ( firstname + surname) pada pengguna jika setidaknya ada firstnameatau surnametidak, atauemail sebagai nilai cadangan jika tidak.

Saya juga ingin metode ini mengambil " use_email" sebagai parameter (boolean), memungkinkan untuk menggunakan email pengguna sebagai nilai fallback. use_emailParameter " " ini seharusnya default (jika tidak dilewatkan) sebagai " true".

Cara paling sederhana untuk menulis itu, di Ruby, adalah:

def name(use_email = true)
 # If firstname and surname are both blank (empty string or undefined)
 # and we can use the email...
 if (firstname.blank? && surname.blank?) && use_email
  # ... then, return the email
  return email
 else
  # ... else, concatenate the firstname and surname...
  name = "#{firstname} #{surname}"
  # ... and return the result striped from leading and trailing spaces
  return name.strip
 end
end

Kode ini adalah cara yang paling sederhana dan mudah dipahami untuk melakukannya. Bahkan untuk seseorang yang tidak "berbicara" Ruby.

Sekarang mari kita coba untuk mempersingkat:

def name(use_email = true)
 # 'if' condition is used as a guard clause instead of a conditional block
 return email if (firstname.blank? && surname.blank?) && use_email
 # Use of 'return' makes 'else' useless anyway
 name = "#{firstname} #{surname}"
 return name.strip
end

Ini lebih pendek, masih mudah dipahami, jika tidak mudah (klausa penjaga lebih alami untuk dibaca daripada blok bersyarat). Penjaga klausa juga membuatnya lebih sesuai dengan pedoman yang saya gunakan, jadi menang-menang di sini. Kami juga mengurangi level indentasi.

Sekarang mari kita gunakan beberapa sihir Ruby untuk membuatnya lebih pendek:

def name(use_email = true)
 return email if (firstname.blank? && surname.blank?) && use_email
 # Ruby can return the last called value, making 'return' useless
 # and we can apply strip directly to our string, no need to store it
 "#{firstname} #{surname}".strip
end

Bahkan lebih pendek dan mengikuti pedoman dengan sempurna ... tetapi jauh lebih tidak jelas karena kurangnya pernyataan pengembalian membuatnya agak membingungkan bagi mereka yang tidak terbiasa dengan praktik ini.

Di sinilah kita dapat mulai mengajukan pertanyaan: apakah itu benar-benar layak? Jika kita mengatakan "tidak, buat itu bisa dibaca dan tambahkan ' return'" (mengetahui ini tidak akan mematuhi pedoman). Atau haruskah kita berkata, "Tidak apa-apa, itu cara Ruby, belajar bahasa sialan!"?

Jika kita mengambil opsi B, mengapa tidak membuatnya lebih pendek:

def name(use_email = true)
 (email if (firstname.blank? && surname.blank?) && use_email) || "#{firstname} #{surname}".strip
end

Ini dia, satu-liner! Tentu saja lebih pendek ... di sini kita mengambil keuntungan dari kenyataan bahwa Ruby akan mengembalikan nilai atau yang lain tergantung mana yang didefinisikan (karena email akan didefinisikan dalam kondisi yang sama seperti sebelumnya).

Kita juga bisa menulisnya:

def name(use_email = true)
 (email if [firstname, surname].all?(&:blank?) && use_email) || "#{firstname} #{surname}".strip
end

Ini singkat, tidak terlalu sulit untuk dibaca (maksud saya, kita semua telah melihat seperti apa bentuk one-liner yang jelek), Ruby yang bagus, itu sesuai dengan pedoman yang saya gunakan ... Tapi tetap saja, dibandingkan dengan cara pertama menulis itu, itu jauh lebih mudah dibaca dan dimengerti. Kami juga dapat berpendapat bahwa baris ini terlalu panjang (lebih dari 80 karakter).

Pertanyaan

Beberapa contoh kode dapat menunjukkan bahwa memilih antara kode "ukuran penuh" dan banyak versi yang diperkecil (turun ke garis satu yang terkenal) bisa jadi sulit karena, seperti yang bisa kita lihat, satu-baris bisa tidak menakutkan tetapi tetap saja, tidak ada yang akan mengalahkan kode "ukuran penuh" dalam hal keterbacaan ...

Jadi, inilah pertanyaan sebenarnya: ke mana harus berhenti? Kapan pendek, cukup pendek? Bagaimana cara mengetahui kapan kode menjadi "terlalu pendek" dan kurang dapat dibaca (dengan mengingat bahwa itu cukup subjektif)? Dan lebih dari itu: bagaimana cara selalu kode sesuai dan menghindari pencampuran satu-liners dengan potongan "ukuran penuh" kode ketika saya hanya merasa seperti itu?

TL; DR

Pertanyaan utama di sini adalah: ketika datang untuk memilih antara "sepotong kode yang panjang tapi jelas, dapat dibaca dan dimengerti" dan "kuat, lebih pendek namun lebih sulit untuk dibaca / dipahami satu-liner", mengetahui keduanya adalah yang teratas dan yang bawah skala dan bukan hanya dua opsi: bagaimana mendefinisikan di mana perbatasan antara "cukup jelas" dan "tidak sejelas yang seharusnya"?

Pertanyaan utama bukanlah klasik "One-liners vs keterbacaan: mana yang lebih baik?" tetapi "Bagaimana menemukan keseimbangan di antara keduanya?"

Edit 1

Komentar dalam contoh kode dimaksudkan untuk "diabaikan", mereka di sini untuk mengklarifikasi apa yang terjadi, tetapi tidak diperhitungkan ketika mengevaluasi keterbacaan kode.

Sudiukil
sumber
7
Terlalu pendek untuk jawaban: pertahankan secara berulang refactoring sampai Anda tidak yakin itu lebih baik daripada iterasi sebelumnya kemudian hentikan dan balikkan refactorisation terakhir.
Dom
8
Saya lebih suka varian 3 dengan returnkata kunci yang ditambahkan . Ketujuh karakter itu menambah kejernihan di mataku.
cmaster - mengembalikan monica
2
Jika Anda merasa benar-benar mengerikan, Anda dapat menulis semuanya sebagai [firstname,surname,!use_email].all?(&:blank?) ? email : "#{firstname} #{surname}".strip... karena false.blank?mengembalikan true dan operator ternary menghemat beberapa karakter ... ¯ \ _ (ツ) _ / ¯
DaveMongoose
1
OK, saya harus bertanya: kejelasan apa yang returnseharusnya ditambahkan kata kunci ?! Tidak memberikan informasi apa pun . Ini kekacauan murni.
Konrad Rudolph
2
Gagasan bahwa keringkasan menghasilkan kejelasan tidak hanya menderita dari hukum pengembalian yang menurun, tetapi berbalik ketika didorong ke ekstrem. Jika Anda menulis ulang untuk membuat fungsi pendek lebih pendek, Anda membuang-buang waktu, dan hal yang sama berlaku untuk mencoba membenarkan praktik tersebut.
sdenham

Jawaban:

26

Apa pun kode yang Anda tulis, terbaca adalah yang terbaik. Pendek adalah yang terbaik kedua. Dan dapat dibaca biasanya berarti cukup singkat sehingga Anda dapat memahami kode tersebut, pengidentifikasi yang dinamai dengan baik, dan mengikuti idiom umum bahasa tempat kode tersebut ditulis.

Jika ini adalah bahasa agnostik, saya pikir ini pasti akan berdasarkan opini, tetapi dalam batas-batas bahasa Ruby saya pikir kita bisa menjawabnya.

Pertama, fitur dan cara penulisan Ruby yang idiomatis adalah menghilangkan returnkata kunci saat mengembalikan nilai, kecuali kembali lebih awal dari suatu metode.

Fitur dan idiom lain yang digabungkan adalah menggunakan ifpernyataan tambahan untuk meningkatkan keterbacaan kode. Salah satu ide mengemudi di Ruby adalah menulis kode yang dibaca sebagai bahasa alami. Untuk ini, kita pergi ke _why Poignant Guide to Ruby, Bab 3 .

Bacalah yang berikut dengan keras untuk diri sendiri.

5.times { print "Odelay!" }

Dalam kalimat bahasa Inggris, tanda baca (seperti titik, tanda seru, tanda kurung) tidak bersuara. Tanda baca menambah makna kata-kata, membantu memberi isyarat tentang apa yang penulis maksudkan dengan kalimat. Jadi mari kita baca di atas sebagai: Lima kali cetak "Odelay!".

Dengan ini, kode contoh # 3 paling idiomatis untuk Ruby:

def name(use_email = true)
  return email if firstname.blank? && surname.blank? && use_email

  "#{firstname} #{surname}".strip
end

Sekarang ketika kita membaca kodenya, tertulis:

Kembalikan email jika nama depan kosong, dan nama belakang kosong dan gunakan email

(kembali) nama depan dan nama belakang dicopot

Yang sangat dekat dengan kode Ruby yang sebenarnya.

Ini hanya 2 baris kode aktual, jadi cukup singkat, dan menganut idiom bahasa.

Greg Burghardt
sumber
Poin yang bagus. Memang benar bahwa pertanyaan itu tidak dimaksudkan sebagai Ruby-centric, tetapi saya setuju bahwa tidak mungkin untuk memiliki jawaban agnostik bahasa di sini.
Sudiukil
8
Saya menemukan ide membuat kode terdengar seperti bahasa alami sangat berlebihan (dan kadang-kadang bahkan bermasalah). Tetapi bahkan tanpa motivasi ini saya sampai pada kesimpulan yang sama dengan jawaban ini.
Konrad Rudolph
1
Ada satu lagi tweak yang akan saya pertimbangkan untuk dilakukan pada kode. Artinya, untuk menempatkan use_emailsebelum kondisi lain karena itu adalah variabel daripada panggilan fungsi. Tapi sekali lagi, interpolasi string mengubah perbedaan.
John Dvorak
Menyusun kode mengikuti struktur bahasa alami dapat membuat Anda jatuh ke dalam perangkap bahasa. Misalnya, ketika Anda membaca persyaratan berikutnya do send an email if A, B, C but no D, mengikuti premis Anda akan alami untuk mengetikkan 2 jika / blok lain , ketika mungkin akan lebih mudah untuk kode if not D, send an email. Hati-hati pada saat membaca bahasa alami dan mengubahnya menjadi kode karena dapat membuat Anda menulis versi baru dari "Neverending story" . Dengan kelas, metode, dan variabel. Lagipula bukan masalah besar.
Laiv
@Lav: Membuat kode dibaca seperti bahasa alami tidak berarti menerjemahkan persyaratan secara harfiah. Ini berarti menulis kode sehingga ketika dibacakan dengan lantang memungkinkan pembaca untuk memahami logika tanpa membaca setiap bit kode, karakter untuk karakter, konstruksi bahasa untuk konstruksi bahasa. Jika coding itu if !Dlebih baik, tidak apa-apa karena Dmemiliki nama yang bermakna. Dan jika !operator tersesat di antara kode lain, maka memiliki pengenal yang dipanggil NotDakan sesuai.
Greg Burghardt
15

Saya tidak berpikir Anda akan mendapatkan jawaban yang lebih baik daripada "menggunakan penilaian terbaik Anda". Singkatnya Anda harus berusaha untuk kejelasan daripada sesak . Seringkali, kode terpendek juga merupakan kode yang paling jelas, tetapi jika Anda fokus hanya untuk mencapai kejelasan singkat mungkin menderita. Ini jelas merupakan kasus dalam dua contoh terakhir, yang membutuhkan lebih banyak upaya untuk memahami daripada tiga contoh sebelumnya.

Pertimbangan penting adalah audiens kode. Keterbacaan tentu saja sangat tergantung pada orang yang membaca. Apakah orang yang Anda harapkan membaca kode (di samping Anda) benar-benar mengetahui idiom bahasa Ruby? Yah pertanyaan ini bukanlah sesuatu yang dapat dijawab oleh orang-orang acak di internet, ini hanya keputusan Anda sendiri.

JacquesB
sumber
Saya setuju dengan poin audiens, tetapi itu adalah bagian dari perjuangan saya: karena perangkat lunak saya sering open-source, audiens mungkin dikomposisikan oleh pemula dan juga "para dewa Ruby". Saya bisa membuatnya tetap sederhana agar dapat diakses oleh kebanyakan orang, tetapi rasanya seperti membuang-buang keuntungan yang ditawarkan oleh bahasa.
Sudiukil
1
Sebagai seseorang yang harus mengambil alih, memperluas dan mempertahankan beberapa kode yang benar-benar mengerikan, kejelasan harus menang. Ingat pepatah lama - Tulis kode Anda seolah-olah pemelihara itu adalah Malaikat Neraka pendendam yang tahu di mana Anda tinggal dan ke mana anak-anak Anda pergi ke sekolah.
uɐɪ
2
@Sudiukil: Itu poin penting. Saya sarankan Anda berjuang untuk kode idiomatik dalam kasus itu (yaitu menganggap pengetahuan bahasa yang baik), karena tidak mungkin pemula akan berkontribusi untuk membuka kode sumber. (Atau jika mereka melakukannya, mereka akan siap untuk berupaya mempelajari bahasa itu.)
JacquesB
7

Bagian dari masalah di sini adalah "apa itu readibility". Bagi saya, saya melihat contoh kode pertama Anda:

def name(use_email = true)
 # If firstname and surname are both blank (empty string or undefined)
 # and we can use the email...
 if (firstname.blank? && surname.blank?) && use_email
  # ... then, return the email
  return email
 else
  # ... else, concatenate the firstname and surname...
  name = "#{firstname} #{surname}"
  # ... and return the result striped from leading and trailing spaces
  return name.strip
 end
end

Dan saya merasa sulit untuk membaca karena penuh dengan komentar "berisik" yang hanya mengulangi kode. Lepaskan mereka:

def name(use_email = true)
 if (firstname.blank? && surname.blank?) && use_email
  return email
 else
  name = "#{firstname} #{surname}"
  return name.strip
 end
end

dan sekarang jauh lebih mudah dibaca. Saat membacanya, saya pikir "hmm, saya ingin tahu apakah Ruby mendukung operator ternary? Dalam C #, saya dapat menuliskannya sebagai:

string Name(bool useEmail = true) => 
    firstName.Blank() && surname.Blank() && useEmail 
    ? email 
    : $"{firstname} {surname}".Strip();

Apakah hal seperti itu mungkin terjadi di ruby? Sedang mengerjakan posting Anda, saya melihat ada:

def name(use_email = true)
 (email if (firstname.blank? && surname.blank?) && use_email) || "#{firstname} #{surname}".strip
end

Semua barang bagus. Tapi itu tidak bisa dibaca oleh saya; hanya karena saya harus menggulir untuk melihat seluruh baris. Jadi mari kita perbaiki:

def name(use_email = true)
 (email if (firstname.blank? && surname.blank?) && use_email) 
 || "#{firstname} #{surname}".strip
end

Sekarang saya senang. Saya tidak sepenuhnya yakin tentang bagaimana sintaks bekerja, tetapi saya dapat memahami apa yang dilakukan oleh kode.

Tapi itu hanya aku. Orang lain memiliki ide yang sangat berbeda tentang apa yang membuat sepotong kode menjadi enak dibaca. Jadi, Anda perlu tahu audiens Anda saat menulis kode. Jika Anda seorang pemula yang benar-benar mengajar, maka Anda ingin membuatnya tetap sederhana dan mungkin menulisnya seperti contoh pertama Anda. Jika Anda bekerja di antara sekumpulan pengembang profesional dengan pengalaman ruby ​​bertahun-tahun, maka tulis kode yang memanfaatkan bahasa dan singkatkan. Jika ada suatu tempat di antara keduanya, maka bidiklah di suatu tempat di antaranya.

Satu hal yang saya akan katakan: waspadalah "kode pintar", seperti pada contoh terakhir Anda. Tanyakan kepada diri sendiri, apakah [firstname, surname].all?(&:blank?)menambahkan sesuatu selain membuat Anda merasa pintar karena itu memamerkan keahlian Anda, bahkan jika sekarang agak sulit untuk dibaca? Saya akan mengatakan contoh ini sepertinya tidak sepenuhnya masuk ke dalam kategori itu. Jika Anda membandingkan lima nilai, saya akan melihatnya sebagai kode yang baik. Jadi sekali lagi, tidak ada garis absolut di sini, hanya berhati-hati menjadi terlalu pintar.

Jadi dalam ringkasan: keterbacaan mengharuskan Anda mengetahui audiens Anda dan menargetkan kode Anda sesuai dan menulis kode ringkas, tetapi jelas; jangan pernah menulis kode "pintar". Tetap pendek, tapi jangan terlalu pendek.

David Arno
sumber
2
Yah, saya lupa menyebutkannya, tetapi komentar itu dimaksudkan untuk "diabaikan", mereka di sini hanya untuk membantu mereka yang tidak mengenal Ruby dengan baik. Poin yang benar tentang penonton, saya tidak memikirkan hal itu. Adapun versi yang membuat Anda bahagia: jika panjang baris yang penting, versi ketiga dari kode saya (yang hanya dengan satu pernyataan pengembalian) agak melakukan itu dan bahkan sedikit lebih dimengerti, bukan?
Sudiukil
1
@Sudiukil, bukan pengembang rubi, saya menemukan bahwa yang paling sulit untuk dibaca dan tidak sesuai dengan apa yang saya cari (dari perspektif bahasa lain) sebagai solusi "terbaik". Namun, untuk seseorang yang akrab dengan fakta bahwa ruby ​​adalah salah satu dari bahasa-bahasa yang mengembalikan nilai dari ekspresi terakhir, itu mungkin mewakili versi paling sederhana, termudah untuk dibaca. Sekali lagi, ini semua tentang audiens Anda.
David Arno
Bukan pengembang Ruby tetapi ini jauh lebih masuk akal bagi saya daripada jawaban terpilih, yang berbunyi seperti "Inilah yang akan saya kembalikan [catatan kaki: dalam kondisi panjang yang spesifik]. Juga, inilah string yang datang terlambat ke pesta." Logika yang pada dasarnya hanya pernyataan kasus harus ditulis seperti pernyataan kasus seragam tunggal, tidak tersebar di beberapa pernyataan yang tampaknya tidak berhubungan.
Paul
Secara pribadi saya akan pergi dengan blok kode kedua Anda kecuali saya akan menggabungkan dua pernyataan di cabang Anda yang lain menjadi satu:return "#{firstname} #{surname}".strip
Paul
2

Ini mungkin pertanyaan di mana sulit untuk tidak memberikan jawaban berdasarkan opini, tapi, inilah dua sen saya.

Jika Anda menemukan bahwa membuat kode lebih pendek tidak berdampak keterbacaan, atau bahkan memperbaikinya, lakukan saja. Jika kode menjadi kurang dapat dibaca, maka Anda perlu mempertimbangkan jika ada alasan yang cukup baik untuk membiarkannya seperti itu. Melakukannya hanya karena lebih pendek, atau keren, atau hanya karena Anda bisa, adalah contoh alasan buruk. Anda juga perlu mempertimbangkan jika membuat kode lebih pendek akan membuatnya kurang dimengerti untuk orang lain yang bekerja dengan Anda.

Jadi apa alasannya? Ini memang panggilan penilaian, tetapi contohnya mungkin seperti optimasi kinerja (setelah pengujian kinerja, tentu saja, tidak di muka). Sesuatu yang memberi Anda manfaat yang bersedia Anda bayar dengan keterbacaan yang menurun. Dalam hal ini, Anda dapat mengurangi kelemahan dengan memberikan komentar yang membantu (yang menjelaskan apa yang dilakukan kode, dan mengapa itu harus dibuat agak samar). Lebih baik lagi, Anda dapat mengekstrak kode itu ke fungsi terpisah dengan nama yang bermakna, sehingga hanya satu baris di situs panggilan yang menjelaskan apa yang terjadi (melalui nama fungsi) tanpa masuk ke perincian (namun, orang memiliki perbedaan pendapat tentang ini, jadi ini adalah panggilan penilaian lain yang harus Anda buat).

Filip Milovanović
sumber
1

Jawabannya agak subyektif, tetapi Anda harus bertanya pada diri sendiri dengan semua kejujuran yang bisa Anda kumpulkan, apakah Anda akan dapat memahami kode itu ketika Anda kembali ke sana dalam satu atau dua bulan.

Setiap perubahan harus meningkatkan kemampuan rata-rata orang untuk memahami kode. Agar kode dapat dipahami, sebaiknya gunakan pedoman berikut:

  • Hormati idiom bahasa . C #, Java, Ruby, Python memiliki cara yang disukai untuk melakukan hal yang sama. Konstruk idiomatik membantu memahami kode yang tidak Anda kenal.
  • Berhenti ketika kode Anda menjadi kurang terbaca . Dalam contoh yang Anda berikan, itu terjadi ketika Anda menekan pasangan kode pengurangan yang terakhir. Anda kehilangan keunggulan idiomatik dari contoh sebelumnya, dan memperkenalkan banyak simbol yang membutuhkan banyak pemikiran untuk benar-benar memahami apa yang terjadi.
  • Hanya gunakan komentar ketika Anda harus membenarkan sesuatu yang tidak terduga . Saya tahu contoh Anda ada di sana untuk menjelaskan konstruk kepada orang yang kurang terbiasa dengan Ruby, dan itu tidak masalah untuk pertanyaan. Saya lebih suka menggunakan komentar untuk menjelaskan aturan bisnis yang tidak terduga, dan menghindarinya jika kode dapat berbicara sendiri.

Yang mengatakan, ada kalanya kode diperluas membantu dengan memahami apa yang terjadi lebih baik. Salah satu contoh dengan itu berasal dari C # dan LINQ. LINQ adalah alat yang hebat dan dapat meningkatkan keterbacaan dalam beberapa situasi, tetapi saya juga mengalami beberapa situasi di mana itu jauh lebih membingungkan. Saya memiliki beberapa umpan balik dalam peer review yang menyarankan untuk mengubah ekspresi menjadi sebuah loop dengan pernyataan yang sesuai jika orang lain dapat mempertahankannya dengan lebih baik. Ketika saya menurut, mereka benar. Secara teknis, LINQ lebih idiomatis untuk C #, tetapi ada kasus-kasus di mana ia menurunkan pemahaman dan solusi yang lebih verbal meningkatkannya.

Saya mengatakan semua itu untuk mengatakan ini:

Tingkatkan ketika Anda bisa membuat kode Anda lebih baik

Ingat, Anda atau seseorang seperti Anda harus mempertahankan kode itu nanti. Lain kali Anda bertemu mungkin berbulan-bulan di telepon. Bantulah diri Anda sendiri dan jangan mengejar mengurangi jumlah baris dengan biaya untuk dapat memahami kode Anda.

Berin Loritsch
sumber
0

Keterbacaan adalah properti yang ingin Anda miliki, memiliki-banyak-satu-liner tidak. Jadi alih-alih "one-liners vs readability" pertanyaannya seharusnya:

Kapan one-liners meningkatkan keterbacaan, dan kapan mereka merusaknya?

Saya percaya one-liner baik untuk dibaca ketika mereka memenuhi dua syarat ini:

  1. Mereka terlalu spesifik untuk diekstraksi ke suatu fungsi.
  2. Anda tidak ingin mengganggu "aliran" membaca kode di sekitarnya.

Misalnya, katakanlah nameitu bukan nama ... yang bagus untuk metode Anda. Bahwa menggabungkan nama depan dan nama keluarga, atau menggunakan email sebagai ganti nama, bukanlah hal yang wajar untuk dilakukan. Jadi, alih-alih namehal terbaik yang bisa Anda dapatkan ternyata menjadi panjang dan rumit:

puts "Name: #{user.email_if_there_is_no_name_otherwise_use_firstname_and_surname(use_email)}"

Nama panjang seperti itu menunjukkan bahwa ini sangat spesifik - jika lebih umum Anda bisa menemukan nama yang lebih umum. Jadi membungkusnya dengan metode tidak membantu dengan keterbacaan (terlalu lama) atau KERING (terlalu spesifik untuk digunakan di tempat lain), jadi lebih baik membiarkan kode di sana.

Tetap saja - mengapa membuatnya satu liner? Mereka biasanya kurang terbaca dari kode multiline. Di sinilah kita harus memeriksa kondisi kedua saya - aliran kode di sekitarnya. Bagaimana jika Anda memiliki sesuatu seperti ini:

puts "Group: #{user.group}"
puts "Title: #{user.title}"
if user.firstname.blank? && user.surname.blank?) && use_email
  name = email
else
  name = "#{firstname} #{surname}"
  name.strip
end
puts "Name: #{name}"
puts "Age: #{user.age}"
puts "Address: #{user.address}"

Kode multiline itu sendiri dapat dibaca - tetapi ketika Anda mencoba membaca kode di sekitarnya (mencetak berbagai bidang), konstruksi multiline mengganggu aliran. Ini lebih mudah dibaca:

puts "Group: #{user.group}"
puts "Title: #{user.title}"
puts "Name: #{(email if (user.firstname.blank? && user.surname.blank?) && use_email) || "#{user.firstname} #{user.surname}".strip}"
puts "Age: #{user.age}"
puts "Address: #{user.address}"

Aliran Anda tidak terganggu, dan Anda dapat fokus pada ekspresi spesifik jika perlu.

Apakah ini kasusmu? Tentu saja tidak!

Kondisi pertama kurang relevan - Anda sudah menganggapnya cukup umum untuk pantas mendapatkan metode, dan muncul dengan nama untuk metode yang jauh lebih mudah dibaca daripada penerapannya. Jelas Anda tidak akan mengekstraknya ke suatu fungsi lagi.

Adapun kondisi kedua - apakah itu mengganggu aliran kode sekitarnya? Tidak! Kode yang mengelilinginya adalah deklarasi metode, yang memilih tujuan nameitu sendiri. Logika memilih nama tidak mengganggu aliran kode di sekitarnya - itu adalah tujuan kode sekitarnya!

Kesimpulan - jangan membuat seluruh fungsi tubuh menjadi satu garis

One-liner bagus jika Anda ingin melakukan sesuatu yang sedikit rumit tanpa mengganggu alurnya. Deklarasi fungsi sudah mengganggu aliran (sehingga tidak akan terganggu ketika Anda memanggil fungsi itu), jadi menjadikan seluruh fungsi tubuh satu-baris tidak membantu keterbacaan.

Catatan

Saya mengacu pada "penuh sesak nafas" fungsi dan metode - fungsi tidak inline atau ekspresi lambda yang merupakan biasanya bagian dari kode sekitarnya dan kebutuhan untuk muat dalam aliran itu.

Idan Arye
sumber