Recentemente, estive envolvido em uma discussão sobre, digamos, técnicas modernas de JavaScript. Na discussão foi feito um ponto sobre como é difícil realizar injeção de dependência, o que eu discordo totalmente. A injeção de dependência (DI) do JavaScript não é apenas relativamente fácil, mas a natureza dinâmica do JavaScript torna extremamente fácil criar stub e simular objetos e seus membros.

Para mim, a parte mais difícil é escrever ou encontrar uma biblioteca que seja testável mock, este é um dos pontos fortes do Angular sobre outras bibliotecas, remetendo objetos mock testáveis, pelo menos foi o que eu li. Meu favorito para realmente testar dependências é com sinonjs , uma biblioteca de simulação e stub. O Sinon não faz nada com injeção de dependência, ao invés disso, ele aproveita a natureza dinâmica do JavaScript e substitui dependências por simulações, stubs e espiões.

Eu tendo a projetar minhas bibliotecas com recursos de DI naturais, o que pode ser muito útil se você deseja substituir uma dependência de objeto inteira. Na verdade, é um produto do projeto de minhas bibliotecas para depender de uma interface implícita (lembre-se de que o JavaScript não tem nenhum conceito de interface real) para que eu possa trocar as bibliotecas mais tarde.

Existem efetivamente 2 lugares onde posso injetar uma biblioteca fictícia quando eu projeto um módulo. Deixe-me mostrar o código da minha biblioteca do SPA. A primeira é a função anônima autoexecutável (SEAF). Isso é algo que eu realmente peguei no jQuery:

(function (window, $, undefined) {
//definição do módulo real aqui
}) (janela , $);

Aqui, existem 3 parâmetros definidos e um par de argumentos passados. Eu faço janela mais para fins de minimização. O $ é onde eu iria ‘injetar’ jQuery ou uma biblioteca que suporte a interface jQuery. Na verdade, escrevi uma pequena biblioteca de utilitários chamada biblioteca dollarbill que é compatível com a interface jQuery para métodos que eu realmente uso. Existem vários outros jQuery como micro bibliotecas disponíveis, então apenas suponha que você pode querer usar um deles em vez da dependência completa do jQuery. Como o SEAF permite que você passe um objeto para $, você está desacoplado de usar jQuery e deve ser capaz de usar uma biblioteca semelhante. O último argumento é um mecanismo de defesa para evitar que alguém mexa com a definição de indefinido.

Deixe-me fazer uma pequena declaração lateral sobre a implementação de uma interface. Não acredito que você precise de 100% de cobertura ao implementar uma interface para uma biblioteca como o jQuery. Na verdade, existem vários módulos que compõem o jQuery, vários que não uso mais, como animações. Eu confio no CSS para realizar animações hoje, não no JavaScript. Portanto, minha implementação da interface jQuery omitiria completamente esses membros. Se você realmente olhar para muitas classes C # e Java, elas geralmente implementam várias interfaces. O mesmo conceito se aplica aqui. Quando digo que estou implementando uma interface jQuery, estou implementando membros em minha biblioteca que realmente uso.

Aqui está o construtor do módulo SPA. Ele tem um parâmetro que é considerado um objeto JavaScript com propriedades que podem substituir os valores padrão, armazenados na propriedade de configurações do módulo (mostrado abaixo). jQuery tem um ótimo método para isso, extend, que é fácil de replicar. O sublinhado tem um método semelhante. Como passei um $ object, presumo que ele implemente o método extend, pois jQuery o possui.


var spa=function (customSettings) {
//self módulo de instanciação:) Obrigado jQuery !!!
var that=new spa.fn.init ();
//Isso mescla todas as propriedades com as configurações padrão
that.settings=$.extend ({}, that.settings, customSettings);
//injetou biblioteca de terceiros com um fallback padrão. Se o padrão falhar, as coisas devem explodir, blá, blá.
that.bp=that.settings.bp || mochila();
//mais inicialização vai aqui
}

Finalmente aqui estão as configurações padrão, observe que mesmo que eu não tenha bp definido aqui, ela pode ser aplicada usando o método extend e então usada. O parâmetro settings me permite injetar um objeto que implementa os métodos usados ​​na minha biblioteca do Backpack, mesmo que não esteja definido no objeto settings. Também tomei o cuidado de incorporar um fallback padrão. Se isso não funcionar, as coisas devem explodir na fase de desenvolvimento, pelo menos essa é a esperança e os desenvolvedores garantirão que a dependência seja incluída.

settings: {
rotas: [],
viewSelector:".content-pane",
currentClass:"current",
mainWrappperSelector:"main",
NotFoundView:"NotFound",
NotFoundRoute:"404",
defaultTitle:"Um site de página única com rotas",
titleSelector:".view-title",
forceReload:"_force_reload_",
autoSetTitle: true,
parseDOM: true,
initView: true,
viewTransition:"slide",
asyncUrl: undefined
}

Portanto, este é um exemplo simples de como você pode fazer DI em um módulo mostrando como posso injetar uma biblioteca jQueryish e uma biblioteca que suporta a interface principal da minha biblioteca Backpack. A propósito, o Backpack é uma biblioteca que escrevi para gerenciar o armazenamento de minhas visualizações em localStorage, mas pretendo criar uma nova biblioteca que implemente a mesma interface para armazenar os valores em IndexDB. Minha biblioteca do SPA não se importa onde os objetos de visualização são persistidos, ela apenas se preocupa com a interface e tentará tornar o Backpack o padrão se nada for fornecido.

Eu acredito que a maior parte disso eu aprendi estudando jQuery’s estrutura, mas já a vi usada em várias outras bibliotecas bem escritas. Angular essencialmente faz isso, apenas uma sintaxe ligeiramente diferente. Eu estarei mergulhando mais fundo no projeto de módulos como este e minhas bibliotecas SPA e Backpack e muito mais em meu próximo livro, Aplicativos de página única de alto desempenho no final deste mês. Portanto, fique alerta para quando o livro estiver disponível. Estou encerrando o conteúdo esta semana e espero que seja lançado nas próximas semanas.

Compartilhe este artigo com seus amigos!

Source link

Categories: Wordpress