Veri türleri için arabirimler kullanmak bir anti-desen midir?


9

Kullanıcı, Ürün, Fatura ve Sipariş gibi, modelimde (EF kullanarak) çeşitli öğelerim olduğunu varsayalım.

Uygulamamda varlıkların önceden belirlenmiş kümeye ait olduğu varlık nesneleri özetlerini yazdırabilen bir kullanıcı denetimi yazıyorum, bu durumda Kullanıcı ve Ürün özetlerinin özetlenebileceğini söylüyorum.

Özetlerin hepsi sadece bir ID ve bir açıklama olacak, bu yüzden bunun için basit bir arayüz oluşturun:

 public interface ISummarizableEntity {     
       public string ID { get; }    
       public string Description { get; } 
 }

Sonra söz konusu varlıklar için, bu arabirimi uygulayan kısmi bir sınıf oluşturun:

public partial class User : ISummarizableEntity
{
    public string ID
    {
        get{ return UserID.ToString(); }
    }

    public string Description 
    {
        get{ return String.Format("{0} {1} is from {2} and is {3} years old", FirstName, LastName, Country, Age); }
    }
}

public partial class Product: ISummarizableEntity
{
    public string ID
    {
        get{ return ProductID.ToString(); }
    }

    public string Description 
    {
        get{ return String.Format("{0} weighs {1}{2} and belongs in the {3} department", ProductName, WeightValue, WeightUnit, Department); }
    }
}

Bu şekilde kullanıcı kontrolüm / kısmi görünümüm herhangi bir ISummarizableEntity koleksiyonuna bağlanabilir ve kaynakla hiç ilgilenmesi gerekmez. Arayüzlerin veri türü olarak kullanılmaması gerektiği söylendi ancak bundan daha fazla bilgi alamadım. Gördüğüm kadarıyla, arayüzler normalde davranışı tanımlasa da, sadece özellikleri kullanmak kendi içinde bir anti-desen değildir, çünkü özellikler zaten alıcılar / ayarlayıcılar için sözdizimsel şekerdir.

Somut bir veri türü oluşturabilir ve varlıklardan buna eşleyebilirim ama faydasını göremiyorum. Varlık nesnelerini soyut bir sınıftan miras alıp sonra özellikleri tanımlayabilirim ama sonra varlıkları birden fazla mirasa sahip olamayacağımız için daha fazla kullanmaya kilitliyorum. Ayrıca istersem herhangi bir nesnenin ISummarizableEntity olması için açıkım (tabii ki arayüzü yeniden adlandıracağım)

Aklımda kullandığım çözüm sürdürülebilir, genişletilebilir, test edilebilir ve oldukça sağlamdır. Burada anti-paterni görebiliyor musunuz?


Bunun gibi bir şeye EntitySummarysahip olmak Userve Producther birinin böyle bir yöntemi olmasını tercih etmenizin bir nedeni var mı public EntitySummary GetSummary()?
Ben Aaronson

@Ben, geçerli bir seçenek öneriyorsunuz. Ancak yine de, arayanın bir nesnenin GetSummary () yöntemine sahip olmasını bekleyebileceğini bilmesini sağlayan bir arabirim tanımını gerektirir. Aslında aynı tasarım, uygulamada ek bir modülerlik seviyesi ile. Hatta özetin kaynağından ayrı olarak (ancak kısaca) kendi başına yaşaması gerekiyorsa iyi bir fikir olabilir.
Kent

@KentAnderson katılıyorum. Bu sınıfların genel arayüzüne ve özetlerin nasıl kullanıldığına bağlı olarak aslında iyi bir fikir olabilir veya olmayabilir.
Ben Aaronson

Yanıtlar:


17

Arayüzler davranışları tanımlamaz. Bazen tam tersi.

Arabirimler, "bu nesneyi bir ISummarizableEntity'yi kabul eden herhangi bir yönteme sunacaksam, bu nesnenin kendisini özetleyebilen bir varlık olması" gibi bir ifadeyi açıklar - sizin durumunuzda, dize kimliği ve bir dize Açıklama.

