Bir sınıfta kaç tane arayüz var? [kapalı]


28

Muhtemelen 23 arayüz uygulayan bir sınıfa sahip olmak için bir kod kokusu veya hatta bir anti-patern olduğunu düşünürdüm. Gerçekten bir anti-kalıp ise, ona ne derdiniz? Yoksa sadece Tek sorumluluk ilkesini izlemiyor mu?


3
Her iki şekilde de sorgulanabilir. Sınıfın hepsinin tek bir sorumluluk üstlendiği 23 yöntemi varsa (tüm sınıfların çok fazla yönteme ihtiyacı yoktur, ancak bu imkansız değildir - özellikle diğer yöntemlerin etrafında üç satırlık uygunluk sarmalayıcıları varsa), sadece çok ince taneli arayüzlere sahipsiniz; )

Söz konusu sınıf bir tür varlıktır ve arayüzler çoğunlukla özelliklere yöneliktir. Bunlardan 113'ü ve sadece dört metodu var.
Jonas Elfström

6
Arayüzlerin temelde statik olarak derlenmiş dillerde ördek yazmak için kullanıldığını düşündüm. Sorun ne? :)
ashes999

2
sadece bir soru: 113 varlığın hepsi bu varlığın her bir örneği için doldurulmuş mu? Yoksa sadece bazı özellikleri dolu olan, farklı bağlamlarda kullanılan bir tür "ortak varlık" mı?
David,

1
Neyin "bir sınıf" teşkil ettiği hakkındaki kavramsal anlayışa geri dönelim. Bir sınıf açıkça tanımlanmış sorumluluk ve rolü olan tek bir şeydir. 23 arabirim nesnenizi bu şekilde tanımlayabilir misiniz? Sınıfınızı yeterince özetleyen tek bir (Joycean olmayan) cümle gönderebilir misiniz? Eğer öyleyse, o zaman 23 arayüz iyi. Olmazsa, o zaman çok büyük, çok karmaşık.
Stephen Gross

Yanıtlar:



23

Bu anti-paternin Tüm İşlemler Jack'i veya belki de Çok Fazla Şapka adını verdim.


2
İsviçre Çakısı nasıl?
SinirliFormsDesigner'la

Görünüşe göre bu terim zaten çok fazla sayıda yönteme sahip arayüzler için kullanılıyor .
Jalayn

1
@FrustratedWithFormsDesigner İsviçreli bir Ordu Bıçağı, 20'den önce yeni değiştirici anahtar sözcüğünden önce gelen 30 özellik içeren IValue adlı bir arayüze sahip olmaktan asla kötü bir zevk alamaz.
Jonas Elfström

3
Pek çok şapka için +1 ... çok kafalı tanrıları
Newtopian

1
Bir İsviçre çakısı yeniden kullanma modelidir. yani, tek bir "bıçak" başarabilir, bu yüzden muhtemelen kötü bir benzetme olabilir!
James Anderson

17

Eğer bir isim vermek zorundaysam, Hydra diyebilirim :

hidra

Yunan mitolojisinde, Lernaean Hydra (Yunanca: Ὕδρναία Ὕδρα) sürüngen özellikleri olan eski bir isimsiz yılan gibi chthonic su canavarıydı; boya ve her kafa kesti için iki tane daha büyüdü - ve zehirli bir nefes aldı ki izleri bile ölümcül oldu.

Özellikle alaka düzeyi, sadece birçok kafaya sahip olması değil, aynı zamanda daha fazla büyümeye devam etmesi ve bu yüzden öldürmesi imkansız olması gerçeğidir. Bu tür tasarımlarla olan deneyimim buydu; geliştiriciler, ekrana sığmayacak kadar çok daha fazla arayüzü sık sık tutmaya devam ediyor ve o zamana kadar programın tasarımında ve onu bölmenin umutsuz bir umut olduğu varsayımlarına çok derinlemesine girmeye başladı (denerseniz, aslında genellikle boşluğu kapatmak için daha fazla ara yüze ihtiyaç duyarız).

Bir "Hydra" nedeniyle yaklaşmakta olan kıyametin erken bir işareti, bir arayüzün diğerine, fazla akıl kontrolü olmadan ve çoğu zaman, aşağıdaki gibi olduğu gibi mantıklı olmayan bir hedefe sık sık dökülmesidir:

public void CreateWidget(IPartLocator locator, int widgetTypeId)
{
    var partsNeeded = locator.GetPartsForWidget(widgetTypeId);
    return ((IAssembler)locator).BuildWidget(partsNeeded);
}

