2013-11-28 4 views
15

나는 샤워를하고 뭔가 생각했다.지연/약속은 Demeter의 법칙을 어기는 것을 촉진합니까?

이연/약속 패턴은 here 언급 한 바와 같이, 체인 전화 기능에 개발자를 허용함으로써, callback hell을 감소하는 것입니다 : - 만약 내가 잘못 정정 해줘 - 내 머리의 상단에서

Parse.User.logIn("user", "pass").then(function(user) { 
    return query.find(); 
}).then(function(results) { 
    return results[0].save({ key: value }); 
}).then(function(result) { 
    // the object was saved. 
}); 

하지만 지연/약속을 사용하는 것이 Demeter의 법칙을 어기는 쉬운 방법이라고 생각하십니까?

데메테르의 법칙 상태 :

  • 객체 자체 : 물체

    방법은 방법을 호출 할 수있다.

  • 메서드의 인수입니다.
  • 메서드 내에서 생성 된 모든 개체입니다.
  • 개체의 모든 직접 속성/필드.

각 장치는 다른 장치에 대한 지식이 제한되어 있어야합니다 : 단위는 현재 장치와 "밀접하게"관련되어 있습니다. 또는 : 각 단위는 의 친구에게만 이야기해야합니다. 낯선 사람과 이야기하지 마세요.

의견이 있으십니까?

는 업데이트 2013년 12월 1일 :

A는 내 질문의 버전을 요약. Promise 프레임 워크는 비동기 코딩을 단순화하고 "callback hell"을 피하도록 설계되었습니다. Promise의 가장 유용한 기능 중 하나는 위 예제에서 볼 수 있듯이 .then()을 사용하여 이벤트를 체인 호출 할 수 있다는 것입니다.

모든 코드/기능은 이제 약속을 사용하는 감안할 때 (벤자민 Gruenbaum 아래 (저자) 현재하고있는처럼), 그것은 등

.then().then().then()를 이동하여 연쇄 호출 기능을 정말 쉽게 그것을 열 수 없습니다 chain-call 함수가 서로 뒤 따르는 코드를 작성하면 (.then().then().then()) Demeter의 법칙을 어기는 법을 설명하는 텍스트 북이어야합니다.

내 질문에; Promise 프레임 워크가 Demeter의 법칙을 악용하거나 파기하기 쉽도록/개장/개선합니까?

+8

"샤워 진술"이 여기에 어떤 도움이 될지는 확실하지 않습니다. :) – benzonico

+0

자바 스크립트 기능은 폐쇄 (매우 편리한 패러다임)를 불가능하게하는 Demeter의 법칙을 따르지 않아도됩니다. 또 다른 의미에서, apply/call을 사용하면 실제로 법에서 "객체"가 무엇인지 다시 정의 할 수 있으므로 실제 실행 전에 JS를 준수 할 수 있습니다. 어느 쪽이든 그것은 중요하지 않습니다. – dandavis

+0

저는 이것이 당신이 왜 데메테르의 법을 어기는지 왜 생각하는지 모르겠습니다. 모든 메소드는 인자로 전달 된 함수 만 호출하고 (객체 지향 목록에서 두 번째 옵션 일반화) 객체를 반환합니다. 체인에서 이러한 객체는 자신의 메서드를 호출합니다. – kybernetikos

답변

10

Demeter 's Law의 의미와 JavaScript와 약속 같은 프레임 워크의 두 언어에 대한 적용 가능성을 잘못 해석했다고 생각합니다.

약속은 Demeter 's Law가 은행 응용 프로그램에서 계정이나 고객과 같은 "클래스"와 같은 것에 상응한다는 의미에서 "단위"가 아닙니다. 이들은 비동기식 제어 흐름을위한 상위 수준의 메타 구조입니다. 그러한 메타 구조가 어떻게 통제되고 설계된 임의의 외부 엔티티 (친구가 아닌)와 "이야기 할"수 없어도 그러한 메타 구조가 어떻게 존재하거나 유용 할 수 있는지를 보는 것은 어렵습니다.

Demeter의 법칙은 모든 것이 클래스 또는 방법 인 고전적인 OO 시스템에 매우 중점을 둔 것처럼 보입니다.명시된 바와 같이, 건네받은 함수가 무엇이든 호출 할 수 없으므로 대부분 함수형 프로그래밍이 아닌 것처럼 보입니다.

이 방법을 보는 또 다른 방법은 약속을이 법을 위반하는 것으로 보는 범위 내에서 콜백이 확실히 수행한다는 것입니다. 결국, 두 개는 기본적으로 동형입니다. 차이는 근본적으로 통사론입니다. 따라서 Demeter의 법칙에 위배되지 않는 것에 고정되어 있다면, 콜백을 사용할 수 없을 것입니다. 그래서 가장 기본적인 비동기 프로그램을 어떻게 작성할 것입니까?

+0

