디자인 모델 - 6 대 원칙 - 디 트 미의 법칙

17470 단어 디자인 모드
대상 을 대상 으로 디자인 된 세계 에서 흔히 무시 되 는 원칙 인 '디 미트 (Law of Demeter)' 법칙 이 있다.이 원칙 은 모든 대상 이나 방법 은 대상 을 호출 할 수 밖 에 없다 고 생각 합 니 다. • 이 대상 자 체 는 매개 변수 로 들 어 오 는 대상 (이 대상 의 필드 일 수도 있 습 니 다) • 방법 내 에 만 든 대상 입 니 다.
이 원칙 은 정확 한 대상 의 협력 을 지도하 고 어떤 대상 이 협력 을 해 야 하 는 지, 어떤 대상 이 그 대상 에 게 는 무지 해 야 하 는 지 를 가 리 는 데 쓰 인 다.
본문 과 관련 된 정보
1. 디 트 미 법칙 2, 최소 지식 법칙 3, 정보 전문가 모델 4, 코드 재 구성 - Move Method
케이스
슈퍼마켓 에서 쇼핑 하 는 장면 을 가정 하면 고객 (Customer) 이 계산대 에 가서 계산 하고 계산 원 (Paper Boy) 이 돈 을 받는다.
public class Customer {
    private String firstName;
    private String lastName;
    private Wallet myWallet;
    public String getFirstName(){
        return firstName;
    }
    public String getLastName(){
        return lastName;
    }
    public Wallet getWallet(){
        return myWallet;
    }
}

public class Wallet {
    private float value;
    public float getTotalMoney() {
        return value;
    }
    public void setTotalMoney(float newValue) {
        value = newValue;
    }
    public void addMoney(float deposit) {
        value += deposit;
    }
    public void subtractMoney(float debit) {
        value -= debit;
    }
}

public class Paperboy {
    public void pay(Customer myCustomer, double payment) {
        Wallet theWallet = myCustomer.getWallet();
        if (theWallet.getTotalMoney() > payment) {
            theWallet.subtractMoney(payment);
        } else {
            //money not enough
        }
    }
}

우 리 는 수금 원 의 수금 방법 을 당신 이 생각 하 는 일치 여 부 를 번역 할 것 입 니 다.
"지갑 내 놔!" 라 고 계산 원 이 고객 이 사려 는 상품 의 총 가 를 계산 한 후 "부 드 럽 게" 고객 에 게 말 했다.손님 은 말 을 잘 듣 고 얼른 지갑 을 꺼 내 서 수금 원 에 게 공손하게 건 네 주 었 다.지갑 을 받 고 수금 원 은 조금도 사양 하지 않 고 열 어 안의 돈 이 충분 한 지 검사 했다.아, 좋아, 돈 은 충분해.수금 원 은 지갑 에서 돈 을 꺼 내 흐뭇 하 게 웃 었 다.(보고 무 섭 지 않 아 요? 고객 이 라면 이런 마 트 에 가서 쇼핑 을 할 수 있어 요?)
사례 의문
PaperBoy 에 게 Wallet 의 호출 은 디 미트 법칙 세 가지 조건 중 하 나 를 만족 시 키 지 못 하기 때문에 PaperBoy 와 Wallet 대상 을 직접 상호작용 하 게 하 는 것 은 잘못된 행위 이다.의인화 적 인 측면 에서 생각하면 Wallet 은 사실 Customer 의 프라이버시 에 속한다.이렇게 중요 한 프라이버시 를 어떻게 수금 원 이라는 낯 선 사람 에 게 직접 맡 길 수 있 습 니까?여기 서 이른바 '프라이버시' 는 '데이터', '정보', '지식' 으로 볼 수 있 기 때문에 우 리 는 디 미트 법칙 을 '최소 지식 법칙' 이 라 고도 부른다.
최소 지식 법칙
우리 가 '최소 지식 법칙' 을 이해 할 때 직책 의 측면 에서 상기 코드 를 생각 할 수 있다.수금 원 역할 에 대해 그의 직책 은 돈 을 받 는 것 이지 지갑 안의 돈 이 충분 한 지 신경 쓰 지 않 아 도 된다. 충분 하면 어떻게 해 야 하 는 지, 부족 하면 어떻게 해 야 하 는 지, 이런 것들 은 모두 그의 직책 에 속 하지 않 는 다.슈퍼마켓 에 인파 가 몰 리 고 모두 가 상품 을 구 매 할 때 모든 수금 원 이 이런 직책 을 맡아 야 한다 면 어떤 모습 이 나타 날 지 생각해 보 자.그래서 '최소 지식 법칙' 은 바로 선법 이다. 대상 지역사회 에서 우 리 는 대상 간 에 서로 깊이 이해 하 는 것 을 줄 여야 한다.가장 작은 지식 을 이해 하 는 것 은 의존 이 가장 적 고 서로 에 게 미 치 는 영향 이 가장 적 다 는 것 을 의미한다.이것 은 사실상 KISS (keep it simple and stupid) 원칙 의 구현 이다.
정보 전문가 모델
정보 전문가 모델 은 "정보의 소지 자 는 이 정 보 를 조작 하 는 전문가" 라 고 말 했다. 대상 에 대해 정보 란 이 대상 내부 의 필드 이다.앞의 예 에서 Wallet 은 Customer 의 필드 이 므 로 Wallet 을 조작 하 는 행 위 는 당연히 Customer 에 게 배분 되 어야 한다.이것 은 문제 에서 응당 받 아야 할 도리 다.'정보 전문가 모델' 은 사실 대상 을 대상 으로 하 는 가장 중요 한 원칙 인 '데이터 와 행 위 는 함께 포장 해 야 한다' 는 별명 이다.분야 에서 모델 링 을 할 때 이 원칙 을 따 를 수 있다 면 빈혈 모델 을 만 드 는 것 을 피 할 수 있다.
코드 재 구성
public class Paperboy {

