web-dev-qa-db-fra.com

«Dépendre d'abstractions, pas de concrétions» quel est le sens exact de ce terme

Je lisais [[# #]] solides [~ # ~] principes sur un site Web, dans lequel pour D - Principe d'inversion de dépendance ça dit:

"Dépendre d'abstractions, pas de concrétions"

En d'autres termes. nous devons concevoir notre logiciel de manière à ce que divers modules puissent être séparés les uns des autres en utilisant une couche abstraite pour les lier ensemble.

Exemple de principe d'inversion de dépendance

L'utilisation classique de ce principe de configuration du bean dans le framework Spring.

Dans Spring Framework, tous les modules sont fournis en tant que composants séparés qui peuvent fonctionner ensemble en injectant simplement des dépendances dans un autre module. Cette dépendance est gérée en externe dans des fichiers XML.

Ces composants séparés sont si bien fermés dans leurs limites que nous pouvons les utiliser dans d'autres modules logiciels en dehors du ressort avec la même facilité. Ceci a été réalisé par inversion de dépendance et principes fermés ouverts. Tous les modules exposent la seule abstraction qui est utile pour étendre la fonctionnalité ou le plug-in dans un autre module.

J'ai quelques questions là-dessus.

  • Dépendre d'abstractions, pas de concrétions Cela signifie, coder en interfaces, pas en classes concrètes?
  • Pourquoi un exemple de haricot de printemps est-il donné? Oui, nous pouvons utiliser des interfaces pour injecter la dépendance. Mais, on peut aussi injecter une classe concrète?
8
kulsin

Dépendre d'abstractions, pas de concrétions Cela signifie, coder vers des interfaces, pas vers des classes concrètes?

Pour les langues qui prennent en charge les interfaces, c'est généralement le cas. Mais cette couche d'abstraction peut être fournie par d'autres moyens, tels qu'une classe abstraite, une usine, une réflexion, etc. L'important est que vous ne coupliez pas directement une exigence à une classe nommée, concrète.

* Pourquoi un exemple de haricot de printemps est-il donné? Oui, nous pouvons utiliser des interfaces pour injecter la dépendance. Mais, on peut aussi injecter une classe concrète?

Vraisemblablement, parce que vous regardez "Principes SOLIDES en Java " (accent sur le mien). Spring est un framework DI populaire pour Java. " Mais, nous pouvons aussi injecter une classe concrète?" Vous injectez toujours une classe concrète. Mais quelle classe de béton est déterminée par votre configuration de ressort. Le récepteur de l'injection ne dépend que d'une abstraction, pas de cette classe spécifique. Avoir autre chose pour lui dire quelle implémentation concrète utiliser est l'essence même de DI.

8
David Arno

Dépendre d'abstractions, pas de concrétions.
Cela signifie, coder vers des interfaces, pas vers des classes concrètes?

Également connu sous le nom de "codage de l'interface (à ne pas confondre avec interface le mot clé), pas l'implémentation".
C'est une technique ancienne appelée abstraction. Toute couche d'abstraction tente de masquer des détails non pertinents et donc de réduire la complexité, permettant de construire des systèmes plus gros et moins sujets aux erreurs. Le coût est que la façon de les cacher, ainsi que de ne pas tirer parti des détails eux-mêmes, a souvent un coût.

Cela n'a rien à voir avec les classes, les fonctions, les constantes ou quoi que ce soit. Cela signifie simplement qu'en fonction du contrat, la promesse que l'implémentation est tenue d'honorer sous peine d'être qualifiée de défectueuse, au lieu de partir avec "ça marche pour moi" (maintenant, ici, pendant que personne ne regarde).

Pourquoi un exemple de haricot de printemps est-il donné? Oui, nous pouvons utiliser des interfaces pour injecter la dépendance. Mais, on peut aussi injecter une classe concrète?

Le Dependency Inversion Principle (DIP) en dépend fortement, car il rend la substitution de différentes implémentations facile, même attendue.

La raison pour laquelle un important framework Java est utilisé est simplement que votre source fonctionne avec Java.

Que vous injectiez un class ou un interface ne fait aucune différence pour DIP, mais les interface sont la porte dérobée de MI en Java et contiennent un comportement codé en dur minimal et pas de données.

6
Deduplicator

L'abstraction ne signifie pas nécessairement une interface. Si vous pensez à deux composants en interaction, à mesure que le code évolue, il y aura des choses qui changeront, mais il y aura des aspects qui resteront plus ou moins les mêmes. Mais les changements dans un composant provoquent généralement des changements dans l'autre composant dépendant.

Si vous reconnaissez ces aspects qui ne changent pas ou qui forment les caractéristiques essentielles de l'interaction, vous les "extrayez" dans une abstraction - une chose qui est une expression de ces aspects: pourrait être une interface, une base concrète ou abstraite classe qui peut être héritée, une structure de données, un ensemble de classes collaboratrices, etc. Mais, c'est pas à propos juste ajouter une interface entre les deux - c'est juste du code supplémentaire; l'interface doit être une généralisation bien conçue suffisamment expressive pour couvrir la plupart des cas sans être modifiée (trop souvent - jusqu'à ce qu'elle se stabilise). Il n'est donc pas nécessairement facile de bien faire les choses.

Une fois que vous avez fait cela, vous réécrivez ensuite les deux composants en termes de cette abstraction (ce que vous avez appelé "codage vers les interfaces") - généralement, un côté passe des appels via l'abstraction, l'autre fournit un service derrière l'abstraction, en veillant à adhérer au "contrat" défini par l'abstraction.

Dans votre propre code, si vous avez un composant A dépendant de B, vous devrez peut-être attendre que plusieurs variantes différentes de B émergent avant de trouver ce qui est commun à tous, et de le retirer dans une interface, ou une autre sorte d'une abstraction. Ou vous en savez peut-être assez sur le domaine problématique pour pouvoir deviner à quoi ressemblerait une bonne abstraction.

1
Filip Milovanović