Interfaces Java / convention de nommage de la mise en œuvre [dupliquer]
cette question a déjà une réponse ici:
- nom D'Interface en Java [fermé] 11 réponses
Comment nommer les différentes classes / interfaces que vous créez?
Parfois, je n'ai pas d'informations d'implémentation à ajouter à l'interface de type nom d'implémentation FileHandler
et classe SqlFileHandler
.
lorsque cela se produit, je nomme habituellement l'interface dans le nom" normal", comme Truck
et nomme la classe réelle TruckClass
.
comment nommez-vous les interfaces et les classes à cet égard?
9 réponses
Nommez votre Interface
ce que c'est. Truck
. Pas ITruck
car il n'est pas un ITruck
c'est un Truck
.
An Interface
en Java est un Type . Alors vous avez DumpTruck
, TransferTruck
, WreckerTruck
, CementTruck
, etc que implement Truck
.
Lorsque vous utilisez le Interface
à la place d'une sous-classe que vous venez de jeter aux Truck
. Comme dans List<Truck>
. Mettre I
devant est juste style Hongrois notation tautologie qui n'ajoute rien mais plus de choses à taper à votre code.
toutes les Interfaces et implémentations de marques Java IDE modernes et ce qui ne va pas sans cette notation idiote. Ne l'appelez pas TruckClass
c'est-à-dire tautologie aussi mauvaise que la IInterface
tautologie.
S'il s'agit d'une implémentation, il s'agit d'une classe. La seule vraie exception à cette règle, et il y a toujours des exceptions, pourrait être quelque chose comme AbstractTruck
. Puisque seules les sous-classes verront cela un jour et que vous ne devriez jamais lancer dans une classe Abstract
, cela ajoute quelques informations que la classe est abstraite et à la façon dont elle devrait être utilisée. Vous pouvez toujours trouver un meilleur nom que AbstractTruck
et utiliser BaseTruck
ou DefaultTruck
à la place puisque le abstract
est dans la définition. Mais depuis Abstract
classes ne devrait jamais faire partie d'une interface publique je crois que c'est une exception acceptable à la règle. Faire les constructeurs protected
va un long chemin à franchir cette ligne de partage.
et le suffixe Impl
n'est que plus bruyant. Plus de la tautologie. Tout ce qui n'est pas une interface est une implémentation, même des classes abstraites qui sont des implémentations partielles. Allez-vous mettre ce stupide suffixe Impl
sur chaque nom de chaque classe ?
le Interface
est un contrat sur ce que les méthodes et les propriétés publiques doivent supporter, il est également Type informations ainsi. Tout ce qui met en œuvre Truck
est un Type de Truck
.
regardez la bibliothèque Java standard elle-même. Tu vois? IList
, ArrayListImpl
, LinkedListImpl
? Non, vous voyez List
et ArrayList
, et LinkedList
. Voici un beau article à propos de cette question exacte. N'importe laquelle de ces conventions de nom de préfixe/suffixe idiotes violent toutes le principe DRY ainsi.
aussi, si vous vous trouvez à ajouter DTO
, JDO
, BEAN
ou d'autres suffixes répétitifs stupides aux objets alors ils appartiennent probablement dans un paquet au lieu de tous ces suffixes. Les espaces de noms correctement empaquetés sont autonomes documenter et réduire toutes les informations redondantes inutiles dans ces systèmes de nommage propriétaires vraiment mal conçus que la plupart des endroits n'adhèrent même pas en interne d'une manière cohérente.
si tout ce que vous pouvez trouver pour rendre votre Class
nom unique est le suffixe Impl
, alors vous devez repenser avoir un Interface
à tous. Alors, quand vous avez une situation où vous avez un Interface
et un seul Implementation
qui est non seulement spécialisé du Interface
vous n'avez probablement pas besoin du Interface
.
j'ai vu des réponses ici qui suggèrent que si vous n'avez qu'une seule implémentation alors vous n'avez pas besoin d'une interface. Cela va à l'encontre du principe de Depencency Injection/Inversion du contrôle (ne nous appelez pas, nous vous appellerons!).
donc oui, il y a des situations dans lesquelles vous souhaitez simplifier votre code et le rendre facilement testable en se basant sur des implémentations d'interfaces injectées (qui peuvent aussi être reproduites - votre code ne le sait pas!). Même si vous avez seulement deux implémentations - un Mock pour tester, et un qui est injecté dans le code de production réel - cela ne rend pas avoir une interface superflue. Une interface bien documentée établit un contrat, qui peut également être maintenu par une mise en œuvre simulée stricte pour les tests.
en fait, vous pouvez établir des tests qui ont des mocks mettre en œuvre le contrat d'interface le plus strict (lancer des exceptions pour les arguments qui ne devraient pas être null, etc) et attraper des erreurs dans les tests, utiliser une implémentation plus efficace dans le code de production (ne pas vérifier les arguments qui ne devraient pas être nuls pour être nuls puisque la simulation a jeté des exceptions dans vos tests et vous savez que les arguments ne sont pas nuls en raison de la correction du code après ces tests, par exemple).
Injection de dépendance / IOC peut être difficile à saisir pour un nouveau venu, mais une fois que vous comprenez son potentiel, vous voudrez l'utiliser partout et vous vous trouverez à faire des interfaces tout le temps-même s'il n'y aura qu'une seule mise en œuvre (production réelle).
pour cette implémentation (vous pouvez en déduire, et vous auriez raison, que je crois que les mocks pour testing devraient s'appeler Mock (InterfaceName)), je préfère le nom par défaut(InterfaceName). Si une mise en œuvre plus spécifique se produit, il peut être nommé de manière appropriée. Cela évite aussi le suffixe Impl que je déteste particulièrement (si ce n'est pas une classe abstraite, bien sûr c'est un "impl"!).
je préfère aussi " Base(InterfaceName)" par opposition à "Abstract(InterfaceName)" parce qu'il y a des situations dans lesquelles vous voulez que votre classe de base devienne instanciable plus tard, mais maintenant vous êtes coincé avec le nom "Abstract(InterfaceName)", et cela vous force à renommer la classe, ce qui peut causer une petite confusion mineure - mais si c'était toujours Base (InterfaceName), supprimer le modificateur abstrait ne change pas ce qu'était la classe.
le nom de l'interface doit décrire le concept abstrait qu'elle représente. Toute classe d'implémentation doit avoir une sorte de traits spécifiques qui peuvent être utilisés pour donner un nom plus spécifique.
S'il n'y a qu'une seule classe d'implémentation et que vous ne pouvez pas penser à quoi que ce soit qui la rende spécifique (implicite en voulant l'appeler -Impl
), alors il semble qu'il n'y ait aucune justification à avoir une interface du tout.
j'ai tendance à suivre les pseudo-conventions établies par Java Core/Sun, p.ex. dans les classes de Collections:
-
List
- interface pour l'objet "conceptuel -
ArrayList
- mise en œuvre concrète de l'interface -
LinkedList
- mise en œuvre concrète de l'interface -
AbstractList
abstrait "partielle" de la mise en œuvre d'aider des implémentations personnalisées
je faisais la même chose en modélisant mes classes d'événements après le paradigme événement/auditeur/Adaptateur AWT.
la convention standard C#, qui fonctionne assez bien en Java aussi, est de préfixer toutes les interfaces avec un I
- donc votre interface de gestionnaire de fichiers sera IFileHandler
et votre interface de camion sera ITruck
. C'est cohérent, et il est facile de distinguer les interfaces des classes.
j'aime les noms d'interface qui indiquent quel contrat une interface décrit, comme" Comparable "ou"sérialisable". Les noms comme "Truck" ne décrivent pas vraiment truck-ness -- quelles sont les capacités d'un truck?
en ce qui concerne les conventions: j'ai travaillé sur des projets où chaque interface commence par un "I"; bien que cela soit quelque peu étranger aux conventions Java, cela rend la recherche d'interfaces très facile. En dehors de cela, le suffixe" Impl " est un nom par défaut raisonnable.
certaines personnes n'aiment pas cela, et c'est plus une convention .NET que Java, mais vous pouvez nommer vos interfaces avec un préfixe de capital I, par exemple:
IProductRepository - interface
ProductRepository, SqlProductRepository, etc. - implementations
les personnes opposées à cette convention de nommage pourraient argumenter que vous ne devriez pas vous soucier de savoir si vous travaillez avec une interface ou un objet dans votre code, mais je le trouve plus facile à lire et à comprendre à la volée.
Je ne nommerais pas la classe implementation avec un suffixe" Class". Cela peut conduire à la confusion, parce que vous pouvez réellement travailler avec des objets "class" (i.e. Type) dans votre code, mais dans votre cas, vous ne travaillez pas avec l'objet class, vous travaillez juste avec un objet simple-Vieux.
TruckClass
ressemble à une classe de Truck
, je pense que la solution recommandée est d'ajouter Impl
suffixe. À mon avis, la meilleure solution est de contenir dans nom d'implémentation certaines informations, ce qui se passe dans cette implémentation particulière (comme nous l'avons avec List
interface et implémentations: ArrayList
ou LinkedList
), mais parfois vous avez juste une implémentation et devez avoir une interface en raison de l'utilisation à distance (par exemple), puis (comme mentionné au début) Impl
est la solution.
j'utilise les deux conventions:
si l'interface est une instance spécifique d'un motif bien connu (par exemple Service, DAO), elle peut ne pas avoir besoin d'un" I " (E. G UserService, AuditService, UserDao) tout fonctionne bien sans le "I", parce que le post-fix détermine le meta pattern.
mais, si vous avez quelque chose une ou deux fois (généralement pour un motif de rappel), alors il aide à le distinguer d'une classe (par exemple IAsynchCallbackHandler, IUpdateListener, IComputeDrone). Il s'agit d'interfaces spéciales conçues pour un usage interne, parfois L'interface attire l'attention sur le fait qu'un opérande est en fait une interface, donc à première vue, il est immédiatement clair.
dans d'autres cas, vous pouvez utiliser le I pour éviter une collision avec d'autres classes de béton généralement connues (ISubject, IPrincipal vs Subject ou Principal).