Search

디미터 법칙이란

Tags
디미터 법칙
Date
2023/10/17

개요

이번 포스팅에서는 객체지향 프로그래밍을 위한 디미터 법칙에 대해 알아보도록 하겠습니다.

1. 디미터 법칙이란?

“다른 객체에게 내부 사정을 보여주지 말라”
저는 디미터 법칙을 위 문장으로 표현하고 싶은데요, 디미터 법칙이란 다른 객체가 어떠한 자료를 가지고 있는지, 그 내부 사정을 몰라야 한다는 것을 의미하며 Don’t talk to stranger 이라고 불리기도 합니다.
위 설명 만으로는 감이 잘 안오실 수 있는데요, 예제 코드를 통해 한 번 알아보도록 하겠습니다.
잘못된 코드의 예시입니다.
public void sendMessageForSeoulUser(final User user) { if("서울".equals(user.getAddress().getRegion())) { sendNotification(user); } }
Java
복사
위 코드를 보면 “유저는 Address 라는 필드를 가지고 있구나” 예측할 수 있게 됩니다. 즉, User 도메인의 내부 사정을 알게된 것이죠.
 디미터 법칙을 적용한 올바른 코드는 어떻게 생겼을까요?
public class Address { private String region; private String details; public boolean isSeoulRegion() { return "서울".equals(region); } } public class User { private String email; private String name; private Address address; public boolean isSeoulUser() { return address.isSeoulRegion(); } }
Java
복사
도메인 계층에 다음과 같은 코드를 작성함으로써 이전과 다른 새로운 코드를 작성할 수 있습니다.
public void sendMessageForSeoulUser(final User user) { if(user.isSeoulUser()) { sendNotification(user); } }
Java
복사
많은 분들이 착각하는 것이 있는데, . 이 많다고 해서 디미터 법칙을 위반하는 것이 아닙니다.
보통 디미터 법칙을 위반한 사례들이 앞선 코드와 같이 (user.getAddress().getRegion() ) . 을 여러 개 이어 붙여 마치 .을 많이 이어 작성하게 되면 디미터 법칙을 위반한다고 생각할 수 있는데 이는 잘못된 사실입니다.
사실 .은 Java 8에서 도입된 stream을 이용할 때 많이 사용되는데요, 중요한 건 .으로 인해 내부 구조가 외부로 유출 되는지 여부입니다. 따라서 이를 잘 판단할 필요가 있습니다.

2. 직접 디미터 법칙을 적용해보자

예제를 하나 가져왔는데요, 위 코드는 명백하게 디미터 법칙을 위반하고 있습니다.
@Service @RequiredArgsConstructor public class PostService { private final PostRepository messageRepository; public Mono<Void> deletePost(final DeletePostCommand command) { return postRepository.findByPostId(command.getPostId()) .switchIfEmpty(Mono.error(new PostNotFoundException())) .flatMap(post -> { if (!post.getUser().getId().equals(command.getDeleter().getUserId())) { return Mono.error(new AccessDeniedException()); } return postRepository.save(post.deleteAndCopy()); }) .then(); } }
Java
복사
 바로 작성자와 삭제 요청자가 일치하는 지 확인하기 위해 여러 객체들에게 정보를 묻고 있기 때문인데요, 이를 디미터 법칙을 적용해서 어떻게 바꿀 수 있을까요?
사실 여기에 정답은 없습니다. 하지만 방법은 여러 개가 나올 수 있죠!
저라면,, 우선 작성자와 삭제 요청자의 아이디가 일치하는 건 post가 검증하도록 할 것 같습니다. 즉, 책임을 위임하는 것이죠!
public class Post { private User user; public Post deleteAndCopy(final PostWriter deleter){ vertifyDeletePermission(deleter); return copyFromThis() .deleted(true) .build(); } private void veriyfyDeletePermission(deleter){ if(!this.user.equals(deleter)){ throw new RuntimeException(); } }
Java
복사