Sadece sınıflandırma için bir arayüz kullanmak kötü bir uygulama mudur?


12

Örneğin:

Ben sınıfları Say A, B, C. İki arayüzüm var, onları arayalım IAnimalve IDog. IDogmiras IAnimal. Ave Bvardır IDogederken, s Cdeğil, ancak bir olduğunu IAnimal.

Önemli olan IDogek işlevsellik sağlamamasıdır. Sadece izin vermek için kullanılan Ave B, ancak C, bazı yöntemlere bir argüman olarak aktarılmasını sağlar.

Bu kötü bir uygulama mı?


8
IAnimalve IDogolan korkunç tautology isimleri!

5
@JarrodRoberson, ben .Net dünyasında çalışıyorsanız, onunla sıkışıp kalıyorsunuz (veya farklı bir şekilde yaparsanız kurulan sözleşmeye karşı çıkacaksınız).
Daniel B

2
@JarrodRoberson IMHO MyProject.Data.IAnimalve MyProject.Data.Animaldaha iyi MyProject.Data.Interfaces.Animalve MyProject.Data.Implementations.Animal
Mike Koder

1
Nokta bir ise bile bakım için herhangi bir neden olmamalıdır olduğunu Interfaceveya Implementationbir tekrarlanan önek veya ya bir ad olsun, bu bir totoloji ya yoludur ve KURU ihlal. Dogönemsemen gereken tek şey. PitBull extends DogUygulama yedekliliğine de gerek yok, kelime extendsbana bilmem gereken her şeyi söylüyor, orijinal yorumuma gönderdiğim bağlantıyı oku.

1
@Jarrod: Bana şikayet etmeyi bırak. .NET geliştirici ekibine şikayet edin. Standarda aykırı olsaydım, geliştirici arkadaşım cesaretimden nefret ederdi.
Kendall Frey

Yanıtlar:


13

Herhangi bir üyesi olmayan veya Marker Arayüzü olarak adlandırılan aynı arayüzden devralınan başka bir arayüzle tam olarak aynı üyeleri olan arayüz ve bir işaretleyici olarak kullanıyorsunuz.

Kötü bir uygulama değildir, ancak kullandığınız dil onu destekliyorsa, arabirim özniteliklerle (ek açıklamalar) değiştirilebilir.

Orchard Projesi'nde ağır kullanım "Marker Arayüzü" desenini gördüğüm için bunun kötü bir uygulama olmadığını güvenle söyleyebilirim

İşte Orchard projesinden bir örnek .

public interface ISingletonDependency : IDependency {}

/// <summary>
/// Base interface for services that may *only* be instantiated in a unit of work.
/// This interface is used to guarantee they are not accidentally referenced by a singleton dependency.
/// </summary>
public interface IUnitOfWorkDependency : IDependency {}

/// <summary>
/// Base interface for services that are instantiated per usage.
/// </summary>
public interface ITransientDependency : IDependency {}

Lütfen İşaretleyici Arayüzüne bakın .


