Temiz Kod - Değişken 1'i sabit olarak mı değiştirmeliyim?

Sihirli sayılardan kaçınmak için, bir değişken için anlamlı bir ad vermemiz gerektiğini sık sık duyuyoruz. Gibi:

//THIS CODE COMES FROM THE CLEAN CODE BOOK
for (int j = 0; j < 34; j++) {
    s += (t[j] * 4)/5;
}

-------------------- Change to --------------------

int realDaysPerIdealDay = 4;
const int WORK_DAYS_PER_WEEK = 5;
int sum = 0;
for (int j = 0; j < NUMBER_OF_TASKS; j++) {
    int realTaskDays = taskEstimate[j] * realDaysPerIdealDay;
    int realTaskWeeks = (realdays/WORK_DAYS_PER_WEEK);
    sum += realTaskWeeks;
}

Bunun gibi kukla bir yöntem var:

Açıklayın: Sanırım hizmet verecek bir listem var ve varsayılan olarak yalnızca yiyecek satın almak için 5 dolar harcıyoruz, ancak birden fazla kişiye sahip olduğumuzda, su ve yiyecek almamız gerekiyor, daha fazla para harcamamız gerekiyor belki 6 dolar. Kodumu değiştireceğim, lütfen değişken 1'e odaklanın , bununla ilgili sorumu.

public int getMoneyByPersons(){
    if(persons.size() == 1){ 
       //TODO - return money for one person
    } else {
       //TODO - calculate and return money for people.
    }

}

Arkadaşlarımdan kodumu incelemelerini istediğimde, biri 1 değeri için bir ad vermenin temiz kod getireceğini söyledi, diğeri de burada sabit bir isme ihtiyacımız olmadığını, çünkü değerin kendisi tarafından anlamlı olduğunu söyledi.

So, my question is Should I give a name for the value 1? When is a value a magic number and when is it not? How can I distinguish context to choose the best solution?

6
Belki de bu mantık moneyService.getMoney() içinde daha uygun olur mu? 1 kişi için getMoney'i aramanız gereken bir an olur mu? Ancak 1’in açık olduğuna dair genel düşünceye katılıyorum. Sihirli sayılar, programcının bu sayıya nasıl ulaştığını soran kafanızı kazımanız gereken sayılardır.
katma yazar Justin Poliey, kaynak
katma yazar gnat, kaynak
@selmaohneh Temiz Kod'un yorumunuzun ve Neil'in bir kombinasyonuna gideceğinden eminim: if kontrolünü 'moneyService'e taşıyın, ancak bu sadece OP'nin sorusunu başka bir yere taşıyor - orada , daha sonra asıl karar için kullanmadan önce, açıklık için 'isSinglePerson' bool değişkenine atayın.
katma yazar R. Schmitz, kaynak
1'den netleşmiyor. Yine de "boyut" u "sayım" olarak değiştirirdim. MoneyService olduğu gibi aptalca, kişilerin toplanmasına bağlı olarak ne kadar para döneceğine karar verebilmelidir. Bu yüzden, ben insanları para almak için geçirip istisnai durumları çözmesine izin verirdim.
katma yazar Martin Maat, kaynak
kişiler nereden geliyor ve ne tarif ediyor? Kodunuzda hiçbir yorum yok, bu yüzden ne yaptığını tahmin etmek zor.
katma yazar Hubert Grzeskowiak, kaynak
Mantıksal ifadeyi if cümlecikten yeni bir yönteme de çıkarabilirsiniz. Belki IsSinglePerson() olarak adlandırın. Bu şekilde, sadece bir değişkenden biraz daha fazlasını çıkarırsınız, ancak if cümlesini biraz daha okunabilir kılarsınız
katma yazar user1875642, kaynak
Üzgünüm, kolay anlaşılması için sorumu güncelleştirdim.
katma yazar Jacky, kaynak

5 cevap

Hayır. Bu örnekte, 1 tamamen anlamlıdır.

