- 이 곳에서 다루는 자료구조는 알고리즘할 때 자료구조와 다른 말이다.
자료 추상화
- 변수를 private으로 선언하더라도 각 값마다 getter, setter 함수를 제공한다면 구현을 외부로 노출하는 셈이다. 그냥 get,setter를 사용하는게 제일 나쁘다.
- 함수로 계층을 만든다고 구현이 저절로 감춰지지 않는다. 추상화가 필요하다.
public class Point {
public double x;
public double y;
}
public interface Point {
double getX();
double getY();
void setCartesian(double x, double y);
double getR();
double getTheta();
void setPolar(double r, double theta);
}
- 구체적인 포인트 클래스는 직교 좌표계다.
- 추상적인 인터페이스는 극좌표계일지, 직교 좌표계일지 아예 다른 좌표계일지 알 수 없다.
자료 / 객체 비대칭
- 객체는 추상화 뒤로 자료를 숨긴 채 자료를 다루는 함수만 공개한다.
- 자료구조는 자료를 그대로 공개하며 별다른 함수를 제공하지 않는다.
- 무조건적으로 객체 지향적인 코드가 좋은 것은 아니다. 때로는 단순한 자료 구조, 절차적인 코드가 가장 적합한 상황이 있다.
- (자료구조를 사용하는) 절차적인 코드는 기존 자료 구조를 변경하지 않으면서 새 함수를 추가하기 쉽다. 반면, 객체 지향 코드는 기존 함수를 변경하지 않으면서 새 클래스를 추가하기 쉽다.
디미터 법칙
- 잘 알려진 휴리스틱(heuristic)이라고 함. 모듈은 자신이 조작하는 객체의 속사정을 몰라야한다.
- 객체는 자료를 숨기고 함수를 공개한다.
클래스 C의 메서드 f는 다음과 같은 객체의 메서드만 호출해야한다.
- 클래스 C
- f가 생성한 객체
- f 인수로 넘어온 객체
- C 인스턴스 변수에 저장된 객체
기차 충돌
final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();
- 위와 같은 코드를 기차 충돌(train wreck)이라 부른다. 조잡하다 여겨지는 방식으로 피하는 편이 좋다.
Option opts = ctxt.getOptions();
File scratchDir = opts.getScratchDir();
final String outputDir = scratchDir.getAbsolutePath();
- 혼란은 조회함수때문에 생긴다.
자료구조는 무조건 함수 없이 공개 변수만 포함하고 객체는 비공개 변수와 공개 함수를 표현한다면 단순해진다.
final String outputDir = ctxt.options.scratchDir.absolutePath;
잡종 구조
- 위같은 혼란 때문에 절반은 객체, 절반은 자료 구조인 잡종 구조가 나온다.
- 잡종 구조는 새로운 함수를 더하기도, 새로운 자료 구조를 더하기도 어려운 단점 덩어리다.
자료 전달 객체
- 자료 구조체의 전형적인 형태는 공개 변수만 있고 함수가 없는 클래스다.
이런 자료구조를 때로는 자료 전달 객체(DTO Data Transfer Object)라 한다.
- DTO는 특히 데이터베이스와 통신하거나 소켓에서 받은 메시지의 구문을 분석할 때 유용하다.
활성 레코드
- DTO의 특수한 형태. 공개 변수가 있거나 비공개 변수에 조회 / 설정 함수가 있는 자료구조지만, 대게 save, find같은 탐색 함수도 제공한다.
- 활성 레코드는 자료 구조로 취급한다. 비즈니스 규칙을 담으면서 내부 자료(주로 인스턴스)를 숨기는 객체는 따로 생성한다.
결론
- 객체는 동작을 공개하고 자료를 숨긴다. 기존 동작을 변경하지 않으면서 새 객체 타입을 추가하기는 쉬운 반면, 기존 객체에 새 동작을 추가하기는 어렵다.
- 자료 구조는 별 다른 동작 없이 자료를 노출한다. 그래서 기존 자료 구조에 새 동작을 추가하기는 쉬우나, 기존 함수에 새 자료구조를 추가하기는 어렵다.
- 새로운 자료 타입을 추가하는 유연성이 필요하다면 객체, 새로운 동작을 추가하는 유연성이 필요하다면 자료구조와 절차적인 코드가 적합하다.