- 자료 추상화
- public으로 각 값마다 getter, setter를 제공하면 구현을 외부로 노출하는 것과 다름없다.
- 구현을 감추기 위해서는 추상화가 필요하다.
- 진정한 의미의 추상화 : 인터페이스를 통해 사용자가 구현을 모른채 자료의 핵심을 조작하도록 한다.
public class Vehicle {
private Weight weight;
private Capacity capacity;
private Vehicle(Weight weight, Capacity capacity){
// 생략
}
// getter
// setter
}
public interface Vehicle { // <-- 자료구조가 드러난다.
Weight getWeight(); // <-- 자료가 그대로 드러난다.
Capacity getCapacity();
}
public interface Vehicle { // <-- 객체. 자료구조가 드러나지 않는다.
getVehicleWeightCapacityRemaining(); // <-- 함수만 드러낸다.
}
- 자료/객체 비대칭
-
절차지향적인 코드 - 자료구조를 쓰는 절차적인 코드는 기존 자료구조 변경하지 않고 새 함수를 쓰기 쉽다. 새로운 자료구조를 추가하기 어렵다. 추가하려면 모든 함수를 고쳐야한다.
* A → B 상태에서 B의 구현 클래스를 추가하는 경우, A의 코드를 수정해야한다.
-
객체지향적인 코드 - 기존 함수를 변경하지 않으면서 새 클래스를 추가하기 쉽다. 그렇지만 새로운 함수를 추가하기는 어렵다. 그러려면 모든 클래스를 고쳐야한다.
- 상위 클래스에 메소드를 추가하는 경우, 하위 클래스를 모두 수정해야한다.
| 절차지향적 |
객체지향적 |
| 자료구조를 사용 |
추상화된 함수 사용 (자료구조는 숨긴다) |
| 함수 추가가 쉽다. |
클래스(자료구조)를 추가하기 쉽다 |
| 새로운 함수를 추가해야할 때 |
새로운 자료 타입이 필요할 때 |
- 디미터 법칙
- 휴리스틱(직관적 판단)의 일종으로, “모듈은 자신이 조작하는 객체의 속사정을 몰라야 한다”
- 객체는 ‘자료’를 숨기고, ‘함수’를 공개한다. (getter로 내부 구조를 공개하지 마라)
- rf. String profileImage = members.getMemberById(email).getProfiles().getTopImage(); [X]
- ㄴ 기차 충돌 ← 조잡하다.
- rf. Member member = members.getMemberById(email);
List<Profile> profiles = member.getProfiles();
String profileImage = profiles.getTopImage();
- 위의 경우, 객체의 경우 디미터 법칙을 위반 / 자료구조라면 디미터 법칙을 위반하는 게 맞다.
- rf. String profileImage = members.email(email).profiles().topImage();
- 절차지향도 아니고 객체지향도 아닌 잡종 구조는 피하라.
- 객체를 사용한다면 내부 구조를 숨겨라
- rf. String profileImage = members.getTopProfileByEmail(email);
- 자료 전달 객체