Arayüzlerin mükemmel kullanımı. Burada anti-desen yok.


2
"Arabirimler davranışı tanımlamaz." "Kendini nasıl özetler" bir davranış değildir?
Doval

2
@ThomasStringer, kalıtım, OO saflık bakış açısıyla, ortak bir soy anlamına gelir (örneğin, bir kare ve bir daire her ikisi de şekillerdir ). OP örneğinde, bir Kullanıcı ve bir Ürün makul bir ortak soy paylaşmaz. Bu durumda kalıtım açık bir anti-desen olacaktır.
Kent

2
@Doval: Sanırım arayüzün adı beklenen davranışı tarif edebilir. Ama buna gerek yok; arayüz eşit olarak IHasIdAndDescription olarak adlandırılabilir ve cevap aynı olacaktır. Arayüzün kendisi davranışı tanımlamaz, beklentileri açıklar.
pdr

2
@pdr Kulaklık jakı üzerinden 20V gönderirseniz kötü şeyler olur. Şekil yeterli değil; bu fişten ne tür bir sinyal geleceğine dair çok gerçek ve çok önemli bir beklenti vardır. Bu yüzden, arabirimlerin kendilerine bağlı davranış belirtimleri yokmuş gibi davranmak yanlıştır. ListListe gibi davranmayanlarla ne yapabilirsiniz ?
Doval

3
Uygun arabirime sahip bir elektrik fişi prize sığabilir, ancak bu elektrik ileteceği anlamına gelmez (istenen davranış).
JeffO

5

Bu tasarım için daha iyi bir yol seçtiniz, çünkü birden çok, farklı nesne türlerinden gerekli olacak belirli bir davranış türü tanımlıyorsunuz. Bu durumda kalıtım, aslında var olmayan sınıflar arasında ortak bir ilişki anlamına gelir. Bu durumda, kalıtılabilirliğe göre bileşimi tercih edilir.


3
Arayüzlerin kalıtımla bir ilgisi yoktur.
DougM

1
@DougM, belki de iyi söylemedim, ama katılıyorum.
Kent

1

Sadece özelliklerini taşıyan Arayüzler gerektiğini beri kaçınılmalıdır:

  • amacı gizliyor: sadece bir veri taşıyıcısına ihtiyacınız var
  • kalıtımı teşvik eder: birisinin gelecekteki endişeleri karıştırması olasılığı
  • serileştirmeyi önler

Burada iki endişeyi karıştırıyorsunuz:

  • veri olarak özet
  • sözleşme olarak özet

Özet iki dizeden oluşur: id ve açıklama. Bu düz veri:

public class Summary {
    private readonly string id;
    private readonly string description;
    public Summary(string id, string description) {
        this.id = id;
        this.description = description;
    }
    public string Id { get { return id; } }
    public string Description { get { return description; } }
}

Artık bir sözleşme tanımlamak istediğiniz özeti tanımladığınıza göre:

public interface ISummarizableEntity {
    public Summary GenerateSummary();
}

Alıcılarda zeka kullanmanın bir anti-desen olduğunu ve bundan kaçınılması gerektiğini unutmayın: bunun yerine işlevlerde bulunmalıdır. Uygulamalar şöyle görünür:

public partial class User : ISummarizableEntity {
    public Summary GenerateSummary() {
        var id = UserID.ToString();
        var description = String.Format("{0} {1} is from {2} and is {3} years old", FirstName, LastName, Country, Age);
        return new Summary(id,description);
    }
}

public partial class Product : ISummarizableEntity {
    public Summary GenerateSummary() {
        var id = ProductID.ToString();
        var description = String.Format("{0} weighs {1}{2} and belongs in the {3} department", ProductName, WeightValue, WeightUnit, Department);
        return new Summary(id,description);
    }
}

"Yalnızca özellik taşıyan arabirimlerden kaçınılmalıdır." Neden böyle düşünüyorsunuz muhakeme sağlayın.
Euphoric

Haklısın bazı detayları ekledim
vanna
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.