Зависимость от инъекции нарушает Закон Деметры
Я добавляю инъекцию зависимостей к моему коду, потому что он делает код намного проще Unit test через насмешку.
Тем не менее, я требую, чтобы объекты выше моей цепочки вызовов, чтобы знать объекты дальше по цепочке вызовов.
Разве это нарушает Закон Деметры? Если это имеет значение?
например: класс A имеет зависимость от интерфейса B, реализация этого интерфейса для использования вводится в конструктор класса A. Любой, кто хочет использовать класс A, теперь должен также иметь ссылку на реализацию B И может вызывать его методы, непосредственно значащие и знающие его субкомпоненты (интерфейс В)
Википедия говорит о законе Деметры: "Основное понятие состоит в том, что данный объект должен как можно меньше предполагать о структуре или свойствах чего-либо еще (включая его подкомпоненты)".
Ответы
Ответ 1
Инъекция зависимостей МОЖЕТ нарушить Закон Деметры. Если вы вынуждаете потребителей делать инъекции зависимостей. Этого можно избежать с помощью статических методов factory и каркасов DI.
Вы можете создать оба объекта, сконструировав свои объекты таким образом, чтобы они требовали передачи зависимостей и в то же время имели механизм их использования без явного выполнения инъекции (factory функции и рамки DI).
Ответ 2
Как это сломается? DI прекрасно вписывается в идею наименьшего знания. DI дает вам низкую связь - объекты менее ответственно друг на друга.
Ссылаясь на Википедию:
... объект A может запросить услугу (вызов метод) экземпляра объекта B, но объект A не может "достигнуть" объекта B для доступа к еще одному объекту...
Обычно DI работает точно так же, т.е. вы используете услуги, предоставляемые инъецированными компонентами. Если ваш объект пытается получить доступ к некоторым из B-зависимостей, то есть он много знает о B, что приводит к высокой связи и ломает идею DI
Однако мне требуются объекты выше моя цепочка звонков, чтобы знать объекты далее вниз по цепочке вызовов
Пример:
Ответ 3
Если я правильно вас понимаю, это не вызвано использованием инъекции зависимостей, вызванной использованием насмешливых стратегий, в которых вы указываете вызовы функций, которые вы ожидаете от метода. Это совершенно приемлемо во многих ситуациях, но, очевидно, это означает, что вам нужно знать что-то о методе, который вы вызываете, если вы указали, что, по вашему мнению, оно должно делать.
Написание хорошего программного обеспечения требует балансировки компромиссов. По мере того как реализация становится более полной, она становится более непоследовательной. Вы должны решить, какие риски создают эти несоответствия, и заслуживают ли они ценности, созданной их присутствием.
Ответ 4
Разве это нарушает закон?
Строго говоря, я думаю, что это так.
Это важно?
Главная опасность нарушения закона заключается в том, что вы делаете свой код более хрупким.
Если вы действительно держите его только на тестах, кажется, что эта опасность не так уж плоха.
Смягчение
Мое понимание Закона Деметра заключается в том, что за ним могут последовать "методы-обертки", которые предотвращают прямое обращение к объектам.
Ответ 5
Закон Деметры указывает, что метод M объекта O может вызывать методы для объектов, созданных/созданных внутри M. Однако нет ничего, что указывало бы, как эти объекты были созданы. Я думаю, что совершенно нормально использовать промежуточный объект для их создания, если только цель этого объекта в жизни - это только создание других объектов от вашего имени. В этом смысле DI не нарушает Закон Деметры.
Ответ 6
Зависит: -)
Я думаю, что лучший ответ неверен, даже с картой, в которой много кода использует инъекцию зависимостей и вводит объекты высокого уровня. Затем вы получаете код спагетти с большим количеством зависимостей.
Инъекция зависимостей лучше всего использовать для всего материала, который будет загрязнять вашу объектную модель, например, ILogger. Если вы делаете бизнес-объект, убедитесь, что он доступен на самом низком уровне и попробуйте передать его традиционный метод, если сможете. Используйте инъекцию dependecy, если она становится грязной.
Ответ 7
Прежде чем добавить свой ответ, я должен его квалифицировать. Сервисно-ориентированное программирование построено поверх принципов ООП и использует языки OO. Кроме того, SOA следуют за инверсией Control и SOLID Principles к зубам. Таким образом, много сервис-ориентированных программистов, несомненно, прибывают сюда. Итак, этот ответ предназначен для сервис-ориентированных программистов, которые приходят на этот вопрос, потому что SOA построена поверх OOP. Это не дает прямого ответа на пример OP, но отвечает на вопрос с точки зрения SOA.
В целом, Закон Деметры не применяется к сервис-ориентированной архитектуре. Для ОО закон Деметры говорит о "богатых объектах" в ООП, которые имеют свойства и методы, и свойства которых также могут иметь методы. С OOP Rich Models можно охватить цепочку объектов и методы доступа, свойства, методы свойств, методы свойств свойств и т.д. Но в сервис-ориентированном программировании данные (свойства) отделяются от процесса (методы). В ваших моделях (в основном) есть только свойства (безусловно, никогда не зависимые), а ваши службы имеют только методы и зависимости от других служб.
В SOP вы можете свободно просматривать свойства модели и свойства ее свойств. Вы никогда не сможете получить доступ к методам, которых вы не должны, только к дереву данных. Но как насчет Сервисов? Применяется ли там Закон Деметры?
Да, Закон Деметры может быть применен к SOP-сервисам. Но опять же, закон был первоначально разработан для Rich Models в ООП. И хотя закон может применяться к Услугам, надлежащая инъекция зависимостей автоматически выполняет Закон Деметры. В этом смысле Д.И. не мог нарушить закон.
В ограниченной оппозиции Марку Родди я не могу найти никакой ситуации, когда вы можете законно говорить об инъекциях зависимостей и "потребителях" в том же предложении. Если под "потребителями" вы подразумеваете класс, который потребляет другой класс, это не имеет смысла. С DI вы должны иметь корневой состав, составляющий ваш граф объектов, и один класс никогда не должен знать, что еще один класс существует. Если "потребители" вы имеете в виду программиста, то как бы они не были вынуждены "делать инъекции". Программист - это тот, кто должен создать Корень Композиции, поэтому они должны делать инъекцию. Программист никогда не должен "делать инъекцию" как экземпляр внутри класса, чтобы потреблять другой класс.
Пожалуйста, просмотрите следующий пример, который показывает фактические отдельные решения, их ссылки и внедряющий код:
![В SOA DI не разрешает ломание LoD></a></p> <p>В правом верхнем углу у нас есть]()
В левом верхнем углу мы имеем внешнюю реализацию ядра. Реализация зависит от Ядра, и поэтому имеет знание об этом.
В левом нижнем углу у нас есть отдельный домен. Домен имеет зависимость от некоторой реализации ядра, но Не нужно знать о реализации.
Здесь я указываю, что ни домен, ни реализация не знают друг друга. Есть вероятность 0%, что либо когда-либо может достичь (или за ее пределами) другой, потому что они даже не знают, что они существуют. Домен знает только, что есть контракт, и он может каким-то образом использовать методы тем, что вводится в него.
В левом нижнем углу находится кортеж композиции или точка входа. Это также известно как "Front Boundary" приложения. Корень приложения знает все его компоненты и делает не что иное, как ввод данных, определяет, кому звонить, составлять объекты и возвращать выходы. Другими словами, он может только сообщить домену "Здесь, используйте это, чтобы выполнить свой контракт для ICalculateThings, а затем дать мне результат CalculateTwoThings.
Существует действительно способ разбить все на один и тот же проект, сделать конкретные экземпляры сервисов, сделать ваши зависимые общедоступные свойства вместо частных полей, STILL Do Dependency-Injection (ужасно), а затем вызвать вызовы служб в зависимости от зависимостей, Но это было бы плохо, м'кай. Вы должны были бы быть плохими, чтобы сделать это.
Боковое замечание, я слишком усложнил это. Эти проекты могут существовать в одном решении (до тех пор, пока Архитектор контролирует эталонную архитектуру), и может быть еще несколько упрощений. Но разделение в изображении действительно показывает, как мало знаний система должна иметь о своих частях. Только часть корня композиции (точка входа, передняя граница) должна знать о деталях.
Заключение (TL; DR;): В Олдскул ООП модели богаты, и закон Деметры можно легко сломать, изучая модели моделей для доступа к их методам. Но в Newskewl SOP (построенном на основе принципов и языков ООП) данные отделены от процесса. Поэтому вы можете свободно смотреть в свойства моделей. Затем для сервисов зависимости всегда являются частными, и ничто не знает, что что-либо еще существует, кроме того, что им говорят абстракции, контракты, интерфейсы.