5

Я работаю в рамках Javascript + BackboneJS (инфраструктура MVC) + Framework RequireJS, но этот вопрос несколько носит общий характер.Инъекция зависимостей против управляемых зависимостей против глобального объекта

Позвольте мне начать с объяснения, что в магистральной сети, ваши взгляды представляют собой смесь традиционных представлений и контроллеров, и ваши HTML шаблоны традиционные MVC Просмотров

ломал голову об этом на некоторое время и я не уверен, какой должен быть правильный/прагматичный подход.

У меня есть объект User, который содержит пользовательские настройки (например, систему единиц, выбор языка, что-то еще), от которых зависит много кода.

Некоторые из моих представлений делают большую часть работы без использования шаблонов (с использованием сторонних библиотек, таких как Mapping и Graphing libs), и поэтому они имеют зависимость от объекта User, чтобы заботиться о преобразовании единиц, например. В настоящее время я использую RequireJS для управления этой зависимостью, не нарушая при этом инкапсуляцию.

Некоторые из моих представлений сами по себе мало работают и передают только данные модели в мой шаблонный шаблон/шаблоны, которые выполняют эту работу и имеют зависимость от объекта User, опять же, для таких вещей, как преобразование единиц. Единственный способ передать эту зависимость в шаблон - это ввести ее в модель и передать модель в механизм шаблона.

Мой вопрос в том, как лучше всего справиться с такой широко требуемой зависимостью? - Создать общедоступный справочный/глобальный объект, доступный везде? (YUK) - Использовать управляемые зависимости RequireJS, хотя обычно рекомендуется использовать управляемую загрузку зависимостей для определений классов/объектов, а не конкретных объектов. - Или только когда-либо применяйте инъекцию зависимостей и вручную передавайте эту зависимость во все, что в ней нуждается?

ответ

4

С чисто технической точки зрения, я бы сказал, что коммутируемые глобальные переменные (глобальные переменные, которые могут меняться), особенно в javascript, являются опасными и неправильными. Тем более, что javascript полон части кода, которые выполняются асинхронно. Рассмотрим следующий код:

window.loggedinuser = Users.get("Paul"); 
addSomeStuffToLoggedinUser(); 
window.loggedinuser = Users.get("Sam"); 
doSomeOtherStuffToLoggedinUser(); 

Теперь, если addSomeStuffToLoggedinUser() выполняется асинхронно где-то (например, это делает Ajax вызов, а затем другой Ajax вызов, когда первый один заканчивает), это может быть очень хорошо добавлять материал к новому loggedinuser («Сэм»), к тому времени, когда он доберется до второго вызова ajax. Ясно, что вы не хотите.

Сказав это, я даже менее сторонник наличия некоторого пользовательского объекта, который мы все время передаем от функции к функции, до бесконечности.

Лично, имея возможность выбирать между этими двумя зол, я бы выбрал глобальную сферу для вещей, которые «очень редко меняются» --- если, возможно, я не строил атомную электростанцию ​​или что-то в этом роде. Таким образом, я стараюсь сделать доступным пользователя в глобальном масштабе в моем приложении, рискуя, что если почему-то по какой-то причине какой-либо вызов выполняется очень поздно, и у меня есть ситуация, когда один пользователь выходит из системы, а другой другой регистрируется, что-то странно может случиться. (опять же, если метеорит врезается в центр обработки данных, в котором размещается мое приложение, может произойти что-то странное ... Я тоже не защищаю это). На самом деле возможным решением было бы перезагрузить все приложение, как только кто-то выйдет из системы.

Итак, я думаю, все зависит от вашего приложения. Одна вещь, которая делает это лучше (и заставляет вас чувствовать, что вы все еще получаете некоторые моменты OO кармы), чтобы скрыть свои данные в некоторых Namespaced одноточечного:

var myuser = MyApp.domain.LoggedinDomain.getLoggedinUser(); 
doSomethingCoolWith(myuser); 

в смену

doSomethingCoolWith(window.loggedinuser); 

хот это в значительной степени то же самое в конце концов ...

+0

Для чего вы можете найти несколько отличных шаблонов для смягчения этой проблемы, используя отложенные данные, чтобы сидеть перед коммутируемыми глобалами, которые могут быть изменены асинхронно –

1

Я думаю, что вы уже ответили на свой вопрос, вы просто хотите, чтобы кто-то еще сказал это вам:) Используйте DI, но вы на самом деле не «вручную» передаете эту зависимость во все, так как вам нужно ссылаться на нее это так или иначе.

1

Учитывая подход TDD, как бы вы протестировали это? DI лучше всего подходит для нового проекта, но JS дает вам гибкие возможности для решения конкретных глобальных зависимостей при тестировании, то есть: построение контекста. Возвращаясь назад, Yahoo выложил шаблон модуля, где все модули были слабо связаны друг от друга и не зависели друг от друга, но было нормально иметь глобальный контекст. Этот глобальный контекст может сделать ваше приложение более прагматичным для вещей, которые постоянно используются повторно. Просто, что вам нужно применять это разумно/экономно, и для того, чтобы быть динамичным, нужны очень сильные случаи.

Смежные вопросы