Gerekirse gelecekte gerekebilecek olması durumunda artık kod eklemeli miyim?


114

Doğru ya da yanlış, şu anda kodumu olabildiğince sağlam kılmaya çalışmam gerektiğine, şu anda herhangi bir kullanımın olmayacağını bildiğim yedekli kod / kontroller eklemek anlamına gelse de inancım var. Çizginin aşağısında x yıl olabilir.

Örneğin, şu anda bu kod parçasına sahip bir mobil uygulama üzerinde çalışıyorum:

public static CalendarRow AssignAppointmentToRow(Appointment app, List<CalendarRow> rows)
{
    //1. Is rows equal to null? - This will be the case if this is the first appointment.
    if (rows == null) {
        rows = new List<CalendarRow> ();
    }

    //2. Is rows empty? - This will be the case if this is the first appointment / some other unknown reason.
    if(rows.Count == 0)
    {
        rows.Add (new CalendarRow (0));
        rows [0].Appointments.Add (app);
    }

    //blah...
}

Özellikle ikinci bölüme baktığımda, birinci bölüm doğruysa ikinci bölümün de doğru olacağını biliyorum. İkinci bölümün neden ifgereksiz olduğu ve ikinci bölümün gereksiz olduğunu gösteren ikinci bölümün neden doğru olduğu konusunda hiçbir sebep düşünemiyorum .

Ancak, gelecekte bu ikinci ififadenin gerçekte gerekli olduğu ve bilinen bir nedenden dolayı bir durum olabilir.

Bazı insanlar buna başlangıçta bakabilir ve gelecekte akılda kalmayı planladığımı düşünebilir, ki bu kesinlikle iyi bir şey. Ama bu tür bir kodun benden "saklı" böcekler çıkardığı birkaç örneği biliyorum. Yani fonksiyonun aslında ne zaman yapması gerektiğini neden xyzyaptığını anlamak daha uzun abcsürdü def.

Öte yandan, bu tür bir kodun yeni davranışlarla kodu geliştirmeyi çok, daha kolay hale getirdiği çok sayıda örnek olmuştur, çünkü geri dönüp ilgili tüm kontrollerin yapıldığından emin olmak zorunda değilim.

Bu tür bir kod için genel kurallar kuralları var mı? (Bunun iyi veya kötü uygulama olarak kabul edilip edilmeyeceğini de duymak isterim?)

Not: Bu, bu soruya benzer olarak düşünülebilir , ancak o sorunun aksine, son tarih olmadığını varsayarak bir cevap istiyorum.

TLDR: Gelecekte potansiyel olarak daha sağlam hale getirmek için fazladan kod eklemeye kadar devam etmeli miyim?



95
Yazılım geliştirmede asla olmaması gereken şeyler her zaman olur.
Roman Reiner

34
if(rows.Count == 0)Asla olmayacağını biliyorsanız , o zaman ne zaman bir istisna yaratabilir ve varsayımınızın neden yanlış olduğunu kontrol edebilirsiniz.
knut

9
Soruyla alakasız, ancak kodunuzun bir hata olduğundan şüpheleniyorum. Satırlar boş olduğunda, yeni bir liste oluşturulur ve (sanırım) atılır. Ancak satırlar boş değilse, varolan bir liste değiştirilir. Daha iyi bir tasarım, müşterinin boş ya da boş olmayan bir listeden geçmesi konusunda ısrar etmek olabilir.
Theodore Norvell

9
Neden rowshiç boş olmasın ? Bir koleksiyonun boş olması için en azından .NET'te hiçbir zaman iyi bir neden yoktur. Boş , kesin ama boş değil . Boşsa bir istisna atardım rows, çünkü arayan tarafın mantığında bir atlamalı olduğu anlamına gelir.
Kyralessa

Yanıtlar:


176

Bir alıştırma olarak, önce mantığınızı doğrulayalım. Göreceğimiz gibi, mantıklı bir problemden daha büyük problemleriniz var.

Birinci koşulu A ve ikinci koşulu B olarak adlandırın.

Önce sen söyledin:

Özellikle ikinci bölüme baktığımda, birinci bölüm doğruysa ikinci bölümün de doğru olacağını biliyorum.

Yani: A, B'yi veya daha basit bir ifadeyle (NOT A) OR B

Ve sonra:

Birinci bölümün neden yanlış olacağına dair hiçbir sebep düşünemiyorum ve ikinci bölüm doğru olarak değerlendirildi, bu da ikinci ifadeyi gereksiz kılıyor.

Yani: NOT((NOT A) AND B). (NOT B) OR AB'nin A anlamına geldiğini almak için Demorgan yasasını uygulayın .

Bu nedenle, eğer ifadelerinizin her ikisi de doğruysa, A, B'yi ve B, A'yı ifade eder; bu, eşit olmaları gerektiği anlamına gelir.

Bu nedenle evet, çekler gereksiz. Program boyunca dört kod yolunuz var gibi görünüyor ama aslında sadece iki tane var.

Öyleyse şimdi soru şu: kodu nasıl yazmalı? Asıl soru şudur: Yöntemin belirtilen sözleşmesi nedir? Koşulların gereksiz olup olmadığı sorusu kırmızı bir ringa balığıdır. Asıl soru "Mantıklı bir sözleşme tasarladım mı ve yöntemim bu sözleşmeyi açıkça uyguladı mı?"

Deklarasyona bakalım:

public static CalendarRow AssignAppointmentToRow(
    Appointment app,    
    List<CalendarRow> rows)

Halka açık, bu yüzden keyfi arayanlardan gelen kötü verilere karşı güçlü olmak zorunda.

Bir değer döndürür, bu nedenle yan etkisi için değil, dönüş değeri için faydalı olmalıdır.

Ve yine de, yöntemin adı, yan etkisi için faydalı olduğunu düşündüren bir fiildir.

List parametresinin sözleşmesi şöyledir:

  • Boş bir liste tamam
  • İçinde bir veya daha fazla eleman bulunan bir liste tamam
  • İçinde element bulunmayan bir liste yanlıştır ve mümkün olmamalıdır.

Bu sözleşme delilik . Bunun için dökümantasyon yazdığınızı düşünün! Test senaryoları yazdığınızı düşünün!

Tavsiyem: baştan başla. Bu API, her yere yazılmış şeker makinesi arayüzüne sahiptir. (İfade, hem fiyatların hem de seçimlerin iki basamaklı sayılar olduğu Microsoft'taki şeker makineleri hakkında eski bir öyküye dayanıyor ve 75 öğesinin fiyatı olan "85" harfini yazmanız çok kolay. Yanlış ürün. Eğlenceli gerçek: evet, Microsoft'ta bir satış makinesinden sakız almaya çalışırken yanlışlıkla bunu yaptım!)

