객체지향 생활 체조 원칙 7 : getter / setter / 프로퍼티를 쓰지 않는다. 📝
어제 다른 데브코스 동기분에게 질문을 받았다. 바로 toDto 의 책임이 Domain 에 있는 것이 적절한지 Dto 에 있는 것이 적절한지
였다. 코드는 아래와 같다.
@Override
public VoucherDto convertVoucherDto() {
String voucherId = String.valueOf(this.voucherId);
String discountAmount = String.valueOf(this.fixedAmount);
return new VoucherDto(voucherId, discountAmount, "fix");
}
FixedAmountVoucher 라는 도메인 클래스에 해당 메서드가 존재한다. 즉, Domain 이 DTO 로 변환하는 책임을 가지고 있는 것이다. 이와 같이 설계한 이유가 getter 사용을 최소화 하기 위함이라고 하셨다. 해당 책임이 DTO 에 있다면, Domain 에 getter 클래스를 사용해야 하기 때문에 객체지향 생활 체조 원칙을 위반하는 것이라고 생각하셨다. 질문을 정리하면 다음과 같다.
Domain 의 코드는 언제 변할까 🧐
위와 같이 toDto 의 책임이 Domain 에 존재하게 되면, Domain 은 언제 변경될까. 먼저 Domain 자체의 요구사항이 변경될 때 코드가 변경될 것이다. 또한 DTO 의 필드가 변경될 때도 Domain 코드가 변경된다. 즉, Domain 은 현재 서로 다른 두 가지의 책임
을 가지고 있다고 생각된다.
이는 객체지향의 5가지 원칙 중 하나인 SRP 를 위반한다.
DTO 는 Domain 에 비해 많이 변경되는 클래스이다 ❗️
DTO 는 계층 간 데이터 교환을 하기 위해 사용하는 객체로서, API 스펙, 요구사항 변경 등에 따라 자주 변경되는 클래스이다. 자주 변하는 DTO 클래스를 자주 변하지 않는 Domain 클래스가 의존하게 되면, Domain 은 DTO 때문에 많은 변경 지점이 발생한다. 만약 반대로 DTO 가 Domain 을 의존한다면, DTO 는 Domain 이 변경됨에 따라 발생하는 변경 지점이 훨씬 적다.
getter 를 무조건 사용하지 않을 수 있을까.
만약 그랬다면 Java 에서 이미 deprecated...😅
getter 를 사용할 수 밖에 없는 로직이 분명히 존재한다. 결국 getter 는 객체의 필드값을 꺼내는 역할을 하는데, 콘솔에서 Domain 의 데이터를 출력해야 하거나, DTO 에 Domain 의 데이터를 담아야 할 때는 무조건 써야한다. 객체지향 생활 체조 원칙은 다소 과격한 이론이라고 생각...
여러 클린 코드 책에서 말하는 getter 를 지양하자는 말은 비지니스 로직에서
라는 말이 생략된 것이라고 생각한다. 비지니스 로직에서 getter 가 사용되면, 중복되는 코드가 발생하기 쉽고 객체가 행위를 하지 않는 구조체 역할을 할 가능성이 높아지기 때문이다.
toDto 는 Domain 이 아닌 DTO 에 존재하는 것이 더 좋다. 👍
답변을 하는 과정에서 나도 객체의 책임에 대해 한번 더 생각해보게 되었고, 생각하다보니 이 내용은 한 번 정리하여 공유하면 좋다고 생각했다. 남을 도와주는 것은 결국 돌고돌아 나를 도와주는 일이라는 문구를 본적이 있다. 이 말을 가장 잘 느낄 수 있는 것이 배움을 공유하는 것이 아닐까 생각한다 😃
저도 이 부분에 대해서 궁금했는데, 글을 읽고 해소되었어요! 좋은 글 감사합니다😄