디미터 법칙(Law of Demeter)이란?
잘 알려진 휴리스틱으로, 모듈은 자신이 조작하는 객체의 속사정을 몰라야 한다는 법칙이다.
쉽게 말하면, "친구의 친구에게 말하지 마라" 인데, 자신이 직접 알고 있는 객체와만 상호작용해야 한다. 이는 허용된 메서드라고 부르는데, 허용된 메소드는 다음과 같다.
클래스 C의 메서드 f는 다음과 같은 객체의 메서드만 호출해야 한다.
- 클래스 C
- f가 생성한 객체
- f의 인수로 넘어온 객체
- C 인스턴스 변수에 저장된 객체
그 외에 허용된 메서드가 반환하는 객체의 메서드는 호출하면 안된다.
필요한 이유는 무엇일까?
- 코드의 결합도를 낮추고
- 유지보수성을 높이며
- 내부 설계 변경에 외부 코드가 휘청이지 않게 만들기 위함이다.
예를 들어, 아래와 같은 코드는 디미터 법칙을 어기는 것으로 보인다.
왜냐하면 Options, ScratchDir 내부가 바뀌면 외부 코드가 전부 깨질 수 있기 때문이다.
아래의 코드는 단순한 메서드 체이닝이 아니다. 서로 다른 객체로 단계별로 파고들기 때문에 각 객체의 내부 설계나 구조 변경에 외부 코드가 민감하게 깨질 위험이 생긴다.
final String outputDir = stxt.getOptios().getScratchDir().getAbsolutePath();
위와 같은 코드를 기차 충돌(train wreck)이라 부르는데, 일반적으로 조잡하다 여겨지는 방식이므로 피하는 것이 좋다.
참고로, 기차 충돌은 메서드 체이닝이 길어졌다고 해서 기차 충돌이라 부르는게 아니고 메서드 체이닝을 통해 객체의 내부에서 내부로 점점 파고드는 체이닝에 대해 말한다. 이는 디미터 법칙 위반이며, 이런 체이닝을 기차 충돌이라고 부른다.
위 코드를 개선해보자.
Options opts = ctxt.getOptions();
File scratchDir = opts.getScratchDir();
final String outputDir = scratchDir.getAbsolutePath();
체이닝을 끊어서 한 단계씩 접근한다.
하지만, 이렇게 하면 직접 체이닝은 줄었지만 사실 객체를 사용하는 것은 그대로라서 본질적으로는 여전히 디미터 법칙을 위반한다.
여기서, ✅ 디미터 법칙 위반 여부는 ctxt, opts, scratchDir이 객체인지 자료구조인지에 따라 달려있다.
하나씩 살펴보자.
- 객체
- 내부 상태와 메서드를 갖고 내부 캡슐화를 보장한다.
- 내부 설계가 바뀌면 코드가 깨질 위험이 크므로 디미터 법칙으로 보호가 필요하다.
- 자료구조
- 주로 데이터 보관용으로 public 필드나 getter로 값만 주고 메서드는 거의 사용하지 않는다.
- 외부에서 마음껏 꺼내 써도 상대적으로 안전하다.
- 내부 설계가 바뀔 위험이 적으므로 getter로 값 꺼내는 것이 문제가 되지 않는다.
- 따라서 디미터 법칙이 적용되지 않는다.
코드를 아래와 같이 구현하면 디미터 법칙을 거론하지 않아도 된다.
final String outputDir = ctxt.options.scratchDir.absolutePath;
단순 값을 조회하는 것일 뿐, 복잡한 설계 보호가 필요 없는 자료구조로 보기 때문이다.
References
Clean code 6장 객체와 자료 구조
'IT 기본지식' 카테고리의 다른 글
ADAPTER 패턴 정리 (0) | 2025.05.08 |
---|---|
Git Flow vs Github Flow : 브랜치 전략 (0) | 2024.05.03 |
Cookie vs LocalStorage vs SessionStorage : 차이점은 무엇일까? (0) | 2023.12.26 |
CORS(Cross-Origin Resource Sharing)에 대하여 (0) | 2023.12.08 |
JSON Web Token(JWT) 에 대해 살펴보자 (0) | 2023.10.04 |
댓글