Во-первых, я хочу ограничить этот вопрос только веб-разработкой.Так что это не зависит от языка, пока язык используется для веб-разработки.Лично я пришел к этому из фона в PHP.
Часто нам нужно использовать объект из нескольких областей.Например, нам может понадобиться использовать класс базы данных в обычной области, но также и из класса контроллера.Если мы создадим объект базы данных в обычном объеме, то мы не сможем получить к нему доступ из класса контроллера.Мы хотим избежать создания двух объектов базы данных в разных областях и поэтому нам нужен способ повторного использования класса базы данных независимо от области видимости.Для этого у нас есть две опции:
- Сделать объект базы данных глобальным, чтобы к нему можно было получить доступ из любого места.
- Передать класс базы данных в класс контроллера вФорма, например, параметр конструктора контроллера.Это известно как внедрение зависимостей (DI).
Проблема становится более сложной, когда во многих классах задействованы все требовательные объекты во многих различных областях.В обоих решениях это становится проблематичным, потому что если мы сделаем каждый из наших объектов глобальным, мы добавим слишком много шума в глобальную область, и если мы передадим слишком много параметров в класс, управлять этим классом станет намного сложнее.
Поэтому в обоих случаях вы часто видите использование реестра.В глобальном случае у нас есть объект реестра, который становится глобальным, а затем добавляем все наши объекты и переменные к нему, делая их доступными в любом объекте, но помещая только одну переменную, реестр, в глобальную область.В случае DI мы передаем объект реестра в каждый класс, уменьшая количество параметров до 1.
Лично я использую последний подход из-за множества статей, которые рекомендуют использовать глобальные переменные, но я столкнулся с двумяпроблемы.Во-первых, класс реестра будет содержать огромное количество рекурсии.Например, класс реестра будет содержать переменные входа в базу данных, необходимые для класса базы данных.Поэтому нам нужно внедрить класс реестра в базу данных.Однако база данных понадобится многим другим классам, и поэтому базу данных нужно будет добавить в реестр, создав цикл.Могут ли современные языки справиться с этим нормально или это вызывает огромные проблемы с производительностью?Обратите внимание, что глобальный реестр не страдает от этого, поскольку он ни во что не передается.
Во-вторых, я начну передавать большие объемы данных объектам, которые в этом не нуждаются.Моя база данных не заботится о моем маршрутизаторе, но маршрутизатор будет передан в базу данных вместе с деталями подключения к базе данных.Это усугубляется из-за проблемы рекурсии, потому что, если у маршрутизатора есть реестр, у реестра есть база данных, а реестр и реестр передаются в базу данных, то база данных передается сама себе через маршрутизатор (т.е. я мог бы сделать $this->registry->router->registry->database
изнутри класса базы данных`).
Кроме того, я не вижу, что дает мне ДИ, кроме большей сложности.Я должен передать дополнительную переменную в каждый объект, и я должен использовать объекты реестра с $this->registry->object->method()
вместо $registry->object->method()
.Теперь это, очевидно, не является серьезной проблемой, но это кажется ненужным, если оно не дает мне ничего общего с глобальным подходом.
Очевидно, что этих проблем не существует, когда я использую DI без реестра, но затем яприходится передавать каждый объект «вручную», что приводит к созданию конструкторов классов со смешным количеством параметров.
Учитывая эти проблемы с обеими версиями DI, разве глобальный реестр не превосходит?Что я теряю, используя глобальный реестр через DI?
Одна вещь, которая часто упоминается при обсуждении DI vs Globals, это то, что globals ограничивают вашу способность правильно тестировать вашу программу. Как именно глобалы мешают мне тестировать программу, в которой DI не будет? Я читал во многих местах, что это происходит из-за того, что глобальный объект может быть изменен из любой точки мира, и поэтому его трудно высмеять. Однако мне кажется, что, поскольку, по крайней мере в PHP, объекты передаются по ссылке, изменение внедренного объекта в некотором классе также изменит его в любом другом классе, в который он был внедрен.