•
설계의 핵심은 의존성
1. 의존성
•
설계란 코드를 어떻게 배치할것인가에 대한 의사결정
•
어떤 클래스에 어떤 코드를 넣을거고, 어떤 패키지에, 어떤 프로젝트에 어떤 코드를 넣을거냐에 따라 설계의 모양이 굉장히 많이 바뀜
•
그럼 어디다가 코드를 넣을거냐라는 의문에 있어서 '변경'에 초점을 맞춰야함
•
같이 변경되는 코드를 같이 넣어야함 → 핵심 의존성
그렇다면 의존성이란?
•
의존성: A가 B를 의존한다라고 하였을 때, B가 변경되면 A도 함께 변경될 수도 있다라는 가능성이 있다고 봄
◦
B라는 클래스의 내부 구현이 변경되더라도 A가 변경되지 않을 수도 있음 → 단, 설계를 잘했을 때
•
의존성은 '클래스 사이에 의존성'과 '패키지 사이의 의존성'이 있을 수 있음
클래스 의존성의 종류
•
Association(연관관계)
◦
A에서 B로 가는 '영구적인' 관계
•
Dependency(의존관계)
◦
A에서 B로 가는 '일시적인' 관계
◦
협력을 하는 어떤 시점에 일시적으로 관계를 맺고 헤어지는 관계
•
Inheritance(상속관계)
◦
B의 구현이 바뀌면 영향을 받음
•
Realization(실체화관계)
◦
B의 오퍼레이션 시그니처가 바뀌면 영향을 받음
패키지 의존성
•
어떤 패키지(패키지A)에 포함된 어떤 클래스(클래스A)가 다른 패키지에 포함된 다른 클래스(클래스B)를 의존할 때, 두 패키지 사이에 의존성이 있다라고함
양방향 의존성을 피하라
•
정답은 아니지만, 몇가지 설계 가이드가 있음
•
위 그림 처럼 A가 B를 의존하고 B가 A를 의존하는 경우, 각 변경이 서로에게 영향을 줌
⇒ 즉, 하나의 클래스로 작성 되어야했던 것을 두 개의 클래스로 찢어놨다라고 보면됨
•
A와 B의 상태를 동기화 시켜줘야함
•
양방향 관계를 가지는 경우, 굉장히 신경쓸게 많음
◦
성능 이슈도 많이 발생하고, 싱크를 맞추는 거에 있어서 많은 버그가 발생함
•
양방향 관계를 피할 수 있다면, 단반향 연관관계로 바꿔줘야함
•
(내 생각) 애플리케이션 관점으로 확장해본다면, 각 마이크로서비스도 마찬가지로 양방향 관계를 가지지 않도록 하는 것이 당연히 좋겠넹
다중성이 적은 방향을 선택하라
•
컬렉션을 인스턴스 변수로 가지면 다양한 이슈가 발생
•
성능 이슈 및 객체간의 관계를 유지하기 위한 다양한 노력이 필요함
◦
(전철호) JPA를 예로 들어주시긴 했는데 마땅한 경험이 떠오르지 않음
◦
(전철호) Ex. Claim
FilePath
패키지 사이의 의존성 사이클을 제거하라
•
패키지 사이에 양방향 의존이 존재하면 안됌
•
[패키지 A → 패키지 B → 패키지 C → 패키지 A]와 같은 관계로 의존성이 싸이클을 가진다면, 이는 세개의 패키지를 하나의 패키지로 관리해야함을 암시
2. 예제 살펴보기
주문 플로우
Domain Concept - 가게 & 메뉴
Domain Object - 가게 & 메뉴
Domain Cencept - 주문
Domain Object - 주문
Domain Object - 메뉴 & 주문
(문제점) 메뉴 선택
(문제점) 장바구니 담기
•
장바구니에 대한 데이터는 휴대폰 로컬 저장소에 저장됨
•
이 상황에서 아래와 같은 문제가 생길 수 있음
◦
사용자가 주문하고자 하는 주문 정보를 장바구니에 담음
◦
점주가 메뉴의 정보를 수정함
◦
메뉴 불일치
(문제점) 업소메뉴변경
(문제점) 메뉴 불일치
주문 Validation
협력 설계하기
클래스 다이어그램
3. 설계 개선하기
Repository를 통한 탐색(약한 결합도)
•
리포지터리에는 연관관계를 구현할 수 있는 오퍼레이션들이 들어가줘야함
•
비즈니스로직은 단방향으로 깔끔하게 만들수 있지만, 조회로직을 넣다보면 양방향 관계가 계속 늘어남
어떤 객체들을 묶고 어떤 객체들을 분리할 것인가?
낮은 응집도의 객체가
•
같이 변경되는 녀석들이 같이 있으면 응집도가 높은 것임
때로는 절차지향이 객체지향보다 좋다
•
(하나의 클래스 내에서)특정 객체의 유효성 검사를 위해 다른 여러 객체가 필요한 경우, 응집도가 확 떨어짐
•
절차지향적으로 모아놓으면 비지니스 플로우가 한눈에 보임
4. 의존성과 시스템 분리
참고자료
세미나 영상 - 조영호님
•
발표자료 - 조영호님