Bağlamdan çıkarıldığında, bu kodla ilgili balık içeren bir şey olduğu açıktır, ancak bunun gerçekleşmesi olasılığı, bir nesnenin büyüdüğü "kafalarla" artar, çünkü geliştiriciler sezgisel olarak her zaman aynı yaratıkla ilgilendiklerini bilirler .

İyi şanslar hiç bir nesne olduğunu uygular 23 arayüzleri üzerinde herhangi bir bakım yapıyor. Sürecinde teminatın zarar görmemesi ihtimali hiç de zayıf.


16

Tanrı Nesne akla gelen; HER ŞEYİ nasıl yapacağını bilen tek bir nesne. Bu, iki ana tasarım metodolojisinin "uyum" gereksinimlerine düşük bağlılıktan gelir; 23 arayüzlü bir nesneye sahipseniz, kullanıcılarına nasıl 23 farklı şey olduğunu bilen bir nesneye sahipsiniz ve bu 23 farklı şey muhtemelen sistemin tek bir görev veya alanı boyunca değil.

SOLID'de, bu nesnenin yaratıcısı açıkça Arayüz Ayrıştırma İlkesini izlemeye çalışmış olsa da, önceki bir kuralı ihlal etmişlerdir; Tek Sorumluluk İlkesi. Bunun "KATI" olmasının bir nedeni var; Tasarım hakkında düşünürken her zaman önce S gelir ve diğer tüm kurallar takip eder.

GRASP'da, böyle bir sınıfın yaratıcısı "Yüksek Uyum" kuralını ihmal etmiştir; GRASP, SOLID'den farklı olarak, bir nesnenin tek bir sorumluluğu bulunmadığını öğretir, ancak en fazla iki ya da üç çok yakın ilişkili sorumluluğu olması gerekir.


Bunun Tanrı Nesnesi anti-patern olduğundan emin değilim, çünkü Tanrı hiçbir arayüz tarafından kısıtlanmamıştır. Bu kadar çok arayüz tarafından sınırlandırılmış olmak, Tanrı'nın sahip olma yeteneğini azaltabilir. ;) Belki bu bir Chimera nesnesidir?
SinirliFormsDesigner'la

Tanrı'nın birçok yüzü var ve birçok insan için birçok şey olabilir. Birleştirilmiş arayüzlerin işlevselliği nesneyi "her şeyi bilen" yaparsa, bu gerçekten Tanrı'yı ​​sınırlayıcı değildir, değil mi?
KeithS

1
Arayüzleri yaratanı değiştirmediyse, onları değiştirir. Öyleyse, arayüz değişikliklerine uyması için Tanrı'nın yeniden düzenlenmesi gerekebilir.
SinirliWeFormsDesigner

3
Sınıfı yaratan benim olduğumu düşünmeniz acı veriyor.
Jonas Elfström

"Siz" i kullanmak, daha çok çoğul, dev ekibinize atıfta bulunuyorsunuz. Bu ekipten bazıları, geçmiş veya şimdiki, bu sınıfı yarattı. Yine de düzenleyeceğim.
Keith

8

23 Sadece bir sayı! Büyük olasılıkla senaryoda, alarm verecek kadar yüksektir. Bununla birlikte, sorarsak, bir "kalıp karşıtı" olarak adlandırılan bir etiketi almadan önce en fazla sayıda yöntem / arayüz nedir? 5 ya da 10 ya da 25 mi? Bu sayının gerçekten bir cevap olmadığını fark edersiniz, çünkü 10 iyiyse, 11 de olabilir - ve bundan sonra herhangi bir tamsayı.

Asıl soru karmaşıklıkla ilgilidir. Ve uzun kodun, metot sayısının veya herhangi bir önlemle sınıfın büyüklüğünün aslında karmaşıklığın tanımı OLMADIĞINI belirtmeliyiz . Evet, daha büyük ve daha büyük kod (daha fazla sayıda yöntem) yeni bir acemi için okumayı ve kavramayı zorlaştırır . Ayrıca, potansiyel olarak çeşitli işlevsellik, çok sayıda istisna ve çeşitli senaryolar için oldukça gelişmiş algoritmalar da kullanmaktadır. Bu karmaşık olduğu anlamına gelmez - sadece sindirimi zordur.

Diğer taraftan, birkaç saat içinde okumayı ümit edebileceğiniz nispeten küçük boyutlu kod hala karmaşık olabilir. İşte kodun (gereksiz yere) karmaşık olduğunu düşünüyorum.

