İki Java 8 varsayılan yöntemini birbirleri açısından uygulamak iyi bir uygulama mudur?


14

Buna benzer iki yöntemle bir arayüz tasarlıyorum:

public interface ThingComputer {
    default Thing computeFirstThing() {
        return computeAllThings().get(0);
    }

    default List<Thing> computeAllThings() {
        return ImmutableList.of(computeFirstThing());
    }
}

Uygulamaların yaklaşık yarısı sadece bir şeyi hesaplarken, diğer yarısı daha fazla hesaplayabilir.

Bunun yaygın olarak kullanılan Java 8 kodunda emsali var mı? Haskell'in bazı tip sınıflarda benzer şeyler yaptığını biliyorum ( Eqörneğin).

Ters iki soyut sınıf ( SingleThingComputerve MultipleThingComputer) vardı daha önemli ölçüde daha az kod yazmak zorunda olmasıdır .

Dezavantajı, boş bir uygulamanın derleme yapması, ancak çalışma zamanında a StackOverflowError. Karşılıklı özyinelemeyi bir ile tespit etmek ThreadLocalve daha güzel bir hata vermek mümkündür , ancak bu, buggy olmayan koda yük ekler.


3
Neden hiç kasten sonsuz özyineleme garantisi verilmiş bir kod yazasınız ki? Bundan iyi bir şey gelemez.

1
Peki "garantili" değildir; uygun bir uygulama bu yöntemlerden birini geçersiz kılar.
Tavian Barnes

6
Bunu bilmiyorsun. Bir sınıfın veya arayüzün kendi başına durması ve bir alt sınıfın büyük mantık hatalarından kaçınmak için belirli bir yol yapacağını varsaymaması gerekir. Aksi takdirde, kırılgandır ve garantilerine kadar yaşayamaz. Arayüzünüzün uygulayıcı bir sınıf throw new Error();veya aptalca bir şey yapabileceğini veya uygulayabileceğini söylemiyorum , sadece arayüzün kendisinindefault yöntemlerle kırılgan bir sözleşmesi olmamalıdır .

@Snowman'a katılıyorum, bu bir kara mayını. Onun 'için ders kitabı Jon Skeet araçlar anlamında "şeytan kodu" düşünmek - kötülük olarak aynı olmadığını not bad , bu kötü değil / zeki / gelen iştah açıcı, ama hala yanlış :) tavsiye youtu.be/lGbQiguuUGc?t=15m26s ( ya da gerçekten, daha geniş bir bağlam için konuşmanın tamamı - çok ilginç).
Konrad Morawski

1
Her fonksiyon diğer cinsinden tanımlanabilir diye gelmez değil ikisi de birbirlerinin cinsinden tanımlanabilir ima. Bu herhangi bir dilde uçmuyor. 2 soyut mirasçıdan oluşan bir arayüz istiyorsanız, her biri diğerini birbirinden uygular, ancak diğerini soyutlar, böylece uygulayıcılar doğru soyut sınıftan miras alarak uygulamak istedikleri tarafı seçerler. Bir taraf diğerinden bağımsız olarak tanımlanmalıdır, aksi takdirde pop yığına gider . Uygulayıcıların sorunu sizin için çözeceğini varsayarak çılgın varsayılanlarınız abstractvar, onları çözmeye zorlamak için var .
Jimmy Hoffa

Yanıtlar:


16

TL; DR: bunu yapma.

Burada gösterdiğiniz şey kırılgan kod.

Arayüz bir sözleşmedir. "Hangi nesneyi alırsanız alın X ve Y'yi yapabilir" diyor. Yazıldığı gibi, arabiriminiz ne X ne de Y yapmaz, çünkü yığın taşmasına neden olacağı garanti edilir.

Bir Hata veya alt sınıfı atmak, yakalanmaması gereken ciddi bir hatayı gösterir:

Hata, makul bir uygulamanın yakalamaya çalışmaması gereken ciddi sorunları gösteren Throwable'ın bir alt sınıfıdır.

