Kontrol akışı olarak istisnalar ciddi bir antipattern olarak kabul edilir mi? Öyleyse neden?


129

90'lı yılların sonunda, istisnaları akış kontrolü olarak kullanan bir kod tabanı ile biraz çalıştım. Telefon uygulamalarını sürmek için sonlu durumlu bir makine kullandı. Son zamanlarda o günleri hatırlatıyorum çünkü MVC web uygulamaları yapıyorum.

Her ikisinde de Controllernereye gidileceğine karar veren ve verileri hedef mantığa sağlayan karar var . DTMF tonları gibi eski bir telefonun etki alanından gelen kullanıcı eylemleri, eylem yöntemlerine parametre haline geldi, ancak a gibi bir şeyleri geri döndürmek yerine, a ViewResultattılar StateTransitionException.

Bence asıl fark, eylem yöntemlerinin voidfonksiyonlar olduğuydu. Bu gerçekle yaptığım her şeyi hatırlamıyorum ama hatırlama yolunda bile tereddüt ettim, çünkü 15 yıl önce olduğu gibi, bu işin yapım kodunda başka bir işte hiç görmedim . Bunun, sözde bir anti-patern olduğunu gösteren bir işaret olduğunu varsaymıştım.

Durum bu mu ve öyleyse neden?

Güncelleme: soruyu sorduğumda, zaten @ MasonWheeler'in cevabı aklımdaydı, bu yüzden bilgime en çok eklenen cevaba ulaştım. Bence onun da sağlam bir cevabı.



25
Hayır. Python'da istisnaları kontrol akışı olarak kullanmak "pythonic" olarak kabul edilir.
user16764

4
Eğer böyle bir şey Java yapmak vardı, kesinlikle bunun için bir istisna değildir. İstisna Dışı, Hata Dışı, Atılabilir hiyerarşiden türemiştir.
Thomas Eding,

2
Mevcut cevaplara eklemek için, işte bana iyi hizmet eden kısa bir kılavuz: - "Mutlu yol" için istisnalar kullanmayın. Mutlu yol tüm isteğin (web için) tamamı ya da sadece bir nesne / yöntem olabilir. Diğer tüm aklı başında kurallar hala geçerlidir, tabi ki :)
Houen

8
İstisnalar her zaman bir uygulamanın akışını kontrol etmiyor mu?

Yanıtlar:


109