Bununla birlikte, hangi şahıs.size() sıfırsa? persons.getMoney() 'in 0 ve 2 için çalıştığı ancak 1 için çalıştığı garip görünüyor

16
katma
1'in anlamlı olduğu konusunda hemfikirim. Teşekkürler, bu arada sorumu güncelledim. Fikrimi almak için tekrar görebilirsin.
katma yazar Jacky, kaynak

Neden bir kod parçası bu özel değişmez değeri içeriyor?

  • Bu değerin sorun alanında özel bir anlamı var mı?
  • Veya bu değer yalnızca bir uygulama detayı mı, bu değer çevre kodunun doğrudan bir sonucudur?

Değişmez değerin bağlamdan açık olmayan bir anlamı varsa, o zaman evet, bu değere bir sabit veya değişken aracılığıyla bir ad vermek faydalı olur. Daha sonra, orijinal içerik unutulduğunda, anlamlı değişken isimli kod daha bakımlı olacaktır. Unutmayın, kodunuz için izleyici kitlesi öncelikle derleyici değil (derleyici mutlu bir şekilde korkunç kodla çalışacaktır), ancak kodun biraz açıklayıcı olduğunu takdir edecek olan bu kodun gelecekteki koruyucularıdır.

  • İlk örneğinizde, 34 , 4 , 5 gibi değişmezlerin anlamı içerikten anlaşılmaz. Bunun yerine, bu değerlerin bazılarının sorun alanınızda özel bir anlamı vardır. Bu yüzden onlara isim vermek güzeldi.

  • İkinci örneğinizde, 1 değişmezinin anlamı bağlamdan çok açık. Bir isim vermek yardımcı değildir.

Aslında, bariz değerler için adlar vermek, asıl değeri gizlediği için de kötü olabilir.

  • Bu, adlandırılmış değerin değiştirilip değiştirilmediğini veya özellikle aynı değişkenin ilgisiz kod bölümlerinde tekrar kullanılması durumunda yanlış olduğunu gizleyebilir.

  • Bir kod parçası belirli bir değer için de işe yarayabilir, ancak genel durumda yanlış olabilir. Gereksiz soyutlama getirerek, kod artık açık bir şekilde doğru değildir.

“Açıkçası” değişmezlerin boyut sınırı yoktur, çünkü bu tamamen bağlama bağlıdır. Örneğin. değişmez 1024 dosya boyutu hesaplama bağlamında veya değişmez işlev bağlamında değişmez 31 veya değişmez dolgusu: 0.5 Bir CSS stil sayfası bağlamında em .

11
katma

Bu kod parçasıyla ilgili olarak, bu şekilde kısaltılabilen birkaç sorun var:

public List getMoneyByPersons() {
    return persons.size() == 1 ?
        moneyService.getMoneyIfHasOnePerson() :
        moneyService.getMoney(); 
}
  1. It is unclear why one person is a special case. I suppose that there is a specific business rule which tells that getting money from one person is radically different from getting money from several persons. However, I have to go and look inside both getMoneyIfHasOnePerson and getMoney, hoping to understand why are there distinct cases.

  2. The name getMoneyIfHasOnePerson doesn't look right. From the name, I would expect the method to check if there is a single person and, if this is the case, get money from him; otherwise, do nothing. From your code, this is not what is happening (or you're doing the condition twice).

  3. Is there any reason to return a List rather than a collection?

Sorunuza geri dönersek, çünkü bir kişiye neden özel bir muamele uygulandığı belli değil, rakamın yerini sabit tutmak gerekiyor, sürece yapmanın başka bir yolu yok kurallar açık. Burada, bir başka sihirli sayısından çok farklı değil. Özel muamelenin bir, iki veya üç kişi için veya sadece on iki kişiden fazlası için geçerli olduğunu söyleyen iş kurallarınız olabilir.

En iyi çözümü seçmek için bağlamı nasıl ayırt edebilirim?

Kodunuzu daha açık hale getiren her şeyi yaparsınız.

örnek 1

