[Clean Code] 6. 객체와 자료구조
이장에서는 객체와 자료구조에 대해 전반적으로 비교한다. 서로의 장단점과 특징을 간단하게 살펴보자
자료 추상화
- 구현을 감추려면 추상화가 필요하다
- 추상 인터페이스를 제공해 사용자가 구현을 모른 채 자료의 핵심을 조작할 수 있어야 진정한 의미의 클래스다.
- 자료를 세세하게 공개하기 보다는 추상적인 개념으로 표현하는것이 좋다.
public class Poing {
public double x;
public double y;
}
public interface Vehicle {
double getFuelTankCapacityInGallons();
double getGallonsOfGasoline();
}
- 구체적 클래스 예시
public interface Point {
double getX();
double getY();
void setCartesian(double x, double y);
double getR();
double getTheta();
void setPolar(double r, double theta);
}
public interface Vehicle {
double getPercentFuelRemaining();
}
- 추상적 클래스 예시
자료/객체 비대칭
- 객체는 추상화 뒤로 자료를 숨긴 채 자료를 다루는 함수만 공개한다.
- 자료구조는 자료를 그대로 공개하며 별다른 함수를 제공하지 않는다.
자료구조(절차적 코드)를 사용할 경우
기존 자료구조를 변경하지 않으면서 새 함수를 추가하기 쉽다.
그러나 새로운 자료구조를 추가하기 어렵다. 추가하려면 모든 함수를 고쳐야 한다.
객체지향을 사용할 경우
기존 함수를 변경하지 않으면서 새 클래스를 추가하기 쉽다.
그러나 새로운 함수를 추가하기 어렵다. 추가하려면 모든 클래스를 고쳐야 한다.
- 객체지향 코드에서 어려운 변경은 절차적 코드에서는 쉬우나, 절차적 코드에서 어려운 변경은 객체지향 코드에서 쉽다.
디미터 법칙
- 모듈은 자신이 조작하는 객체의 속사정을 몰라야 한다는 법칙이다.
- 객체는 조회함수로 내부 구조를 공개하면 안된다는 의미이다.
기차 충돌
final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();
- 위와 같은 코드를 기차충돌(train wreck)라고 부른다. 일반적으로 피하도록 하자
Options opts = ctxt.getOptions();
File scratchDir = opts.getScratchDir();
fianl String outputDir = scratchDir.getAbsolutePath();
- 기차충돌을 개선한 방식
위의 같은 코드가 디미터 법칙을 위반하는지 여부는 ctxt, Options, ScratchDir 객체인지 아니면 자료구조에 따라 다르다. 객체라면 내부 구조를 숨겨야 하므로 위반이나, 자료구조라면 당연히 내부 구조를 노출해야 하므로 적용되지 않는다.
잡종구조
- 절반은 객체, 절반은 자료 구조를 뜻한다
- 양 구조의 단점만 모나옿은 구조이므로 피할수 있다면 피하자.
구조체 감추기
- ctxt, options, scratchDir이 객체라면 아래코드와 같이 개선할 수있다.
BufferedOutputStream bos = ctxt.createScratchFileStream(classFileName); //scratchDir.absoultePath 가 필요한 이유를 함수로 선언한다.
자료 전달 객체(Data Transfer Object)
- 정보를 객체로 변환할때 가장 많이 사용하는 구조체
- 흔히 DB에서 저장된 가공되지 않은 정보를 코드로 가져올때 가장 처음으로 사용되는 구조체
public class Player {
private String id;
private String name;
private String gender;
private int age;
public Player(String id, String name, String gender, int age) {
this.id = id;
this.name = name;
this.gender = gender;
this.age = age;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getGender() {
return gender;
}
public int getAge() {
return age;
}
}
- DTO 예시
활성 레코드
- DTO의 특수한 형태로, get/set 만 있는 구조가 아니라 save, find와 같은 탐색 함수를 제공한다.
- 단 비즈니스 규칙 메서드 를 추가하여 객체로 취급하지는 말자.
마치며..
이번장은 내용이 짧으나 쉬운 내용이 아니란 생각이 든다. 지금까지 배운 사상을 조금씩 응용하는 단계인 것 같은데, 과연 얼마나 고려하며 작성할 수 있을지는 의문이 들기는 한다..
Leave a comment