캡슐화(2) 캡슐화를 위한 두 개의 규칙

  • Tell, Don't Ask
  • 데미테르의 법칙(Law of Demeter)

"Tell, Don't Ask" 규칙은 간단하다.
데이터를 물어보지 않고, 기능을 실행해 달라고 말하라는 규칙이다.
이전 포스팅의 '회원 만료 여부를 확인하는 코드'를 다시 보면, 절차 지향 방식(캡슐화 이전)은 만료 일자 데이터를 가져와서, 직접 만료 여부를 확인했다.

if(member.getExpiryDate() != null &&
	member.getExpiryDate().getDate() < System.currentTimeMillis() ) {
	//만료 되었을 때의 처리    
}

데이터를 읽는 것은 데이터를 중심으로 코드를 작성하게 만드는 원인이 되며, 따라서 절차지향적인 코드를 유도하게 된다.
데이터 대신에 기능을 실행해달라고 명령을 내리려면 만료 일자 데이터를 가진 객체에게 만료 여부를 확인해 달라고 해야 한다.
아래 코드와 같이 기능 실행을 요청하는 방식으로 코드를 작성하게 되면, 자연스럽게 해당 기능을 어떻게 구현했는지 여부가 감춰진다. 즉, 기능 구현이 캡슐화되는 것이다.

if (member.isExpired()) {
	// 만료에 따른 처리
}

데미테르의 법칙은 'Tell, Don't Ask' 규칙을 따를 수 있도록 만들어 주는 또 다른 규칙이다.
데미테르의 법칙은 다음과 같이 간단한 규칙으로 구성된다.

  • 메서드에서 생성한 객체의 메서드만 호출
  • 파라미터로 받은 객체의 메서드만 호출
  • 필드로 참조하는 객체의 메서드만 호출
public void processSome(Member member) {
	if (member.getDate().getTime() < ... ) { //데미테르 법칙 위반
    	...
    }
}

데미테르의 법칙에 따르면 파라미터로 전달받은 객체의 메서드만 호출하도록 되어 있는데, 위 코드의 경우 파라미터로 전달받은 member의 getDate() 메서드를 호출한 뒤에, 다시 getDate()가 리턴한 Date 객체의 getTime()메서드를 호출했기 때문이다.
데미테르의 법칙을 따르려면 한 번의 member 객체 메서드 호출로 변경해야 한다.

member.getDate().getTime() -> member.someMethod()

좋은 웹페이지 즐겨찾기