Ward's Wiki'de bununla ilgili ayrıntılı bir tartışma var . Genel olarak, kontrol akışı için istisnaların kullanımı, kayda değer bir durum olan - ve dile özgü ( örneğin Python'a bakınız ) öksürük istisnaları öksürük gibi bir anti- paterndir .

Genel bir neden olarak, bunun bir anti-kalıp olduğu için kısa bir özet:

  • İstisnalar, özünde, sofistike GOTO ifadeleridir.
  • Bu nedenle, istisnalar dışında programlama kodu okumak ve anlamakta zorlanır
  • Çoğu dil istisnalar dışında problemlerinizi çözmek için tasarlanmış kontrol yapılarına sahiptir.
  • Verimlilik argümanları, istisnaların kontrol akışı için kullanılmadığı varsayımıyla optimizasyon yapma eğiliminde olan modern derleyiciler için tartışılmaz.

Daha ayrıntılı bilgi için Ward'ın wiki sayfasındaki tartışmayı okuyun.


Ayrıca bu sorunun bir kopyasını da burada görebilirsiniz.


18
Cevabınız, her koşul için istisnalar kötü gibi görünüyor, soru ise akış kontrolü olarak istisnalara odaklanmış durumda.
whatsisname,

14
@MasonWheeler Aradaki fark, döngü döngüleri için akış kontrol değişikliklerini açıkça ve bu süre içinde içermesi ve kodun okunmasını kolaylaştırmasıdır. Kodunuzda bir for ifadesi görürseniz, hangi dosyanın döngünün sonunu içerdiğini bulmanız gerekmez. Goto fena değil, çünkü bazı tanrılar öyle dediler, sadece kötülerden daha zor oldukları için, kötülerdir. İstisnalar benzerdir, imkansız değildir ama işleri karıştırabilecekleri kadar zordur.
Bill K

24
@BillK, o zaman savunun ve istisnaların nasıl gerçekleştiğine dair basit açıklamalar yapmayın.
Winston Ewert

6
Tamam ama ciddiyim, sunucu tarafındaki ve uygulama geliştiricilerindeki hatalar JavaScript'teki boş alıcı ifadeleriyle hataları gömme konusunda ne yapıyor? Bu bana çok zaman harcayan iğrenç bir fenomon ve bağırmadan nasıl soracağımı bilmiyorum. Hatalar senin arkadaşın.
Erik,

12
@ mattnz: ifve foreachayrıca sofistike GOTOs. Açıkçası, goto ile karşılaştırmanın faydalı olmadığını düşünüyorum; neredeyse aşağılayıcı bir terim gibi. Bu ciddi problemler vardır ve istisnalar - GOTO kullanımı özünde kötü değildir belki o paylaşabilir, ancak olmayabilir. Bu sorunları duymak daha yararlı olur.
Eamon Nerbonne

110

İstisnalar için tasarlanan kullanım durumu, "Bu noktada tam olarak çözemediğim bir durumla karşılaştım, çünkü bununla başa çıkmak için yeterli bağlamım yok, ama beni çağıran rutin (veya çağrıyı devam ettiren bir şey) "nasıl işleneceğini bilmeli."

İkincil kullanım durumu ise “Sadece ciddi bir hatayla karşılaştım ve şu anda veri bozulmalarını veya diğer hasarları önlemek için bu kontrol akışından çıkmak, devam etmeye devam etmekten daha önemli.”

Bu iki nedenden biri için istisnalar kullanmıyorsanız, bunu yapmanın daha iyi bir yolu olabilir.


18
Bu soruya cevap vermiyor. Ne için tasarlandıkları önemli değil; İlgili olan tek şey, onları kontrol akışı için kullanmanın neden kötü olduğunu ve dokunmadığınız bir konudur. Örnek olarak, C ++ şablonları bir şey için tasarlandı, ancak tasarımcıların asla beklemeyeceği bir kullanım olan metaprogramlama için kullanılmak üzere tamamen iyi.
Thomas Bonini

6
@Krelp: Tasarımcılar kazara bir Turing komple şablon sistemine son vermek gibi pek çok şey beklemiyorlardı ! C ++ şablonları burada kullanmak için iyi bir örnek değil.
Mason Wheeler

15
@Krelp - C ++ şablonları metaprogramming için 'mükemmel' değil. Onları doğru elde edene kadar kabuslar, ve eğer şablon dehası değilseniz, sadece yazma koduna yönelirler. Daha iyi bir örnek seçmek isteyebilirsiniz.
Michael Kohne

İstisnalar özellikle fonksiyon kompozisyonuna zarar verir ve genel olarak kısalık kodlar. Örneğin deneyimsizken bir projede bir istisna kullandım ve uzun zaman sıkıntılarına neden oldu, çünkü 1) insanlar onu yakalamayı hatırlamak zorunda kaldılar, 2) yazamazsınız const myvar = theFunctionçünkü myvar denemek için yaratılmalı, bu yüzden artık sabittir. Bu, C # 'da, herhangi bir sebepten dolayı bir ana akım olduğu için kullanmadığım anlamına gelmez, ama yine de onları azaltmaya çalışıyorum.
Hi-Angel

2
@AndreasBonini Konular için ne tasarlandılar / tasarlandılar çünkü bu genellikle tasarımla uyumlu derleyici / çerçeve / çalışma zamanı uygulama kararları ile sonuçlanır. Böyle vb yığın izleri gibi kod ayıklama birine yardım amaçlı bilgileri toplar çünkü Örneğin, bir özel durum atma basit getiri çok daha “pahalı” olabilir
binki

29

İstisnalar Devamlılıklar ve kadar güçlüdür GOTO. Onlar evrensel bir kontrol akış yapısıdır.

Bazı dillerde, tek evrensel kontrol akışı yapısıdır. Örneğin, JavaScript'in Devamları yoktur GOTO, Uygun Kuyruk Çağrıları bile yoktur. Dolayısıyla, karmaşık denetim akışını JavaScript'te uygulamak istiyorsanız , İstisnalar'ı kullanmanız gerekir .

