web-dev-qa-db-fra.com

Les noms d'interface doivent-ils commencer par un préfixe «I»?

J'ai lu " Clean Code " de Robert Martin pour, je l'espère, devenir un meilleur programmeur. Bien que rien de tout cela n'ait jusqu'à présent été vraiment révolutionnaire, cela m'a fait penser différemment à la façon dont je conçois les applications et j'écris du code.

Il y a une partie du livre avec laquelle non seulement je ne suis pas d'accord, mais qui n'a pas de sens pour moi, en particulier en ce qui concerne les conventions de dénomination des interfaces. Voici le texte, extrait directement du livre. J'ai mis en gras cet aspect que je trouve confus et que j'aimerais obtenir des éclaircissements.

Je préfère laisser les interfaces sans fioritures. Le précédent I, si courant dans les liasses héritées d'aujourd'hui, est une distraction au mieux et trop d'informations au pire. Je ne veux pas que mes utilisateurs sachent que je leur remets une interface .

C'est peut-être parce que je ne suis qu'un étudiant, ou peut-être parce que je n'ai jamais fait de programmation professionnelle ou en équipe, mais Je voudrais que l'utilisateur sache que c'est une interface. Il y a une grande différence entre l'implémentation d'une interface et l'extension d'une classe.

Donc, ma question se résume à, "Pourquoi devrions-nous cacher le fait qu'une partie du code attend une interface?"

Modifier

En réponse à une réponse:

Si votre type est une interface ou une classe est votre entreprise, pas celle de quelqu'un qui utilise votre code. Vous ne devez donc pas divulguer les détails de votre code dans ce code tiers.

Pourquoi ne devrais-je pas "divulguer" les détails de savoir si un type donné est une interface ou une classe vers du code tiers? N'est-il pas important pour le développeur tiers qui utilise mon code de savoir s'il va implémenter une interface ou étendre une classe? Les différences ne sont-elles tout simplement pas aussi importantes que je les fais croire dans mon esprit?

78

Si vous vous arrêtez pour y penser, vous verrez qu'une interface n'est vraiment pas sémantiquement très différente d'une classe abstraite:

  • Les deux ont des méthodes et/ou des propriétés (comportement);
  • Aucun des deux ne doit avoir de champs non privés (données);
  • Aucun des deux ne peut être instancié directement;
  • Dériver d'un signifie implémenter toutes les méthodes abstraites dont il dispose, sauf si le type dérivé est également abstrait.

