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


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

закон можно сформулировать просто как "использовать только одну точку".

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

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

Так это идет вместе?

6 54

6 ответов:

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

также обратите внимание, что "закон" - это только рекомендации по лучшей практике для" классических " API. Fluent interfaces-это совершенно другой подход к проектированию 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, который обычно представляет весь домен в виде графа объектов, может быть идея определить приемлемую "область" для конкретного объекта. Возможно, нам следует принять закон Деметры, чтобы предложите, чтобы вы не отображали весь график как доступный.

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

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

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) Как говорит Добрый старина Фил Хаак:закон Деметры - это не упражнение по подсчету точек

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