Devez-vous toujours coder pour les interfaces en Java?

Je comprends les principes du codage aux interfaces: découpler l’implémentation de l’interface et permettre aux implémentations de l’interface d’être échangées.

Devrais-je coder pour les interfaces de chaque classe que j’écris ou est-ce excessif ? Je ne veux pas doubler le nombre de fichiers source dans un projet, sauf si cela en vaut vraiment la peine.

Quels facteurs puis-je utiliser pour décider de coder par interface ou non?

En général, je suis d’accord avec les autres réponses: utilisez une interface lorsque vous connaissez ou prévoyez un changement et / ou une implémentation différente, ou optez pour la testabilité.

Mais il n’est pas toujours facile de savoir à l’avance ce qui peut changer à l’avenir, surtout si vous n’êtes pas expérimenté. Je pense que la solution à ce problème est la refactorisation: restz simple (= pas d’interface) tant que cela n’est pas nécessaire. Lorsque le besoin s’en fait sentir, faites simplement un refactoring de “Introduce / Extract Interface” (supporté par presque tous les IDE décents).

Lorsque vous le faites, extrayez uniquement les méthodes réellement nécessaires aux appelants. N’ayez pas peur d’extraire plus d’une interface séparée (si toutes les méthodes extraites ne sont pas vraiment cohérentes).

Un des moteurs du refactoring pourrait être le test: si vous ne pouvez pas facilement tester quelque chose avec des classes, envisagez d’introduire une / des interface (s). Cela vous permettra également d’utiliser des moqueries, ce qui peut grandement simplifier les tests dans de nombreux cas.

Edit: basé sur le commentaire de Tarski, j’ai réalisé un autre scénario / ajustement important aux déclarations précédentes:
Si vous fournissez une API externe (pour d’autres projets [sub], ou libérez-la vraiment à l’état sauvage), alors utiliser des interfaces dans l’API (à l’exception des classes de valeurs simples) est presque toujours une bonne idée.
Cela vous permettra de changer l’impl si vous voulez sans déranger le code client. Vous aurez un problème uniquement si vous devez également modifier l’interface. Ne pas rompre la compatibilité sera très délicat (voire impossible).

Je l’utilise quand au moins une des actions suivantes est vraie:

1) Je veux découpler les modules / classes sans rapport les uns avec les autres, et je veux qu’ils soient reflétés par les dépendances des paquets java.

2) Lorsque le découplage est important en termes de dépendances de construction

3) Lorsque l’implémentation peut changer par configuration ou dynamicment à l’exécution (généralement à cause d’un modèle de conception)

4) Quand je veux qu’une classe soit testable, je fais ses “points de lien” vers des interfaces de ressources externes, afin que je puisse utiliser des implémentations fictives.

5) Moins fréquent: quand je veux avoir une option pour restreindre l’access à certaines classes. Dans ce cas, ma méthode retourne une interface à la place de la classe réelle, donc l’appelant sait que je ne m’attends pas à ce qu’il effectue d’autres opérations sur la valeur renvoyée.

Non, chaque classe ne doit pas avoir d’interface. C’est exagéré au carré.

Vous utilisez une interface lorsque vous avez besoin d’abstraire ce qui a été fait, et vous êtes certain que la mise en œuvre peut changer.

Jetez un oeil à l’API Collections java.util pour un bon exemple. L’interface List est une belle abstraction pour l’idée générale d’une liste, mais vous pouvez voir qu’il existe plusieurs façons de l’implémenter: ArrayList, LinkedList, etc.

MISE À JOUR: Qu’en est-il de ce cas où vous concevez une classe concrète, décidez après avoir des clients qu’une interface est nécessaire, puis vous brisez vos clients en ajoutant une interface? Ouais, c’est ce qui se passe. Comment pouvez-vous savoir ce que vous ne savez pas? Aucun logiciel ou méthodologie ne peut résoudre ce problème.

La bonne nouvelle pour vous est que l’extraction d’une interface à partir d’une classe concrète est un remaniement facile à faire pour vous et vos clients. Les IDE gèrent ce genre de choses de manière routinière. Vous et vos clients devriez en profiter.

Je dirais que les couches, comme les services et la persistance, devraient toujours avoir des interfaces. Tout ce qui peut être proxy devrait avoir une interface. Si vous faites Spring AOP, tout ce que vous souhaitez décorer avec un aspect doit avoir une interface.

Les objects de modèle ou de valeur, tels que Personne, Adresse ou Téléphone, ne doivent pas avoir d’interface. Un object de valeur immuable ne doit pas avoir d’interface.

Le rest tombe dans les zones grises. Utilisez votre meilleur jugement.

Longue histoire courte, non. Vous êtes le créateur de l’application, vous avez donc une bonne idée de ce qui pourrait changer. À mon avis, certains livres de modèles de conception deviennent un peu fous car ils semblent toujours pousser la conception vers des interfaces et non la mise en œuvre, peu importe quoi. Parfois, c’est juste exagéré. Pour ma dernière application (petite taille), j’ai une interface de firebase database car je pense qu’il y a une chance que je puisse la porter ultérieurement sur le Web et passer à MySQL. Bien sûr, dans la réalité, il serait facile de créer une interface de firebase database à partir de ma classe existante et d’append simplement “implémente myDbInterface” plus tard avec quelques petites modifications. Cela fonctionne parce que je suis le seul développeur cependant. Sur une équipe plus grande ou un type de produit différent, la réponse peut être différente. Utilisez simplement votre meilleur jugement (après avoir lu toutes les bonnes réponses SO bien sûr).

J’aime à penser que l’on utilise des interfaces lorsque la connectivité et le potentiel de comportement différent sont importants. Les services sont la solution idéale. On peut vouloir une implémentation par défaut, mais simuler (moqueur), etc. en est un autre. Cela signifie évidemment qu’il devrait y avoir un intf car il y aura toujours au moins 2 formes.

Les types de valeur doivent être des classes finales. Ils ne devraient jamais être étendus. Les types de valeur incluent quelque chose comme Suburb, MimeType. S’il y a des variations de ces compositions, utilisez-les. En tant que but, j’essaie de mettre peu de comportement, le cas échéant, dans mes types de valeur. Valider le type simple qu’il encapsule, etc. est probablement la chose la plus complexe. Par exemple, une classe Color qui prend r / g / b doit valider que chaque composant est compris entre 0 et 255 et que c’est tout.

Oui, utilisez l’interface lorsque vous attendez un comportement à modifier. . Dans le futur.

Ou votre classe qui peut gérer les changements de manière claire.

par exemple.

public static void main(Ssortingng s[]) { Employee e1=new Employee(new Salesman()); Employee e2=new Employee(new Manager()); system.out.println(e1.performaction()); system.out.println(e1.performaction()); } Class Employee { //which changes frequently Authority a; public Employee(Authority a) { this.a=a; } public Ssortingng performAction() { a.action(); } } 

// —————————————————- ——————

 interface Authority { public Ssortingng action(); } class Manager implements Authority { public Ssortingng action() { returns "I manages People"; } class SalesMan implements Authority { public Ssortingng action() { returns "I Sell things Company makes "; } }