이 답변에 다소 오랜 시간이 걸리기 시작했습니다.하지만 가장 기본적인 비동기 프로그램을 작성하는 방법에 대해 한 가지 질문을 할 것입니다. - 모든 비동기식 애플리케이션이 자동으로 Demeter의 법칙을 깨뜨릴 것이라고 말하고 있습니까? 나를 위해, 당신은 "callback 지옥"을 피할 수있는 방법으로 비동기식 응용 프로그램을 설계했지만 여전히 Demeter의 법칙을 존중합니다. 동의하지 않니? – corgrath

+0

약속이 법을 어 기고 또는 가능성이 있다고 생각하는 정도까지는 콜백 문제는 실제로 관련이 있습니다. 왜냐하면 약속과 콜백이 동형이기 때문입니다 (기본적으로 약속은 캡슐화로 간주 될 수 있습니다 콜백 메카니즘에 대해) 콜백이 법을 어기는 지에 대해서도 염려 할 권리가 있습니다. 또는 그들이 믿는다. 반대로, 콜백이 법을 어 기고 있다고 생각하지 않거나 생각하지 않는다면, 유사점이 주어지면 정의로 인해 약속도 그렇게하지 않는다고 생각하십시오. –

+0

자바 스크립트와 전통적인 콜백이 Demeter의 법칙을 위반하는지 여부는 내 주제가 아닙니다.하지만 Promise 프레임 워크가 쉽게 깨뜨릴 수 있다면. 아주 간단하게 (완전히 오프 주제지만 당신이 내 질문을 더 잘 이해할 것이다) 예제를 만들 수 있습니다. 미성년 자녀가 술을 마시지 못하게하고 법의 법이라고 부를 수있는 법이 있습니다. 미성년 자녀가 술을 마시는 것이 나쁘기 때문에 법에 어긋납니다. 지금 우리는 학교 식당에 술을 팔 수있는 가능성을 부여한다고 말합니다 (우리는 Promise 프레임 워크를 소개합니다). – corgrath

5

짧은 대답은 예입니다.

저는이 문제가 Demeter의 법칙과 직접적으로 관련이있는 것은 아니지만 사람들이이 문제를 혼란스럽게 생각하기 때문에 필요 이상으로 복잡해 졌다고 생각합니다. 사실 우리는 자바 스크립트에 대해 이야기하고 있습니다. 또는 우리가 콜백을 다루고 있다는 사실. 그것들은 적용되지 않는 세부 사항입니다.

토론을 다시 시작하고 재설정하십시오. 소프트웨어 엔지니어링에서 가장 중요한 목표는 커플 링을 최대한 제한하는 것입니다. 즉, 코드를 변경하면 주말에 많은 코드가 변경되도록 강제하지 않습니다. Demeter의 법칙은 한 유형의 커플 링을 방지하기 위해 존재합니다. feature envy. 그것은 어떤 방법으로 f이 작업을 수행하는 데 사용할 수있는 형식적인 제한을 제공함으로써 그렇게합니다.

OP @corgrath는 이러한 제한을 열거 할 정도로 좋습니다. Demeter의 법칙 위반을 특징 짓는 쉬운 방법은 다음과 같습니다. "허용 된 4 가지 객체 중 하나를 호출 할 수는 없습니다."

이제 마지막으로 @corgrath에서 제공하는 샘플 코드 :

Parse.User.logIn("user", "pass").then(function(user) { 
    return query.find(); 
}).then(function(results) { 
    return results[0].save({ key: value }); 
}).then(function(result) { 
    // the object was saved. 
}); 

객체에 반대의이Parse데이터 구조를 부르 자 (했다 삼촌 밥의 멋진 책 Clean Code의 6 장을 참조하십시오 구별에 더 많은 것, Demeter의 법칙에 대한 나의 첫 번째 노출). 그렇다면 우리는 Parse.User으로 괜찮습니다.

그러나 User은 분명히 메서드 및 동작이있는 개체입니다. 이러한 방법 중 하나는 logIn입니다. 이 값은 Promise입니다. 이 물체에 대해 무엇이든 부르 자마자 은 Demeter Law을 위반했습니다.

그게 전부입니다.

JavaScript로는 곧 functions are objects까지 언급 할 것입니다. 따라서 Demeter의 법칙은 각 then 호출에 전달 된 콜백 함수에도 적용됩니다. 그러나 존재하지 않는 함수의 메서드는 각각 호출되지 않으므로 then 호출은 이 아니며은 Demeter의 법칙을 위반합니다.

지금이 흥미로운 것은 입니다.이 법칙 위반의 명백한 위반이 일지 여부입니다. 소프트웨어 엔지니어링은 예술입니다. 우리에게는 모든 종류의 법과 원칙과 관행이 있지만 종교적 순응은 그들에 대한 무지만큼 비생산적입니다. 100 % 코드 적용을 시도하는 것은 어리 석다. 단위 테스트 게터와 세터에게는 바보입니다. 100 % 종류를 위해 싸우는 것은 어리 석다 cohesion; 100 % 패키지를 만드는 것은 어리 석다. stability; 기타

