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