Nesne yönelimli tasarımın her bir bilgeliği buraya "karmaşık" tanımlamak için yerleştirilebilir, ancak burada "çok sayıda yöntemin" karmaşıklığın bir göstergesi olduğunu göstermek için kısıtlardım.

  1. Karşılıklı Bilgi (aka eşleştirme) Her şey bir şeyler sınıf olarak yazıldığında, hepimizin "güzel" nesne yönelimli kod olduğunu düşünüyoruz. Ancak, diğer sınıfla ilgili varsayım, esasen gerçek ihtiyaç duyulan kapsüllemeyi bozuyor. Algoritmaların iç durumu hakkında derinlemesine "sızdıran" metotlara sahip olduğunuzda - ve uygulama, hizmet veren sınıfın içsel durumu ile ilgili temel varsayımlarla inşa edilir.

  2. Çok fazla yineleme (zorla girme) Benzer adlara sahip, ancak işle çelişen veya benzer işlevli isimlerle çelişen yöntemler olduğunda. Çoğu zaman kodlar, farklı uygulamalar için biraz farklı arayüzleri desteklemek üzere gelişir.

  3. Çok fazla rol Sınıf, yan işlevler eklemeye devam ettiğinde ve onun gibi insanlar kadar genişlemeye devam ettiğinde, yalnızca sınıfın gerçekten de iki sınıf olduğunu bilmek. Şaşırtıcı bir şekilde, bunların hepsi gerçek ile başlargereksinimleri ve bunu yapmak için başka bir sınıf yok. Bunu düşünün, işlemin ayrıntılarını anlatan bir İşlem sınıfı vardır. Şimdiye kadar iyi görünüyor, şimdi birileri "işlem zamanında" (UTC ve benzerleri arasında) format dönüşümüne ihtiyaç duyuyor, daha sonra insanlar bazı işlemlerin geçersiz kılmak için belirli tarihlerde olup olmadığını kontrol etmek için kurallar ekliyor. - Tüm hikayeyi yazmayacağım ama sonunda, işlem sınıfı içinde tüm takvimi oluşturuyor ve ardından insanlar "sadece takvim" bölümünü kullanmaya başlıyor! Bu çok karmaşık (hayal etmek için) neden bir "takvim" in bana sağlayacağı bir işlevselliğe sahip olmak için "işlem sınıfı" nı başlatacağım!

  4. (In) API tutarlılığı book_a_ticket () yaptığımda - Bir bilet tutarım! Bu, gerçekleşmesi için kaç tane kontrol ve işlem yapıldığına bakılmaksızın, çok basit. Şimdi zaman akışı bunu etkilemeye başladığında karmaşık bir hal alıyor. Tipik bir, ve olası mevcut / kullanılamaz durum "arama" sonra tekrar-n-ileri bir sonra bilet içindeki bazı bağlam işaretçileri kaydetmeye başlar azaltmasına olanak sağlayacak başvurmak bilet kitaba söyledi. Ara tek işlevsellik değildir; bu tür birçok "yan işlevsellik" den sonra işler daha da kötüye gider. Bu süreçte book_a_ticket () anlamı book_that_ticket () anlamına gelir! ve bu düşünülemez derecede karmaşık olabilir.

Muhtemelen, çok gelişmiş bir kodda göreceğiniz birçok durum vardır ve pek çok kişinin senaryolar ekleyebileceğinden eminim, "çok fazla yöntem" in mantıklı gelmediği veya açıkça düşündüğünüzü yapmadığı durumlar. Bu anti-kalıptır.

Benim kişisel deneyimim, oldukça aşağıdan yukarıya doğru başlayan projeler başladığında , gömülü veya daha kötülerinde gerçek sınıflar olması gereken birçok şeyin farklı sınıflar ve eşleşme artışları arasında hala bölünmüş kalmasıdır. Çoğu zaman 10 sınıfı hakedecek olan, ancak sadece 4 olan, birçoğunun çok amaçlı kafa karıştırıcı ve çok sayıda metoda sahip olması muhtemeldir. Bir TANRI ve DRAGON olarak adlandırın, BAD budur.

AMA özenle tutarlı ÇOK BÜYÜK sınıflarına rastlıyorsunuz, 30 yöntemleri var - ve hala çok temiz. İyi olabilirler.


