Değerleri uygulamalarımızda kodlamak iyi bir fikir mi? Ya da değişmeleri gerektiğinde bu tür değerleri dinamik olarak çağırmak her zaman doğru mu?
pi
değişebileceğini asla bilemezsiniz ...
Değerleri uygulamalarımızda kodlamak iyi bir fikir mi? Ya da değişmeleri gerektiğinde bu tür değerleri dinamik olarak çağırmak her zaman doğru mu?
pi
değişebileceğini asla bilemezsiniz ...
Yanıtlar:
Evet, ama bunu açıkça belli et .
Yap:
Yapma:
diameter = 2 * radius
ya da diameter = RADIUS_TO_DIAMETER_FACTOR * radius
? Gerçekten de sihirli sayının daha iyi bir çözüm olabileceği köşe senaryoları var.
diameter = radius << 1
? Sanırım bu da olabilir diameter = radius << RADIUS_TO_DIAMETER_BITS_TO_SHIFT
.
diameter = radius.toDiameter()
Şimdiye kadar bu soru-cevap hakkında garip bulduğum şey, hiç kimsenin "sabit kodu" veya daha da önemlisi alternatifleri açıkça tanımlamaya çalışmadığıdır.
tl; dr: Evet, bir koda değerlerine iyi bir fikir bazen, bunlarla hiçbir basit kural var olduğunda ; tamamen içeriğe bağlıdır.
Soru, sihirli sayılar demek için aldığım değerlere indirgiyor , ama iyi bir fikir olup olmadıklarının cevabı, gerçekte ne için kullanıldıklarına bağlı!
"Kodlanmış" değerlerin birkaç örneği:
Yapılandırma değerleri
Ben ifadeleri gördüğünüzde ben yaltaklanmak command.Timeout = 600
. Neden 600 Buna kim karar verdi? Daha önce zaman aşımına uğradı mı ve birileri temel performans sorununu düzeltmek yerine zaman aşımını kesmek olarak mı artırdı? Yoksa işlem süresi için bilinen ve belgelenmiş bir beklenti mi?
Bunlar sihirli sayılar veya sabitler olmamalı, anlamlı bir isimle bir konfigürasyon dosyasında veya veritabanında dışsallaştırılmalıdır, çünkü optimum değerleri büyük ölçüde veya tamamen uygulamanın içinde bulunduğu ortam tarafından belirlenir.
Matematiksel formüller
Formüller genellikle oldukça statik olma eğilimindedir, öyle ki içerisindeki sabit değerlerin niteliği gerçekten özellikle önemli değildir. Bir piramidin hacmi (1/3) b * h'dir. 1 veya 3'ün nereden geldiğine önem veriyor muyuz? Pek sayılmaz. Önceki bir yorumcu, haklı diameter = radius * 2
olarak muhtemelen daha iyi olduğunu belirtti diameter = radius * RADIUS_TO_DIAMETER_CONVERSION_FACTOR
- ama bu yanlış bir ikiliktir.
Bu tür bir senaryo için yapmanız gerekenler bir işlev oluşturmaktır . Formülün nasıl ortaya çıktığını bilmeme gerek yok ama bunun ne için olduğunu hala bilmem gerekiyor . Eğer yukarıda yazılı saçmalıkların yerine, ben yazı yazarım, volume = GetVolumeOfPyramid(base, height)
sonra aniden her şey çok daha netleşir ve fonksiyonun içinde sihirli sayılar olması mükemmel olur ( return base * height / 3
) çünkü formülün sadece bir kısmı oldukları açıktır.
Buradaki anahtar elbette kısa ve basit fonksiyonlara sahip olmak . Bu, 10 argüman ve 30 satırlık hesaplama içeren fonksiyonlar için işe yaramaz. Bu durumda işlev bileşimi veya sabitleri kullanın.
Etki alanı / işletme kuralları
Bu daima gri alandır, çünkü değerin tam olarak ne olduğuna bağlıdır. Çoğu zaman, bu sabit sayılara dönüşmeye aday olan sihirli numaralardır, çünkü program mantığını zorlaştırmadan programın daha kolay anlaşılmasını sağlar. Test düşünün if Age < 19
VS. if Age < LegalDrinkingAge
; muhtemelen olabilir sabiti olmadan neler olup bittiğini anlamaya, ama açıklayıcı bir başlık ile daha kolaydır.
Bunlar olabilir ayrıca örneğin fonksiyon soyutlama için adaylar haline function isLegalDrinkingAge(age) { return age >= 19 }
. Tek şey, iş mantığınızın genellikle bundan çok daha karmaşık olduğu ve her birinin 20-30 parametresi olan düzinelerce işlev yazmaya başlamasının bir anlamı olmayacağıdır. Nesnelere ve / veya fonksiyonlara dayalı net bir soyutlama yoksa sabitlere başvurmak tamamdır.
Dikkat, vergi departmanı için çalışıyorsanız, yazması gerçekten, gerçekten külfetli ve dürüstçe anlamsız hale gelir AttachForm(FORM_CODE_FOR_SINGLE_TAXPAYER_FILING_JOINTLY_FOR_DEPRECIATION_ON_ARMPIT_HAIR)
. Bunu yapmayacaksın, yapacaksın, AttachForm("B-46")
çünkü şimdiye kadar çalışmış ya da hiç çalışacak olan her geliştirici, "B-46" nın tek bir vergi mükellefinin blah filanını dosyalama biçiminin kod olduğunu bilecek - form kodları alanın bir parçasıdır, asla değişmezler, bu yüzden gerçekten sihirli sayılar değildir.
Bu yüzden iş mantığında sabit bir şekilde kullanmanız gerekiyor; Temel olarak, "sihirli sayı" nın aslında bir sihirli sayı olup olmadığını ya da alanın iyi bilinen bir yönü olup olmadığını anlamalısınız. Eğer etki alanı ise, o zaman gerçekten değişmesi için iyi bir şans yoksa, yazılımı yumuşak bir şekilde kodlamayın.
Hata kodları ve durum bayrakları
Bunlar hiçbir zaman sert kodlara uymaz, Previous action failed due to error code 46
size vurulmuş olan zavallı heriflerin size söyleyebileceği gibi. Diliniz destekliyorsa, bir numaralandırma türü kullanıyor olmalısınız. Aksi takdirde, genellikle belirli bir hata tipi için geçerli değerleri belirten sabit bir tam dosya / modül elde edersiniz.
return 42
Hata işleyicide görmeme hiç izin verme , Capiche? Bahane yok.
Muhtemelen birkaç senaryoyu dışlamıştım ama bunun çoğunu kapsadığını düşünüyorum.
Bu yüzden, evet, bazen kod kodlama için kabul edilebilir bir uygulamadır. Sadece bu konuda tembel olmayın; düz eski özensiz kod yerine bilinçli bir karar olmalıdır.
Bir numaraya tanımlayıcı atamak için çeşitli nedenler vardır.
Bu bize sabit kodlama hazırlıkları için kriterler verir. Değişmez, yazması zor değil, yalnızca bir yerde veya bağlamda meydana gelen ve tanınabilir bir anlama sahip olmalıdırlar. 0'ı ARRAY_BEGINNING, örneğin 1 veya ARRAY_INCREMENT olarak tanımlamanın bir anlamı yoktur.
Diğer cevaplara ek olarak. Mümkünse karakter dizileri için sabitler kullanın. Tabii ki istemezsin
const string server_var="server_var";
ama yapmalısın
const string MySelectQuery="select * from mytable;";
(aslında tüm sonuçları belirli bir tablodan almak istediğiniz bir sorguya sahip olduğunuzu varsayarsak)
Bunun dışında, 0 dışında herhangi bir sayı için sabitler kullanın (genellikle). 255 izin bit maskesine ihtiyacınız varsa kullanmayın
const int 8th_bit=255; //or some other obscure naming scheme that equates to 255.
yerine kullan
const int AllowGlobalRead=255;
Tabii ki, sabitler ile birlikte, ne zaman numaralandırıcılar kullanılacağını bilmek. Yukarıdaki durum muhtemelen bir tanesine çok yakışacaktı.
typedef enum {init_state=0, parse_state=1, evaluation_state=2, ... }
Kodlamada ne düşündüğünüze bağlı. Herhangi bir kod kodlu şeyden kaçınmaya çalışırsanız, yazılım kodlama alanına girersiniz ve yalnızca yaratıcının yönetebileceği bir sistem yaparsınız (ve bu esas koddur)
Birçok şey makul bir çerçevede kodlanmış ve işe yarıyor. yani bir C # uygulamasının giriş noktasını değiştirmemem için hiçbir teknik neden yoktur (statik geçersiz Ana), ancak herhangi bir kullanıcı için herhangi bir problem yaratmayan kodlama (ara sıra SO sorusu hariç )
Kullandığım başparmak kuralı, tüm sistemin durumunu etkilemeden değişebilecek ve değişecek olan her şeyin birbirine bağlanabilir olması gerektiğidir.
Yani, IMHO, hiç değişmeyen şeyleri kodlamak aptalca değil (pi, yerçekimi sabiti, matematiksel formülde sabit - kürenin hacmi).
Ayrıca, sisteminizde herhangi bir durumda programlama gerektiren bir etkiye sahip olacak şeyleri veya işlemleri kodlamamak aptalcadır, yani, herhangi bir ek alanın bakım geliştiricisine gereksinim duyması durumunda, kullanıcının bir forma dinamik alanlar eklemesine izin vermek gereksizdir. İçeri gir ve o şeyin çalışmasını sağlayacak bir senaryo yaz. Ayrıca, bazı yapılandırma araçları oluşturmak aptalcadır (ve bunu birkaç kez kurumsal ortamlarda gördüm), bu nedenle hiçbir şey kodlanmış değildir, ancak yalnızca BT departmanındaki geliştiricilerin kullanabileceği ve kullanmaktan daha kolay olduğu Visual Studio'da yapmak için.
Sonuç olarak, bir şeyin kodlanmış olması gerekip gerekmediği iki değişkenin bir işlevidir:
Değerleri uygulamalarımızda kodlamak iyi bir fikir mi?
Ben değerlerini kod gömme sadece değerler eğer belirtilen (şartname nihai sürümü üzerinde) Şartnamede, örneğin HTTP TAMAM yanıtı her zaman olacaktır 200
benim kodları bazılarında (öyleyse, göreceksiniz, (RFC içinde değişmediği sürece) gibi sabitler:
public static final int HTTP_OK = 200;
Aksi takdirde, özellikler dosyasında sabitleri saklarım.
Spesifikasyonları tanımlamamın nedeni, spesifikasyonlardaki sabit değişimlerin, paydaşların değişimi gözden geçireceği ve onaylayacağı / onaylayamayacağı değişiklik yönetimi gerektirmesidir. Asla bir gecede olmaz ve onaylanması aylar / yıllar alır. Pek çok geliştiricinin spesifikasyonlar kullandığını unutmayın (örneğin, HTTP), bunu değiştirmek milyonlarca sistemi kırmak anlamına gelir.
Kodunuzdan herhangi bir veri çıkarabildiğiniz zaman, kalanları iyileştirdiğini fark ettim. Yeni refactorings fark etmeye ve kodunuzun tüm bölümlerini iyileştirmeye başlarsınız.
Sabitleri çıkarmaya çalışmak iyi bir fikir, biraz aptal bir kural olarak düşünmeyin, daha iyi kodlama için bir fırsat olarak düşünün.
En büyük avantaj, benzer sabitleri, kod gruplarındaki tek fark olarak bulabilmenizdir - onları dizilere soyutlamak, bazı dosyaları boyutlarının% 90'ını küçültmeme ve bu arada epeyce kopyala ve yapıştır hatalarını düzeltmeme yardımcı oldu. .
Henüz veri çıkarmamak için tek bir avantaj görmedim.
Geçenlerde iki lat / long çifti arasındaki mesafeyi uygun şekilde hesaplamak için bir MySQL fonksiyonunu kodladım. Sadece pythagorus yapamazsınız; boylam çizgileri kutuplara doğru enlem arttıkça birbirine yaklaşır, bu yüzden bazı kıllı trigler vardır. Demek istediğim, dünyanın yarıçapını temsil eden değerin mil cinsinden sabitlenip kodlanmayacağı konusunda oldukça yorgundum.
Gerçeğe rağmen, lat / lng çizgileri aya daha yakın olduklarını söyleyerek bitirdim. Ve benim fonksiyonum, Jüpiter’deki noktalar arasındaki mesafeleri büyük ölçüde düşük gösterecekti. İnşa ettiğim web sitesinin ihtimal dışı olduğunu düşündüğüm dünya dışı bir yerin oldukça zayıf olduğunu düşündüm.
Dilinizin derlenip derlenmediğine bağlı. Derlenmediyse, önemli değil, programcı olmayanlar için biraz hassas olsa bile kaynak kodunu düzenlersiniz.
Derlenmiş bir dille programlama yapıyorsanız, bu kesinlikle iyi bir fikir değildir, çünkü değişkenler değişirse, bu değişkeni ayarlamak istiyorsanız büyük bir zaman kaybı olan yeniden derlemeniz gerekir.
Değişkenini dinamik olarak değiştirmek için kaydırıcı veya arabirim yapmanız gerekmez, ancak yapabileceğiniz en az bir metin dosyasıdır.
Örneğin, ogre projemde, her zaman bir config dosyasına yazdığım bir değişkeni yüklemek için ConfigFile sınıfını kullanıyorum.
Sabitlerin olduğu iki durum (bence en azından) Tamam:
Başka hiçbir şeyle ilgili olmayan sabitler; Bu sabitleri istediğiniz zaman, başka bir şeyi değiştirmek zorunda kalmadan değiştirebilirsiniz. Örnek: Izgara sütununun varsayılan genişliği.
Kesinlikle değişmez, kesin, bariz sabitler, "haftada gün sayısı" gibi. Bir sabit ile days = weeks * 7
değiştirmek neredeyse hiç değer sağlar.7
DAYS_PER_WEEK
Jonathan ile tamamen aynı fikirdeyim ama tüm kurallarda istisnalar var ...
"Spesifikasyonda sihirli sayı: Koddaki sihirli sayı"
Temel olarak, tanımlayıcı bağlam elde etmek için makul teşebbüsler yaptıktan sonra spesifikasyonda kalan herhangi bir sihirli sayının, kodda olduğu gibi yansıtılması gerektiğini belirtir. Eğer sihirli sayılar kodda kalırsa, onları izole etmek ve menşe noktalarıyla açıkça bağlantılı olmaları için her türlü çaba gösterilmelidir.
İletileri veritabanından eşlenen değerlerle doldurmanın gerekli olduğu birkaç arabirim sözleşmesi yaptım. Çoğu durumda, haritalama oldukça yalındır ve Jonathan'ın genel kılavuz çizgisine sığacaktı, ancak hedef mesaj yapısının sadece korkunç olduğu durumlar ile karşılaştım. Yapıya aktarılması gereken değerlerin% 80'inden fazlası, uzaktaki sistemin şartnamesi tarafından uygulanan sabitlerdi. bu, mesaj yapısının büyük olduğu gerçeğiyle birleştiğinde, bu tür sabitlerin bir LOT'unun doldurulması gerektiğine neden oldu. Çoğu durumda bir anlam veya sebep sağlamadılar, sadece "M'yi buraya koy" veya "4.10.53.10100.889450.4452'yi buraya koy" dediler. Her ikisinin de yanına bir yorum koyma girişiminde bulunmadım, sonuçta ortaya çıkan kodu okunamaz hale getirdi.
Demek, bunu düşündüğünüzde ... her şeyi açıklığa kavuşturmakla ilgili ...
Dünyanın yerçekimi sabitinin değerini kodlarsanız, kimse umursamaz. Proxy sunucunuzun IP adresini kodlarsanız, başınız belada demektir.
Çoğunlukla hayır, ama kodlanmış değeri kopyalamaya başladığınızda en çok sorun yaşayacağınıza dikkat çekiyor. Eğer onu çoğaltmazsanız (ör. Bir sınıfın uygulanmasında sadece bir kez kullanın), o zaman bir sabit kullanmamak tamam olabilir.