C # 6.0의 새로운 Null 조건부 연산자는 Demeter of Laws에 적용됩니까?


29

데메테르법칙은 다음과 같이 말합니다.

  • 각 장치에는 다른 장치에 대한 정보가 제한적이어야합니다. 현재 장치와 "가까운"장치 만 있습니다.
  • 각 부대는 친구들과 만 대화해야합니다. 낯선 사람과 이야기하지 마십시오.
  • 가까운 친구와 만 대화하십시오.

C # 6.0은 null 조건부 연산자 라는 새로운 연산자를 도입했습니다 . IMHO, 코딩이 쉬워지고 가독성이 향상됩니다. 그러나 클래스 필드를 탐색하는 것이 더 쉽고 이미 null을 확인하는 것처럼 더 많은 결합 코드를 작성하는 것이 더 쉽습니다 var x = A?.B?.C?.D?.E?.F?.

이 새로운 운영자가 데메테르 법칙에 위배된다고 말하는 것이 맞습니까?


2
A?.B?.C?.D?.E?.F?그것을 위반 한다고 생각하는 이유 -LoD는 점의 수에 관한 것이 아니며 호출 방법에 해당 지점을 위반하지 않는 구조에 대한 정보가있는 경우 그러한 호출은 완벽하게 허용됩니다. 즉, 이러한 코드 수있는 디테일 정도를 위반는 모두가 사용하는 말하는 것만으로는 충분하지 않습니다 디테일 정도를 위반.

14
" 계량기의 법칙은 도트 카운팅 운동이 아닙니까?" 이 정확한 예를 설명합니다.
outis

@ outis : 탁월한 읽기. 나는 형식의 모든 코드 X.Y.Z.W.U가 "법"에 위배 된다고 말하지 않습니다 . 그러나 코드를 다루는 경험에서 90 %의 시간은 평범한 추악한 코드입니다.
Arthur Rizzo

2
@ArthurRizzo 그러나 null 조건부 연산자가 LoD에 대해 문제가되지는 않습니다. 그것이 잘못 된 코드입니다. 운영자는 사람이 쉽게 읽을 수있는 도구 일뿐입니다. 은 .?더 이상보다 디테일 정도를 위반하지 +또는 -않습니다.

1
RC Martin은 순수한 데이터 클래스와 행동 클래스를 구별합니다. 경우 액세스되는 속성이 행동 클래스의 내부 데이터를 노출 코드 조각은 확실히 디테일 정도를 위반, 그러나 이것은 널 조건 연산자와는 아무 상관이있다. 어쨌든 속성은 내부 데이터를 노출하도록 바인딩되지 않았으며, 이는 냄새 일 수 있지만 LoD를 위반하지 않습니다. RC Martin에 따르면 스키마는 순수한 데이터 클래스에서 절대적으로 유효 할 수 있습니다.
Paul Kertscher

답변:


44

이 새로운 운영자가 데메테르 법칙에 위배된다고 말하는 것이 맞습니까?

아니요 *


* null 조건부 연산자는 언어 및 .NET 프레임 워크 내의 도구입니다. 모든 도구는 주어진 응용 프로그램의 유지 관리 성을 손상시킬 수있는 방식으로 남용되고 사용될 수 있습니다.

그러나 도구 가 남용 될 있다고해서 반드시 도구 가 남용 되거나 해당 도구 가 보유 할 수있는 특정 원칙을 위반하는 것은 아닙니다.

Demeter의 법칙 및 기타는 코드 작성 방법 에 대한 지침 입니다. 도구가 아닌 인간을 대상으로합니다. 따라서 C # 6.0 언어에 새로운 도구가 있다는 사실이 코드를 작성하고 구성 하는 방법에 반드시 영향을 미치지는 않습니다 .

새로운 도구를 사용하면 코드를 유지 관리하는 사람이 폭력적인 정신병자라면 ... 으로 평가해야합니다 . 이것은 다시 사용되는 도구가 아니라 코드를 작성하는 사람을위한 지침입니다.


foo = new FiveDMatrix(); foo.get(0).get(0).get(0).get(0).set(0,1);괜찮을 것입니다 (그리고 나쁘지 않을 것입니다 foo[0][0][0][0][0] = 1) ... 그리고 그러한 것이 LoD를 위반하지 않는 다른 많은 상황들.

@MichaelT 차원의 행렬에 들어가기 시작하면 인덱스를 벡터 / 튜플 / 배열 자체로 취급하는 것이 쉬워지고 행렬 클래스의 내부가 데이터가 실제로 저장되는 방식에 대해 걱정하게 만드는 것처럼 보입니다. (내가 생각하기에, 적어도 캡슐화와 관련하여 데메테르의 법칙을 적용한 것이다.)
JAB

