Moduł wymagający a wstrzykiwanie zależności w JavaScript

24

W dzisiejszych czasach pojawiło się pytanie:

Czy sposób, w jaki JavaScript jest sprzeczny z prawie wszystkim, co jest uważane za dobrą praktykę w tradycyjnym tworzeniu oprogramowania?

Mam serię pytań / spostrzeżeń związanych z tym stwierdzeniem, ale aby uszanować format StackExchange, lepiej będzie, jeśli podzielę je na różne pytania.

Moduł wymagający

Obecnie standardowy kod JavaScript wygląda następująco:

const someModule = require('./someModule')

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

Zalety

  • Hermetyzacja: moduł działa samodzielnie i wie wszystko, czego potrzebuje do wykonywania swoich funkcji.
  • Kolorystyka ułatwia klientom korzystanie z modułu.

Niedogodności

  • Słaba testowalność: jest to standard, gdy nie używa się DI, ale w dynamicznych językach, takich jak Javscript, można go obejść * przez moduły takie jak mockerylub rewire.
  • Z pewnością narusza DIP - nie należy mylić go z wtryskiem zależności. - ponieważ mogę importować tylko konkretne moduły.
  • Prawdopodobnie narusza OCP - na przykład wyobraź sobie, że mam moduł dziennika, który zapisuje do systemu plików (poprzez fsmoduł). Gdybym chciał rozszerzyć ten moduł dziennika, aby wysłać go do sieci, byłoby to bardzo trudne.

* Może to działać z modułami CommonJS lub nawet AMD, ponieważ są one implementowane głównie w obszarze użytkownika. Nie jestem jednak pewien, jak to możliwe dzięki importskładni ES6 .

Wstrzykiwanie zależności

Przy użyciu wstrzykiwania zależności byłoby to bardziej jak:

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

Zalety

  • Zwiększona testowalność: teraz łatwiej jest stubować / wyśmiewać someModule, nawet przy użyciu składni ES6.
  • Jest to możliwe , aby uczcić DIP: niekoniecznie jednak jako moduł klient może nadal być zaprogramowany do wykonania i nie interfejsu.

Niedogodności

  • Zerwana enkapsulacja: głównym pozostałym pytaniem jest:

    Ok, to kto utworzy / będzie wymagał zależności?

  • Robienie tego u każdego klienta modułu wydaje się bardzo MOKRE .
  • Prawdopodobnie wymagałoby to ode mnie użycia kontenera DI, aby było to wykonalne w prawdziwym projekcie.

Tak więc prawdziwe pytanie brzmi:

Dlaczego programiści Javascript skłaniają się ku pierwszemu podejściu?

Czy to tylko „sposób Javascript”?

Przez większość czasu sam piszę taki kod. Miałem swój dobry udział w konfiguracji testów przy użyciu fałszywych bibliotek, ale zawsze czułem się źle.

Czy coś brakuje?

Henrique Barcelos
źródło
Jako facet .Net, który ostatnio zainteresował się NodeJ, również miałem z tym problem. Znalazłem małpa łatanie zależności z Proxyquire (podobnie jak ReWire), aby być w porządku do celów testowych, ale czasami potrzeba wielu implementacje legit z zależnością ...
RubberDuck

Odpowiedzi:

6

Jestem głównie programistą PHP, ale od około roku mam kontakt z 4 zespołami JavaScript.

Jako programista obiektowy najlepszym rozwiązaniem wydaje się zasada wstrzykiwania zależności, jednak kilku programistów JS powiedziało mi inaczej. JS to zupełnie inny świat.

Ponieważ JavaScript pozwala małpować łatać wszystko i wszystko przy użyciu bardzo prostych technik, programiści JavaScript nauczyli się dostosowywać inną technologię do tworzenia aplikacji JavaScript na większą skalę. Większość z nich jest zbudowana jako zestawy samodzielnych modułów, które ujawniają funkcjonalność poprzez publiczny eksport, ukrywając elementy wewnętrzne modułu, aby nie pozwolić innym na przepisanie funkcji, na których się opierasz.

Zwykle podejście polega na tym, że nawet nie ujawnia się konstruktora, ale raczej ujawnia konstrukcję obiektu za pomocą fabrycznego opakowania - z tego samego powodu: jeśli dasz komuś dostęp do obiektu, może on bezpośrednio utworzyć instancję mogą zmieniać cokolwiek.

Korzystając z modułowej konstrukcji, nie pozwalasz innym manipulować funkcjami, których spodziewasz się działać, ale nadal możesz testować swoje moduły - za pośrednictwem publicznego interfejsu API wymaganego pliku, utworzonego interfejsu API.

Andy
źródło