İşte mantıklı bir sözleşmenin nasıl yapılacağı:

Yönteminizi her ikisi için de değil, yan etkisi veya geri dönüş değeri için yararlı hale getirin.

Değişken türleri girişler gibi kabul etmeyin; listeler; Bir bilgi dizisine ihtiyacınız varsa, bir IEnumerable alın. Sadece diziyi okuyun; o olmadığı sürece geçti-in koleksiyonuna yazmayın çok bu yöntemin sözleşme olduğunu açıkça. IEnumerable alarak, arayan kişiye koleksiyonlarını değiştirmeyeceğinize dair bir mesaj gönderirsiniz.

Asla boşları kabul etmeyin; boş bir dizi bir abomination. Bu, mantıklıysa, asla boş bırakmayacaksa, arayanın boş bir sıra geçmesini isteyin.

Arayan sözleşmenizi ihlal ederse derhal çarpışır, onlara iş demek istediğinizi öğretir ve böylelikle hatalarını üretimde değil testlerde yakalarlar.

İlk önce sözleşmeyi mümkün olduğunca mantıklı olacak şekilde tasarlayın ve ardından sözleşmeyi açıkça uygulayın. Bir tasarımı geleceğe korumanın yolu budur .

Şimdi, sadece sizin özel durumunuz hakkında konuştum ve siz genel bir soru sordunuz. Yani burada bazı ek genel tavsiyeler:

  • Bir geliştirici olarak karar verebileceğiniz ancak derleyicinin yapamayacağı bir gerçek varsa, bu gerçeği belgelemek için bir iddia kullanın. Gelecekte olduğu gibi siz ya da iş arkadaşlarınızdan biri olan başka bir geliştirici bu varsayımı ihlal ederse iddia size söyleyecektir.

  • Bir test kapsamı aracı edinin. Testlerinizin her kod satırını kapsadığından emin olun. Eğer çözülmemiş kod varsa, o zaman ya da eksik bir teste sahip olursunuz ya da ölü kodunuz vardır. Ölü kod şaşırtıcı derecede tehlikelidir, çünkü genellikle ölü olması amaçlanmamıştır! İnanılmaz derecede korkunç Apple "başarısız" derken birkaç yıl öncesindeki güvenlik açığı derhal akla geliyor.

  • Statik bir analiz aracı edinin. Heck, birkaç olsun; her aracın kendine özgü bir uzmanlığı vardır ve hiçbiri diğerlerinin bir süperseti değildir. Ulaşılamayan veya gereksiz kod olduğunu söylerken dikkat edin. Yine, bunlar muhtemelen böceklerdir.

Söylediğim gibi geliyorsa: ilk önce kodu iyi tasarlayın ve ikincisi, bugün doğru olduğundan emin olmak için heck'i test edin. Bunları yapmak, gelecekle başa çıkmayı çok daha kolaylaştıracak; Geleceğe dair en zor kısım, geçmişte insanların yazdığı tüm buggy şeker makinesi koduyla uğraşmak. Bugün doğru alın ve gelecekte maliyetler düşecektir.


24
Daha önce böyle bir yöntem hakkında hiç düşünmedim, şimdi düşününce her zaman her olayı deniyor ve örtüşüyorum, gerçekte ne zaman benim yöntemimi çağıran kişi / yöntem bana ihtiyacım olanı geçerse, o zaman yapmamalıyım. hatalarını düzeltmeyi denemeyin (gerçekte ne amaçladıklarını bilmediğimde), sadece dışarı çıkmalıyım. Bunun için teşekkürler, değerli bir ders öğrenildi!
KidCode

4
Bir yöntemin bir değer vermesi, bunun yan etkisi için de faydalı olmaması gerektiği anlamına gelmez. Eşzamanlı kodda, işlevlerin her ikisini de geri döndürme kabiliyeti genellikle hayati önem taşır ( CompareExchangeböyle bir kabiliyet olmadan hayal edin !) Ve eşzamanlı olmayan senaryolarda bile "yoksa, varsa bir kayıt ekleyin ve her ikisini de döndürün kayıt veya var olanı "hem yan etki hem de getiri değeri kullanmayan herhangi bir yaklaşımdan daha uygun olabilir.
supercat, 16.04'te

5
@KidCode Evet, Eric bazı şeyleri net bir şekilde açıklamakta gerçekten iyi, hatta bazı karmaşık konular bile. :)
Mason Wheeler

3
@supercat Tabii, ama aynı zamanda aklınıza gelmesi zor. İlk önce, muhtemelen küresel bir durumu değiştirmeyen bir şeye bakmak isteyeceksiniz, böylece hem eşzamanlılık sorunlarından hem de devlet yolsuzluğundan kaçınılmalıdır. Bu makul olmadığında, ikisini izole etmek isteyeceksiniz - bu size eşzamanlılığın bir sorun olduğu (ve dolayısıyla çok tehlikeli olduğu düşünülen yerler) ve ele alındığı yerler hakkında net bilgi verir. Bu, orijinal OOP belgesindeki ana fikirlerden biriydi ve aktörlerin faydalarının çekirdeğini oluşturuyor. Dini kural yok - sadece mantıklı olduğunda ikisini ayırmayı tercih ediyorum. Genellikle yapar.
Luaan

5
Bu hemen hemen herkes için çok yararlı bir yazıdır!
Adrian Buzea

89

Yukarıda gösterdiğiniz kodda yaptığınız şey, savunma kodlaması kadar geleceği kanıtlamak değildir .

Her iki ififade de farklı şeyler için test eder. Her ikisi de ihtiyaçlarınıza bağlı olarak uygun testlerdir.

Bölüm 1 bir nullnesneyi test eder ve düzeltir . Yan not: Liste oluşturmak herhangi bir alt öğe oluşturmaz (örn CalendarRow.).

Bölüm 2, kullanıcı ve / veya uygulama hatalarını test eder ve düzeltir. Sırf bir List<CalendarRow>şeyin olması, listede herhangi bir öğenin olduğu anlamına gelmez. Kullanıcılar ve uygulayıcılar, sizin için mantıklı gelse de yapmasınlar, yapabilecekleri için hayal edemediğiniz şeyleri yapacaklardır.


1
Aslında girdi demek için 'aptal kullanıcı hileleri' alıyorum. EVET, girdilere asla güvenmemelisiniz. Sınıfınızın hemen dışında bile. Doğrulamak! Bunun sadece gelecekteki bir endişe olduğunu düşünüyorsanız, bugün sizi hacklemekten mutluluk duyarım.
candied_orange