    public void charge(Customer myCustomer, double payment) {
        pay(myCustomer, payment)
    }
    private void pay(Customer myCustomer, double payment) {
        Wallet theWallet = myCustomer.getWallet();
        if (theWallet.getTotalMoney() > payment) {
            theWallet.subtractMoney(payment);
        } else {
            //money not enough
        }
    }
}

추출 한 pay () 의 방법 체 는 charge () 방법 과 완전히 같 지만, PaperBoy 류 에 서 는 charge () 방법 을 보류 하고 있 으 며, 다만 이 방법 은 아무것도 하지 않 았 고, 방법 요청 을 받 은 후 에는 pay () 방법 에 위임 했다.우 리 는 추상 적 인 차원 에서 수금 은 수금 원 의 직책 이 라 고 이해 할 수 있다.실현 차원 에서 pay () 방법 은 수금 행 위 를 지 지 했 고 이 는 고객 에 게 귀속 된다.pay () 방법 을 살 펴 보면 우 리 는 이 방법 으로 조작 한 데 이 터 는 모두 Customer 에서 온 것 을 발견 했다.우 리 는 Martin Fowler 의 이른바 '특성 애틋 함 (Feature Envy)' 이라는 나 쁜 냄새 를 맡 았 다.이 나 쁜 맛 에 대해 Martin Fowler 는 이렇게 설명 했다. "함수 가 어떤 종류 에 대한 관심 이 자신 이 처 한 종류 에 대한 관심 보다 높다." 더 이상 질투 하지 마라. 다 리 는 다리 로 돌아 가 고 길 은 돌아 가 며 방법 을 자신 이 가장 좋아 하 는 곳 으로 돌아 가게 하 자.'Move Method' 재 구성 기법 을 활용 해 pay () 방법 을 Customer 로 이동
코드 재 구성
public class Customer {
    private String firstName;
    private String lastName;
    private Wallet myWallet;
    public String getFirstName(){
        return firstName;
    }
    public String getLastName(){
        return lastName;
    }
    private void pay(double payment) {
    
        if (theWallet.getTotalMoney() > payment) {
            theWallet.subtractMoney(payment);
        } else {
            //money not enough
        }
    }
}
public class Paperboy {

    public void charge(Customer myCustomer, double payment) {
       myCustomer.pay(payment);
    }
    
}

방법 을 정확 한 위치 로 옮 긴 후에 우 리 는 노출 된 getWallet () 방법 이 전혀 의미 가 없다 는 것 을 발견 했다.더구나 지갑 을 노출 하 는 것 은 부 를 과시 하려 는 것 일 까?좀 조용히 하 는 것 이 좋 겠 다. 자신의 '프라이버시' 를 숨 기 는 것 이 남 에 게 노 리 고 횡 화 를 초래 하 는 위험 보다 낫다.그래서 내 연 (inline).
법칙 에 어 긋 나 는 지 아 닌 지 를 판단 하 다.
코드 가 디 미트 의 법칙 에 어 긋 나 는 지 판단 하 는 작은 비결 은 호출 코드 가 a. m1 (). m2 (). m3 (). m4 () 와 같은 코드 가 나타 나 는 지 를 보 는 것 이다.이 코드 는 마 틴 파 울 러 의 '재 구성' 이라는 책 에서 '메시지 체인 (Message Chain)' 으로 불 리 며 '기차 잔해' 라 는 과장 되 는 이름 을 붙 였 다.교통사고 현장 이 여, 정말 끔찍 하 다.그렇다면 다음 코드 는 이런 잔해 가 아 닐 까?
str.split("&")
    .stream()
    .map(str -> str.contains(elementName) ? str.replace(elementName + "=", "") : "")
    .filter(str -> !str.isEmpty())
    .reduce("", (a, b) -> a + "," + b);

아 닙 니 다.이러한 코드 를 우 리 는 일반적으로 '유창 한 인터페이스 나 연결 인터페이스 (Fluent Interface)' 라 고 부른다.이들 의 차 이 는 체인 을 형성 하 는 모든 방법 이 다른 대상 으로 돌아 가 는 지, 아니면 대상 자체 로 돌아 가 는 지 관찰 하 는 것 이다.다른 대상 으로 돌아 가면 메시지 체인 이다.이른바 m1 (). m2 (). m3 (). m4 () 의 호출 은 호출 자가 필요 하지 않 고 알 고 싶 지 않 은 '지식' 이다. 이러한 중간 과정의 세부 사항 을 드 러 내 는 것 은 의미 가 없고 호출 자가 관심 을 가 지 는 것 은 최종 결과 이다.상기 코드 중의 map () 와 filter () 등 방법 은 사실 Stream 류 를 되 돌려 줍 니 다.이 호출 방식 은 중간 과정의 세부 사항 을 알려 주 는 것 이 아니 라 성명 식 DSL 표현 으로 호출 자 는 자 유 롭 게 조합 할 수 있다.
참조 문장 demeter

좋은 웹페이지 즐겨찾기