Запутался в законе принципа Деметры

Чтобы объяснить мою проблему, позвольте мне показать вам пример кода на C#.

interface IConstructorInfoSelector
{
    //ConstructorInfo is System.Reflection.ConstructorInfo class.
    ConstructorInfo SelectConstructorInfo(Type declaringType);
}

class TestClass
{
    private readonly ConstructorInfo _constructorInfo;

    public TestClass(IConstructorInfoSelector constructorInfoSelector, Type type)
    {
        //Let the line to (A)
        _constructorInfo = constructorInfoSelector.SelectConstructorInfo(type);
    }

    public TestClass(ConstructorInfo constructorInfo)
    {
        _constructorInfo = constructorInfo;
    }

    public Type GetTypeForConstructor()
    {
        //Let the line to (B)
        return _constructorInfo.DeclaringType;
    }
}

В примере, если я создам TestClass с помощью ctor(IConstructorInfoSelector, Type) и вызову GetTypeForConstructor, это нарушит LoD (закон принципа Деметры) через линии (A) и (B).

Однако, если я выполню следующий код, не нарушит ли этот код LoD? Я думаю, что, с одной стороны, это не нарушает, потому что объект testClass в строке (C) инициализируется внутри метода и вызывается метод GetTypeForConstructor, а с другой стороны, похоже, что он нарушает принцип, как в приведенном выше случае. Подводя итог, если возвращаемый объект используется для создания другого объекта, это выполнение будет считаться нарушением LoD?

class LoDQuestionForTestClass
{
    public void DeosThisVoliateTheLoD()
    {
        IConstructorInfoSelector concreteSelector = ...; 
        Type testType = ...;
        var selectConstructorInfo = concreteSelector.SelectConstructorInfo(testType);
       //Let the line to (C)
        var testClass = new TestClass(selectConstructorInfo);
        var result = testClass.GetTypeForConstructor();
    }
}

person Jin-Wook Chung    schedule 08.05.2012    source источник


Ответы (1)


Если один объект зависит от поведения другого объекта, предоставленного третьим объектом, вы нарушаете LoD. Популистская версия которой: «Не доверяй другу друга».

Во втором примере у вас есть другой объект, зависящий от объекта, предоставленного третьей стороной, так что да, это нарушает «не доверять другу друга» кроме, если selectConstructorInfoиспользуется только для его значения.

Стоит отметить, что LoD был создан для конкретного проекта (Demeter) и что в самой строгой форме он может не применяться ни к какому другому проекту.

person Rune FS    schedule 08.05.2012
comment
Спасибо за Ваш ответ. Можно еще вопрос? 1) Не могли бы вы дать мне больше информации о том, за исключением случаев, когда selectConstructorInfoиспользуется только когда-либо.... Это означает, что метод возвращает только значение (или объект) как указанный возвращаемый тип без логики или операции. - person Jin-Wook Chung; 08.05.2012
comment
Извините, это немного длинно. 2) Насколько я понимаю, соблюдение принципа LoD означает, что метод должен возвращать только простое значение (int, string и т. д.) или значение структуры данных, например DTO (объект передачи данных), потому что любой метод возвращаемого значения не следует использовать в прикованном состоянии. - person Jin-Wook Chung; 08.05.2012
comment
@jwjung Любой объект имеет поведение, но также является значением. В вашем случае, если вы сравниваете selectedConstructorInfo с другим объектом, вы используете его для его значения. Если вы создаете новый объект с помощью метода Invoke, вы теперь полагаетесь на поведение друга-друга, которое нарушает LoD. - person Rune FS; 08.05.2012
comment
Я понимаю что ты имеешь ввиду. Однако var testClass = new TestClass(selectConstructorInfo); нарушает LoD, но если я использую как new TestClass(concreteSelector);, это означает, что последнее не является нарушением. (название параметров см. выше). - person Jin-Wook Chung; 08.05.2012