(물론 이러한 종류의 연습을 통해 다차원 슬라이싱을 쉽게 구현하고 실제로 강력한 매트릭스 도구를 사용할 수 있습니다.)
JAB

1
@JAB 나는 방금 예를 제시하려고했습니다. 더 좋은 방법은 아마도 Dom file = prase("some.xml"); file.get(tag1).getChild().get(tag2).getChild() ...멍청한 코드의 구조를 처리하는 문제 일 것 입니다. 그것은 낯선 사람이 아닙니다 ... 단지 바보입니다. 이 .?됩니다 매우 이러한 구조에서 유용합니다.

10

일종의.

하나의 액세스 ( a?.Foo) 만 수행하는 경우 다음과 같습니다.

a == null ? null : a.Foo

대부분의 사람들이 동의하는 것은 데메테르 법칙을 위반하지 않습니다. 그 시점에서 가독성을 향상시키는 것은 단지 구문 설탕입니다.

그것보다 더 중요한 것은 아마도 Demeter의 법칙에 위배 될 것입니다. 그리고이 기능은 이런 종류의 사용을 촉진시키는 경향이 있습니다. 심지어 위의 "좋은"사용법만으로는 이러한 종류의 언어 변경을 보증하기에 충분하지 않기 때문에 덜 명확한 사용법을 지원하기를 기대합니다.

그러나 데메테르의 법칙은 그 자체로 법이 아니라 더 많은 지침이라는 것을 기억할 가치가 있습니다. 많은 코드가 그것을 위반하고 잘 작동합니다. 때로는 디자인이나 코드의 단순성이 데메테르 법칙을 위반함으로써 발생하는 위험보다 더 가치가 있습니다.


그 이상으로 LoD를 깨뜨릴 필요는 없습니다
.

@Telastyn : 우리가 말하는 새로운 언어 구문에 대한 수행 지원 메서드 호출을 : a?.Func1(x)?.Func2(y) 널 병합 연산자는 다른 것입니다.
Ben Voigt

@ BenVoigt-아, 기사에서 벗어 났으며 필드, 속성 및 인덱서에서만 작동한다고 표시했습니다. MSVS2015를 테스트하기에 편리하지 않았습니다. 네 말이 맞아
Telastyn

1
a? .Foo는 == null과 동일하지 않습니까? null : a. 푸. 전자는 한 번만 평가하고 후자는 두 번 평가합니다. 반복자라면 문제가 될 수 있습니다.
Loren Pechtel

9

아닙니다. 운영자 자신과 그에 대한 많은 체인 사용을 고려해 봅시다.

그 자체로 .?A클래스에 대한 지식과 동일한 양의 지식에 의존합니다 .A != null. A속성이 존재 한다는 사실을 알아야 하고와 비교할 수있는 값을 반환합니다 null.

우리는 유형 속성이 그렇게한다면 이것이 Demeter의 법칙을 위반한다고 주장 할 수 있습니다. 우리는 A구체적인 유형으로 강요받지 않아도 됩니다 (그 값은 파생 된 유형 일 수 있음). 여기의 커플 링은 최소입니다.

이제 생각해 보자 var x = A?.B?.C?.D?.E?.F.

어떤 수단 Anull이 될 수있다, 또는이 할 수있는 유형이어야합니다 B널 (null)이거나 가질 수있는 유형이어야 재산 C등의 형태까지에, 속성을 Enull 일 수 또는 수 프로퍼티 인 뭔가 F재산을 가질 수 있습니다 .

다시 말해, 정적으로 형식이 지정된 언어로이 작업을 수행하거나 타이핑이 느슨한 경우 반환 될 수있는 형식에 제약 조건을 적용해야합니다. 대부분의 경우 C #은 정적 타이핑을 사용하므로 아무것도 변경하지 않았습니다.

우리가 그렇다면 다음 코드도 법을 위반합니다.

ExplicitType x;
var b = A.B;
if (b == null)
  x = null;
else
{
  var c = b.C;
  if (c == null)
    x = null;
  else
  {
    var d = c.D;
    if (d == null)
      x = null;
    else
    {
      var e = d.E;
      if (e == null)
        x = null;
      else
        x = e.F;
    }
  }
}

이는 정확히 같은 . 서로 다른 요소의 커플 링을 사용 하는 이 코드 는 커플 링의 전체 체인에 대해 "알아야"하지만,이를 위해 Demeter의 법칙을 위반하지 않는 코드를 사용하고 있습니다. 다음.


3
+1 새로운 연산자는 여러분이 설명한 쓴 요리법에 대한 구문 설탕 일뿐입니다.
로스 패터슨

