web-dev-qa-db-fra.com

Module nécessitant une injection de dépendance en Javascript

Ces jours-ci, une question m'est venue à l'esprit:

La façon dont nous Javascript va-t-elle à l'encontre de presque tout ce qui est considéré comme une bonne pratique dans le développement de logiciels traditionnel?

J'ai une série de questions/observations liées à cette déclaration, mais afin de respecter le format de StackExchange, il sera préférable de les diviser en différentes questions.

Module nécessitant

Le code Javascript standard ressemble de nos jours à:

const someModule = require('./someModule')

module.exports = function doSomethingWithRequest() {
  // do stuff
  someModule.someFunc()
  // do other stuff
}

Les avantages

  • Encapsulation: le module fonctionne de manière autonome et sait tout ce dont il a besoin pour exécuter ses fonctions.
  • En tant que coloraire, il est plus facile pour les clients d'utiliser le module.

Désavantages

  • Mauvaise testabilité: ceci est standard lorsque vous n'utilisez pas DI, mais dans les langages dynamiques, tels que Javscript, il peut être contourné * par des modules comme mockery ou rewire .
  • Il viole certainement le DIP - à ne pas confondre avec l'injection de dépendance. - puisque je ne peux importer que des modules concrets.
  • Il viole probablement le OCP - par exemple, imaginez que j'ai un module de journalisation qui écrit dans le système de fichiers (via le module fs) . Si je veux étendre ce module de journalisation pour l'envoyer au réseau, ce serait très difficile.

* Cela peut fonctionner avec les modules CommonJS ou même AMD car ils sont implémentés principalement dans le pays utilisateur. Cependant, je ne sais pas comment cela pourrait être possible avec la syntaxe ES6 import.

Injection de dépendance

En utilisant l'injection de dépendances, ce serait plus comme:

module.exports = function doSomethingWithRequest(someModule) {
  // do stuff
  someModule.someFunc()
  // do other stuff
}

Les avantages

  • Testabilité accrue: il est désormais plus facile de stub/mock someModule, même en utilisant la syntaxe ES6.
  • Il est possible d'honorer le DIP: pas nécessairement cependant, car le module client peut toujours être programmé pour l'implémentation et non une interface.

Désavantages

  • Encapsulation brisée: la principale question en suspens est:

    Ok, alors qui va créer/exiger les dépendances?

  • Faire cela dans chaque client du module semble très MOUILLÉ .
  • Cela nécessiterait probablement que j'utilise un conteneur DI pour être réalisable dans un projet réel.

Donc, la vraie question ici est:

Pourquoi les développeurs Javascript ont tendance à tendre vers la première approche?

Est-ce juste "la manière Javascript"?

J'écris moi-même du code comme ça la plupart du temps. J'ai eu ma part de configuration de test à l'aide de bibliothèques de simulation, mais cela m'a toujours semblé mal de le faire.

Suis-je en train de manquer quelque chose?

26
Henrique Barcelos

Je suis principalement un programmeur PHP, mais j'ai été en contact avec 4 équipes JavaScript au cours de la dernière année environ).

En tant que programmeur orienté objet, le principe de l'injection de dépendances semble être le meilleur moyen, mais quelques développeurs JS m'ont dit le contraire. JS est un tout autre monde.

Parce que JavaScript vous permet de patcher tout et n'importe quoi à l'aide de techniques très simples, les développeurs JavaScript ont appris à adapter une technologie différente sur la façon de créer des applications JavaScript à plus grande échelle. La plupart d'entre eux sont construits sous forme d'ensembles de modules autonomes, qui exposent la fonctionnalité par le biais d'exportations publiques, masquant les éléments internes du module pour ne pas permettre aux autres de réécrire les fonctions sur lesquelles vous vous appuyez.

L'approche habituelle consiste généralement à aller jusqu'à ne pas exposer un constructeur, mais à exposer la construction d'un objet à l'aide d'un wrapper d'usine - pour la même raison: si vous donnez à quelqu'un accès à un objet, il peut instancier directement sont autorisés à changer quoi que ce soit.

En tirant parti de la conception modulaire, vous refusez aux autres de jouer avec les fonctions que vous prévoyez de travailler, mais vous avez toujours la possibilité de tester vos modules - via l'API publique du fichier requis, l'API que vous avez créée.

6
Andy