Модуль, що вимагає введення залежності від залежності в JavaScript


24

Цими днями у мене в голові спливе запитання:

Чи суперечить нам спосіб Javascript майже всьому, що вважається хорошою практикою в традиційній розробці програмного забезпечення?

У мене є низка запитань / спостережень, пов'язаних з цим твердженням, але для того, щоб поважати формат StackExchange, буде краще, якщо я розділю їх на різні запитання.

Модуль, що вимагає

На сьогодні стандартний код Javascript виглядає так:

const someModule = require('./someModule')

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

Переваги

  • Інкапсуляція: модуль працює автономно і знає все, що потрібно для виконання його функцій.
  • Як кольоровий, клієнтам простіше використовувати модуль.

Недоліки

  • Погана перевіряемость: це звичайно, коли не використовується DI, але в динамічних мовах, таких як Javscript, його можна обійти * модулями, як mockeryабо rewire.
  • Це, безумовно, порушує DIP - не плутати з введенням залежності. - оскільки я можу імпортувати лише конкретні модулі.
  • Це, ймовірно, порушує OCP - наприклад, уявіть, що у мене є модуль журналу, який записує у файлову систему (через fsмодуль). Якщо я хочу розширити цей модуль журналу, щоб надіслати його в мережу, було б дуже важко.

* Це може працювати з CommonJS або навіть модулями AMD, оскільки вони в основному реалізовані в країні користувачів. Однак я не впевнений, як це могло бути можливим із importсинтаксисом ES6 .

Ін'єкційна залежність

Використовуючи ін'єкційну залежність, це було б більше як:

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

Переваги

  • Підвищена заповідність: тепер легше someModuleзаглушити / знущатися , навіть використовуючи синтаксис ES6.
  • Це можна шанувати DIP: не обов'язково , хоча, як клієнтський модуль все ще може бути запрограмований для реалізації і не інтерфейс.

Недоліки

  • Розбита інкапсуляція: головне питання, що залишається:

    Добре, тоді хто буде створювати / вимагати залежності?

  • Це в кожному клієнті модуля здається дуже мокрим .
  • Це, можливо, вимагає від мене використовувати контейнер DI, щоб це було можливо в реальному проекті.

Отже, справжнє питання тут:

Чому розробники Javascript схиляються до першого підходу?

Це просто "шлях Javascript"?

Я сам пишу такий код більшу частину часу. Я мав свою частку тестових налаштувань з використанням насмішкувальних бібліотек, але це завжди було не так.

Я щось пропускаю?


Як хлопець .Net, який останнім часом зацікавився NodeJs, я теж боровся з цим. Я знайшов мавпу зашивання залежностей з Proxyquire (так само, як ReWire) , щоб бути в порядку для цілей тестування, але іноді законні потреби кілька реалізацій в залежності ...
RubberDuck

Відповіді:


6

Я в основному програміст PHP, але останній рік контактую з 4 командами JavaScript.

Як об'єктно-орієнтований програміст, принцип ін'єкції залежності здається найкращим способом, однак мені було сказано інакше декількома розробниками JS. JS - це зовсім інший світ.

Оскільки JavaScript дозволяє вам латати мавпами що завгодно і все, використовуючи дуже прості методи, розробники JavaScript навчилися адаптувати іншу технологію щодо побудови додатків JavaScript більшого масштабу. Більшість із них складаються як набори автономних модулів, які розкривають функціональність за допомогою публічного експорту, приховуючи внутрішні модулі, щоб не дозволяти іншим переписати функції, на які ви покладаєтесь.

Звичайний підхід, як правило, полягає навіть у тому, щоб не піддавати конструктору те, що коли-небудь, а навпаки, розкривати конструювання об'єкта за допомогою фабричної обгортки - саме з тієї ж причини: якщо ви дасте комусь доступ до об'єкта, він може інстанціювати безпосередньо його дозволяється будь-що змінювати.

Скориставшись модульним дизайном, ви заперечуєте інших поспілкуватися з вашими функціями, які ви очікуєте працювати, але ви все ще маєте можливість протестувати свої модулі - через відкритий API потрібного файлу, створений вами API.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.