문제

그만큼 위키피디아 기사 ~에 대한 데메테르의 법칙 말한다:

이 법칙은 간단히 "단 하나의 점만 사용하세요"라고 설명할 수 있습니다.

그러나 간단한 예 ~의 유창한 인터페이스 다음과 같이 보일 수 있습니다:

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

그럼 이게 같이 가는 건가요?

도움이 되었습니까?

해결책

음, 법의 짧은 정의는 법을 너무 단축시킵니다.실제 "법률"(실제로는 좋은 API 설계에 대한 조언)은 기본적으로 다음과 같이 말합니다.자신이 직접 만들었거나 인수로 전달된 개체에만 액세스하세요.다른 개체를 통해 간접적으로 개체에 액세스하지 마십시오.유창한 인터페이스의 메소드는 객체 자체를 반환하는 경우가 많기 때문에 객체를 다시 사용해도 법을 위반하지 않습니다.다른 방법은 객체를 생성하므로 위반도 없습니다.

또한 "법률"은 "클래식" API에 대한 모범 사례 조언일 뿐입니다.Fluent 인터페이스는 API 설계에 대한 완전히 다른 접근 방식이며 디미터 법칙으로 평가할 수 없습니다.

다른 팁

반드시 그런 것은 아닙니다."점 하나만 사용하세요"는 디미터의 법칙을 부정확하게 요약한 것입니다.

디미터의 법칙은 각 점이 다른 객체의 결과를 나타낼 때 여러 개의 점을 사용하는 것을 권장하지 않습니다. 예:

  • 첫 번째 점은 ObjectA에서 호출되어 ObjectB 유형의 객체를 반환하는 메서드입니다.
  • Next dot은 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) Good Ol' Phil Haack은 다음과 같이 말합니다. 데메테르의 법칙은 점 계산 연습이 아닙니다

귀하의 예에는 문제가 없습니다.결국 회전, 워터마킹 등을 하게 됩니다.항상 같은 이미지.나는 당신이 항상 파이프라인 객체와 대화하고 있다고 생각합니다. 따라서 코드가 파이프라인 클래스에만 의존하는 한 LoD를 위반하지 않습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top