“Sadece neye ihtiyacınız olduğunu sor” arayüz prensibi var mı?


9

Temel olarak "sadece neye ihtiyacınız olduğunu sorun" diyen arayüzleri tasarlamak ve tüketmek için bir prensip kullanarak büyüdüm.

Örneğin, silinebilecek bir grup türüm varsa, bir Deletablearayüz yapacağım :

interface Deletable {
   void delete();
}

Sonra genel bir sınıf yazabilirsiniz:

class Deleter<T extends Deletable> {
   void delete(T t) {
      t.delete();
   }
}

Kodun başka bir yerinde her zaman müşteri kodunun ihtiyaçlarını karşılamak için mümkün olan en küçük sorumluluğu isteyeceğim. Yalnızca bir silmeniz gerekiyorsa Yani File, hala bir isteyeceğimiz Deletablebir değil File.

Bu ilke, ortak bilgi ve zaten kabul edilmiş bir isme sahip mi? Tartışmalı mı? Ders kitaplarında tartışıldı mı?


1
Gevşek kavrama belki? Veya dar arayüzler?
tdammers

Yanıtlar:


16

Bunun Robert Martin'in Arayüz Ayrışma İlkesi dediği şeyi ifade ettiğine inanıyorum . Arayüzler küçük ve özlü olanlara ayrılır, böylece tüketiciler (müşteriler) sadece kendilerini ilgilendiren yöntemler hakkında bilgi sahibi olurlar. SOLID hakkında daha fazla bilgi edinebilirsiniz .


4

Vadim'in çok iyi cevabını genişletmek için "tartışmalı mı?" Sorusunu "hayır, gerçekten değil" şeklinde cevaplayacağım.

Genel olarak, arayüz ayrımı, ilgili çeşitli nesnelerin genel "değişim nedenleri" sayısını azaltarak iyi bir şeydir. Temel ilke, çoklu yöntemlere sahip bir arayüzün değiştirilmesi gerektiğinde, arayüz yöntemlerinden birine bir parametre eklemenin dendiği durumlarda, değişen yöntemi kullanmasalar bile , arayüzün tüm tüketicilerinin en azından yeniden derlenmesi gerekir.. “Ama bu sadece bir derleme!” Dediğini duydum; bu doğru olabilir, ancak ikilideki değişiklik ne kadar önemli olursa olsun, tipik olarak yeniden derlediğiniz her şeyin bir yazılım yamasının parçası olarak dışarı itilmesi gerektiğini unutmayın. Bu kurallar, ortalama masaüstü iş istasyonunun cebinizdeki telefondan daha az güçlü olduğu 90'ların başında kavramsallaştırıldı, 14.4k baud çevirmeli bağlantı alevlendi ve 3.5 "1.44MB" disketler "birincil çıkarılabilir medyaydı. 3G / 4G'nin şu andaki döneminde bile, kablosuz internet kullanıcılarının genellikle sınırlarla veri planları vardır, bu nedenle bir yükseltme yayınlanırken, indirilmesi gereken daha az ikili dosya daha iyidir.

Bununla birlikte, tüm iyi fikirler gibi, yanlış bir şekilde uygulandığında arayüz ayrımı kötüleşebilir. Öncelikle, bu arayüzleri uygulayan nesneyi korurken (bağımlılıkları yerine getirerek) nispeten değişmeden arayüzleri ayırarak, bir "Hydra", bir "Hydra" ile karşılaşabilirsiniz. nesnenin her şeyi bilen, her şeyin güçlü doğası, dar arayüzlerden bağımlı olanlardan gizlenir. En azından Tanrı Nesnesi'nin bakımı kadar zor olan çok başlı bir canavarın yanı sıra tüm arayüzlerini korumanın yükü ile sonuçlanırsınız. Aşmamanız gereken çok fazla arabirim yoktur, ancak tek bir nesneye uyguladığınız her arabirimin önüne "Bu arabirim nesneye katkıda bulunuyor mu?"

İkincisi, SRP'nin size söyleyebilmesine rağmen, yöntem başına bir arayüz gerekli olmayabilir. Sonunda "mantı kodu" ile sonuçlanabilir; o kadar çok ısırık boyutu var ki, olayların tam olarak nerede olduğunu bulmak zor. Ayrıca, o arabirimin tüm geçerli kullanıcılarının her iki yönteme de ihtiyacı varsa bir arabirimi iki yöntemle bölmek de gereksizdir. Bağımlı sınıflardan biri sadece iki yöntemden birine ihtiyaç duysa bile, yöntemleri kavramsal olarak çok yüksek bir bütünlüğe sahipse, ara yüzün bölünmemesi genel olarak kabul edilebilirdir (iyi örnekler birbirlerinin tam karşıtları olan "antonimik yöntemlerdir").