Microsoft Volta projesi, keyfi .NET kodunu JavaScript'e derlemek için hazırlanmış bir araştırma projesiydi. .NET, semantikleri JavaScript’le tam olarak eşleşmeyen İstisnalar içeriyor, ancak daha da önemlisi, Konuları var ve bunları bir şekilde JavaScript’le eşlemeniz gerekiyor. Volta bunu JavaScript İstisnalarını kullanarak Volta Devamlarını uygulayarak ve ardından tüm .NET kontrol akışı yapılarını Volta Devam Ediyor olarak uygulayarak yaptı. Onlar vardı çünkü, kontrol akış olarak İstisnalar kullanmak başka hiçbir kontrol akış oluşturmak olduğunu yeterince güçlü.

Devlet Makinelerinden bahsettiniz. SM'ler Doğru Kuyruk Çağrıları ile uygulama için önemsizdir: her durum bir alt yordamdır, her durum bir alt yordamdır. SM'ler ayrıca GOTOveya Coroutines veya Continuations ile kolayca uygulanabilir . Ancak, Java bu dört herhangi yoktur, ancak does İstisnalar var. Bu nedenle kontrol akışı olarak kullanmak tamamen kabul edilebilir. (Aslında, doğru seçim muhtemelen uygun kontrol akışı yapısına sahip bir dili kullanmak olacaktır, ancak bazen Java ile sıkışmış olabilirsiniz.)


7
Keşke uygun bir kuyruk çağrısı özyinemesi yapsaydık, belki JavaScript ile istemci tarafı web geliştirmeye hükmedebilirdik ve ardından sunucu tarafına ya da orman yangını gibi en iyi pan platformu çözümü olarak harekete geçerek onu izleyebilirdik. Ne yazık ki, ama öyle değildi. Bizim yetersiz birinci sınıf fonksiyonlarımız, kapanışlarımız ve olaya dayalı paradigmamıza lanet olsun. Gerçekten ihtiyacımız olan şey gerçek şeydi.
Erik,

20
@ErikReppen: Sadece alaycı olduğunuzu anlıyorum ama. . . Ben gerçekten biz "JavaScript ile istemci tarafı web gelişiminde egemen olan" dilin özellikleri ile ilgisi olduğunu gerçeğini düşünmüyorum. Bu pazarda bir tekele sahip olduğu için alay ile birlikte yazılamayan birçok sorunu çözebildi.
ruakh

1
Kuyruk özyineleme güzel bir ikramiye olurdu (gelecekte kullanmak için işlev özelliklerini kullanımdan kaldırıyorlardı) ama evet, özellik ile ilgili nedenlerden dolayı VB, Flash, Applets vb. Karmaşıklığı azaltmadıysa ve olduğu gibi kolayca normalize etmeseydi, bir noktada gerçek bir rekabete girecekti. Şu anda Node.js'yi çirkin bir C # + Java yığını için 21 config dosyasının yeniden yazılmasını sağlamak için kullanıyorum ve orada bunu yapan tek kişi olmadığını biliyorum. Neyin iyi olduğu konusunda çok iyi.
Erik, 05: 13'te

1
Pek çok dilde ne goto ne de (Goto zararlı!), Coutine'ler veya süreklilikler mevcut değildir ve sadece ifs, whiles ve fonksiyon çağrıları (veya gosubs!) Kullanarak mükemmel bir geçerli akış kontrolü uygular. Bunların çoğu aslında birbirlerini taklit etmek için kullanılabilir, tıpkı yukarıdakilerin hepsini temsil etmek için bir devamın kullanılması gibi. (Örneğin kodlamak için kötü bir yol olsa bile, bir if gerçekleştirmek için bir süre kullanabilirsiniz). Bu nedenle, gelişmiş akış kontrolü yapmak için hiçbir istisna gerekli değildir.
Shayne

2
Evet, eğer haklı olabilirsin. Bununla birlikte, C tarzı formunda "For" ifadesi garip bir şekilde belirtildiği gibi kullanılabilir ve bir süre sonra diğer tüm akış kontrol formlarını taklit edebilen sonlu bir durum makinesini uygulamak için bir if ile birlikte kullanılabilir. Yine, kodlamak için kokmuş bir yol, ama evet. Ve yine, goto zararlı olarak kabul edildi. (Ve istisnai durumlar dışında istisnalar kullanarak da tartışacağım). Unutmayın, ne geçerli ne de istisnalar sağlayan ve gayet iyi çalışan, tamamen geçerli ve çok güçlü diller var.
Shayne

19

