Нарушают ли плавные интерфейсы Закон Деметры?

StackOverflow https://stackoverflow.com/questions/67561

Вопрос

А статья в Википедии о Закон Деметры говорит:

Закон можно сформулировать просто: «используйте только одну точку».

Однако простой пример из свободный интерфейс может выглядеть так:

static void Main(string[] args)
{
   new ZRLabs.Yael.Pipeline("cat.jpg")
        .Rotate(90)
        .Watermark("Monkey")
        .RoundCorners(100, Color.Bisque)
        .Save("test.png");
}

Так это сочетается?

Это было полезно?

Решение

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

Также обратите внимание, что «закон» — это всего лишь рекомендации по передовому опыту для «классических» API.Свободные интерфейсы — это совершенно другой подход к проектированию API, и его нельзя оценить с помощью закона Деметры.

Другие советы

Не обязательно.«Используйте только одну точку» — неточное изложение Закона Деметры.

Закон Деметры не рекомендует использовать несколько точек, когда каждая точка представляет результат другого объекта, например:

  • Первая точка — это метод, вызываемый из ObjectA, возвращающий объект типа ObjectB.
  • Следующая точка — это метод, доступный только в ObjectB, возвращающий объект типа ObjectC.
  • Следующая точка — это свойство, доступное только в ObjectC.
  • до бесконечности

Однако, по крайней мере, на мой взгляд, Закон Деметры не нарушается, если возвращаемый объект каждой точки по-прежнему имеет тот же тип, что и исходный вызывающий объект:

var List<SomeObj> list = new List<SomeObj>();
//initialize data here
return list.FindAll( i => i == someValue ).Sort( i1, i2 => i2 > i1).ToArray();

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

Что, как говорится не все свободные интерфейсы нарушают Закон Деметры, если они возвращают тот же тип, что и вызывающая сторона.

Да, хотя к ситуации придется применить некоторый прагматизм.Я всегда принимаю Закон Деметры как руководство, а не как правило.

Конечно, вы можете захотеть избежать следующего:

CurrentCustomer.Orders[0].Manufacturer.Address.Email(text);

возможно заменить на:

CurrentCustomer.Orders[0].EmailManufacturer(text);

Поскольку все больше из нас используют ORM, который обычно представляет весь домен в виде графа объектов, возможно, стоит определить приемлемую «область действия» для конкретного объекта.Возможно, нам следует воспользоваться законом Деметры и предположить, что не следует отображать весь граф как достижимый.

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

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

1) Это совершенно не нарушает его.

Код эквивалентен

var a = new ZRLabs.Yael.Pipeline("cat.jpg");
a = a.Rotate(90);
a = a.Watermark("Monkey");
a = a.RoundCorners(100, Color.Bisque);
a = a.Save("test.png");

2) Как говорит старый добрый Фил Хаак: Закон Деметры — это не подсчет точек

С вашим примером проблем нет.В конце концов, вы вращаете, ставите водяные знаки и т. д.всегда одно и то же изображение.Я считаю, что вы все время разговариваете с объектом Pipeline, поэтому, пока ваш код зависит только от класса Pipeline, вы не нарушаете LoD.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top