클린 코드(Clean Code) - 6장 객체와 자료구조

Muzi·2023년 1월 11일
0

Clean Code

목록 보기
6/14

객체와 자료구조

남들이 변수에 의존하지 않게 만들고 싶어 변수를 private로 정의한다 그렇다면 어째서 수많은 프로그래머가 get()과 set()을 당연하게 공개해 private 변수를 외부로 노출하는가?

1. 자료 추상화

추상 인터페이스를 제공해 사용자가 구현을 모른 채 자료의 핵심을 조작할 수 있어야 진정한 의미의 클래스다

// 목록 6-1 구체적인 Point 클래스 (구현을 외부에 노출)
public class Point {
  public double x;
  public double y;
}

// 목록 6-2 추상적인 Point 클래스 (구현을 완전히 숨김)
public interface Point {
  double getX();
  double getY();
  void setCartesian(double x, double y);
  double getR();
  double getTheta();
  void setPolar(double r, double theta);
}
  • 변수를 private으로 선언하더라도 get()과 set()을 제공한다면 구현을 외부로 노출하는 셈이다
  • 자료를 세세하게 공개하기보다는 추상적인 개념으로 표현하는 편이 좋다
  • 개발자는 객체가 포함하는 자료를 표현할 가장 좋은 방법을 고민해야 한다
  • 아무 생각없이 get/set을 추가하는 방법이 가장 나쁘다

2. 자료/객체 비대칭

객체는 추상화 뒤로 자료를 숨긴 채 자료를 다루는 함수만 공개한다. 자료 구조는 자료를 그대로 공개하며 별다른 함수를 제공하지 않는다

  • 절차적인 코드는 새로운 자료 구조를 추가하기 어렵다. 그러려면 모든 함수를 고쳐야 한다.
  • 객체 지향 코드는 새로운 함수를 추가하기 어렵다. 그러면 모든 클래스를 다 고쳐야 한다.
  • 분별있는 프로그래머는 모든 것이 객체라는 생각이 미신임을 잘 안다. 때로는 단순한 자료구조와 절차적인 코드가 가장 적합한 상황도 있다

3. 디미터 법칙

모듈은 자신이 조작하는 객체의 속사정을 몰라야한다. 즉, 객체는 조회 함수로 내부 구조를 공개하면 안 된다는 의미

  • 객체가 가지고있는 자료를 확인하는게 아니라, 객체에게 메세지를 보내야한다.
// 디미터 법칙 위반
@Service
public class NotificationServiceImpl implements NotificationService {
  
  @Override
  publid void sendMessageForSeoulUser(final User user) {
    if ("서울".equals(user.getAddress().getRegion())) {
      sendNotification(user);
    }
  }
  
}

// 디미터 법칙 준수
@Getter
public class User {
  private String email;
  private String name;
  private Address address;
  
  public boolean isSeoulUser() {
    return address.isSeoulRegion();
  }
}

@Getter
public class Address {
  private String region;
  private String details;
  
  // 데이터로 사용자의 지역을 파악하는게 아닌 메세지를 통해 파악
  public boolean isSeoulRegion() {
    return "서울".equals(region);
  }
}

기차 충돌

final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();
  • 여러 객체가 한 줄로 이어진 기차처럼 보이며 조잡하다 여겨지기에 지양하자
Options opts = ctxt.getOptions();
File scratchDir = opts.getScratchDir();
final String outputDir = scratchDir.getAbsolutePath();
  • 위 코드의 디미터 법칙 위반은 ctxt, Options, ScratchDir이 객체인지 자료구조인지에 달렸다.
    • 객체라면 내부 구조를 숨겨야 하므로 확실히 디미터 법칙을 위반한다
    • 반면, 자료 구조라면 당연히 내부 구조를 노출하므로 디미터 법칙 적용 x
final String outputDir = ctxt.options.scratchDir.absolutePath;
  • 자료구조는 무조건 함수 없이 public 변수만 포함하고 객체는 private 변수와 public 함수를 포함한다면 문제는 간단해진다

잡종 구조

  • 절반은 객체, 절반은 자료 구조인 경우
  • 새로운 함수, 새로운 자료구조도 추가하기 어렵다 지양

마치며

중요한 건 get/set을 남발하는게 아니라 목적을 잘 표현하는 메서드를 제공자료의 핵심을 조작하는 것

profile
좋아하는걸 열심히

0개의 댓글