Search
Duplicate
🎱

Law of Demeter

디미터 법칙은 Object-Oriented Programming: An Objective Sense of Style에서 처음 소개된 개념이다.
디미터라는 이름의 프로젝트를 진행하던 도중, 객체지향 프로그래밍에서 객체들의 협력 경로를 제한하면 결합도를 효과적으로 낮출 수 있다는 사실을 발견해 이 법칙을 만들었다.
디미터 법칙은 객체 간 관계를 설정할 때, 객체 간의 결합도를 효과적으로 낮출 수 있는 유용한 지침 중 하나로 소개되며 객체 지향 생활 체조원칙 중, One Dot Per Line으로 요약되기도 한다.

Don’t Talk to Strangers

디미터 법칙의 핵심은 객체 구조의 경로를 따라 멀리 떨어져 있는 낯선 객체에 무언가를 요청하지 말라는 것이다.
바꿔 말해서 객체는 내부적으로 보유하고 있거나 요청을 통해 확보한 정보만 가지고 의사 결정을 내려야하고 다른 객체를 탐색해나가면서 뭔가를 일으켜서는 안 된다는 것이다.
한 마디로 다음과 같은 설계를 피하라는 것이다.
public class Post { private final List<Comment> comments; public Post(List<Comment> comments) { this.comments = comments; } public List<Comment> getComments() { return comments; } }
Java
복사
public class Board { private final List<Post> posts; public Board(List<Post> posts) { this.posts = posts; } public void addComment(int postId, String content) { posts.get(postId).getComments().add(new Comment(content)); } ... }
Java
복사
Board 클래스의 addComment 메소드를 보면 점이 무려 세개나 찍혀있다. 이처럼 getter를 거듭해, 자신과 의존성이 낮은 객체를 참조하는 것은 위험한 행위다.
자신의 객체가 아닌 내부 객체인 commentsadd를 해당 객체에서 참조하는 것이 문제인 것이다.
왜 이처럼 낯선 객체에 메시지를 보내는 설계를 피해야 할까?
전혀 연관성이 없는 객체끼리도 변경에 의한 영향을 받기 때문이다. 즉 사이드 이펙트가 여기저기 퍼질 위험이 있다.
이러한 설계가 여기저기에 존재한다면 하나를 변경하더라도 수많은 변경사항이 발생하는 시한폭탄을 가지고 개발을 하는 것이다.

규칙화

디미터 법칙은 “노출 범위를 제한하기 위해 객체의 모든 메소드는 다음에 해당하는 메소드만 호출해야 한다.”고 했다.
1.
자신의 멤버 메소드
2.
메소드의 파라미터로 넘겨받은 객체들의 메소드
3.
메소드 내부에서 생성하는 객체의 메소드
4.
멤버 변수로 소유중인 객체의 메소드

주의사항

자료구조라면 디미터 법칙을 개의치 않아도 된다.
객체라면 내부 구조를 감추어야하므로 디미터 법칙을 지켜야 한다. 하지만 자료구조, VO라면 내부 구조를 노출해야 하므로 적용되지 않는다.
객체지향 생활체조 4번 규칙을 강조하는 규칙은 아니다.
디미터 법칙은 객체지향 4번 규칙으로 요약되기도 한다. 하지만 다음과 같은 코드는 디미터 법칙도 객체지향 생활체조 규칙도 위반하지 않는다.
IntStream.of(1, 15, 3, 20).filter(x -> x > 10).count();
Java
복사
위 코드는 객체의 내부구조가 노출되지 않는다. 단지 메소드만을 사용할뿐이다.
객체 내부 구현에 대한 어떤 정보도 외부로 노출하지 않는다면 괜찮다.