Diğerlerinin sayısız şekilde belirttiği gibi ( örneğin, bu Yığın Taşması sorusunda ), en az şaşkınlık ilkesi, yalnızca kontrol akışı amacıyla aşırı istisnalar kullanmanıza izin vermeyecektir. Öte yandan, hiçbir kural% 100 doğru değildir ve her zaman bir istisnanın "sadece doğru araç" olduğu durumlar da vardır - gotobu arada, kendisi gibi, Java biçiminde breakve continueJava gibi dillerde gönderilenler genellikle kaçınılması mümkün olmayan, ağır şekilde yuvalanmış ilmeklerden atlamak için mükemmel bir yoldur.

Aşağıdaki blog yazısı, yerel olmayanlar için oldukça karmaşık ama aynı zamanda oldukça ilginç bir kullanım durumunu açıklıyor ControlFlowException:

Bu nasıl iç açıklar jOOQ (Java için SQL soyutlama kitaplığı) (uyarı: Ben satıcı için çalışmak), bu tür istisnalar bazen bazı "nadir" koşul karşılandığında erken SQL render işlemini iptal etmek için kullanılır.

Bu gibi koşullara örnekler:

  • Çok fazla bağlama değeriyle karşılaşıldı. Bazı veritabanları, SQL deyimlerinde rastgele sayıda bağlama değerini desteklemez (SQLite: 999, Ingres 10.1.0: 1024, Sybase ASE 15.5: 2000, SQL Server 2008: 2100). Bu durumlarda, jOOQ, SQL oluşturma aşamasını iptal eder ve SQL ifadesini satır içi bağlama değerleriyle yeniden işler. Örnek:

    // Pseudo-code attaching a "handler" that will
    // abort query rendering once the maximum number
    // of bind values was exceeded:
    context.attachBindValueCounter();
    String sql;
    try {
    
      // In most cases, this will succeed:
      sql = query.render();
    }
    catch (ReRenderWithInlinedVariables e) {
      sql = query.renderWithInlinedBindValues();
    }

    Her seferinde saymak için AST sorgusunun bağlanma değerlerini açıkça çıkarırsak, bu sorundan muzdarip sorguların% 99.9'u için değerli CPU çevrimlerini boşa harcarız.

  • Bazı mantık, yalnızca "kısmen" yürütmek istediğimiz bir API üzerinden dolaylı olarak kullanılabilir. Bu UpdatableRecord.store()yöntem , 'iç bayraklarına bağlı olarak bir INSERTveya UPDATEifadesi üretir Record. "Dışardan" ne tür bir mantık içerdiğini bilmiyoruz store()(örneğin, iyimser kilitleme, olay dinleyicisi kullanımı, vb.), Bu nedenle bir toplu iş ifadesinde birkaç kayıt sakladığımızda bu mantığı tekrarlamak istemiyoruz, Burada store()sadece SQL deyimini oluşturmak istedik , aslında onu değil. Örnek:

    // Pseudo-code attaching a "handler" that will
    // prevent query execution and throw exceptions
    // instead:
    context.attachQueryCollector();
    
    // Collect the SQL for every store operation
    for (int i = 0; i < records.length; i++) {
      try {
        records[i].store();
      }
    
      // The attached handler will result in this
      // exception being thrown rather than actually
      // storing records to the database
      catch (QueryCollectorException e) {
    
        // The exception is thrown after the rendered
        // SQL statement is available
        queries.add(e.query());                
      }
    }

    Biz dışlanmışken olsaydı store()isteğe şekilde özelleştirilebilir "Çok kullanımlık" API içine mantığı değil SQL çalıştırmak, neredeyse yeniden kullanılabilir, bakımı oldukça zor API oluşturma içine bakıyor olurduk.

Sonuç

Temelde, bu yerel olmayanları kullanmamız goto, sadece Wheeler’nın cevabında söylediklerinin sınırlarında:

“Bu noktada tam olarak üstesinden gelemediğim bir durumla karşılaştım, çünkü başa çıkacak yeterli bağlamım yok, ama beni (ya da çağrı yığınının yukarısındaki bir şey) olarak adlandıran rutin bunun nasıl başa çıkacağını bilmeli ."

Her iki kullanımının ControlFlowExceptionsda alternatiflerine göre uygulanması oldukça kolaydı, bu da geniş bir mantığın tekrar kullanılmasına gerek kalmadan ilgili içsellerin dışına çıkarılmamızı sağladı.

