Нарушает ли зависимость зависимость закон Деметры - PullRequest
15 голосов
/ 02 октября 2008

Я добавил инъекцию зависимостей в мой код, потому что это делает код гораздо проще для модульного тестирования с помощью имитации.

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

Это нарушает закон Деметры? Если так, то имеет ли это значение?

например: класс A имеет зависимость от интерфейса B. Реализация этого интерфейса для использования вставляется в конструктор класса A. Любой, кто хочет использовать класс A, должен теперь также иметь ссылку на реализацию B И может вызывать его методы непосредственно в смысле и знать его подкомпоненты (интерфейс B)

Википедия говорит о законе Деметры: «Фундаментальное понятие состоит в том, что данный объект должен как можно меньше предполагать о структуре или свойствах чего-либо еще (включая его подкомпоненты)».

Ответы [ 7 ]

12 голосов
/ 02 октября 2008

Внедрение зависимости МОЖЕТ нарушить закон Деметры. Если вы заставляете потребителей делать инъекции зависимостей. Этого можно избежать с помощью статических фабричных методов и структур DI.

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

3 голосов
/ 02 октября 2008

Как это сломать? Я прекрасно вписываюсь в идею наименьшего количества знаний. DI дает вам слабую связь - объекты меньше обвиняют друг друга.

Ссылаясь на Википедию:

... объект А может запросить услугу (позвонить метод) экземпляра объекта B, но объект А не может «пройти сквозь» объект B для доступа к еще одному объекту ...

Обычно DI работает точно так же, то есть вы пользуетесь услугами, предоставляемыми внедренными компонентами. Если ваш объект пытается получить доступ к некоторым из зависимостей B, то есть он много знает о B - это приводит к сильной связи и нарушает представление о DI

Однако мне требуются объекты выше до моей цепочки вызовов, чтобы иметь знания о объекты дальше по цепочке вызовов

Какой-нибудь пример?

2 голосов
/ 02 октября 2008

Если я правильно вас понимаю, это не связано с использованием внедрения зависимостей, это связано с использованием стратегий насмешек, в которых вы указываете вызовы функций, которые вы ожидаете от метода. Это вполне приемлемо во многих ситуациях, но, очевидно, это означает, что вы должны знать кое-что о вызываемом методе, если вы указали, что, по вашему мнению, он должен делать.

Написание хорошего программного обеспечения требует баланса компромиссов. По мере того как реализация становится более полной, она становится более противоречивой. Вы должны решить, какие риски создают эти несоответствия и стоят ли они ценности, создаваемой их присутствием.

1 голос
/ 02 октября 2008

Закон Деметры указывает, что метод M объекта O может вызывать методы для объектов, созданных / созданных внутри M. Однако нет ничего, что определяло бы, как эти объекты были созданы. Я думаю, что совершенно нормально использовать промежуточный объект для их создания, если целью этого объекта в жизни является только создание других объектов от вашего имени. В этом смысле Д.И. не нарушает закон Деметры.

1 голос
/ 02 октября 2008

Это нарушает закон?
Строго говоря, я так думаю.
Имеет ли это значение?
Главная опасность нарушения закона состоит в том, что вы делаете свой код более хрупким.
Если вы действительно придерживаетесь только тестов, кажется, что опасность не так уж и велика.
Смягчение
Мое понимание Закона Деметры заключается в том, что за ним могут следовать "методы-обертки", которые предотвращают прямой вызов в объекты.

0 голосов
/ 20 июня 2017

Прежде чем я добавлю свой ответ, я должен уточнить его. Сервис-ориентированное программирование построено на принципах ООП и использует ОО-языки. Кроме того, СОА следуют принципам обращения и твердости к зубам. Таким образом, многие Сервис-ориентированные программисты наверняка прибудут сюда. Таким образом, этот ответ предназначен для сервис-ориентированных программистов, которые приходят к этому вопросу, потому что SOA построен поверх OOP. Это не дает прямого ответа на пример OP, но отвечает на вопрос с точки зрения SOA.

В общем, закон Деметры не распространяется на сервис-ориентированные архитектуры. Для ОО Закон Деметры говорит о «богатых объектах» в ООП, которые имеют свойства и методы, и чьи свойства также могут иметь методы. С помощью OOP Rich Models можно получить доступ через цепочку объектов и методов доступа, свойств, методов свойств, методов свойств свойств и т. Д. Но в сервис-ориентированном программировании данные (свойства) отделены от процесса (методы). ). Ваши модели (в основном) имеют только свойства (конечно, никогда не зависят), а ваши службы имеют только методы и зависимости от других служб.