1
@CandiedOrange, niyet neydi, ancak ifadeler girişimi mizahı iletmedi. İfadeleri değiştirdim.
Adam Zuckerman

3
Buradaki kısa bir soru, eğer bir uygulama hatası / hatalı veri ise, hatalarını düzeltmek yerine sadece çökmemem gerekir mi?
KidCode

4
@KidCode Ne zaman kurtarmaya çalışırsan, "hatalarını düzelt", iki şeyi yapman, iyi bilinen bir duruma geri dönmen ve değerli girişlerini sessizce kaybetmemeniz gerekir. Bu kuralın ardından bu durumda şu soru sorulur: Sıfır satır listesi değerli bir girdi mi?
candied_orange 28:16

7
Bu cevaba kesinlikle katılmıyorum. Bir fonksiyon geçersiz girdi alırsa, tanım olarak programda bir hata var demektir. Doğru yaklaşım, geçersiz girdiye bir istisna atmaktır, bu nedenle sorunu keşfedersiniz ve hatayı düzeltirsiniz. Tanımladığınız yaklaşım sadece onları daha sinsi ve izlemelerini zorlaştıran hatalar gizleyecek. Savunma kodlaması, girdilere otomatik olarak güvenmediğiniz ancak doğruladığınız anlamına gelir; ancak geçersiz veya beklenmedik girdileri "düzeltmek" için rasgele tahminlerde bulunmanız gerektiği anlamına gelmez.
JacquesB

35