Ancak bunun gelecekteki bakımcılar için biraz sürpriz olduğu hissi devam ediyor. Kod oldukça hassas hissediyor ve bu durumda doğru seçim olsa da, sıradan dallanma kullanmaktan kaçınmanın kolay olduğu yerel kontrol akışı için istisnalar kullanmamayı her zaman tercih ederiz if - else.


11

Kontrol akışı için istisnaların kullanılması genellikle bir anti-desen olarak kabul edilir, ancak istisnalar da vardır (punto amaçlanmamıştır).

İstisnaların istisnai durumlar için kullanıldığı binlerce kez söylenmiştir. Kırık bir veritabanı bağlantısı olan olağanüstü bir durumdur. Bir giriş alanına yalnızca rakamlara izin vermesi gereken harfleri giren bir kullanıcı değildir .

Bir işlevi neden senin yazılımındaki bir hata, örneğin yasadışı argümanlarla çağrılacak nulldeğil, izin verir nerede olduğunu istisnai bir durumdur.

İstisnai olmayan bir şey için istisnalar kullanarak, çözmeye çalıştığınız sorun için uygun olmayan soyutlamaları kullanıyorsunuzdur.

Ancak performans cezası da olabilir. Bazı dillerde az ya da çok etkili istisna işleme uygulaması vardır, bu nedenle tercih ettiğiniz dil etkin istisna işleme sahip değilse, performans açısından çok maliyetli olabilir *.

Ancak diğer dillerde, örneğin Ruby, kontrol akışı için istisna benzeri bir sözdizimine sahiptir. İstisnai durumlar raise/ rescueoperatörler tarafından ele alınmaktadır . Ancak istisna benzeri kontrol akış yapıları için throw/ kullanabilirsiniz catch.

Bu nedenle, istisnalar genel olarak kontrol akışı için kullanılmamasına rağmen , tercih ettiğiniz dilin başka deyimleri olabilir.

* İstisnai olarak pahalı bir performans kullanımı örneği: Kötü performans gösteren bir ASP.NET Web Form uygulamasını optimize etmek üzere ayarlanmış bir kez. Büyük bir masanın renderlenmesinin int.Parse()yakl. ortalama bir sayfada bin boş dizge, sonuçta yaklaşık. Bin istisnalar ele alınıyor. Kodu değiştirerek int.TryParse()bir saniye tıraş oldum! Her sayfa talebi için!

** Bu, her iki gibi diğer dillerden Ruby gelen bir programcı için çok kafa karıştırıcı olabilir throwve catchdiğer birçok dilde istisnalar ile ilişkili anahtar kelimelerdir.


1
+1 "İstisnai olmayan bir şey için istisnalar kullanarak, çözmeye çalıştığınız sorun için uygun olmayan soyutlamalar kullanıyorsunuz."
Giorgio

8

İstisnalar kullanılmadan hata koşullarının üstesinden gelmek tamamen mümkündür. En önemlisi C olan bazı dillerin bile istisnaları yoktur ve insanlar hala onunla oldukça karmaşık uygulamalar oluşturmayı başarırlar. İstisnaların faydalı olmasının nedeni, aynı kodda temelde bağımsız iki kontrol akışını kesin olarak belirlemenizi sağlar: biri bir hata oluşursa ve diğeri olmazsa. Onlar olmadan, şuna benzeyen her yere kod girersiniz:

status = getValue(&inout);
if (status < 0)
{
    logError("message");
    return status;
}

doSomething(*inout);

Veya kendi dilinizde eş değer, örneğin bir hata durumu olarak bir değere sahip bir tuple döndürmek ifgibi İstisnaları kullanmayın.

Bu desen en çok hataları veya diğer "istisnai koşulları" ele alırken ortaya çıksa da, bence başka durumlarda bu gibi bir boyler kodunu görmeye başlarsanız, istisnaları kullanmak için oldukça iyi bir tartışmanız var. Duruma ve uygulamaya bağlı olarak, bir durum makinesinde geçerli olan istisnaları görebiliyorum, çünkü iki ortogonal kontrol akışınız var: biri durumu değiştiren ve biri eyalet içinde meydana gelen olaylar için.