Aşağıdaki kod parçasını hayal edin:

if (sequence.size() == 0) {
    return null;
}

return this.processSequence(sequence);

Buradaki sıfır büyülü bir değer midir? Kod oldukça açık: eğer dizide eleman yoksa, onu işlemeyelim ve özel bir değer verelim. Ancak bu kod da şöyle yazılabilir:

if (sequence.isEmpty()) {
    return null;
}

return this.processSequence(sequence);

Burada, daha fazla sabit yok ve kod daha açık.

Örnek 2

Başka bir kod parçası alın:

const result = Math.round(input * 1000)/1000;

round (değer, hassasiyet) aşırı yükü olmayan JavaScript gibi dillerde ne yaptığını anlamak çok zaman almaz.

Şimdi, bir sabit tanıtmak istersen, nasıl adlandırılır? Alabileceğiniz en yakın terim Kesinlik . Yani:

const precision = 1000;
const result = Math.round(input * precision)/precision;

Okunabilirliği arttırır mı? Olabilir. Burada bir sabitin değeri oldukça sınırlıdır ve kendinize yeniden düzenlemeyi yapmanız gerekip gerekmediğini sorabilirsiniz. Buradaki en güzel şey şu ki, hassasiyet yalnızca bir kez bildirildi, bu nedenle değişirse, aşağıdaki gibi bir hata yapma riskiyle karşılaşmazsınız:

const result = Math.round(input * 100)/1000;

bir konumdaki değeri değiştirmek ve diğerinde yapmayı unutmak.

Örnek 3

Bu örneklerden, her durumda sayıların sabitlerle değiştirilmesi gerektiği izlenimini edinebilirsiniz. Bu doğru değil. Bazı durumlarda, bir sabite sahip olmak kod geliştirmeye yol açmaz.

Aşağıdaki kod parçasını alın:

class Point
{
    ...
    public void Reset()
    {
        x, y = (0, 0);
    }
}

Sıfırları bir değişkenle değiştirmeye çalışırsanız, zorluk anlamlı bir isim bulmak olacaktır. Nasıl adlandırırdın? ZeroPosition ? Taban ? Varsayılan ? Burada bir sabit tanıtmak, kodu hiçbir şekilde geliştirmez. Biraz daha uzun ve sadece bu olur.

Ancak bu gibi durumlar nadirdir. Kodda bir sayı bulduğunuzda, kodun nasıl yeniden düzenlenebileceğini bulmak için çaba gösterin. Sayıya bir iş olup olmadığını kendinize sorun. Eğer evet ise, bir sabit zorunludur. Eğer değilse, numarayı nasıl isimlendirirsiniz? Anlamlı bir isim bulursanız, bu harika. Aksi halde, sabitin gereksiz olduğu bir durum bulursunuz.

4
katma
3a'yı eklerdim: Para kelimesini değişken isimlerinde kullanmayın, miktar, denge ya da benzeri şeyler kullanın. Bir para toplama bir anlam ifade etmiyor, miktarların ya da bakiye tahsilatlarının önemi yok. (Tamam, küçük bir yabancı para tahsilatım var (daha doğrusu bozuk para) ama bu farklı bir programlama dışı sorun.
katma yazar Bent, kaynak

Tek bir parametre alan ve ilk örneği kullanırken hala ne yaptığını temiz bir takma ad sunan dörte beş bölü döndüren bir işlev yapabilirsiniz.

Sadece kendi genel stratejimi sunuyorum ama belki ben de bir şeyler öğreneceğim.

Benim düşündüğüm şey.

// Just an example name  
function normalize_task_value(task) {  
    return (task * 4)/5;  
}  

// Is it possible to just use tasks.length or something like that?  
// this NUMBER_OF_TASKS is the only one thats actually tricky to   
// understand right now how it plays its role.  