Ayrıca, StackOverflowError öğesinin üst sınıfı olan VirtualMachineError şunları söylüyor:

Java Sanal Makinesinin bozulduğunu veya çalışmaya devam edebilmesi için gerekli kaynakların tükendiğini belirtmek için atılır.

Programınız JVM kaynakları ile ilgilenmemelidir . JVM'nin işi budur. Normal çalışmanın bir parçası olarak JVM hatasına neden olan bir program yapmak kötüdür. Programınızın çökmesini garanti eder veya bu arabirimin kullanıcılarını, ilgilenmemesi gereken hataları yakalamaya zorlar.


Eric Lippert'i "C # dil tasarım komitesinin üyesi" emeritus gibi çabalardan tanıyabilirsiniz . İnsanları başarıya veya başarısızlığa iten dil özelliklerinden bahsediyor: bu bir dil özelliği veya dil tasarımının bir parçası olmasa da, arayüzleri uygulamak veya nesneleri kullanmak söz konusu olduğunda aynı derecede geçerli.

Westley uyandığında ve kendini çaresiz bir albino ve uğursuz altı parmaklı Kont Rugen ile Çaresizlik Çukuru'nda kilitli bulduğunda Prenses Gelin'i hatırlıyor musun? Çaresizlik çukurunun temel fikri iki yönlüdür. Birincisi, bir çukur ve bu yüzden içine düşmek kolay ama tırmanmak zor bir iş. İkincisi, umutsuzluğa neden oluyor. Dolayısıyla adı.

Kaynak: C ++ ve Umutsuzluk Çukuru

Bir arayüzün StackOverflowErrorvarsayılan olarak atanması, geliştiricileri Çaresizlik Çukuru'na iter ve kötü bir fikirdir . Bunun yerine, geliştiricileri Başarı Çukuruna doğru itin . O Make kolay ve doğru JVM çökmesini olmadan arayüzü kullanmak.

Burada yöntemler arasında yetki vermek iyidir. Ancak, bağımlılık bir yoldan gitmelidir. Yöntem delegasyonunu yönlendirilmiş bir grafik gibi düşünmeyi seviyorum . Her yöntem grafikteki bir düğümdür. Bir yöntem başka bir yöntemi her çağırdığında, çağıran yöntemden çağrılan yönteme bir kenar çizin.

Bir grafik çizip döngüsel olduğunu fark ederseniz, bu bir kod kokusudur. Bu, geliştiricileri Çaresizlik Çukuru'na itme potansiyeli. Kategorik olarak yasaklanmaması gerektiğini, yalnızca kişinin dikkatli olması gerektiğini unutmayın . Özyinelemeli algoritmaların çağrı grafiğinde döngüleri olacaktır: bu iyi. Belgeleyin ve geliştiricileri uyarın. Özyinelemeli değilse, bu döngüyü kırmayı deneyin. Yapamıyorsanız, hangi girdilerin yığın taşmasına neden olabileceğini bulun ve bunları azaltın ya da başka bir şey işe yaramazsa son durum olarak belgeleyin.


Mükemmel cevap. Bunun neden Haskell'de bu kadar yaygın bir uygulama olduğunu merak ediyorum. Farklı geliştirici kültürler sanırım.
Tavian Barnes

Haskell'de tecrübeli değilim ve bunun fonksiyonel programlamada daha yaygın olup olmadığı hakkında konuşamam.

Biraz daha bakıldığında, Haskell topluluğu da bundan memnun değil gibi görünüyor. Ayrıca derleyici yakın zamanda "asgari tam tanımları" kontrol etmeyi öğrendi, böylece boş bir uygulama en azından bir uyarı üretecektir.
Tavian Barnes

1
Çoğu işlevsel programlama dili kuyruk çağrısı optimizasyonuna sahiptir. Bu optimizasyon ile kuyruk özyineleme yığını vurmaz, bu nedenle bu tür uygulamalar mantıklıdır.
Jason Yeo
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.