В SOP вы можете свободно просматривать свойства модели и свойства ее свойств. Вы никогда не сможете получить доступ к методам, которые не должны, только к дереву данных. Но как насчет услуг? Применяется ли там закон Деметры?

Да, Закон Деметры Может применяться к Службам СОП. Но опять же, закон изначально был разработан для богатых моделей в ООП. И хотя закон может быть применен к услугам, правильное внедрение зависимостей автоматически выполняет закон Деметры. В этом смысле Д.И. не мог нарушить закон.

В условиях ограниченной оппозиции Марку Родди я не могу найти ни одной ситуации, в которой вы могли бы на законных основаниях говорить о внедрении зависимости и «потребителях» в одном предложении. Если под «потребителями» вы подразумеваете класс, который потребляет другой класс, это не имеет смысла. С DI у вас будет Composition Root, составляющий ваш объектный граф, и один класс никогда не должен знать, что другой класс даже существует. Если под «потребителями» вы подразумеваете программиста, то как бы они не были бы вынуждены «делать инъекции». Программист - это тот, кто должен создать корень композиции, поэтому он должен выполнить внедрение. Программист никогда не должен «делать инъекцию» в качестве экземпляра внутри класса, чтобы использовать другой класс.

Пожалуйста, просмотрите следующий пример, который показывает реальные отдельные решения, их ссылки и код реализации:

In SOA, DI doesn't allow breaking of LoD

В верхнем правом углу у нас есть "Ядро". Многие пакеты в NuGet и NPM имеют «базовый» проект, который имеет модель, интерфейсы и, возможно, даже реализации по умолчанию. Ядро никогда не должно зависеть от чего-то внешнего.

В верхнем левом углу у нас есть внешняя реализация ядра. Реализация зависит от Ядра и поэтому знает об этом.

В левом нижнем углу у нас есть автономный домен. Домен имеет зависимость от некоторой реализации ядра, но Не нужно знать о реализации .

Здесь я отмечаю, что ни Домен, ни Реализация не знают друг друга. Вероятность того, что кто-либо из них когда-либо достигнет (или превзойдет) другого, равна 0%, поскольку они даже не знают о своем существовании. Домен знает только, что есть контракт, и он может каким-то образом потреблять методы любым способом, введенным в него.

В левом нижнем углу находится корень композиции или точка входа. Это также известно как «Передняя граница» приложения. Корень приложения знает все его компоненты и делает не больше, чем принимает входные данные, определяет, кому вызывать, создает объекты и возвращает выходные данные. Другими словами, он может сообщить домену только «Здесь, используйте это, чтобы выполнить ваш контракт на ICalculateThings, а затем дайте мне результат CalculateTwoThings.

Действительно, есть способ втиснуть все в один и тот же проект, сделать конкретные экземпляры Сервисов, сделать ваши зависимости открытыми свойствами вместо частных полей, STILL Do Dependency-Injection (ужасно), а затем заставить сервисы вызывать зависимости зависимостей , Но это было бы плохо, хорошо. Вы должны пытаться быть плохим, чтобы сделать это.

Примечание: я специально усложнил это. Эти проекты могут существовать в одном решении (при условии, что Архитектор контролирует Эталонную архитектуру), и может быть еще несколько упрощений. Но разделение на изображении действительно показывает, насколько мало система должна знать о своих частях. Только корень композиции (точка входа, передняя граница) должен знать о деталях.

Заключение (TL; DR;): В ООП Oldskewl Модели богаты, и закон Деметры может быть легко нарушен, если посмотреть модели моделей для доступа к их методам. Но в Newskewl SOP (построенном на принципах и языках ООП) данные отделены от процесса. Таким образом, вы можете свободно смотреть на свойства моделей. Затем для Сервисов зависимости всегда являются частными, и никто не знает, что существует что-то еще, кроме того, что им говорят абстракции, контракты, интерфейсы.

0 голосов
/ 26 мая 2009

Зависит от: -)

Я думаю, что верхний ответ не верен, даже если в фреймворке много кода использует внедрение зависимостей и внедряет высокоуровневые объекты. Затем вы получите спагетти-код с множеством зависимостей.

Внедрение зависимостей лучше всего использовать для всего, что может загрязнить вашу объектную модель, например, для ILogger. Если вы вводите бизнес-объект, убедитесь, что он находится на самом низком уровне, и попытайтесь передать его традиционным способом, если можете. Используйте инъекцию зависимости, только если она становится грязной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...