1
글쎄, 개발자가 그처럼 보이는 코드를 작성하면 무언가가 옳지 않다는 것을 쉽게 알 수 있다고 생각합니다. 나는 연산자가 100 % syntatic sugar라는 것을 알고 있지만, 사람들은 var x = A?.B?.C?.D?.E?.F결국 같은 경우라도 모든 if / eles보다 더 편한 글을 쓰는 경향이 있다고 생각 합니다.
Arthur Rizzo

2
A?.B?.C?.D?.E?.F잘못 될 수있는 것이 적기 때문에 옳지 않은 것을 발견하는 것이 더 쉽습니다 . 우리는 F그 경로를 통과 하려고 노력해야 하거나 길을 길어야합니다. 긴 형식은 경로 내에 오류가있을뿐만 아니라 올바른 작업이 아닌 오류가있을 수 있습니다.
Jon Hanna

@ArthurRizzo 그러나 위의 종류의 코드를 LoD 위반과 연결하면 null 검사가 필요하지 않고 그냥 할 수있는 경우에는 쉽게 놓칠 수 있습니다 A.B.C.D. 매우 관련이없는 세부 사항 (널 체크)에 의존하는 두 가지 다른 것보다는 (체인 속성 액세스)를 찾는 것이 훨씬 간단합니다.
Ben Aaronson

5

객체는 행동을 캡슐화하거나 데이터를 보유 할 목적으로 생성 될 수 있으며, 외부 코드와 공유되거나 생성자가 개인적으로 보유 할 목적으로 생성 될 수 있습니다.

행위를 캡슐화하기 위해 (공유 여부에 관계없이) 또는 외부 코드와 공유하기 위해 (행위 또는 데이터를 캡슐화하든) 생성되는 객체는 일반적으로 표면 인터페이스를 통해 액세스해야합니다. 그러나 데이터 보유 오브젝트가 작성자가 독점적으로 사용할 수 있도록 작성되는 경우 "심층적 인"액세스를 피하는 일반적인 De- 법인 이유는 적용되지 않습니다. 객체에 데이터를 저장하거나 조작하는 클래스의 일부가 다른 코드를 조정해야하는 방식으로 변경되면 위에서 언급 한 것처럼 객체가 생성 되었기 때문에 이러한 코드가 모두 업데이트되도록 보장 할 수 있습니다. 한 클래스의 독점 사용.

내가 생각하는 동안?. 연산자는 아마도 더 잘 설계되었을 수 있습니다. 개체가 중첩 된 데이터 구조를 사용하는 충분한 상황이있을 수 있습니다. 운영자는 Demeter의 법칙에 의해 표현 된 원칙을 위반하지 않는 많은 사용 사례를 가지고 있습니다. LoD를 위반하는 데 사용될 수 있다는 사실은 "."보다 나쁘지 않기 때문에 운영자에 대한 논쟁으로 간주되어서는 안됩니다. 그 점에서 운영자.


데이터 미터 객체에 데 미터 법칙이 적용되지 않는 이유는 무엇입니까?
Telastyn

2
@Telastyn : LoD의 목적은 코드가 다른 객체 가 조작하거나 관심을 가질 수있는 내부 객체에 액세스 할 때 발생할 수있는 문제를 피하는 것입니다 . 우주의 다른 어떤 것도 내부 물체의 상태를 조작하거나 돌볼 수 없다면 그러한 문제를 막을 필요가 없습니다.
supercat

동의하지 않습니다. 다른 것들은 데이터를 수정해야 할 것이 아니라 경로를 통해 포함 된 객체에 연결하는 것입니다 (실제로 세 개의 연결 지점-두 객체와 그 관계). 때때로 그 커플 링은 큰 일이 아니지만 여전히 나에게 냄새가납니다.
Telastyn

@ Telastyn : 경로에 대한 요점은 좋은 것이지만 내 요점은 괜찮습니다. 여러 경로를 통해 객체에 액세스하면 해당 경로간에 커플 링이 생성됩니다. 일부 액세스가 얕은 경로를 통해 이루어지면 깊은 경로를 통해 액세스해도 원치 않는 커플 링이 발생할 수 있습니다. 그러나 모든 액세스가 하나의 특정 딥 경로를 통해 이루어지는 경우 해당 딥 경로에 연결할 항목이 없습니다.
supercat

@Telastyn 데이터 구조를 탐색하여 데이터를 자세히 살펴 보는 것이 좋습니다. 중첩 된 메소드 호출과 동일하지 않습니다. 당신은 때때로 자료 구조를 알 필요하며이 중첩되는 방법, 동일한는 서비스 자체 중첩 된 서비스 / 저장소 등 같은 개체를 이동하지 않습니다
당 Hornshøj-Schierbeck
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.