6장: 객체와 자료 구조

자료 추상화

구체적인 Point 클래스

public class Point {
  public double x;
  public double y;
}

확실한 직교좌표계를 사용, 개별적으로 좌표값을 읽고 설정하게 강제한다.

추상적인 Point 클래스

public interface Point {
  double getX();
  double getY();
  void setCartesian(double x, double y);
  double getR();
  double getTheta();
  void setPolar(double r, double theta);
}
  • 점이 직교좌표계를 사용하는 지, 극좌표계를 사용하는 지 알 길이 없다. 그럼에도 불구하고 인터페이스는 자료구조를 명백하게 표현한다.

  • 추상적인 Point 클래스는 자료구조 이상을 표현한다. 클래스 메서드가 접근 정책을 강제한다. 좌표를 읽을 때는 각 값을 개별적으로 읽어야한다. 하지만 좌표를 설정할 때는 두 값을 한꺼번에 설정해야 한다.

  • 변수 사이에 함수라는 계층을 넣는다고 구현이 저절로 감춰지지는 않는다. 구현을 감추려면 추상화가 필요하다!

구체적인 Vehicle 클래스

public interface Vehicle {
  double getFuelTankCapacityInGallons();
  double getGallonsOfGasoline();
}
  • 위의 구체적인 클래스는 두 함수가 변수값을 읽어 반환할 뿐이라는 사실이 거의 확실하다.

추상적인 Vehicle 클래스

public interface Vehicle {
  double getPercentFuelRemaining();
}
  • 위의 경우 정보가 어디서 오는지 두드러지지 않는다.

자료/객체 비대칭

객체와 자료구조

구분설명

객체

추상화 뒤로 자료를 숨긴 채 자료를 다루는 함수만 공개한다.

자료구조

자료를 그대로 공개하며 별다른 함수는 제공하지 않는다.

객체와 자료구조의 특징

  • 객체와 자료구조는 상호 보완적인 특질이 있다.

  • 객체 지향 코드에서 어려운 변경은 절차적인 코드에서 쉬우며, 절차적인 코드에서 어려운 변경은 객체 지향 코드에서 쉽다!

  • 모든 것이 객체라는 생각은 미신! 단순 자료구조와 절차적인 코드가 가장 적합한 상황도 있다.

디미터 법칙

  • 디미터 법칙은 잘 알려진 휴리스틱으로, 모듈은 자신이 조작하는 객체의 속사정을 몰라야 한다는 법칙이다.

  • 클래스 $C$의 메서드 $f$는 다음과 같은 객체의 메서드만 호출해야 한다.

    • 클래스 $C$

    • $f$가 생성한 객체

    • $f$의 인수로 넘어온 객체

    • $C$ 인스턴스 변수에 저장된 객체

기차 충돌

  • 다음과 같은 코드는 디미터 법칙을 어기는 듯 보인다.

    final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();
  • 여러 객차가 한 줄로 이어진 기차처럼 보이는 코드를 기차 충돌 (train wreck) 이라 부른다. 일반적으로 조잡하다 여겨지는 방식이므로 피하는 편이 좋다.

  • 위 코드는 여러 변수로 나누는 편이 좋으나, 이것이 디미터 법칙을 어기는 지는 알 수 없다. 객체인지 자료구조인지 알 수 없기 때문이다!

  • 객체라면 내부 구조를 유출하고 있으므로 디미터 법칙을 위반한다. 자료 구조라면 당연히 내부 구조를 노출하므로 디미터 법칙이 적용하지 않는다.

잡종 구조

  • 때때로 절반은 객체, 절반은 자료 구조인 잡종 구조가 나온다.

  • 잡종 구조는 새로운 함수는 물론이고 새로운 자료구조도 추가하기 어렵다. 양쪽 세상에서 단점만 모아놓은 구조이므로 피하는 것이 좋다.

구조체 감추기

  • ctxt, options, stratchDir이 진짜 객체라면, 앞선 코드 예제처럼 줄줄이 사탕으로 엮여서는 안 된다.

자료 전달 객체

  • 자료구조체의 전형적인 형태는 공개 변수만 있고 함수가 없는 클래스이다. 이런 자료구조체를 때로는 자료 전달 객체(Data Transfer Object, DTO)라 한다.

  • 좀 더 일반적인 형태는 빈(Bean) 구조로, 빈은 비공개 변수를 조회/설정 함수로 조작한다.

활성 레코드

  • DTO의 특수한 형태. 공개 변수가 있거나 비공개 변수에 조회/설정 함수가 있는 자료구조지만, 대개 save나 find같은 탐색 함수도 제공한다.

결론

  • 객체는 동작을 공개하고 자료를 숨진다.

    • 기존 동작을 변경하지 않으면서 새 객체 타입을 추가하기 쉽다.

    • 그러나 기존 객체에 새 동작을 추가하기는 어렵다.

    • 새로운 자료 타입을 추가하는 유연성이 요구될 때는 객체를 사용하자.

  • 자료구조는 별다른 동작 없이 자료를 노출한다.

    • 기존 자료구조에 새 동작을 추가하기는 쉽다.

    • 그러나 기존 함수에 새 자료구조를 추가하기는 어렵다.

    • 새로운 동작을 추가하는 유연성이 필요하면 자료구조와 절차적인 코드가 더 적합하다.

  • 우수한 소프트웨어 개발자는 편견없이 이 사실을 이해해 직면한 문제에 최적인 해결책을 선택한다.

Last updated