76 votes

Sont vides interfaces odeur de code?

J'ai une fonction qui retourne même type d'objets (les résultats de la requête), mais avec pas de propriétés ou méthodes en commun. Afin de disposer d'un type commun, j'ai eu recours à l'aide d'une interface vide comme un type de retour et "mis en œuvre", que sur les deux.

Ce n'est pas, bien sûr. Je ne peux que me console en s'accrochant à l'espoir qu'un jour, ces classes ont quelque chose en commun et je vais passer que la logique commune à mon interface vide. Pourtant, je ne suis pas satisfait et de réflexion pour savoir si je dois avoir deux méthodes différentes, et à condition d'appel suivant. Ce serait une meilleure approche?

J'ai été également dit que .NET Framework utilise vide interfaces à des fins de marquage.

Ma question est: est une interface vide un signe fort d'un problème de conception ou est-il largement utilisé?

EDIT: Pour ceux que cela intéresse, j'ai découvert plus tard que les victimes de syndicats dans les langages fonctionnels sont la solution parfaite pour ce que je cherche à réaliser. C# ne semble pas être amical avec ce concept encore.

48voto

UrbanEsc Points 2070

Bien qu'il semble qu'il existe un motif de conception (beaucoup ont parlé de "marqueur" d'interface de maintenant) pour ce cas d'utilisation, je crois que l'utilisation de ce type de pratique est une indication d'un code d'odeur (la plupart du temps au moins).

@V4Vendetta posté, il y a une analyse statique de la règle qui cible ce: http://msdn.microsoft.com/en-us/library/ms182128(v=VS.100).aspx

Si votre conception comprend vide interfaces de types sont appelés à mettre en œuvre, vous êtes probablement à l'aide d'une interface comme un marqueur ou d'un moyen d'identifier un groupe de types. Si cette identification se fera au moment de l'exécution, la bonne façon de le faire est d'utiliser un attribut personnalisé. Utilisez la présence ou l'absence de l'attribut, ou les propriétés de l'attribut, d'identifier les types de cibles. Si l'identification doit se produire au moment de la compilation, alors il est acceptable d'utiliser une interface vide.

C'est la cité de MSDN recommandation:

Supprimer l'interface ou ajouter des membres. Si l'interface vide est utilisé pour qualifier un ensemble de types, de remplacer l'interface avec un attribut personnalisé.

Cela reflète également la Critique de la section de la déjà posté le lien wikipédia.

Un problème majeur avec le marqueur interfaces une interface définit un contrat pour la mise en œuvre de classes, et que le contrat est héritée par toutes les sous-classes. Cela signifie que vous ne pouvez pas "unimplement" un marqueur. Dans l'exemple donné, si vous créez une sous-classe que vous ne voulez pas serialize (peut-être parce qu'elle dépend de l'état transitoire), vous devez recourir à explicitement jeter NotSerializableException (par ObjectOutputStream docs).

9voto

ColinE Points 36907

Vous dites que votre fonction "revient entièrement différents objets en fonction de certains cas" - mais combien différents sont-ils? Peut-on être un flux écrivain, une INTERFACE de classe, l'autre un objet de données? Non ... j'en doute!

Vos objets peuvent ne pas avoir toutes les communes des méthodes ou des propriétés, cependant, ils sont probablement semblables dans leur rôle ou leur utilisation. Dans ce cas, un marqueur de l'interface semble tout à fait approprié.

8voto

Oded Points 271275

Si pas utilisé comme un marqueur de l'interface, je dirais que oui, c'est une odeur de code.

Une interface définit un contrat que l'opérateur respecte - si vous avez vide interfaces que vous n'utilisez pas la réflexion au-dessus (comme on le fait avec le marqueur interfaces), alors vous pourriez aussi bien utiliser Object (déjà existant) type de base.

6voto

Luchian Grigore Points 136646

Vous avez répondu à votre propre question... "j'ai une fonction qui retourne complètement différents objets en fonction de certains cas."... Pourquoi voudriez-vous avoir la même fonction qui retourne complètement différents objets? Je ne vois pas une raison pour que ce soit utile, peut-être vous avez une bonne, dans ce cas, s'il vous plaît partager.

EDIT: compte tenu de vos précisions, vous devez, en effet, utiliser un marqueur de l'interface. "complètement différent" est tout à fait différente de celle "sont de la même nature". Si ils étaient complètement différents (pas seulement qu'ils n'ont pas partagé les membres), qui serait une odeur de code.

4voto

KeithS Points 36130

Comme beaucoup l'ont probablement déjà dit, une interface vide ne la validité de l'utiliser comme un "marqueur"d'interface.

Probablement le meilleur usage, je pense, pour désigner un objet comme appartenant à un sous-ensemble du domaine, géré par un Référentiel. Disons que vous disposez de différentes bases de données à partir de laquelle vous pouvez récupérer les données, et que vous avez un Référentiel de mise en œuvre pour chaque. Un Référentiel spécifique, ne peut gérer qu'un sous-ensemble, et ne doit pas être donnée une instance d'un objet à partir de toute autre sous-ensemble. Votre modèle de domaine pourrait ressembler à ceci:

//Every object in the domain has an identity-sourced Id field
public interface IDomainObject
{
   long Id{get;}
}

//No additional useful information other than this is an object from the user security DB
public interface ISecurityDomainObject:IDomainObject {}

//No additional useful information other than this is an object from the Northwind DB
public interface INorthwindDomainObject:IDomainObject {}


//No additional useful information other than this is an object from the Southwind DB
public interface ISouthwindDomainObject:IDomainObject {}

Vos dépôts peuvent être effectués générique pour ISecurityDomainObject, INorthwindDomainObject, et ISouthwindDomainObject, et vous avez alors le moment de la compilation de vérifier que votre code n'est pas en essayant de passer un objet de Sécurité de la base de données Northwind (ou tout autre permutation). Dans de telles situations, l'interface fournit de précieux renseignements sur la nature de la classe, même si elle ne fournit pas de contrat de mise en œuvre.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X