Sorulardaki sınıfın 23 arayüzü vardır ve bunların hepsi 113 kamu mülkü ve dört metodu içerir. Sadece bazıları salt okunur. C # otomatik olarak uygulanan özelliklere sahip, bu yüzden yöntemler ve özellikler arasında fark var msdn.microsoft.com/en-us/library/bb384054.aspx
Jonas Elfström

7

Sınıflar tam olarak doğru sayıda arayüze sahip olmalıdır; ne fazla ne az.

"Çok fazla" demek, bu arayüzlerin hepsinin o sınıfta yararlı bir amaca hizmet edip etmediğine bakmadan imkansız olurdu. Bir nesnenin bir arabirim uyguladığını bildirmek, sınıfın derlemesini beklerseniz, yöntemlerini uygulamanız gerektiği anlamına gelir. (Baktığınız sınıfı yapar sanırım.) Arayüzdeki her şey uygulanırsa ve bu uygulamalar sınıfın içindekilerine göre bir şey yaparsa, uygulamanın orada olmaması gerektiğini söylemek zor olacaktır. Bu kriterleri karşılayan bir ara yüzün nereye ait olamayacağını düşünebildiğim tek vaka dışsal: kimse kullanmadığında.

Bazı diller, Java'nın extendsanahtar kelimesi gibi bir mekanizma kullanarak arayüzlerin "alt sınıflara alınmasına" izin verir ve bunu kim yazdıysa, bunu bilmiyor olabilir. Aynı zamanda, 23'ün hepsinin, onları bir araya getirmenin bir anlamı olmadığından, yeterince uzak tutulması olabilir.


Bu sorunun güzel bir agnostik olduğunu düşündüm. Gerçek kod C # 'dadır.
Jonas Elfström

Herhangi bir C # yapmadım, ancak benzer bir arabirim devralma biçimini desteklediği görülüyor.
Blrfl

Evet, bir arayüz diğer arayüzleri "devralabilir" vb.
Jonas Elfström

Bunun birçok tartışmalar ne odaklanmak olduğunu ilginç bulmak sınıflar yerine olandan, yapmalıyım örneklerini yapmalıdır. Ortak bir şasiye bağlı çeşitli görüntüleme ve ses sensörlerine sahip bir robot, bir konum ve oryantasyona sahip, manzaraları ve sesleri görebilen, duyan ve ilişkilendirebilen bir varlık olarak modellenmelidir. Bu işlevlerin arkasındaki gerçek mantığın tümü diğer sınıflarda olabilir, ancak robotun kendisi "ileride bir nesne olup olmadığına bakın", "alandaki herhangi bir gürültüyü dinleyin" veya "öndeki nesnenin öyle olup olmadığını görün" gibi yöntemleri desteklemelidir. algılanan seslerin üretilmesi. "
supercat

Belirli bir robotun işlevselliğini alt sistemlere belirli bir yolla bölmesi gerektiği, ancak robotu kullanan pratik kodun belli bir robotun içindeki işlevselliğin nasıl bölündüğü hakkında bilgi sahibi olması veya bakımı gerektirmemesi gerekebilir. "Gözler" ve "kulaklar" dış dünyaya ayrı nesneler olarak maruz bırakıldıysa, ancak ilgili sensörler ortak bir uzatma kolundaysa dış kod, aynı zamanda yer seviyesindeki sesleri dinlemek için "kulaklardan" isteyebilir. “gözlerden” bir engelin üstünden bakmasını istedi.
supercat

1

Tipik bir "fasulye" için normal olduğu gibi her özellik için bir "alıcı" / "ayarlayıcı" çiftine sahip olduklarını düşündüğü gibi sesler ve tüm bu yöntemleri arabirime yükselttiler. Peki " fasulye " demeye ne dersin ? Veya çok fazla fasulyenin iyi bilinen etkilerinden sonra daha fazla Rabelaci "Yassılık".


C # dilinde ve Auto-Implemented Properties özelliğine sahip. Bu 23 arayüz, hepsinde, böyle 113 özellik içerir.
Jonas Elfström

1

Genel bir nesne farklı ortamlarda kullanıldığında, arabirimlerin sayısı genellikle artar. C # 'da IComparable değişkenleri, IEqualityComparer ve IComparer, farklı kurulumlarda sıralamaya izin verir, bu nedenle genel olarak güçlü olmayan sürümleri ve genel olmayan sürümleri uygulayabildiğinizden bazıları, bir kereden fazla olabilir. Ek olarak, jeneriklerden birden fazlasını uygulayabilirsiniz.

