bağlam
Geçenlerde daha iyi biçimlendirilmiş kod üretmek ilgimi çekti. Ve daha iyisi, "bunu iyi bir uygulama olarak kabul edecek kadar insan tarafından onaylanmış kuralları takip etmek" demek istiyorum (çünkü elbette kodlamanın eşsiz bir "en iyi" yolu olmayacak).
Bugünlerde çoğunlukla Ruby'de kod yazıyorum, bu yüzden bana kodumun "kalitesi" hakkında biraz bilgi sağlamak için bir linter (Rubocop) kullanmaya başladım (bu "kalite" topluluk odaklı proje ruby-style-guide tarafından tanımlanıyor ).
Bazı durumlarda, kod verimi aslında bile, çok değil kodun verimliliğine ilişkin "biçimlendirme kalitesi" gibi "kalite" kullanacağı Not edilmektedir kod yazılır nasıl etkilenir.
Her neyse, tüm bunları yaparak, birkaç şey fark ettim (veya en azından hatırladım):
- Bazı diller (özellikle Python, Ruby ve benzeri) mükemmel bir kod satırı oluşturmaya izin verir
- Kodunuz için bazı yönergelere uymanız, kodu önemli ölçüde kısaltabilir ve yine de çok açık hale getirebilir
- Yine de, bu yönergeleri çok sıkı bir şekilde uygulamak, kodu daha az net / okunması kolay hale getirebilir
- Kod, bazı yönergelere neredeyse mükemmel şekilde saygı gösterebilir ve yine de düşük kalitede olabilir
- Kod okunabilirliği çoğunlukla özneldir ("açık bulduğum şey, bir geliştirici için tamamen belirsiz olabilir" de olduğu gibi)
Bunlar sadece gözlemler, elbette mutlak kurallar değil. Ayrıca, kod okunabilirliğinin ve aşağıdaki yönergelerin bu noktada alakasız görünebileceğini de unutmayın, ancak burada yönergeler, bir kod parçasını yeniden yazmanın yol sayısını daraltmanın bir yoludur.
Şimdi, bazı örnekler, bunları daha açık hale getirmek için.
Örnekler
Basit bir kullanım örneği ele alalım: " User
" modeli olan bir uygulamamız var . Bir kullanıcının isteğe bağlı firstname
ve surname
zorunlu bir email
adresi vardır.
Ben en azından onun veya varsa kullanıcının name
adı ( firstname + surname
) , ya da değilse bir geri dönüş değeri olarak dönecektir bir yöntem " " yazmak istiyorum .firstname
surname
email
Ben de bu yöntemi bir use_email
parametre olarak "(boolean) almak, kullanıcı e-posta yedek değer olarak kullanmak için izin istiyorum. Bu " use_email
" parametresi varsayılan olarak ("geçilmezse)" true
" olarak ayarlanmalıdır .
Bunu Ruby'de yazmanın en basit yolu:
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
Bu kod, bunu yapmanın en basit ve anlaşılması kolay yoludur. Ruby konuşmayan biri için bile.
Şimdi bunu kısaltmaya çalışalım:
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
Bu, daha kolay olmasa bile daha kısa, anlaşılması kolaydır (koruma maddesi bir koşullu bloktan daha doğaldır). Guard yan tümcesi ayrıca kullandığım yönergelerle daha uyumlu olmasını sağlar, bu yüzden burada kazan-kazan. Girinti seviyesini de düşürüyoruz.
Şimdi biraz daha kısa yapmak için Ruby sihri kullanalım:
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
Daha kısa ve yönergeleri mükemmel bir şekilde takip etmek ... ama dönüş ifadesinin eksikliği bu uygulamaya aşina olmayanlar için biraz kafa karıştırıcı hale geldiğinden çok daha az net.
Burada şu soruyu sormaya başlayabiliriz: gerçekten buna değer mi? "Hayır, okunabilir kılın ve ' return
'" diyelim (bunu bilmek kurallara uymayacaktır). Yoksa "Sorun değil, Ruby yolu, lanet dili öğren!" Mi demeliyiz?
B seçeneğini kullanırsak, neden daha da kısa hale getirmeyelim:
def name(use_email = true)
(email if (firstname.blank? && surname.blank?) && use_email) || "#{firstname} #{surname}".strip
end
İşte, tek astar! Tabii ki daha kısa ... burada Ruby'nin hangisinin tanımlandığına bağlı olarak bir değer veya diğeri döndüreceği gerçeğinden yararlanıyoruz (çünkü e-posta daha önce olduğu gibi aynı koşulda tanımlanacaktır).
Ayrıca yazabiliriz:
def name(use_email = true)
(email if [firstname, surname].all?(&:blank?) && use_email) || "#{firstname} #{surname}".strip
end
Kısa, okumak o kadar da zor değil (yani, çirkin bir astarın neye benzeyebileceğini gördük), iyi Ruby, kullandığım kılavuza uyuyor ... Ama yine de, ilk yazma yöntemine kıyasla okuması ve anlaması çok daha az kolaydır. Bu satırın çok uzun (80 karakterden fazla) olduğunu da iddia edebiliriz.
Soru
Bazı kod örnekleri, bir "tam boyutlu" kod ile indirgenmiş sürümlerinin birçoğu (ünlü tek astara kadar) arasında seçim yapmanın zor olabileceğini gösterebilir, çünkü görebildiğimiz gibi, bir astar o kadar korkutucu olmayabilir ama yine de hiçbir şey okunabilirlik açısından "tam boyutlu" kodu geçmeyecektir ...
İşte asıl soru: nerede durmalı? Ne zaman kısa, yeterince kısa? Kodun ne zaman "çok kısa" ve daha az okunabilir hale geldiğini (oldukça öznel olduğunu akılda tutarak) nasıl öğrenebilirim? Ve daha da fazlası: nasıl her zaman buna göre kodlamak ve sadece gibi hissediyorum zaman tek satırları "tam boyutlu" kod parçaları ile karıştırmak kaçının?
TL; DR
Buradaki ana soru şudur: "uzun ama net, okunabilir ve anlaşılabilir bir kod yığını" ve "bu satırın üst ve alt sadece iki seçenek değil, bir ölçeğin altında: "yeterince net" ve "olması gerektiği kadar net değil" arasındaki sınırın nasıl tanımlanacağı?
Ana soru, klasik "Tek gömlekler ve okunabilirlik: hangisi daha iyi?" ama "Bu ikisi arasındaki denge nasıl bulunur?"
Düzenle 1
Kod örneklerindeki yorumların "yoksayılması" amaçlanmıştır, neler olduğunu açıklığa kavuşturmak için buradadırlar, ancak kodun okunabilirliğini değerlendirirken dikkate alınmamalıdırlar.
return
3. varyantı tercih ederim . Bu yedi karakter gözlerime biraz netlik katıyor.
[firstname,surname,!use_email].all?(&:blank?) ? email : "#{firstname} #{surname}".strip
... çünkü false.blank?
doğru döner ve üçlü operatör size birkaç karakter kazandırır ... ¯ \ _ (ツ) _ / ¯
return
anahtar kelimenin ne kadar netlik katması gerekiyor ?! Sağladığı hiçbir bilgi olursa olsun . Saf dağınıklık.