Sanırım, bu soru temelde tadına bakmaktan ibaret. Evet, sağlam bir kod yazmak iyi bir fikirdir, ancak örneğinizdeki kod KISS ilkesinin hafif bir ihlalidir (bu tür "gelecekteki kanıtların çoğu gibi).

Şahsen büyük olasılıkla kod gelecek için kurşun geçirmez hale getirme zahmetinde bulunmaz. Geleceği bilmiyorum ve bu nedenle, böyle bir “gelecekteki kurşun geçirmez” kod, gelecek geldiğinde perişan kalmaya mahkumdur.

Bunun yerine, farklı bir yaklaşımı tercih ederim: assert()Makroyu ya da benzeri özellikleri kullanarak açık yaptığınız varsayımlarını yapın . Bu şekilde, gelecek kapıya geldiğinde, varsayımlarınızın artık nerede durmadığını size kesin olarak söyleyecektir.


4
Geleceğin neye sahip olduğunu bilmeme konusundaki amacını beğendim Şu anda tek yaptığım, bir problemin ne olacağını tahmin etmek, sonra çözüm için tekrar tahmin etmek.
KidCode

3
@KidCode: İyi gözlem. Buradaki kendi düşüncen aslında kabul ettiğin de dahil, buradaki cevapların çoğundan daha akıllı.
JacquesB

1
Bu cevabı beğendim. Kodu minimumda tutun, böylece gelecekteki bir okuyucunun neden herhangi bir kontrolün gerekli olduğunu anlaması kolaydır. Gelecekteki bir okuyucu gereksiz görünen şeyleri kontrol ederse, çekin neden orada olduğunu anlamaya çalışmakla zaman alabilir. Gelecekteki bir insan, onu kullanan diğerlerinden ziyade, bu sınıfı değiştiriyor olabilir. Ayrıca, hata ayıklayamayacağınız bir kod yazmayın ; bu, şu anda gerçekleşmeyen durumları ele almaya çalışırsanız, böyle olacaktır. (Ana programın uygulayamadığı kod yollarını kullanan birim testleri
Peter Cordes

23

Düşünmek isteyebileceğiniz bir diğer prensip de hızlı başarısızlığa uğrama fikridir . Buradaki fikir, programınızda bir şeyler ters gittiğinde, en azından serbest bırakmadan önce geliştirirken programı derhal tamamen durdurmak istediğinizdir. Bu ilkeye göre, varsayımlarınızın geçerli olduğundan emin olmak için çok sayıda kontrol yazmak istiyorsunuz, ancak ciddi şekilde varsayımlar ihlal edildiğinde programınızın izini kesmesini beklediğinizi düşünün.

Cesaretle söylemek gerekirse, programınızda küçük bir hata olsa bile, izlerken tamamen çökmesini istiyorsunuz!

Bu, sezgisel görünebilir gibi görünebilir, ancak rutin gelişim sırasında hataları olabildiğince çabuk keşfetmenizi sağlar. Bir kod parçası yazıyorsanız ve bitmiş olduğunu düşünüyorsanız, ancak sınarken çöküyor, henüz bitmediğiniz bir soru yok. Ayrıca, çoğu programlama dili, bir hatadan sonra elinden gelenin en iyisini yapmaya çalışmak yerine, programınız tamamen çöktüğünde, kullanımı en kolay olan mükemmel hata ayıklama araçları sunar. En büyük, en yaygın örnek, işlenmeyen bir istisna atarak programınıza zarar verirseniz, istisna mesajının, hangi kod satırının başarısız olduğunu ve programın geçtiği kodun yolunu içeren hata hakkında inanılmaz miktarda bilgi vermesidir. bu kod satırına (yığın izi) giden yol.

Daha fazla düşünce için bu kısa makaleyi okuyun: Programınızı Dik Konumda Çivilemeyin


Bu sizinle ilgilidir çünkü bazen yazdığınız kontrollerin orada olması mümkündür çünkü programınızın bir şeyler ters gittiğinde bile çalışmaya devam etmesini istersiniz. Örneğin, Fibonacci dizisinin bu kısa uygulamasını göz önünde bulundurun:

// Calculates the nth Fibonacci number
int fibonacci(int n) {
    int a = 0;
    int b = 1;

    for(int i = 0; i < n; i++) {
        int temp = b;
        b = a + b;
        a = temp;
    }

    return b;
}

Bu işe yarıyor, fakat ya biri işlevinize negatif bir sayı verirse? O zaman işe yaramaz! Böylece, fonksiyonun negatif olmayan bir girişle çağrıldığından emin olmak için bir kontrol eklemek isteyeceksiniz.

Bu işlevi şöyle yazmak cazip gelebilir:

// Calculates the nth Fibonacci number
int fibonacci(int n) {
    int a = 0;
    int b = 1;

    // Make sure the input is nonnegative
    if(n < 0) {
        n = 1; // Replace the negative input with an input that will work
    }

    for(int i = 0; i < n; i++) {
        int temp = b;
        b = a + b;
        a = temp;
    }

    return b;
}

Ancak, bunu yaparsanız, daha sonra yanlışlıkla Fibonacci fonksiyonunuzu negatif bir girişle çağırın, asla farkına varamazsınız! Daha da kötüsü, programınız çalışmaya devam edecek, ancak bir şeyin yanlış gittiği yeri hakkında hiçbir ipucu vermeden saçma sapan sonuçlar üretmeye başlayacak. Bunlar düzeltilmesi en zor hatalardır.

Bunun yerine, böyle bir çek yazmak daha iyidir:

// Calculates the nth Fibonacci number
int fibonacci(int n) {
    int a = 0;
    int b = 1;

    // Make sure the input is nonnegative
    if(n < 0) {
        throw new ArgumentException("Can't have negative inputs to Fibonacci");
    }

    for(int i = 0; i < n; i++) {
        int temp = b;
        b = a + b;
        a = temp;
    }

    return b;
}

Şimdi, eğer yanlışlıkla Fibonacci işlevini negatif bir girişle çağırırsanız, programınız derhal durur ve bir şeyin yanlış olduğunu size bildirir. Ayrıca, size bir yığın izlemesi vererek, program programınızın hangi bölümünün Fibonacci işlevini hatalı bir şekilde yerine getirmeye çalıştığını size bildirir ve size yanlış olanı ayıklamak için mükemmel bir başlangıç ​​noktası sunar.


1
C # 'nın geçersiz argümanları veya aralık dışı argümanları belirtmek için belirli bir istisnası yok mu?
JDługosz

@ JDługosz Yep! C # ArgumentException , Java ise IllegalArgumentException .
Kevin

Soru c # kullanıyordu. İşte bütünlüğü için C ++ (özete bağlantı) .
JDługosz

3
"En yakın güvenli duruma hızlıca erişilemez" daha makul. Uygulamanızı, beklenmeyen bir şey olduğunda çökmesine neden olacak şekilde yaparsanız, kullanıcının verilerini kaybetme riskiyle karşı karşıya kalırsınız. Kullanıcının verilerinin tehlikede olduğu yerler "son derece" istisnai durumların ele alınması için harika yerlerdir (her zaman hiçbir şey yapamayacağınız durumlar vardır - ellerinizi yukarı kaldırın - nihai çarpışma). Yalnızca hata ayıklamada çökmesine neden olmak, başka bir solucan kutusu açmaktır; yine de kullanıcıya dağıtmakta olduğunuz şeyi test etmeniz gerekir ve şimdi test süresinin yarısını, kullanıcının asla görmeyeceği bir sürümde harcıyorsunuzdur.
Luaan

2
@Luaan: bu, örnek fonksiyonun sorumluluğunda değildir.
whatsisname,

11

Gereksiz kod eklemeniz gerekir mi? Hayır.

Ancak, tanımladığınız şey gereksiz kod değildir .

Tanımladığınız şey, işlevinizin ön koşullarını ihlal eden çağrı koduna karşı savunma olarak programlamaktır. Bunu yapmak veya sadece belgeleri okumak ve bu ihlalleri kendileri önlemek için kullanıcılara bırakıp, tamamen özneldir.

Şahsen ben bu metodolojiye inanan biriyim, ama her konuda olduğu gibi dikkatli olmalısınız. Örneğin, C ++ 'ları alın std::vector::operator[]. VS'nin hata ayıklama modu uygulamasını bir anlığına bir kenara bırakarak, bu işlev sınır denetimi yapmaz. Varolmayan bir öğeyi talep ederseniz, sonuç tanımsızdır. Geçerli bir vektör indeksi sağlamak kullanıcıya bağlıdır. Bu oldukça kasıtlıdır: çağrı alanına ekleyerek kontrol sınırlarını "kabul edebilirsiniz", ancak operator[]uygulama bunu gerçekleştirecek olsaydı "vazgeçemezsiniz ". Oldukça düşük seviyeli bir fonksiyon olarak bu mantıklı geliyor.

Ancak AddEmployee(string name), bazı üst düzey arayüzler için bir işlev yazıyorsanız , bu işlevden hemen önce name, bildirimden hemen önce belgelenmiş bir boş ve bir ön koşul sağladıysanız, bu işlevin bir istisna oluşturmasını beklerdim . Bugün bu işleve sterilize edilmemiş kullanıcı girişi sağlamıyor olabilirsiniz, ancak bu şekilde "güvenli" hale getirilmesi, gelecekte ortaya çıkacak zorlu bir domino zincirini tetiklemek yerine, kolayca teşhis edilebilecek herhangi bir ön koşul ihlali anlamına gelir. hataları tespit etmek. Bu artıklık değil: titizlik.

Genel bir kural bulmak zorunda olsaydım (her ne kadar genel bir kural olarak, bunlardan kaçınmaya çalışsam da), aşağıdakilerden herhangi birini sağlayan bir fonksiyon olduğunu söyleyebilirim:

  • Süper üst düzey bir dilde yaşıyor (diyelim, C yerine JavaScript)
  • arayüz sınırında oturuyor
  • performans açısından kritik değil
  • doğrudan kullanıcı girişini kabul eder

… Savunma programlarından yararlanabilirler. Diğer durumlarda, asserttest sırasında yangın çıkaran, ancak sürüm bulmada devre dışı bırakılan iyonları yazabilir ve böcek bulma yeteneğinizi daha da artırabilirsiniz.

Bu konu Wikipedia'da daha fazla araştırılmaktadır ( https://en.wikipedia.org/wiki/Defensive_programming ).


9

On programlama komutundan ikisi burada ilgilidir:

  • Girişin doğru olduğunu kabul etmemelisiniz

  • Gelecekte kullanım için kod yazmazsınız

Burada, null değerinin kontrol edilmesi "gelecekteki kullanım için kod yapmak" değildir. Gelecekte kullanım için kod yapmak, arayüz eklemek gibi şeylerdir, çünkü "bir gün" yararlı olabileceklerini düşünüyorsunuz. Başka bir deyişle, emir şu anda gerekli olmadıkça soyutlama katmanları eklememektir.

Boş değerin kontrol edilmesinin gelecekteki kullanımla ilgisi yoktur. Komut # 1 ile ilgili olmalı: girişin doğru olacağını varsaymayın. Asla fonksiyonunuzun bazı girdi alt kümelerini alacağını varsaymayın. Bir işlev, girdiler ne kadar sahte ve dağılmış olursa olsun, mantıklı bir şekilde yanıt vermelidir.


5
Bu programlama emirleri nerede. Bir bağlantın var mı? Merak ediyorum, çünkü bu emirlerin ikincisine abone olan birkaç program üzerinde çalıştım ve bazıları yapmadı. Her zaman, emirlere abone olanlar, emirlerin sezgisel mantığına rağmen, daha önceThou shall not make code for future use bakım sorunlarıyla karşılaştılar . Gerçek hayattaki kodlamada, bu emir sadece özellik listesini ve son teslim tarihlerini kontrol ettiğiniz kodda etkili olduğunu ve onlara ulaşmak için geleceğe yönelik kodlara ihtiyacınız olmadığından emin olun ... ki bu asla söylenemez.
Cort Ammon

1
Önemsizce kanıtlanabilir: Gelecekte kullanım olasılığını ve "gelecekteki kullanım" kodunun öngörülen değerini tahmin edebiliyorsa ve bu ikisinin ürünü "gelecekteki kullanım" kodunu eklemenin maliyetinden daha büyükse, bu durum istatistiksel olarak en uygun kodu ekleyin. Bence emir, geliştiricilerin (veya yöneticilerin) tahmin becerilerinin istedikleri kadar güvenilir olmadığını kabul etmek zorunda kaldıkları durumlarda ortaya çıktığını, bu nedenle savunmacı bir önlem olarak sadece gelecekteki görevi tahmin etmemeyi seçtiklerini düşünüyorum.
Cort Ammon

2
@CortAmmon Programlamada dini emirlere yer yoktur - "en iyi uygulamalar" yalnızca bağlamda anlam ifade eder ve gerekçe olmadan uyum sağlayamayan "en iyi uygulama" öğrenmek. YAGNI'yi çok faydalı buldum, ancak bu daha sonra uzatma noktaları eklemenin pahalı olacağı yerler hakkında düşünmediğim anlamına gelmez - bu sadece vaktinden sonraki basit durumlar hakkında düşünmek zorunda kalmamam anlamına gelir. Elbette, bu aynı zamanda zamanla değişir, çünkü kodunuzla ilgili daha fazla varsayımlar cıvatalanır, kodunuzun arayüzünü etkin bir şekilde arttırır - bu bir dengeleme hareketidir.
Luaan

2
@CortAmmon "Öngörülebilir olarak kanıtlanabilir" durumunuz iki önemli maliyeti göz ardı eder - tahminin kendisinin maliyeti ve (muhtemelen gereksiz) uzatma noktasının bakım maliyetleri. İnsanların son derece güvenilmez tahminleri aldığı yer - tahminleri hafife almak. Çok basit bir özellik için, birkaç saniyeliğine düşünmek yeterli olabilir, ancak başlangıçta "basit" olan özelliğin izini süren bir sürü solucan bulabilirsin. İletişim anahtardır - işler büyüdükçe, lideriniz / müşterinizle konuşmanız gerekir.
Luaan

1
@Luaan Amacınız için tartışmaya çalışıyordum, programlamada dini emirlere yer yok. Uzatma noktasının tahmin ve bakım maliyetlerinin yeterince sınırlandırıldığı bir iş vakası olduğu sürece, söz konusu "emir" in sorgulanabileceği bir durum söz konusudur. Kod konusundaki deneyimlerime göre, bu uzatma noktalarından ayrılıp ayrılmayacağı sorusu, bir şekilde veya başka bir şekilde tek satırlık bir emre hiç uymuyor.
Cort Ammon

7

'Gereksiz kod' ve 'YAGNI' tanımı genellikle ne kadar ileriye baktığınıza bağlı.

Bir sorunla karşılaşırsanız, gelecekteki kodu bu sorunu önleyecek şekilde yazma eğilimindedir. Bu sorunu yaşamamış başka bir programcı, kodunuzun fazla overkill olduğunu düşünebilir.

Benim önerim, yükleri ve akranları sizden daha hızlı bir şekilde özellikleri dışarıda bırakıyorsa, 'henüz bozulmamış şeylere' ne kadar zaman harcadığınızı takip etmektir.

Ancak, eğer benim gibiyseniz, umarım hepsini 'varsayılan' olarak yazmış olacaksınız ve bu sizi daha fazla almadı.


6

Parametrelerle ilgili varsayımları belgelemek iyi bir fikirdir. Müşteri kodunuzun bu varsayımları ihlal etmediğini kontrol etmek iyi bir fikirdir. Bunu yapardım:

/** ...
*   Precondition: rows is null or nonempty
*/
public static CalendarRow AssignAppointmentToRow(Appointment app, List<CalendarRow> rows)
{
    Assert( rows==null || rows.Count > 0 )
    //1. Is rows equal to null? - This will be the case if this is the first appointment.
    if (rows == null) {
        rows = new List<CalendarRow> ();
        rows.Add (new CalendarRow (0));
        rows [0].Appointments.Add (app);
    }

    //blah...
}

[Bunun C # olduğu varsayılarak, Assert, serbest bırakılmış kodda derlenmediğinden iş için en iyi araç olmayabilir. Ama bu başka bir gün için bir tartışma.]

Bu neden yazdıklarından daha iyi? Müşterinizin değiştiği bir gelecekte, müşteri boş bir listeye girdiğinde, kodunuz mantıklı olacaktır, yapılacak ilk şey ilk bir satır eklemek ve randevularına uygulama eklemek olacaktır. Ama bunun böyle olacağını nereden biliyorsun? Şimdi gelecekle ilgili daha az varsayım yapmak daha iyidir.


5

Şimdi bu kodu eklemenin maliyetini tahmin edin . Göreceli olarak ucuz olacak çünkü zihninizde tamamen taze, bu nedenle hızlı bir şekilde yapabileceksiniz. Ünite testleri eklemek gereklidir - bir yıl sonra bazı metotları kullanmaktan daha kötüsü yoktur, işe yaramaz ve baştan kırıldığını ve hiç çalışmadığını anlarsınız.

Gerektiğinde bu kodu eklemenin maliyetini tahmin edin. Daha pahalı olacak çünkü koda geri dönmelisin, hepsini hatırla ve çok daha zor.

Ek kodun gerçekten gerekli olabileceği ihtimalini tahmin edin. O zaman matematiği yap.

Öte yandan, "X asla olmayacak" varsayımlarıyla dolu kod hata ayıklama için korkunç. Bir şey beklendiği gibi çalışmazsa, ya aptalca bir hata ya da yanlış bir varsayım anlamına gelir. "X asla olmayacak" bir varsayımdır ve bir böcek varlığında şüphelidir. Bu da bir sonraki geliştiriciyi üzerinde zaman kaybetmeye zorlar. Bu varsayımlara güvenmemek genellikle daha iyidir.


4
İlk paragrafınızda, gerçekte ihtiyaç duyulan özelliğin gereksiz yere eklenen özellik ile karşılıklı olarak dışlandığı ortaya çıktığında, zaman içinde bu kodu sürdürmenin maliyetinden bahsetmeyi unuttunuz . . .
ruakh

Ayrıca, geçersiz girdilerde başarısız olmadığınız için programa girebilecek hataların maliyetini de tahmin etmeniz gerekir. Ancak, tanım olarak beklenmedik olmadıklarından böceklerin maliyetini tahmin edemezsiniz. Yani bütün "matematik yap" dır.
JacquesB

3

Buradaki ana soru "yaparsanız / yapmazsanız ne olur"?

Diğerlerinin de belirttiği gibi, bu tür bir savunma programlaması iyidir, ancak bazen de tehlikelidir.

Örneğin, varsayılan bir değer sağlarsanız, programı devam ettirirsiniz. Ancak program şimdi yapmasını istediğiniz şeyi yapmıyor olabilir. Örneğin, bu boş diziyi bir dosyaya yazarsa, şimdi "hatayı boşa verdiğim için" boşa verdiğim için takvim satırlarını temizlemeye başladığımdan dolayı "hatayı" çöker "durumuna çevirmiş olabilirsiniz. (örneğin , listede "// blah" yazan kısımda görünmeyenleri silmeye başlarsanız )

Benim için anahtar Asla bozuk veridir . Bunu tekrar edeyim; ASLA. CORRUPT. VERİ. Programınız istisnalar dışında, ekleyebileceğiniz bir hata raporu alırsınız; Kötü verileri daha sonra yazacağı bir dosyaya yazarsa, yere tuz ekmeniz gerekir.

Tüm "gereksiz" kararlarınız bu öncül göz önünde bulundurularak verilmelidir.


2

Burada uğraştığınız şey temelde bir arayüzdür. "Giriş olduğunda null, girişi başlat" davranışını ekleyerek, yöntem arabirimini etkili bir şekilde genişlettiniz - şimdi her zaman geçerli bir listede çalışmak yerine, girişi "düzelt" yaptınız. Bu, arabirimin resmi veya resmi olmayan bir parçası olup olmadığına bakılmaksızın (muhtemelen siz dahil) birinin bu davranışı kullanacağına bahse girebilirsiniz.

Arabirimler basit tutulmalı ve nispeten kararlı olmalıdır - özellikle de public staticyöntem gibi bir şeyde . Özel yöntemlerde, özellikle de özel örnek yöntemlerinde biraz yeriniz olsun. Arabirimi dolaylı olarak genişleterek, uygulamada kodunuzu daha karmaşık hale getirdiniz. Şimdi, aslında bu kod yolunu kullanmak istemediğinizi düşünün - bu yüzden kaçınmalısınız. Şimdi , yöntemin davranışının bir parçası gibi davranan , denenmemiş bir kodunuz var . Ve şimdi size muhtemelen bir hata olduğunu söyleyebilirim: bir listeyi geçtiğinde, bu liste metoda göre mutasyona uğrar. Ancak, yapmazsanız, yerellistele ve sonra at. Bu, belirsiz bir hatayı bulmaya çalışırken, yarım yılda ağlamanızı sağlayacak tutarsız davranışlardır.

Genel olarak, savunma programlaması oldukça yararlı bir şeydir. Ancak savunma kontrolleri için kod yolları , diğer herhangi bir kodda olduğu gibi test edilmelidir . Böyle bir durumda, kodunuzu sebepsiz yere karmaşıklaştırıyorlar ve bunun yerine böyle bir alternatif tercih ediyorum:

if (rows == null) throw new ArgumentNullException(nameof(rows));

Sen yok istediğiniz bir giriş rowsboş, ve tüm arayanlar için hata bariz yapmak istiyorum mümkün olduğunca çabuk .

Yazılım geliştirirken dolaşmanız gereken birçok değer var. Sağlamlığın kendisi bile çok karmaşık bir kalitedir - örneğin, savunma kontrolünüzü bir istisna yapmaktan daha sağlam görmezdim. İstisnalar, güvenli bir yerden tekrar denemeniz için güvenli bir yer sağlamanız için oldukça kullanışlıdır - veri bozulması sorunları genellikle bir sorunu daha erken tanımak ve güvenli bir şekilde ele almaktan çok daha zordur. Sonunda, size sadece sağlamlık illüzyonunu verme eğilimindedirler ve bir ay sonra, randevularınızın onda birinin gittiğini farkedersiniz, çünkü farklı bir listenin güncellendiğini asla farketmediniz. Ahh.

İkisini ayırdığınızdan emin olun. Defansif programlama , en alakalı oldukları bir yerde hataları yakalamak, hata ayıklama çabalarınıza önemli ölçüde yardımcı olmak ve "sinsi yolsuzlukları" önlemek için iyi istisnalarla baş etmek için yararlı bir tekniktir. Erken başarısız, hızlı başarısız. Öte yandan, yaptığınız şey daha çok "hata gizleme" gibidir - girdileri hokkabazlık ediyor ve arayanın ne anlama geldiğiyle ilgili varsayımlarda bulunuyorsunuz. Bu, kullanıcının karşılaştığı kod için çok önemlidir (örn. Yazım denetimi), ancak geliştiriciye yönelik kodu görerken dikkatli olmalısınız.

Asıl sorun şu ki, yaptığınız soyutlama ne olursa olsun, kaçak olacak ("Önceden değil, aptal yazım denetleyicisi! sürdürmeniz, anlamanız ve kodlamanız gerekir. Üretimde bir yıl sonra olan hatayı düzeltmek için boş olmayan bir listenin iletildiğinden emin olmak için harcadığınız çabayı karşılaştırın - bu bir takas değil. İdeal bir dünyada, her yöntemin yalnızca kendi girdisiyle çalışmasını, bir sonuç döndürmesini ve hiçbir küresel durumu değiştirmemesini istersiniz. Tabii ki, gerçek dünyada, bunun olmadığı durumlarda birçok olay bulacaksınız.en basit ve en net çözüm (örneğin, bir dosyayı kaydederken), ancak genel durumu okumak ya da işlemek için hiçbir sebep olmadığında, yöntemleri "saf" tutmanın kodun nedenini çok daha kolay hale getirdiğini buluyorum. Ayrıca yöntemlerinizi bölmek için size daha doğal puanlar verme eğilimindedir :)

Bu, beklenmeyen her şeyin uygulamanızın çökmesine neden olması gerektiği anlamına gelmez. İstisnaları iyi kullanırsanız, doğal olarak istikrarlı uygulama durumunu geri yükleyebileceğiniz ve kullanıcının yaptıklarını sürdürmesine izin verebileceğiniz (kullanıcı için herhangi bir veri kaybını önlerken idealdir) güvenli hata işleme noktaları oluşturur. Bu kullanım noktalarında, sorunların giderilmesi ("2212 sipariş numarası bulunamadı. 2212b mi demek istediniz?") Veya kullanıcı denetimi ("Veritabanına bağlanırken hata oluştu.") İle ilgili sorunları göreceksiniz. Böyle bir seçenek olsa bile, en azından bu size hiçbir şey bozuk var bir şans verecek - Ben kullandığı kod takdir başladım usingve try... finallyçok daha fazla try...catchİstisnai koşullar altında bile değişmezleri korumak için size birçok fırsat sunar.

Kullanıcılar verilerini ve çalışmalarını kaybetmemelidir. Bu hala geliştirme maliyetleri vb. İle dengelenmek zorundadır, ancak oldukça iyi bir genel kılavuzdur (kullanıcılar yazılımınızı satın alıp almayacağına karar verirse - dahili yazılımda genellikle bu lüks yoktur). Eğer kullanıcı sadece yeniden başlatıp ne yaptıklarına geri dönebilirlerse, uygulamanın çökmesini engellemek bile daha az problem yaratır. Bu gerçek bir sağlamlıktır - Word , belgenizi diskte bozulmadan çalışmanızı her zaman korur ve size bir seçenek sunarçökmeden sonra Word'ü yeniden başlattıktan sonra bu değişiklikleri geri yüklemek için. Her şeyden önce böcek olmamasından daha mı iyidir? Muhtemelen hayır - Nadir bir böcek yakalamak için harcanan işin her yerde daha iyi harcanabileceğini unutmayın. Ancak alternatiflerden çok daha iyidir - örneğin, diskteki bozuk bir belge, son kaydetme işleminden bu yana yapılan tüm çalışmalar, belge çökmeden önce otomatik olarak değiştirilen belge, Ctrl + A ve Sil gibi.


1

Buna, sağlam kodun size "yıllar" fayda sağlayacağı varsayımına dayanarak cevap vereceğim. Uzun vadeli faydalar amacınızsa, tasarım ve sağlamlığa karşı sürdürülebilirliği öncelikli yapardım.

Tasarım ve sağlamlık arasındaki denge zaman ve odaktır. Çoğu geliştirici, bazı sorunlu noktalardan geçmek ve bazı ek koşul veya hata yönetimi yapmak anlamına gelse bile, iyi tasarlanmış bir kod setine sahip olmayı tercih eder. Birkaç yıllık kullanımdan sonra, gerçekten ihtiyaç duyduğunuz yerler muhtemelen kullanıcılar tarafından tanımlanmıştır.

Tasarımın aynı kalitede olduğu varsayılarak, daha az kodun bakımı daha kolaydır. Bu, bilinen sorunların birkaç yıl devam etmesine izin verirseniz daha iyi olacağımız anlamına gelmez, ancak ihtiyacınız olmadığını bildiğiniz şeyleri eklemek zorlaştırır. Hepimiz eski kodlara baktık ve gereksiz parçalar bulduk. Yıllarca çalışmış olan üst düzey bir güven değiştirme koduna sahip olmalısınız.

Uygulamanızın olabildiğince iyi tasarlandığını, bakımı kolay ve herhangi bir hataya sahip olmadığını düşünüyorsanız, ihtiyacınız olmayan kod eklemekten daha iyi bir şey bulun. Anlamsız özellikler üzerinde uzun saatler boyunca çalışan diğer tüm geliştiricilere saygı göstermeden yapabileceğiniz en az şey.


1

Hayır yapmamalısın. Ve aslında bu kodlamanın bu tür böcekleri gizleyebileceğini söylerken kendi sorunuzu cevaplıyorsunuz . Bu, kodu daha sağlam hale getirmez - daha çok hataları ve daha fazla hata ayıklamayı zorlaştırır.

rowsArgüman hakkındaki mevcut beklentilerinizi belirtirsiniz: Ya boş ya da aksi halde en az bir maddeye sahip. Öyleyse soru şudur: rowsSıfır öğelerin bulunduğu beklenmeyen üçüncü durumu ele almak için kodu yazmak iyi bir fikir midir?

Cevap hayır. Beklenmeyen bir giriş durumunda her zaman bir istisna atmalısınız. Bunu göz önünde bulundurun: Kodun bazı bölümleri, yöntemin beklentisini (yani sözleşmeyi) ihlal ederse, bunun bir hata olduğu anlamına gelir . Bir hata varsa, onu mümkün olduğunca erken bilmek istersiniz, böylece düzeltebilirsiniz ve bir istisna bunu yapmanıza yardımcı olacaktır.

Şu anda kodun yaptığı, kodda bulunabilecek veya bulunmayabilecek bir hatadan nasıl kurtarılacağını tahmin etmektir. Ancak bir hata olsa bile, ondan tamamen nasıl kurtulacağınızı bilemezsiniz. Tanımı gereği böceklerin bilinmeyen sonuçları vardır. Belki de bazı başlatma kodları beklendiği gibi çalıştırılmamıştır, yalnızca eksik satırdan başka birçok sonucu olabilir.

Yani kod şöyle görünmeli:

public static CalendarRow AssignAppointmentToRow(Appointment app, List<CalendarRow> rows)
{
    if (rows != null && rows.Count == 0) throw new ArgumentException("Rows is empty."); 

    //1. Is rows equal to null? - This will be the case if this is the first appointment.
    if (rows == null) {
        rows = new List<CalendarRow> ();
        rows.Add (new CalendarRow (0));
        rows [0].Appointments.Add (app);
    }

    //blah...
}

Not: Bazı vardır spesifik o "tahmin" mantıklı durumlar nasıl sadece bir istisna atma yerine geçersiz giriş işlemek için. Örneğin, harici girişi ele alırsanız üzerinde kontrolünüz yoktur. Web tarayıcıları rezil bir örnektir, çünkü her türlü hatalı biçimlendirilmiş ve geçersiz girişi incelikle ele almaya çalışırlar. Ancak, bu yalnızca programın diğer bölümlerinden gelen çağrılarla değil, dışsal girdilerle anlamlıdır.


Düzenleme: Diğer bazı cevaplar, savunma programlaması yaptığınızı belirtir . Katılmıyorum. Savunma programlama, girişin geçerli olması için otomatik olarak güvenmediğiniz anlamına gelir. Bu nedenle, parametrelerin doğrulanması (yukarıdaki gibi), savunma amaçlı bir programlama tekniğidir, ancak bu, tahmin ederek beklenmedik veya geçersiz girdi değiştirmeniz gerektiği anlamına gelmez. Sağlam savunma yaklaşımı, girişi doğrulamak ve beklenmeyen veya geçersiz girdi olması durumunda bir istisna atmaktır.


1

Gerekirse gelecekte gerekebilecek olması durumunda artık kod eklemeli miyim?

Herhangi bir zamanda fazladan kod eklememelisiniz.

Sadece gelecekte gerekli olan kodu eklememelisiniz.

Ne olursa olsun, kodunuzun iyi davrandığından emin olmalısınız.

"İyi davranmak" tanımı sizin ihtiyaçlarınıza bağlıdır. Kullanmayı sevdiğim tekniklerden biri "paranoya" istisnaları. Belli bir vakanın asla gerçekleşemeyeceğinden% 100 emin olursam, yine de bir istisna programlarım, ancak bunu a) herkese bunun olmasını asla beklemeyeceğimi söyler ve b) açıkça görüntülenip kaydedilir ve bu nedenle daha sonra sürünen yolsuzluğa yol açmaz.

Örnek sözde kodu:

file = File.open(">", "bla")  or raise "Paranoia: cannot open file 'bla'"

file.write("xytz") or raise "Paranoia: disk full?"

file.close()  or raise "Paranoia: huh?!?!?"

Bu açıkça,% 100 dosyayı her zaman açabileceğim, yazabileceğim ya da kapatabileceğimden, yani ayrıntılı bir hata işleme oluşturma kapsamına girmediğimden emin olduğumu açıkça belirtiyor. Ancak (hayır: ne zaman) dosyayı açamazsam, programım kontrollü bir şekilde başarısız olur.

Tabii ki kullanıcı arayüzü bu mesajları kullanıcıya göstermeyecek, yığın izlemesi ile birlikte dahili olarak kaydedilecektir. Yine bunlar, beklenmedik bir şey olduğunda kodun "durduğundan" emin olmasını sağlayan iç "Paranoya" istisnasıdır. Bu örnek biraz pratiktir, pratikte dosyaları açarken hatalar için gerçek hata işlemeyi uygularım, bu düzenli olarak gerçekleşir (yanlış dosya adı, USB bellek salt okunur şekilde monte edilmiş, ne olursa olsun).

Çok önemli bir ilgili arama terimi, diğer cevaplarda da belirtildiği gibi "hızlı başarısız" olabilir ve sağlam bir yazılım oluşturmak için çok faydalıdır.


-1

Burada çok fazla karmaşık cevap var. Muhtemelen bu soruyu sordunuz, çünkü bu parça kodu hakkında doğru bir şey hissetmediniz ancak neden veya nasıl düzelteceğinizden emin değildiniz. Yani benim cevabım, sorunun kod yapısında (her zamanki gibi) çok muhtemel olduğudur.

İlk olarak, yöntem başlığı:

public static CalendarRow AssignAppointmentToRow(Appointment app, List<CalendarRow> rows)

Hangi satıra randevu atayın ? Bu hemen parametre listesinden silinmelidir. Başka bilgi olmadan, ben yöntemi parametreler şöyle arayacakları: (Appointment app, CalendarRow row).

Sonra, "giriş kontrolleri":

//1. Is rows equal to null? - This will be the case if this is the first appointment.
if (rows == null) {
    rows = new List<CalendarRow> ();
}

//2. Is rows empty? - This will be the case if this is the first appointment / some other unknown reason.
if(rows.Count == 0)
{
    rows.Add (new CalendarRow (0));
    rows [0].Appointments.Add (app);
}

Bu saçmalık.

  1. kontrol edin) Yöntem arayan, yalnızca yöntem içinde başlatılmamış değerleri geçmediğinden emin olmalıdır. Aptal olmamak bir programcının sorumluluğudur (denemek için).
  2. kontrol) rowsYönteme geçmenin muhtemelen yanlış olduğunu dikkate almazsam (yukarıdaki yoruma bakınız), o zaman bir AssignAppointmentToRowyere atamaktan başka herhangi bir şekilde satırları işlemek için kullanılan yöntemin sorumluluğu olmamalıdır .

