Si no utiliza una biblioteca DI completa, ¿la única forma de burlarse de los objetos en JS es parchear la función require ()?

JavaScript permite módulos paramétricos, que son el único requisito que necesita para la inyección de dependencia. Esto es más directo que los contenedores DI, pero también puede requerir escribir / cambiar más cosas.

Gilad Bracha tiene un par de publicaciones en el blog que explican esto (aquí y aquí), aunque no estoy seguro de cuán accesible es para las personas fuera de la comunidad PL.

Sin embargo, la intuición no requiere tanto conocimiento fuera de los objetos y parámetros. Por ejemplo, si tiene algún código que depende del sistema de archivos, tiene dos opciones:

1) Usted elige una implementación particular de sistemas de archivos y la vincula directamente a su código. De esta manera obtienes:

const fs = require (‘fs’);

función readJson (ruta) {
devolver nueva promesa ((resolver, rechazar) => {
fs.readFile (ruta, ‘utf8’, (err, data) => {
if (err) devuelve rechazar (err);
tratar {
resolver (JSON.parse (datos));
} catch (err) {
rechazar (err);
}
});
});
}

module.exports = {readJson};

// consumer.js
require (‘algún módulo’). readJson (‘foo.json’);

2) Permitir que los usuarios externos le proporcionen una implementación particular del sistema de archivos. De esta manera obtienes:

función jsonReader (fileSystem) {
regreso {
readJson (ruta) {
devolver nueva promesa ((resolver, rechazar) => {
fileSystem.readFile (ruta, ‘utf8’, (err, data) => {
if (err) devuelve rechazar (err);
tratar {
resolver (JSON.parse (datos));
} catch (err) {
rechazar (err);
}
});
});
}
}
}

module.exports = jsonReader;

// consumer.js
const fs = require (‘fs’);
const reader = require (‘algún módulo’) (fs) .readJson (‘foo.json’);

El segundo funciona muy bien para las aplicaciones que controlas, pero funciona menos bien para los módulos, ya que todo lo demás en el lenguaje usa implementaciones directamente. Dicho esto, muchas bibliotecas npm funcionan de la misma manera que se describe en (2), en particular las bibliotecas de envoltorios.

Otro problema con este enfoque es que es mucho más trabajo pasar todas estas dependencias a su alrededor. Una biblioteca de inyección de dependencia ayuda con esa parte, mientras realiza otras compensaciones (la indirección requiere comprender el sistema DI antes de comprender su código, por ejemplo).

No. Siempre puede inyectar dependencias a través del constructor e implementar su propia fábrica. Si recurre a requerir / importar en el fondo de su aplicación, tgis conduce a un acoplamiento estrecho … en algunos casos, como cuando extiende una clase, está bien …