이 경우 Demeter Law 위반은 중요하지 않습니다. Promise 어떤 식 으로든 내부를 노출시키지 마십시오. 그들은 다른 동작을 수행하기 위해 추상화를 노출합니다 (이 경우에는 콜백을 등록하지만 토론과 관련이 없습니다). 다른 말로하면,이 모든 것을 then 전화로 주말에 작업하는 것에 대해 걱정해야합니까? 희박한 가능성은 이며 전체적으로는입니다. 즉, 메서드 이름을 andThen 또는 whenYoureReadyDoThis으로 바꿀 수도 있지만 의심 스럽습니다.

내 주말을 좋아하기 때문에 이것은 매우 중요합니다. 불필요한 일을하고 싶지 않습니다. Stack Overflow에서 에세이 답변 게시와 같은 재미있는 일을하고 싶습니다.

  • Promise 코드는 데메테르의 법칙을 깰 않습니다

    그래서 요약, 두 가지 질문이 있습니다? 예.

  • 중요합니까? 아니요

두 가지를 모으고 모든 종류의 불필요한 정보를 토론에 포함 시키면 문제가 혼란스럽게됩니다.

+0

반환 된 약속에 대한 어떤 것을 호출해도 [Demeter의 법칙] (https://en.wikipedia.org/wiki/Law_of_Demeter)을 위반하는 이유는 무엇입니까? "* 메소드 내에서 생성되거나 인스턴스화 된 모든 객체"에서 메소드를 호출 할 수 있습니까? 그렇지 않으면 우리가 '15'에서 더하기를 호출하기 때문에'3 * 5 + 1'도 무효가됩니다 ... – Bergi

3

좋은 질문! LoD를 준수하는 측면에 초점을 맞추지는 않지만 은 약속 패턴과 충돌 할 것이라고 생각합니다. 그러나 사용자 의견에서 주로 콜백 체인 및 사용에 관심이 있음을 알 수 있습니다.

연결은 패턴의 구현에서 일반적이지만 의미를 추가하지는 않습니다. 실제로는 문법적하지만 아무것도 없다, 다음 코드를 만드는 것은 동의어 :

someAsyncPromise.then(/*do some stuff first*/).then(/*do other stuff*/); 

someAsyncPromise.then(/*do some stuff first*/); 
someAsyncPromise.then(/*do other stuff*/); 

는 위, then 방법은 원래의 약속 개체 someAsyncPromise하지 새로운/다른 약속 개체에 대한 참조를 반환합니다. 이것은 아마도 물체가 체인 자신의 방법 (디 오 : 아마도 그것은 쉽게 일반적인 jQuery를 선택 인식을 호출하는 것이 정결의 디테일 정도를, 다른 OO 원칙을 위반 있지만 :

$('#element').hide().text('oh hi').css('color', 'fuchsia'); 
//synonymous to 
$('#element').hide(); 
$('#element').text('oh hi'); 
$('#element').css('color', 'fuchsia'); 

(좋아,하지 정말 동의어 $() 선택이 두 번째 예제의 요소 다시 조회 할 것이기 때문에;!. 우리는 jQuery 오브젝트를 캐시 한 경우는 이 될 것입니다하지만 당신은 요점을 파악) 콜백에

하자 초점을 지금. 자바 스크립트의 아름다움은 기능이 일류 시민이며 당신이 그들을 전달할 수 있다는 것입니다. 귀하의 모범에있는 일은 무엇을합니까?

function(result) { 
    // the object was saved. 
} 

부화되기를 기다리는 달걀처럼 거기에 앉아있을뿐입니다. 함수 표현식을 사용하여 익명 함수를 작성한 다음 .then() 인수로 전달하면이를 실행 약속 스택으로 푸시합니다.

그래서 방법

는 약속 패턴의 하나 개의 해석은 디테일 정도에 부착 교과서 예제로 볼 수있을 것입니다!

...

하는 것은 매우 잘못된, 현재 위키 백과 항목은 이럴을 말함으로써 나에게 마무리를하자 : 필드 ID로 점을 사용하는 많은 현대적인 객체 지향 언어의

를, 법은 간단하게 만 사용 "으로 언급 될 수있다 하나의 도트 ". 즉, a.b.Method() 코드는 a.Method()이없는 법칙을 위반합니다.

Lolwut? 이것은 기본 구조와 아키텍처보다는 구문과 외형에 너무 많은 초점을 둡니다. 그 둘 사이의 차이점을 다루는 a very comprehensive explanation (위키피디아 항목의 다른 누출 부분)과 대신 the law's non-wikified version을 사용할 수 있습니다.

+4

'.then()'은 같은 약속을 되돌려주지 않습니다. 지금까지 jQuery 약속이 망가 졌다고해도 (1.8 :)). 그러한 "약속들"은 완전히 쓸모 없으며 당신에게 실질적인 이익을주지 못합니다. – Esailija

+0

@Esailija : 좋은 지적; jQuery 지연에 초점을 맞추고 있지 않았습니다. jQuery는 단순히 체인의 예제로 등장한 것입니다. 최근의'Q'와'webdriver' 대기열에 대한 나의 경험은 이것과 완벽하게 일치합니다. :) –