Quel est le but d'une interface de marqueur?
Réponses
Trop de publicités?C'est un peu une tangente en fonction de la réponse par "Mitch Blé".
Généralement, quand je vois des gens qui citent le cadre des lignes directrices de conception, j'aime toujours mentionner que:
Il est généralement préférable d'ignorer le cadre des lignes directrices de conception la plupart du temps.
Ce n'est pas à cause d'un problème avec le cadre des lignes directrices de conception. Je pense que l' .NET framework est une fantastique bibliothèque de classe. Beaucoup de fantasticness découle de la conception du cadre des lignes directrices.
Cependant, la conception de lignes directrices ne s'appliquent pas à la plupart de code écrit par la plupart des programmeurs. Leur but est de permettre la création d'un grand cadre qui est utilisé par des millions de développeurs, de ne pas faire de la bibliothèque de l'écriture plus efficace.
Beaucoup de suggestions qui peuvent vous guider à faire des choses que:
- Peut-être pas la façon la plus simple de mettre en place quelque chose
- Peut conduire à une duplication de code
- Peut avoir un surplus de gestion d'exécution
L' .net framework est grand, très grand. Il est si grand qu'il serait totalement déraisonnable de supposer que quelqu'un a des connaissances approfondies sur tous les aspects. En fait, il est beaucoup plus sûr de supposer que la plupart des programmeurs heurtent souvent à des parties de l'infrastructure qu'ils n'ont jamais utilisé avant.
Dans ce cas, les principaux objectifs d'une API de concepteur sont les suivants:
- Garder les choses en accord avec le reste du cadre
- Éliminer l'inutile complexité dans l'API de la surface
Le cadre des lignes directrices de conception de pousser les développeurs à créer du code qui répondent à ces objectifs.
Cela signifie faire des choses comme éviter les couches de la succession, même si cela signifie la duplication de code, ou de pousser tous les exception jeter de code de "points d'entrée" plutôt que de l'utilisation partagée des aides (alors que les traces de pile plus de sens dans le débogueur), et beaucoup d'autres choses semblables.
La principale raison que ces lignes directrices suggèrent à l'aide d'attributs au lieu de marqueur interfaces est parce que la suppression du marqueur interfaces rend la structure d'héritage de la bibliothèque de classe beaucoup plus accessible. Un diagramme de classe avec 30 types et 6 couches de la hiérarchie d'héritage est très intimidant par rapport à celui avec 15 types et les 2 couches de la hiérarchie.
Si vraiment il y a des millions de développeurs à l'aide de votre Api, ou de votre base de code est vraiment très grand (disons plus de 100K LOC) puis à la suite de ces lignes directrices peuvent aider beaucoup.
Si 5 millions de développeurs passer 15 minutes dans l'apprentissage d'une API plutôt que de dépenser 60 minutes d'apprentissage, le résultat est une économie nette de 428 homme ans. C'est beaucoup de temps.
La plupart des projets, cependant, ne concernent pas des millions de développeurs, ou 100K+ LOC. Dans un projet classique, avec 4 développeurs et autour de 50K de la ldc, l'ensemble des hypothèses sont très différentes. Les développeurs de l'équipe aura une bien meilleure compréhension de la façon dont le code fonctionne. Cela signifie qu'il fait beaucoup plus de sens à l'optimisation de la production de haute qualité de code rapidement, et pour réduire la quantité de bugs et l'effort nécessaire pour apporter des changements.
Les dépenses de 1 semaine à développer du code qui est cohérent avec la .net framework, vs 8 heures à écrire du code qui est facile à changer et a moins de bugs peut entraîner:
- Fin des projets
- Baisse des primes
- Augmentation de bug compte
- Plus de temps passé au bureau, et moins de temps sur la plage à boire des margaritas.
Sans 4,999,999 d'autres développeurs pour absorber les coûts, il n'est généralement pas la peine.
Par exemple, le test de marqueur interfaces se résume à une simple "est" l'expression, et les résultats en moins de code à la recherche pour les attributs.
Donc, mon conseil est:
- Suivez les lignes directrices du cadre religieusement si vous êtes le développement de bibliothèques de classe (ou widgets) pour une large diffusion de la consommation.
- Envisager l'adoption de certains d'entre eux si vous avez plus de 100K LOC dans votre projet
- Sinon les ignorer complètement.
Marqueur Interfaces sont utilisées pour marquer la capacité d'une classe implémentant une interface spécifique au moment de l'exécution.
La Conception de l'Interface et .NET Type de Directives de Conception - la Conception de l'Interface de décourager l'utilisation de marqueur interfaces en faveur de l'utilisation des attributs en C#, mais comme @Jay Bazuzi points, il est plus facile de vérifier marqueur interfaces que pour les attributs: o is I
Ainsi, au lieu de ceci:
public interface IFooAssignable {}
public class FooAssignableAttribute : IFooAssignable
{
...
}
L' .NET directives recommandé de le faire:
public class FooAssignableAttribute : Attribute
{
...
}
[FooAssignable]
public class Foo
{
...
}
Puisque chaque autre réponse a déclaré: "ils doivent être évités", il serait utile d'avoir une explication de pourquoi.
Tout d'abord, pourquoi marqueur interfaces sont utilisées: Elles existent pour permettre le code à l'aide de l'objet qui l'implémente de vérifier la possibilité de mettre en œuvre ladite interface et de traiter l'objet différemment si elle n'.
Le problème avec cette approche est qu'elle casse l'encapsulation. L'objet lui-même a maintenant un contrôle indirect sur la façon dont il sera utilisé à l'extérieur. En outre, il a la connaissance du système, il est destiné à être utilisé dans. En appliquant le marqueur de l'interface, la définition de la classe est à croire qu'il s'attend à être utilisé quelque part qui vérifie l'existence de la marque. Il a connaissance implicite de l'environnement qu'il est utilisé dans et tente de définir la manière dont il doit être utilisé. Cela va à l'encontre de l'idée de l'encapsulation, car il a la connaissance de la mise en œuvre d'une partie du système qui existe, entièrement à l'extérieur de son propre champ.
Au niveau pratique, cela réduit la portabilité et la réutilisabilité. Si la classe est ré-utilisé dans une autre application, l'interface doit être copié à travers de trop, et il ne peut avoir aucun sens dans le nouvel environnement, le rendant entièrement redondantes.
En tant que tel, le "marqueur" est métadonnées à propos de la classe. Ces métadonnées ne sont pas utilisés par la classe elle-même et n'est significatif que pour (certains!) client externe code de sorte qu'il peut traiter l'objet d'une certaine manière. Parce qu'il n'a de sens que pour le code client, les métadonnées doivent être dans le code du client, et non pas la classe de l'API.
La différence entre un "marqueur" d'interface et de normal de l'interface est une interface avec les méthodes raconte le monde extérieur, comment il peut être utilisé alors qu'une interface vide implique, c'est à dire le monde extérieur, comment il doit être utilisé.
Marqueur interfaces peut être parfois un mal nécessaire quand une langue n'est pas en charge les victimes de l'union types.
Supposons que vous souhaitez définir une méthode qui attend un argument dont le type doit être exactement l'un des A, B, ou C. Dans de nombreux fonctionnelle-les langues premières (comme le F#), ce type peut être correctement définie comme:
type Arg =
| AArg of A
| BArg of B
| CArg of C
Cependant, dans OO-première de langages tels que C#, ce n'est pas possible. La seule façon d'obtenir quelque chose de similaire ici est de définir une interface IArg et de "marquer" A, B et C avec elle.
Bien sûr, vous pourriez éviter en utilisant le marqueur de l'interface par la simple acceptation de type "objet" comme argument, mais alors vous perdez de l'expressivité et un certain degré de sécurité de type.
Victime de types d'union sont extrêmement utiles et ont existé dans les langages fonctionnels pour les moins de 30 ans. Curieusement, à ce jour, tous les langages à objets ont ignoré cette fonctionnalité, même si elle a effectivement rien à voir avec de la programmation fonctionnelle en soi, mais appartient au type de système.
Une interface de marqueur est juste une interface qui est vide. Une classe implémenterait cette interface sous forme de métadonnées à utiliser pour une raison quelconque. En C #, vous utiliseriez plus couramment des attributs pour baliser une classe pour les mêmes raisons que vous utiliseriez une interface de marqueur dans d'autres langues.