En fait, les distinctions les plus importantes entre les classes et les interfaces sont:

  • Les interfaces ne peuvent pas avoir de données privées;
  • Les membres de l'interface ne peuvent pas avoir de modificateurs d'accès (tous les membres sont "publics");
  • Une classe peut implémenter plusieurs interfaces (par opposition à pouvoir généralement hériter d'une seule classe de base).

Étant donné que les seules distinctions particulièrement significatives entre les classes et les interfaces tournent autour (a) des données privées et (b) de la hiérarchie des types - qui ne font pas la moindre différence pour un appelant - il n'est généralement pas nécessaire de savoir si un type est une interface ou une classe. Vous n'avez certainement pas besoin de l'indication visuelle .

Cependant, il y a certains cas d'angle à connaître. En particulier, si vous utilisez la réflexion, l'interception, les proxys/mixins dynamiques, le tissage de bytecode, la génération de code ou tout ce qui implique de jouer directement avec l'environnement de taper le système ou le code lui-même - alors il est très utile et parfois nécessaire de savoir immédiatement si vous avez affaire à une interface ou à une classe. Vous ne voulez clairement pas que votre code échoue mystérieusement parce que vous avez essayé d'ajouter une classe, plutôt qu'une interface, en tant que mixage.

Cependant, pour le code logique d'entreprise classique Vanilla, les distinctions entre les classes abstraites et les interfaces n'ont pas besoin d'être annoncées car elles n'entreront jamais en jeu.

Tout cela étant dit, j'ai tendance à préfixer mes interfaces C # avec I de toute façon parce que c'est la convention .NET utilisée et préconisée par Microsoft. Et lorsque j'explique les conventions de codage à un nouveau développeur, il est beaucoup moins compliqué d'utiliser simplement les règles de Microsoft que d'expliquer pourquoi nous avons nos propres règles "spéciales".

70
Aaronaught

À bien des égards, la cohérence est plus importante que la convention. Tant que vous êtes cohérent dans vos schémas de dénomination, ils ne seront pas difficiles à travailler. Le préfixe s'interface avec un I si vous le souhaitez, ou laissez simplement le nom sans fioritures, cela ne m'importe pas tant que vous choisissez un style et que vous vous y tenez!

14
Jim Nutt

Le livre est plein de bonnes choses, mais j'ajouterais quand même "I" au nom de l'interface.

Imaginez que vous avez public interface ILog avec une implémentation par défaut public class Log.

Maintenant, si vous décidez d'avoir public interface Log, tout d'un coup, vous devez changer la classe Log en public class LogDefault ou quelque chose du genre. Vous êtes passé d'un personnage supplémentaire à sept - c'est certainement du gaspillage.

Il y a souvent une fine frontière entre la théorie et la pratique. En théorie, c'est une très bonne idée, mais en pratique ce n'est pas si bon.

13
CodeART

Eh bien, il ne s'agit pas d'implémenter l'interface ou d'étendre une classe. Dans ces cas, vous savez de toute façon ce que vous faites.

Cependant, lorsque du code tiers (un autre module de l'application par exemple) manipule vos données, ce code ne devrait pas se soucier si vous présentez une interface ou une classe.

C'est tout le point de l'abstraction. Vous présentez à ce code tiers un objet d'un type donné. Ce type donné a une fonction membre que vous pouvez appeler. C'est assez.

Si votre type est une interface ou une classe est votre entreprise, pas celle de quelqu'un qui utilise votre code. Vous ne devez donc pas divulguer les détails de votre code à ce code tiers.

Soit dit en passant, les interfaces et les classes sont des types de référence à la fin. Et c'est ça qui compte. C'est donc ce que votre convention de dénomination doit souligner.

8
deadalnix

La plupart des réponses semblent supposer que le langage de programmation est soit Java ou C # où il existe un concept (ou mot-clé) pour les interfaces/classes abstraites. Dans ces cas, dans un IDE décent, il est immédiatement visible avec quel type de classe un traite et écrit public interface IMyClass est une duplication inutile. C'est comme si vous n'écriviez pas public final FinalMyClass - imaginez mettre chaque mot-clé dans le nom des classes.

Cependant, à mon avis en C++, la situation est un peu différente car il faut plonger dans le fichier d'en-tête et voir si la classe a des méthodes virtuelles pour savoir s'il s'agit d'une classe abstraite. Dans ce cas, je vois clairement un argument pour écrire class AbstractMyClass.

Ma réponse serait donc: cela dépend du langage de programmation.

Mise à jour 2016: 2 ans d'expérience C++ plus tard, je considérerais probablement comme une mauvaise pratique de préfixer les noms de classe avec Abstract, bien que je dirais qu'il existe probablement des bases de code si complexes que cela pourrait avoir un sens.

6
Ela782

Suivez les idiomes de la langue que vous utilisez.

Chaque langue a ses propres idiomes et directives de codage. Par exemple, en C #, il est idiomatique de préfixer les interfaces avec I. En Go, ce n'est pas le cas.

4
Pete

Dans mon code (Java), j'ai tendance à avoir cette convention dans les API que j'expose aux appelants:

  • La fonctionnalité est fournie via les interfaces et jamais par les classes.
  • Les pièces non fonctionnelles sont des classes.

Par non fonctionnel, je veux dire des choses comme des structures de données pures (telles que des classes qui agissent comme des ponts vers la sérialisation XML ou l'ORM), des énumérations et des exceptions, qui ne peuvent pas être des interfaces (enfin, vous pouvez le faire pour les classes de données pures, mais c'est beaucoup de travail pour très peu de gain car il n'y a rien que ces classes fassent sauf conserver les données).

En termes de conventions de dénomination, les interfaces ont tendance à correspondre à des noms d'acteurs (par exemple, FooBarWatcher) ou à des adjectifs (par exemple, FooBarWatchable) et les classes de données pures et les énumérations sont mappées à des noms non actifs ( par exemple, FooBarStatus); le IDE peut guider le consommateur d'API sans conventions de dénomination spéciales. Les exceptions suivent les conventions habituelles Java (FooBarException, FooBarError, FooBarFault) bien sûr.

Je mettrai aussi souvent les interfaces dans leur propre paquet ou même dans leur propre bibliothèque, juste pour m'assurer que je ne suis pas tenté de casser mes propres règles. (Cela m'aide également à gérer la génération lorsque je dérive le code de sources externes telles que des documents WSDL.)

0
Donal Fellows