Örnek bir senaryo ele alalım, diyelim ki başka bir şey satın alabileceğiniz kredi alabileceğiniz bir web mağazası (stok fotoğraf siteleri genellikle bu şeması kullanır). Aynı temeli oluşturan bir "Valuta" ve "Kredi" sınıfına sahip olabilirsiniz. Valuta'da, "Para Birimi" özelliği hakkında endişelenmeden hesaplamalar yapmanıza izin veren bazı operatör aşırı yüklemeleri ve karşılaştırma rutinleri vardır (örneğin, dolarlara pound ekler). Krediler çok daha basittir ancak başka davranışları da vardır. Bunları birbirleriyle karşılaştırabilmek için, her ikisine de IComparable ve IComparable ve diğer karşılaştırma arayüzleri çeşitlerini uygulayabilirsiniz (temel sınıfta veya başka bir yerde olsa da ortak bir uygulama kullanıyor olsalar bile).

Serileştirme uygulanırken, ISerializable, IDeserializationCallback uygulanır. Sonra geri alma yığınlarını geri alma uygulaması: IClonable eklenir. IsDirty işlevselliği: IObservable, INotifyPropertyChanged. Kullanıcıların dizeleri kullanarak değerleri düzenlemelerine izin vermek: IConvertable ... Liste uzayıp gidebilir ...

Modern dillerde, bu yönleri ayırmaya ve onları kendi sınıflarına, çekirdek sınıfın dışına yerleştirmeye yardımcı olan farklı bir eğilim görüyoruz. Dış sınıf veya görünüş daha sonra açıklama (nitelikler) kullanılarak hedef sınıfla ilişkilendirilir. Çoğu zaman dış görünüş sınıflarını aşağı yukarı jenerik hale getirmek mümkündür.

Niteliklerin kullanımı (açıklama) yansımaya tabidir. Bir dezavantajı küçük (ilk) performans kaybı. (Genellikle duygusal) bir sakınca, kapsülleme gibi prensiplerin gevşetilmesi gerektiğidir.

Her zaman başka çözümler vardır, ancak her şık çözüm için bir takas veya bir tuzak vardır. Örneğin, bir ORM çözümü kullanmak tüm özelliklerin sanal olarak ilan edilmesini talep edebilir. Seri hale getirme çözümleri, sınıflarınızda varsayılan kurucuları talep edebilir. Bağımlılık enjeksiyonunu kullanıyorsanız, tek bir sınıfa 23 adet arayüz uygulayabilirsiniz.

Benim gözümde 23 arayüz tanım gereği kötü olmak zorunda değildir. Arkasında iyi düşünülmüş bir şema veya yansıma veya aşırı kapsülleme inançlarının kullanılmaması gibi bazı ilkeler belirlenebilir.

Ne zaman bir işi değiştirirseniz ya da mevcut bir mimariyi inşa etmek zorunda kalıyorsanız. Tavsiyem ilk önce tam olarak tanışmak, her şeyi çok hızlı bir şekilde yeniden denemeye çalışmayın. Orijinal geliştiriciyi dinleyin (hala oradaysa) ve gördüklerinizin arkasındaki fikir ve düşünceleri anlamaya çalışın. Sorular sorarken, bunu kırma uğruna değil, ama öğrenmek için yapın ... Evet, herkesin kendi altın çekiçleri vardır, ancak ne kadar çok çekiç toplarsanız meslektaşlarınızla ne kadar iyi anlaşırsanız o kadar kolaylaşırsınız.


0

"Çok fazla" özneldir: programlama tarzı? performans? standartlara uygunluk? emsal? sadece düz rahatlık duygusu / güven?

Kodunuz doğru davrandığı ve bakım sorunları olmadığı sürece, 23 norm bile olabilir. Bir gün daha sonra "23 arayüz ile mükemmel bir iş yapabilirsin, bakınız: Jonas Elfström" diyebilirim.


0

Limitin 23'ten daha küçük bir sayı olması gerektiğini söyleyebilirim - daha çok 5 veya 7 gibi,
ancak bu, bu arayüzlerin devraldığı herhangi bir sayıda arayüzü veya temel sınıflar tarafından uygulanan herhangi bir sayıda arayüzü içermez.

(Tamamen, N + herhangi bir sayıda kalıtsal arayüz, N <= 7'dir.)

Sınıfınız çok fazla arabirim kullanıyorsa, muhtemelen bir tanrı sınıfıdır .

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.