Bununla birlikte, bu durumlar nadirdir ve kuralın istisnasını (amaçlanan şekilde) yapacaksanız, üstünlüğünü diğer çözümlere göstermek için daha iyi hazır olmalısınız. Bu gerekçesiz bir sapmaya haklı olarak anti-patern denir.


2
İfadeler sadece “istisnai” durumlarda başarısız olduğu sürece, modern CPU'ların şube tahmin mantığı maliyetlerini ihmal edilebilir kılmaktadır. Bu, dikkatli olduğunuz ve içinde çok fazla şey yapmaya çalışmadığınız sürece, makroların gerçekten yardımcı olabileceği bir yerdir.
James

5

Python'da, özel durumlar üreteç ve yineleme sonlandırma için kullanılır. Python'un blokları hariç / denemek için çok verimli denemesi var, fakat aslında bir istisna yaratmanın bazı ek yükü var.

Python'da çok seviyeli kırılmalar ya da çoktan açık bir ifade olmamasından dolayı bazen istisnalar kullandım:

class GOTO(Exception):
  pass

try:
  # Do lots of stuff
  # in here with multiple exit points
  # each exit point does a "raise GOTO()"
except GOTO:
  pass
except Exception as e:
  #display error

6
Bir derin iç içe açıklamada yere hesaplama sonlandırmak ve bazı ortak devamı koduna gitmek varsa, yürütmenin bu özel yolu çok muhtemelen ile bir fonksiyonu olarak dışarı edilebildiğini returnyerine goto.
9000,

3
@ 9000 Aynı şeyi yorumlamak üzereydim ... try:Lütfen blokları 1 ya da 2 satırda tutun , asla try: # Do lots of stuff.
wim

1
9000'de, bazı durumlarda, elbette. Fakat daha sonra yerel değişkenlere erişiminizi kaybedersiniz ve işlem tutarlı, doğrusal bir işlem olduğunda, kodunuzu başka bir yere taşırsınız.
gahooa

4
@gahooa: Senin gibi düşünürdüm. Kodumun zayıf bir yapısının işareti oldu. İçinde daha çok düşündüğümde, yerel bağlamların birbirine karışmadığını ve bütün karışıklığın birkaç fonksiyon, birkaç kod satırı ve çok net bir anlamla kısa fonksiyonlara girebileceğini fark ettim. Asla arkama bakmadım.
9000,

4

Böyle bir İstisna kullanımı taslağını çizelim:

Algoritma bir şey bulunana kadar tekrarlı olarak arama yapar. Bu nedenle, özyinelemeden geri dönmenin sonucun bulunup bulunmadığını kontrol etmesi ve geri dönmesi gerekir, aksi takdirde devam edin. Ve bu tekrar tekrar bazı özyineleme derinliklerinden geri geliyor.

