객체지향 스터디를 준비하던 중, 객체지향의 사실과 오해의 저자이신 조영호 님의 객체지향 세미나를 보게 되었다.
자료
- slideshare : https://www.slideshare.net/baejjae93/ss-150432699
- 코드
의존성이란?
객체 세계에서 협력은 필수적이며, 객체가 협력한다는 것은 객체 간의 의존성이 존재하는 것이다. 의존성이란, 파라미터나 리턴값 또는 지역 변수 등으로 다른 객체를 참조하는 것을 의미한다.
애플리케이션 설계 시 어떤 코드를 어떤 패키지에, 어떤 클래스에 넣을 지 많은 고민을 하게 되는데, 의존성의 경우 변경에 초점을 맞추어야 한다. 즉, 협력 관계에 있는 객체 중 하나가 변경이 되면, 다른 객체가 변경되지 않도록 고려해야 한다.
클래스 의존성
(1) 연관 관계
class A {
private B b;
}
A와 B 객체 사이에서 요청이 빈번하다면, 의도적으로 연관 관계를 맺어줄 수 있다.
(2) 의존 관계
class A {
public B method(B b) {
return new B();
}
}
(3) 상속 관계
class A extends B {
}
(4) 실체화 관계
class A implements B {
}
패키지 의존성
패키지에 포함된 클래스 사이의 의존성
좋은 의존성 관리를 위한 규칙
(1) 양방향 의존성을 피하라
문제
class A {
private B b;
public void setA(B b) {
this.b = b;
this.b.setA(this);
}
}
class B {
private A a;
public void setA(A a) {
this.a = a;
}
}
위처럼 A와 B는 서로 연관 관계가 존재하고, B가 바뀔 때 A도 바뀌고, A가 바뀔 때 B도 바뀌게 된다. 가급적이면 단방향으로 구현하자.
해결책
class A {
private B b;
public void setA(B b) {
this.b = b;
}
}
class B {
}
(2) 다중성이 적은 방향을 선택하라
문제
class A {
private Collections<B> bs;
}
class B {
}
Collection을 다루다 발생 우려되는 문제가 많으므로, 일대다보다 다대일을 권장한다.
해결책
class A {
}
class B {
private A a;
}
(3) 의존성이 필요없다면 제거하라
(4) 패키지 사이의 의존성 사이클을 제거하라
예제 소개
- 본 예제는 배달의민족 앱에서 장바구니에 있는 메뉴를 주문하는 로직을 단순화한 것이다.
도메인 컨셉
가게 & 메뉴
주문
문제점
- 손님이 장바구니에 1인 세트를 저장한 상태다. 단, 장바구니의 값은 손님의 로컬 저장소에만 저장된다고 가정한다. 이때 사장님이 1인 세트를 0.5인 세트로 변경한다면? 메뉴가 불일치하는 문제가 발생한다. 이를 위해 주문을 검증하는 로직을 만든다.
- 주문 검증 로직
- 메뉴의 이름과 주문 항목의 이름 비교
- 옵션 그룹의 이름과 주문 옵션 그룹의 이름 비교
- 옵션의 이름과 주문 옵션의 이름 비교
- 옵션의 가격과 주문 옵션의 가격 비교
- 가게가 영업 중인지 확인
- 최소 주문 금액 이상인지 확인
주문 검증 로직을 토대로 협력 설계하기
관계에는 방향성이 필요하다. 관계의 방향 == 협력의 방향 == 의존성의 방향
설계 개선하기_객체 참조로 인한 문제점
문제
Shop과 Order 사이에 의존성 사이클이 발생한다.
해결1_중간 객체를 이용한 의존성 사이클 끊기
해결2_객체 참조 끊어내기
객체 참조의 단점
도메인이 전부 연결되어 있는 상태라면, JPA 같은 경우 연관된 모든 도메인 값을 DB로부터 가져오므로, lazy loading 이슈가 발생할 수 있다. 따라서, 한 도메인을 읽어올 때 어디까지 읽어와야 하는 지 고민을 해야 한다. 즉, 트랜잭션 경계를 적절히 지정해야 한다.
Primary Key만 가지게 하자
Repository로 탐색해오면 되므로, 약한 결합도를 가지게 된다.
해결3_때로는 절차지향이 낫다
모든 Validation 로직을 각 객체에 넣게 되면, 어떤 Validation 로직이 수행되는 지 헷갈릴 수 있다. Validation 로직 같은 경우 한 눈으로 보는게 유리할 수 있기 때문에, 이런 경우 OrderValidator와 같은 객체를 새로 생성하여, Validation 책임을 위임시킬 수 있다. 이로써 가독성이 좋아질 수 있다.
설계 개선하기_패키지 사이클로 인한 문제점
// 공사중
출처
https://jojoldu.tistory.com/425