Arabirim ayrımı, arabirime bağlı olan sınıflara dayanmalıdır:

  • Arabirime bağlı yalnızca bir sınıf varsa, ayırmayın. Sınıf bir veya daha fazla arabirim yöntemini kullanmıyorsa ve arabirimin tek tüketicisi ise, bu yöntemleri ilk etapta ortaya çıkarmamalısınız.

  • Arabirime bağlı birden fazla sınıf varsa ve tüm bağımlılar arabirimin tüm yöntemlerini kullanıyorsa, ayırmayın; arayüzü değiştirmek zorundaysanız (yöntem eklemek veya imza değiştirmek için), mevcut tüm tüketiciler ayırıp ayırmamanızdan etkilenecektir (en azından bir bağımlıya ihtiyaç duymayacak bir yöntem ekliyorsanız, Değişikliğin yeni bir arayüz olarak uygulanması gerekiyorsa, muhtemelen mevcut arayüzden devralınmalıdır).

  • Orada arabirimde birden fazla sınıf bağımlıdır ve onlar yoksa değil hepsi aynı yöntemleri kullanmak, bu ayrımı için bir aday. Arayüzün “tutarlılığına” bakın; tüm yöntemler tek ve çok özel bir programlama hedefini daha da ileri götürüyor mu? Arayüz (ve uygulayıcıları) için birden fazla temel amaç belirleyebiliyorsanız, daha az "değiştirme nedeni" olan daha küçük arayüzler oluşturmak için arayüzleri bu çizgiler boyunca bölmeyi düşünün.


Ayrıca, arayüzlerin kesin bir kombinasyon belirtmesine izin verebilecek bir OOP dili / sistemi kullanılıyorsa, arayüz ayırmanın iyi ve zahmetli olabileceğini belirtmek gerekir, ancak en azından .NET'te, ciddi bir baş ağrısına neden olabilir, çünkü iyi bir şey yoktur. "IFoo ve IBar'ı uygulayan, ancak başka hiçbir şekilde ortak hiçbir şeyi olmayan şeyler" koleksiyonunu belirtmenin bir yolu.
supercat

Genel tür parametreleri, birden çok arabirimin uygulanması da dahil olmak üzere ölçütlerle tanımlanabilir, ancak statik bir tür gerektiren ifadelerin genellikle birden fazla belirtmeyi desteklemediğini kabul edersiniz. Statik bir tipin hem IFoo hem de IBar'ı uygulamasına ihtiyaç varsa ve bu arabirimlerin ikisini de kontrol ediyorsanız, IBaz : IFoo, IBarbunun yerine uygulanması ve gerekli olması iyi bir fikir olabilir .
KeithS

İstemci kodu olarak kullanılabilecek bir şeye ihtiyaç duyuyorsa IFoove IBarbir kompozit tanımlamak IFooBariyi bir fikir olabilir, ancak arayüzler ince bir şekilde bölünmüşse, düzinelerce farklı arayüz türü gerektirmek kolaydır. Koleksiyonların sahip olabileceği aşağıdaki özellikleri göz önünde bulundurun: Numaralandırma, Raporlama sayısı, nth öğesi okuma, nth öğesi yazma, nth öğeden önce ekle, nth öğesinden sil, Yeni öğe (yeni alanın koleksiyonunu ve dönüş dizinini büyüt) ve Ekle. Dokuz yöntem: ECRWIDNA. Muhtemelen birçok farklı kombinasyonu doğal olarak destekleyecek düzinelerce türü tanımlayabilirim.
supercat

Örneğin, diziler ECRW'yi destekleyecektir. Bir arraylist ECRWIDNA'yı destekleyecektir. İş parçacığı için güvenli bir liste ECRWNA'yı destekleyebilir [ancak A genellikle yalnızca listeyi önceden doldurmak için yararlı olacaktır]. Salt okunur bir dizi sarıcı ECR'yi destekleyebilir. Bir kovaryant liste arayüzü ECRD'yi destekleyebilir. Jenerik olmayan bir arayüz tip-güvenli destek C veya CD sağlayabilir. Takas bir seçenek olsaydı, bazı türler CS'yi destekleyebilir, ancak D'yi (ör. Diziler) desteklerken, diğerleri CDS'yi destekleyebilirdi. Gerekli her yetenek kombinasyonu için farklı arayüz tipleri tanımlamaya çalışmak bir kabus olacaktır.
supercat

Şimdi, bir koleksiyonun, koleksiyonun yapabileceği her şeyi yapabilen, ancak her işlemi kaydeden bir nesneyle sarmak istediğini düşünün. Kaç tane paketleyiciye ihtiyaç var? Tüm koleksiyonlar, yeteneklerini tanımlamak için özellikler içeren ortak bir arayüzden miras alınırsa, bir sargı yeterli olacaktır. Bununla birlikte, tüm arayüzler farklıysa, düzinelerce insan gerekir.
supercat
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.