Je me suis plongé récemment dans une programmation plus "organisée" et j'ai appris que je devrais programmer sur une interface, pas une implémentation. Dans cet esprit, serait-il préférable de "dessiner" un projet dans des interfaces avant d'en écrire l'implémentation dans la mesure du possible?
Et si tel est le cas, dans le cas de l'utilisation de bibliothèques tierces (c'est-à-dire Lidgren), dois-je également les encapsuler dans des interfaces et les résoudre via des conteneurs IOC, ou est-ce correct de les exposer aux interfaces?
Réponses:
Malheureusement, vous constaterez que cela se résume souvent à vos préférences personnelles.
Ce que vous avez décrit jusqu'à présent, cependant, semble bon. En fait, si vous le souhaitez (et je le recommande), vous pouvez utiliser l'approche suivante:
Vous vous concentrez sur l'écriture de code plus "organisé". Suivre TDD vous y aidera.
Quelques points supplémentaires:
la source
Oui, vous devez coder contre des interfaces plutôt que des implémentations connues, et oui, vous devez d'abord construire des interfaces plutôt que de les faire émerger de votre propre code.
Les raisons des deux recommandations sont en grande partie les mêmes: la programmation informatique concerne principalement les facteurs humains. Beaucoup trouvent cela surprenant, mais réfléchissent: il existe un nombre presque infini de façons différentes de résoudre le même problème informatique qui fonctionnent aussi bien. Presque tous sont complètement impossibles à comprendre pour quiconque ne les a pas écrits (ou en fait à l'auteur peu de temps après).
Il s'ensuit qu'une bonne ingénierie logicielle consiste essentiellement à obtenir l'effet souhaité (calcul correct avec une efficacité raisonnable) d'une manière qui permette de travailler avec le code source plus tard. Les interfaces et les API sont une partie cruciale de cette discipline: elles vous permettent de penser à un problème à un niveau de description à la fois. C'est beaucoup plus facile que de penser à des règles de cohérence métier et à des implémentations de listes chaînées en même temps, et donc imposer une telle séparation des préoccupations de force est mieux que de permettre au programmeur client d'utiliser votre code comme il l'entend.
C'est difficile à croire pour de nombreux programmeurs de cow-boys, qui sont convaincus qu'ils comprennent tout ce qu'ils écrivent, sont bien meilleurs que les penseurs moyens, et peuvent gérer toute la complexité qui pose des problèmes aux programmeurs "moindres". Ne pas être conscient de ses propres limites cognitives est un phénomène extrêmement courant - c'est pourquoi les meilleures pratiques dans l'organisation du code sont si importantes (et si souvent ignorées).
Pour répéter, les interfaces et les barrières API sont largement bonnes , même lorsque vous ne coopérez qu'avec vous-même. En ce qui concerne les bibliothèques externes, si elles apportent une API bien pensée avec elles, je ne vois aucun problème à l'utiliser, car tant que vous ne prévoyez pas d'avoir à échanger cette bibliothèque contre une autre. Sinon, un wrapper ou une couche anti-corruption peut être une très bonne idée.
la source
IBlah
implémenté parBlah
ouBlah
implémenté parBlahImpl
. Je n'aime pas les deux, et ont tendance à utiliserBlah
mis en œuvre parOralBlah
,WrittenBlah
ouASLBlah
. Mais comme d'habitude, il est plus important de se conformer à votre base de code et à vos attentes existantes qu'à toute norme générale.Plutôt que de simplement servir de programmation aux interfaces, pourquoi ne pas vous intéresser au développement / conception piloté par les tests (TDD)?
Beaucoup de gens pensent que TDD est une pratique de test, mais en fait c'est une approche de conception où vous laissez les tests exposer comment votre code sera utilisé via des tests (initialement via des tests unitaires, mais peut également l'être via des tests d'intégration).
La programmation vers les interfaces est une arme importante dans votre ensemble d'outils, mais comme la plupart des choses, ce n'est pas toujours la solution / technique / pratique appropriée, car elle n'est pas toujours nécessaire. Vous devez programmer les interfaces où vous en avez besoin.
L'utilisation de TDD vous obligera à explorer où ces interfaces sont importantes et où, franchement, cela n'a pas d'importance. Et à la fin, vous devriez avoir un assez bon ensemble de tests unitaires sur votre base de code.
Quant à l'utilisation de bibliothèques tierces, je recommande fortement de les inclure dans vos propres abstractions, le cas échéant; et ne pas en informer les clients de votre API.
Bonne chance!
[modifier: vu la réponse de megaflight - tout à fait d'accord]
la source
Je pense que c'est exagéré. Si l'utilisateur de votre API n'a pas besoin d'être forcé d'implémenter / utiliser quelque chose d'une certaine manière, je le laisserais de côté. Les interfaces sont des contrats, si je n'en ai pas besoin, alors pourquoi m'en donner un?
Je pense que les gens abusent des interfaces. Vous ajoutez une couche de complexité qui n'est pas nécessaire dans la plupart des cas.
la source
La programmation contre un contrat est presque toujours une bonne idée. Ce contrat n'a pas besoin d'être une interface, il peut être rempli par une classe à la place. À mon avis, les interfaces sont devenues quelque peu surutilisées avec DI en raison de problèmes de tests unitaires et de cadres de simulation.
Personnellement, je préfère n'apporter des interfaces que lorsque je pourrais très probablement avoir ou avoir plus d'une mise en œuvre d'un contrat. Les interfaces sont idéales pour les référentiels où je souhaite supprimer l'accès aux données, mais probablement moins pour ma logique métier standard, qui est susceptible d'être relativement rigide.
Désormais, l'absence d'interface peut entraîner des problèmes avec les tests unitaires, en particulier pour les puristes. Mais je veux me moquer des dépendances externes de mes programmes, pas de ses dépendances internes. Je veux que mes tests effectuent la validation du code, pas l'écho de la structure du code.
la source