Fazladan bir boole ihtiyaç duymanın yanı sıra found(aksi takdirde sadece int'nin geri verilebileceği bir sınıfta paketlenecek) ve özyineleme derinliği için aynı postlude olur.

Bir çağrı yığınının böyle bir gevşetilmesi, bunun istisnasının tam olarak nedenidir. Bu yüzden bana benzeyen, daha acil ve uygun bir kodlama aracı gibi görünüyor. Gerek yok, nadir kullanım, belki kötü stil, ama noktaya. Prolog kesim işlemi ile karşılaştırılabilir.


Hmm, tam tersi pozisyon için mi yoksa yetersiz mi, kısa tartışma mı? Ben gerçekten merak ediyorum.
Joop Eggen

Tam olarak bu çıkmazla karşı karşıyayım, sonraki sorum hakkında ne düşündüğünüzü görebileceğinizi umuyordum? Yinelemeli bir üst düzey istisna nedenini (mesaj) birikmeye istisnaları kullanılarak codereview.stackexchange.com/questions/107862/...
CL22

@Jodes Yeni ilginç tekniğinizi okudum, ancak şimdilik oldukça meşgulüm. Umarım bir başkası konuyla ilgili ışığını tutacaktır.
Joop Eggen

4

Programlama işle ilgili

Buna cevap vermenin en kolay yolunun, OOP'un yıllar içindeki ilerlemesini anlamak olduğunu düşünüyorum. OOP'de yapılan her şey (ve bu konuda çoğu programlama paradigması) yapılan işe ihtiyaç duyulması üzerine modellenmiştir .

Her ne zaman bir yöntem çağrılırsa, arayan kişi “Bu işi nasıl yapacağımı bilmiyorum ama nasıl yapacağını biliyorsun, bu yüzden benim için yapıyorsun” diyor.

Bu bir zorluk sundu: çağrılan yöntem genellikle işin nasıl yapıldığını bildiğinde ne olur? Biz iletişim kurmak için bir yol gerekli "Sana yardım etmek istedim, gerçekten yaptım, ama sadece bunu yapamam."

Bunu iletmenin erken bir metodolojisi basitçe bir "çöp" değeri vermekti. Belki olumlu bir tamsayı bekliyorsunuz, bu nedenle çağrılan yöntem negatif bir sayı döndürüyor. Bunu başarmanın başka bir yolu, bir yerde bir hata değeri ayarlamaktı. Ne yazık ki, her iki yol da kazan plakasında, her şeyin şifresiz kodunu kontrol etmeme izin verdi . İşler daha karmaşık hale geldikçe, bu sistem dağılıyor.

Olağanüstü Bir Analoji

Diyelim ki bir marangoz, tesisatçı ve elektrikçiniz var. Lavabonuzu tamir etmek için tesisatçı olmak istiyorsunuz, o da ona bir göz attı. Yalnızca size, "Üzgünüm, düzeltemem. Bozuldu." Demesi yararlı olmaz. Cehennem, bakması, ayrılması ve düzeltemeyeceğini söyleyen bir mektup göndermesi daha da kötü. Şimdi istediğini yapmadığını bile bilmeden önce postanı kontrol etmelisin.

Tercih edeceğiniz şey, “Bak, tamir edemedim çünkü pompanız çalışmıyor gibi görünüyor” demesini sağlamak.

Bu bilgilerle, elektrik teknisyeninin soruna bakmasını istediğiniz sonucuna varabilirsiniz. Belki elektrikçi marangoz ile ilgili bir şeyler bulacaktır ve marangozun tamir etmesini sağlamalısınız.

Heck, bir elektrikçiye ihtiyacınız olduğunu bile bilmiyor olabilirsiniz, kime ihtiyacınız olduğunu bilmiyor olabilirsiniz . Bir ev tamir işinde sadece orta düzey bir yöneticisiniz ve odak noktalarınız sıhhi tesisat. Yani size sorun hakkında ediyoruz patronuna söyle, sonra o bunu düzeltmek için elektrikçi söyler.

İstisnaların modellendiği şey budur: ayrık bir tarzda karmaşık arıza modları. Tesisatçının elektrik teknisyeni hakkında bir bilgisi olması gerekmez - zincirdeki birisinin sorunu çözebileceğini bile bilmesi gerekmez. Sadece karşılaştığı sorunu bildirir.

Yani ... bir anti-pattern?

Ok, bu nedenle anlayış noktası istisnalar ilk adımdır. Bir sonraki anti-paternin ne olduğunu anlamaktır.

Bir anti-kalıp olarak nitelenmek için,

  • problemi çöz
  • kesin olumsuz sonuçları var

İlk nokta kolayca karşılanır - sistem çalıştı, değil mi?

İkinci nokta stickier. İstisnaları normal kontrol akışı olarak kullanmanın birincil nedeni kötü, çünkü amaçları değil. Bir programdaki herhangi bir işlevsellik parçasının göreceli olarak net bir amacı olmalı ve bu amaç için işbirliği yapılması gereksiz kafa karışıklığına yol açmalıdır.

Ama bu kesin bir zarar değil . İşleri yapmak için kötü bir yol ve garip, ama bir anti-patern? Hayır. Sadece ... garip.


En azından tam yığın izi sağlayan dillerde kötü bir sonuç var. Kod, çok fazla satır içi ile yoğun şekilde optimize edildiğinden, gerçek yığın izi ve geliştiricinin çok fazla farketmek istediği, dolayısıyla yığın izi oluşturma masraflıdır. Aşırı kullanım istisnaları, bu tür dillerde (Java, C #) performans için çok kötü.
maaartinus

“İşleri yapmak için kötü bir yol” - Bunu bir kalıp karşıtı model olarak sınıflandırmak yeterli olmaz mı?
Maybe_Factor

@ Maybe_Factor Bir karınca modelinin tanımı başına, hayır.
MirroredFate
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.