Değerleri uygulamalarımızda kodlamak iyi bir fikir mi?


45

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?


2
Bir config parametresi size yardımcı olur
Gopi

53
Değerinin ne zaman pideğişebileceğini asla bilemezsiniz ...
Gabe

12
Sanırım @gabe gibi insanlar bunun bir "Kural" olmasının nedeni. Kodunuzdaki 20 yerde 3.14'ü tekrarlarsanız ve gerçekten daha fazla hassasiyete ihtiyacınız olduğunu fark ederseniz, mahvolmuş olursunuz. Bunun açık olmadığını farketmedim.
Bill K,

17
Bu biraz kabaydı, @Bill. @ Gabe açıkça şaka yapıyordu, ama bunun dışında, soru sabit kodlama ile konfigürasyon parametreleriyle ilgiliydi, birden fazla yerde sabit ve tekrarlı sihir sayıları kullanmıyordu.
David Conrad

1
Evet, kodlama bazen iyi bir fikir olabilir. "Softcoding" anti-pattern hakkındaki Wikipedia makalesine bakın.
user16764,

Yanıtlar:


64

Evet, ama bunu açıkça belli et .

Yap:

  • Kullanım sabitleri
  • açıklayıcı bir değişken adı kullanın

Yapma:


44
Hangisi daha temiz, diameter = 2 * radiusya 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.
Joonas Pulakka

5
Bu cevaba yeterince katılıyorum. Bir romancı gibi programlamayı düşünüyorum. Hikayenizi kod aracılığıyla anlatıyorsunuz ve insanlar mantığı anlayamıyorsa, kodunuzu bence değersiz hale getiriyor. Bu nedenle, adlandırma kurallarının iyi düşünülmüş olması esasen okunabilirlik içindir. Ayrıca, sihirli sayıları kullanmak için iyi bir neden yoktur. Sihirli sayıları kullanarak, "neden" i denklemden kaldırır ve anlaşılmasını zorlaştırırsınız. Örneğin: "çap = 2 * yarıçap" İkisi ne için? Bu "çap = RADIUS_TO_DIAMETER_FACTOR * radius" çok daha anlamlı.
chrisw

9
çap = 2 * yarıçap, lise matematiğinden doğruca düzdür. "2" yi isimlendirmemenin nedeni, başka bir şeyin değerini almasının fizik veya matematik yasalarında veya her ikisinde de değişiklik yapması gerektiğidir. (Diğer taraftan, Pi veya Plancks sabitini adlandırmak basit okunabilirlik için iyi bir harekettir).
hızla_ben

8
@Joonas: Pfft. Kesinlikle demek istiyorsun diameter = radius << 1? Sanırım bu da olabilir diameter = radius << RADIUS_TO_DIAMETER_BITS_TO_SHIFT.
Karınca

4
nasıl bazılarınıdiameter = radius.toDiameter()
Carson Myers

26

Ş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 * 2olarak 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 < 19VS. 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 46size 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 42Hata 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.


İyi arıza için teşekkürler! - çoğu insan "Ortam Konfigürasyonu" ekleyebileceğim tüm seçenekleri düşünmüyor - Bunlardan kaçınılması gerektiğini düşünüyorum (kodlanmış değil) çünkü çoğu verinin bir yapılandırma dosyasına veya veritabanına konması gerekiyor. Bu, MVC veya MVVM'nin dayanağı olan "veri ve mantığı ayrı tutma" ilkesini izler. string TestServerVar = "foo"; string ProdServerVal = "bar";
m1m1k

7