Ancak bir yerde randevu atama kavramı gariptir (bu, kodun GUI parçası olmadığı sürece). Kodunuz bir takvimi temsil eden açık bir veri yapısı içeriyor (ya da en azından denemeye çalışıyor) (yani List<CalendarRows><- Calendarbu şekilde gitmek istiyorsanız, o zaman Calendar calendaryönteminize geçiyorsunuz ). Bu şekilde giderseniz calendar, randevuları daha sonra yerleştirdiğiniz (atadığınız) yuvalarla önceden doldurulmasını beklerim (örneğin calendar[month][day] = appointmentuygun kod olur). Ancak, takvim yapısını ana mantıktan tamamen çıkarmayı seçebilir List<Appointment>ve Appointmentnesnelerin nitelik içerdiği yere sahip olabilirsiniz.date. Ve sonra, GUI'de bir yerde bir takvim oluşturmanız gerekiyorsa, oluşturmadan hemen önce bu 'açık takvim' yapısını oluşturabilirsiniz.

Uygulamanızın ayrıntılarını bilmiyorum, bu yüzden bazıları sizin için geçerli olmayabilir, ancak bu kontrollerin her ikisi (esas olarak ikincisi) , kodunuzdaki endişelerin ayrılmasında bir yerde bir şeyin yanlış olduğunu söylüyor .