function normalize_all_task_values(tasks, accumulator) {  
    for (int i = 0; i < NUMBER_OF_TASKS; i++) {  
        accumulator += normalize_task_value(tasks[i]);  
}  

Temel değil ama sadece bir JavaScript geliştiricisi olduğum için üzgünüm.

2
katma
Peki bu 4 ve 5 değerleri ne anlama geliyor? Bunlardan birinin değişmesi gerekiyorsa, numaranın benzer bir bağlamda kullanıldığı bütün yerleri bulabilir ve bu konumları uygun şekilde güncelleyebilir misiniz? Orijinal sorudaki nokta budur.
katma yazar Dee, kaynak
@ gnasher729: Sabitler iyi adlandırılmış, iyi belgelenmiş bir işlevin kaynak kodunda tam olarak bir kez görünüyorsa, adlandırılmış bir sabit kullanılması gerekmeyebilir. Bir sabit, aynı anlama sahip birden çok kez göründüğünde, bu sabite bir ad vermek, değişmez 42'nin tüm bu örneklerinin aynı şeyi ifade edip etmeyeceğini çözmenize gerek kalmamasını sağlar.
katma yazar Dee, kaynak
@BartvanIngenSchenau Tüm işlev yanlış adlandırılmıştır. Daha iyi bir fonksiyon ismi, fonksiyonun ne döndürmesi gerektiğini belirten bir yorum ve * 4/5'in neden bunu başardığı hakkında bir yorum yapmayı tercih ederim. Sabit isimler gerçekten gerekli değildir.
katma yazar gnasher729, kaynak
Bence ilk örnek oldukça açıklayıcıydı, bu yüzden cevaplayabileceğim biri olmayabilir. Operasyon gelecekte değişmemeli, ihtiyacınız olanı başarmak için yeni bir tane yazmam gerekiyorsa. Yorumlar, bu amaca en çok fayda sağlayacağını düşündüğüm şey. Bu benim dilimi azaltmak için tek bir hat arama. Görevlinin kesin olarak anlaşılır hale getirilmesi ne kadar önemlidir?
katma yazar Brad, kaynak
Bunun merkezinde, evet değerini değiştirmeniz gerekebilir. Ancak değişkeni temsil etmek için bunu bir const olarak değiştirirdim. Durumun böyle olduğunu sanmıyorum ve bu sadece bunun üzerinde yer alan bir ara değişken olmalı. Çıkmak ve her şeyi bir işlevin parametresi yapmak istemiyorum ama eğer değişebiliyorsa, ancak nadiren o değişikliği yapmak için çalıştığınız yerde bu işleve veya nesne/yapı kapsamına bir iç parametre yaparım tek başına küresel kapsam.
katma yazar Brad, kaynak

Bu sayı 1, farklı bir sayı olabilir mi? 2 veya 3 olabilir mi, yoksa 1 olması gerekenin mantıklı nedenleri var mı? 1 olması gerekiyorsa, 1 kullanarak iyidir. Aksi takdirde, bir sabit tanımlayabilirsiniz. Buna sabit ONE deme. (Bunu yaptığımı gördüm).

Bir dakikada 60 saniye - sabit bir ihtiyacınız var mı? Eh, 60 saniyedir, 50 veya 70 değil. Böylece bir sayı kalabilir.

Sayfa başına yazdırılan 60 öğe - bu sayı kolayca 59 ya da 55 ya da 70 olabilirdi. Aslında, yazı tipi boyutunu değiştirirseniz, 55 ya da 70 olabilir. Bu nedenle, burada anlamlı bir sabit daha istenir.

Aynı zamanda anlamın ne kadar açık olduğu da bir mesele. "Minutes = seconds/60" yazarsanız, bu kesindir. Eğer "x = y/60" yazarsanız, bu kesin değildir. Bir yerde bazıları anlamlı isimler olmalı.

Mutlak bir kural var: Mutlak kural yok. Uygulamada, sayıları ne zaman ve ne zaman adlandırılmış sabitleri kullanacağınızı çözeceksiniz. Yapmayın çünkü bir kitap öyle diyor - neden böyle olduğunu anlayana kadar.

0
katma