Bir numaraya tanımlayıcı atamak için çeşitli nedenler vardır.

  • Numara değişebilirse, bir tanımlayıcıya sahip olmalıdır. NUMBER_OF_PLANETS'yi bulmak, her 9 örneğini aramaktan ve bunun 8 olarak değiştirilip değiştirilmemesi gerektiğini düşünmekten daha kolaydır (Yazılımın farklı bir dilde kullanılması gerekiyorsa, kullanıcının görebildiği dizelerin değişmesi gerekebileceğini unutmayın. önceden tahmin etmek zor bir şey.)
  • Numarayı herhangi bir şekilde yazmak zorsa. Pi gibi sabitler için, birkaç yerde, muhtemelen yanlış şekilde yeniden yazmak yerine, bir maksimum hassasiyet tanımı tanımlamak daha iyidir.
  • Sayı farklı yerlerde ortaya çıkarsa. Bitişik fonksiyonlarda 45'in iki kullanımına bakmak ve aynı şeyi mi anlamadıklarını merak etmek zorunda değilsiniz.
  • Anlam anında tanınabilir değilse. Herkesin 3.14159265'in ne olduğunu bildiğini varsaymak güvenlidir. Herkesin yerçekimi sabitini, hatta pi / 2'yi tanıyacağını varsaymak güvenli değildir. (Buradaki "Herkes", yazılımın niteliğine bağlıdır. Sistem programcılarının Unix izin bitlerinin veya benzerlerinin sekizli gösterimini bilmeleri beklenebilir. 1.1 ya da daha büyükse, üzerinde çalışması gereken herhangi biri için tamamen kendi kendini açıklayıcı olabilir.
  • Bağlam tanınabilir değilse. Herkes bir saatte 60 dakika olduğunu biliyor, ancak miktarın bir zaman değeri veya oran değeri olduğunun hemen bir göstergesi olmadığı takdirde 60 ile çarpılması veya bölünmesi net olmayabilir.

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.


5

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 {state_0 = 0, state_1 = 1, state_2 = 2, ...} ... Gülme, bittiğini gördüm. O kişiyi kafanın etrafına ıslak bir balıkla sürün!
hızla_ben

Elbette, daha iyi bir şey gibi daha fazlasını istersiniztypedef enum {init_state=0, parse_state=1, evaluation_state=2, ... }
Earlz

6
THIS_NAMING_CONVENTION_IS_RECOMMENDED_FOR_CONSTANTS
StuperUser

4
Dizeler için sadece sabit istemezsiniz. Kullanıcı tarafından görülebilir herhangi bir dizgiyi bir tür kaynak dosyasına koymak istiyorsunuz (detaylar platformunuza bağlı olacaktır), böylece kolayca başka bir dile geçebilirsiniz.
David Thornley

Ayrıca, iş mantığıyla ilgili dizeleri (SQL sorguları gibi) bir tür şifreleme veya gizleme ile bir kaynak dosyasına yapıştırmak isteyebilirsiniz. Bu "meraklı" kullanıcıların mantığınızı (veya veritabanı şemasını) tersine mühendislik yapmasını önler.
TMN

4

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ğer değişecek mi
  • Değerdeki bir değişiklik sistemi nasıl etkiler?

4

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 200benim 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.


3
  • eğer değer değişebiliyorsa ve gerçekten değişebiliyorsa, ilgili çaba beklenen getiriyi aşmadığı sürece, mümkün olduğu her durumda yazılımı yumuşak kodlayın
  • bazı değerler yumuşak kodlanmış olamaz ; Jonathan'ın bu (nadir) davalardaki kurallarını takip edin

2

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.


2

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.


Evet, muhtemelen, ama peki ya google.com/moon
Residuum

1

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.


1

Sabitlerin olduğu iki durum (bence en azından) Tamam:

  1. 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.

  2. Kesinlikle değişmez, kesin, bariz sabitler, "haftada gün sayısı" gibi. Bir sabit ile days = weeks * 7değiştirmek neredeyse hiç değer sağlar.7DAYS_PER_WEEK


0

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 ...


0

Dünyanın yerçekimi sabitinin değerini kodlarsanız, kimse umursamaz. Proxy sunucunuzun IP adresini kodlarsanız, başınız belada demektir.


1
Dünyanın yerçekimi sabiti için daha fazla hassasiyet gerekebilir, bu yüzden birkaç kez kodlamak sorunlara yol açabilir.
user281377,

1
Peter Noone? Herman'ın Hermits'inden mi?
David Conrad

Dünyadaki kütleçekimsel ivmelenme çoğu enlem ve irtifa için 9.81 m / s ^ 2'dir (tabii ki, eğer yeraltında petrol arıyorsanız veya Kuzey Kutbu üzerinden ICBM'leri çekiyorsanız, yerçekimindeki değişimi bilmek çok önemlidir. çok daha ondalık basamaklarda), diğer gezegenlerde yerçekimi ivmesi farklı bir sayıya sahipken, ancak bildiğim kadarıyla yerçekimi sabiti evren çevresinde sabittir. G değişken olsaydı değişmesi gereken birçok fizik var.
Tangurena

0

Ç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.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.