Öznitelikler / ek açıklamalar derleme zamanı kontrolünü destekleyebilir mi (C #'ı referans dili olarak kullanarak)? Nesnenin özniteliği yoksa bir istisna atabilir biliyorum, ancak arabirim deseni derleme zamanında hataları yakalar.
Kendall Frey

İşaretleyici Arabirimi kullanıyorsanız, derleme kontrolüne sahip olamıyorsanız. Temelde arabirime göre tip kontrolü yapıyorsunuz.
Freshblood

Kafam karıştı. Bu 'Marker arayüzü' örüntüsü derleme zamanı kontrolleri sağlar, çünkü Cbir IDog.
Kendall Frey

Bu kalıbı kullanıyorsanız yansıtıcı işler yapıyorsunuz. Yani dinamik veya statik olarak kontroller yapıyorsunuz. Eminim kullanım durumunuzda yanlış bir şey var ama nasıl kullandığınızı görmedim.
Freshblood

Telastyn'in cevabı hakkındaki yorumda yaptığım gibi tanımlayayım. örneğin bir s Kennellistesini saklayan bir sınıfım var IDog.
Kendall Frey

4

Evet, neredeyse her dilde kötü bir uygulama.

Veri kodlamak için türler yoktur; verilerinizin gitmesi gereken yere gittiğini ve davranması gerektiği gibi davrandığını kanıtlamaya yardımcı olurlar. Alt tipin tek nedeni, polimorfik bir davranışın değişmesidir (ve her zaman değil).

Yazma olmadığından, bir IDog'un yapabilecekleri ima edilir. Bir programcı bir şeyi düşünüyor, diğeri başka bir şeyi düşünüyor ve işler yıkılıyor. Ya da daha ince taneli kontrole ihtiyaç duyduğunuz için temsil ettiği şeyler artar.

[değiştir: açıklama]

Demek istediğim, arayüze dayalı bazı mantık yapıyorsunuz . Neden bazı yöntemler sadece köpeklerle ve diğer hayvanlarla çalışabilir? Bu farkı ima eden bir sözleşmedir çünkü farkı sağlayan gerçek bir üye yoktur; sistemde gerçek veri yok . Tek fark arabirimdir (bu nedenle 'yazmadan' yorum) ve bunun anlamı programcılar arasında farklılık gösterecektir. [/Düzenle]

Bazı diller, bunun çok kötü olmadığı, ancak ayrıntılandırma değil yeteneklere odaklanma eğilimi olan özellik mekanizmaları sağlar. Onlarla çok az deneyimim var, bu yüzden orada en iyi uygulamalarla konuşamıyorum. C ++ / Java / C # olsa ... iyi değil.


Ortadaki iki paragrafınızla kafam karıştı. 'Alt tip' ile ne demek istiyorsun? Uygulama değil, sözleşme olan arayüzler kullanıyorum ve yorumlarınızın nasıl uygulandığından emin değilim. 'Yazmama' ile ne demek istiyorsun? 'Zımni' ile ne demek istiyorsun? Bir IDog, bir IAnimal'in yapabileceği her şeyi yapabilir, ancak daha fazlasını yapabileceği garanti edilmez.
Kendall Frey

Açıklama için teşekkürler. Benim özel durumumda, arayüzleri tam olarak farklı şekilde kullanmıyorum. Muhtemelen en iyi Kennelbir IDogs listesini saklayan bir sınıf var diyerek açıklanabilir .
Kendall Frey

@KendallFrey: Ya arayüzden çıkıyorsunuz (kötü) ya da yanlış bir soyutlama kokan yapay bir ayrım yaratıyorsunuz.
Telastyn

2
@Telastyn - Arayüz gibi bir amaç bir meta veri sağlamaktır
Freshblood

1
@Telastyn: Peki, özellikler derleme zamanı kontrolüne nasıl uygulanır? AFAIK, C # 'da, nitelikler yalnızca çalışma zamanında kullanılabilir.
Kendall Frey

2

Ben sadece C # biliyorum, bu yüzden genel olarak OO programlama için söyleyemeyiz, ancak sınıfları kategorize etmeniz gerekiyorsa, bir C # örneği olarak, bariz seçenekler arayüzler, enum özelliği veya özel niteliklerdir. Genellikle başkalarının ne düşündüğüne bakılmaksızın arayüzü seçerdim.

if(animal is IDog)
{
}
if(animal.Type == AnimalType.Dog)
{
}
if(animal.GetType().GetCustomAttributes(typeof(DogAttribute), false).Any())
{
}


var dogs1 = animals.OfType<IDog>();
var dogs2 = animals.Where(a => a.Type == AnimalType.Dog);
var dogs3 = animals.Where(a => a.GetType().GetCustomAttributes(typeof(DogAttribute), false).Any());


var dogsFromDb1 = session.Query<IDog>();
var dogsFromDb2 = session.Query<Animal>().Where(a => a.Type == AnimalType.Dog);
var dogsFromDb3 = session.Query<Animal>().Where(a => a.GetType().GetCustomAttributes(typeof(DogAttribute),false).Any());


public void DoSomething(IDog dog)
{
}
public void DoSomething(Animal animal)
{
    if(animal.Type != AnimalType.Dog)
    {
        throw new ArgumentException("This method should be used for dogs only.");
    }
}
public void DoSomething(Animal animal)
{
    if(!animal.GetType().GetCustomAttributes(typeof(DogAttribute), false).Any())
    {
        throw new ArgumentException("This method should be used for dogs only.");
    }
}

Kodun son bölümü çoğunlukla bunun için kullanıyorum. Derleme süresinin kontrol edilmesinin yanı sıra arayüz sürümünün açıkça daha kısa olduğunu görebiliyorum.
Kendall Frey

Ben simillar kullanım durum var ama çoğu .net devs buna karşı şiddetle tavsiye, ama öznitelikleri kullanmayacağım
GorillaApe

-1

İkinci arayüzün tüm uygulamalarının, önceki uygulamaların bazı uygulamalarının yapamayacağı şeyleri yararlı bir şekilde yapabilmesi bekleniyorsa, yeni üyeler eklemeden başka bir arayüze miras kalan bir arayüze sahip olmanın yanlış bir yanı yoktur. Gerçekten de, IMHO'nun .net Framework gibi şeylerde daha fazla kullanılması gereken iyi bir modeldir, özellikle de sınıfı daha türetilmiş arayüzün getirdiği kısıtlamaları doğal olarak karşılayacak bir uygulayıcı, daha türetilmiş arayüzü uygulayarak bunu gösterebilir. üye-uygulama kodunu veya bildirimlerini değiştirmek zorunda kalmadan.

Örneğin, arayüzlerim olduğunu varsayalım:

arayüz IMaybeMutableFoo {
  Bar Thing {get; set;} // Ve diğer özellikler de
  bool IsMutable;
  IImmutableFoo AsImmutable ();
}
arayüz IImmutableFoo: IMaybeMutableFoo {};

Bir uygulamanın IImmutableFoo.AsImmutable()kendiliğinden geri dönmesi beklenir; değişebilir bir sınıf uygulamasının IMaybeMutableFoo.AsImmutable()verilerin anlık görüntüsünü içeren derinden değişmeyen yeni bir nesne döndürmesi beklenir. A'da tutulan verilerin anlık görüntüsünü saklamak isteyen bir rutin IMaybeMutableFooaşırı yükler sunabilir:

genel void StoreData (IImmutableFoo ThingToStore)
{
  // ThingToStore'un değişmez olduğu bilindiğinden referansı kaydetmek yeterli olacaktır
}
genel void StoreData (IMaybeMutableFoo ThingToStore)
{
  StoreData (ThingToStore.AsImmutable ()); // Daha spesifik aşırı yükü arayın
}

Derleyicinin depolanacak şeyin bir olduğunu bilmediği durumlarda IImmutableFooarayacaktır AsImmutable(). Öğe zaten değiştirilemezse işlev hızlı bir şekilde dönmelidir, ancak arabirim üzerinden bir işlev çağrısı hala zaman alır. Derleyici öğenin zaten bir olduğunu biliyorsa IImmutableFoo, gereksiz işlev çağrısını atlayabilir.


Downvoter: Yorum yapmak ister misiniz? Yeni bir şey eklemeden bir arayüzü miras alan zamanlar vardır, ama bu iyi (ve IMHO az kullanılan) bir teknik olduğu zamanlar olmadığı anlamına gelmez.
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.