Módulo que requiere vs inyección de dependencia en Javascript

24

En estos días surgió una pregunta en mi mente:

¿La forma en que Javascript va en contra de casi todo lo que se considera una buena práctica en el desarrollo de software tradicional?

Tengo una serie de preguntas / observaciones relacionadas con esta declaración, pero para respetar el formato de StackExchange, será mejor si las divido en diferentes preguntas.

Módulo que requiere

El código Javascript estándar hoy en día se ve así:

const someModule = require('./someModule')

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

Ventajas

  • Encapsulación: el módulo funciona de manera independiente y sabe todo lo que necesita para realizar sus funciones.
  • Como colorario, es más fácil para los clientes usar el módulo.

Desventajas

  • Poca capacidad de prueba: esto es estándar cuando no se usa DI, pero en lenguajes dinámicos, como Javscript, puede ser burlado * por módulos como mockeryo rewire.
  • Ciertamente, viola el DIP , que no debe confundirse con la inyección de dependencia. - Ya que solo puedo importar módulos concretos.
  • Probablemente viola el OCP ; por ejemplo, imagine que tengo un módulo de registro que escribe en el sistema de archivos (a través del fsmódulo). Si quiero extender este módulo de registro para enviarlo a la red, sería muy difícil.

* Esto podría funcionar con los módulos CommonJS o incluso AMD, ya que se implementan principalmente en la tierra del usuario. Sin embargo, no estoy seguro de cómo esto podría ser posible con la importsintaxis de ES6 .

Inyección de dependencia

Usando la inyección de dependencia, sería más como:

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

Ventajas

  • Mayor capacidad de prueba: ahora es más fácil tropezar / burlarse someModule, incluso utilizando la sintaxis ES6.
  • Es posible honrar el DIP: aunque no necesariamente, ya que el módulo del cliente todavía se puede programar para la implementación y no una interfaz.

Desventajas

  • Encapsulación rota: la pregunta principal que queda es:

    Ok, entonces, ¿quién creará / requerirá las dependencias?

  • Hacer eso en cada cliente del módulo parece muy MOJADO .
  • Esto probablemente requeriría que use un contenedor DI para ser factible en un proyecto real.

Entonces, la verdadera pregunta aquí es:

¿Por qué los desarrolladores de Javascript tienden a inclinarse hacia el primer enfoque?

¿Es esto simplemente "la forma Javascript"?

Yo mismo escribo código como este la mayor parte del tiempo. He tenido mi parte justa de configuración de prueba usando bibliotecas burlonas, pero siempre me sentí un poco mal al hacerlo.

¿Me estoy perdiendo de algo?

Henrique Barcelos
fuente
Como un tipo .Net que recientemente se interesó en NodeJs, también he estado luchando con esto. He descubierto que las dependencias de parches de monos con Proxyquire (al igual que ReWire) están bien para fines de prueba, pero a veces es necesario que se implementen varias veces una dependencia ...
RubberDuck

Respuestas:

6

Principalmente soy un programador de PHP, pero he estado en contacto con 4 equipos de JavaScript durante el último año más o menos.

Como programador orientado a objetos, el principio de inyección de dependencia parece la mejor manera, sin embargo, pocos desarrolladores de JS me han dicho lo contrario. JS es un mundo completamente diferente.

Debido a que JavaScript le permite parchear cualquier cosa usando técnicas muy simples, los desarrolladores de JavaScript aprendieron a adaptar una tecnología diferente sobre cómo construir aplicaciones JavaScript a mayor escala. La mayoría de estos están construidos como conjuntos de módulos autónomos, que exponen la funcionalidad a través de exportaciones públicas, ocultando elementos internos del módulo para no permitir que otros reescriban las funciones en las que confía.

Por lo general, el enfoque habitual es incluso ir tan lejos como para no exponer a un constructor, sino exponer la construcción de un objeto utilizando una envoltura de fábrica, por la misma razón: si le da a alguien acceso a un objeto, puede instanciarlo directamente. están autorizados a cambiar cualquier cosa.

Al aprovechar el diseño modular, niega que otros jueguen con sus funciones que espera que funcionen, pero aún tiene la capacidad de probar sus módulos, a través de la API pública del archivo requerido, la API que creó.

Andy
fuente