-2

Basit olması için, nihayetinde bu kod parçasına N gün içinde (daha sonra veya daha önce değil) ihtiyacınız olacağını veya hiç ihtiyacınız olmadığını varsayalım.

pseudocode:

let C_now   = cost of implementing the piece of code now
let C_later = ... later
let C_maint = cost of maintaining the piece of code one day
              (note that it can be negative)
let P_need  = probability that you will need the code after N days

if C_now + C_maint * N < P_need*C_later then implement the code else omit it.

Faktörler C_maint:

  • Kodu genel olarak iyileştirir mi, daha fazla kendini belgelemeyi ve test etmesini kolaylaştırır mı? Eğer evet ise, olumsuz C_maintbeklenen
  • Kodu daha büyük kılıyor mu (bu nedenle okunması zor, derlemesi daha uzun, testleri uygulamak, vb.)?
  • Herhangi bir yeniden düzenleme / yeniden tasarım beklemede mi? Eğer öyleyse çarp C_maint. Bu durum gibi değişkenlerle daha çok kez daha karmaşık bir formül gerektirir N.

Bu nedenle kodu sadece ağırlaştıran ve düşük olasılıkla sadece 2 yıl içinde ihtiyaç duyabilecek kadar büyük bir şey bırakılmalıdır, ancak faydalı iddialar ve% 50'sinin 3 ay içinde gerekeceği konusunda% 50 oranında bir önlem almalıdır. .


Ayrıca, geçersiz girişi reddetmediğiniz için programa girebilecek hataların maliyetini de hesaba katmanız gerekir. Peki, bulunması zor olan potansiyel hataların maliyetini nasıl tahmin ediyorsunuz?
JacquesB
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.