시그마 삽질==six 시그마

우아한 객체지향 본문

프로그래밍/Programming stuff

우아한 객체지향

Ethan Matthew Hunt 2020. 4. 11. 23:46
본 내용은 우아한 형제들의 조영호 개발실장님의

19.6.20 우아한 테크세미나 강의 내용을 바탕으로 작성하였습니다.

관련 유튜브영상은  요기를 클릭해주세요

 

1. 의존성

 

변경에 의해 영향 받을 수 있는 가능성

 

1)클래스의 의존성

 

(1)연관관계

 

협력을 위해 (빈번하게) 필요한 영구적인 탐색구조(navigability)

a에서 b 영구적으로 갈수 있는 이동경로있는것

 

 객체사이에 협력이 필요하고

 객체의 관계가 영구적이라면

연관관계를 이용해 탐색 경로 구현

 

Order가 <—>Shop하고 빈번하게 연결되면 연관관계

연관관계 협력을 위해 필요한 영구적인 탐색구조

 

Order —>OrderLineItem

order가 무엇인지 알면, order를 통해 원하는 orderLineItem을 찾을 수 있다.

연관관계==탐색가능성(navigability)

 

메소드가 필요한 이유는 메세지를 받기때문

메세지를 결정하고 메소드를 만드는데 주문이라는 객체가 place라는 메세지 받고 가게와 주문항목에 메세지를 보낼 수 있어야한다.

즉 협력 경로가 필요하다(가게 영업중? 최소주문금액 이상?)

 

(2)의존관계

 

협력을 위해 일시적으로 필요한 의존성(파라미터,리턴타입,지역변수)

일시적으로 갈수 있는 이동경로있는것

파라미터가  타입이거나 , 리턴타입이  타입이거나 메소드내에서  인스턴스 생성시

 

(3)상속관계

 

(4)실체화관계

 

 

2)패키지 의존성

 

패키지에 포함된 클래스 사이의 의존성

 

양방향보다는 단방향 관계사용하라.  양방향이면 서로 의존. 한클래스로 해도되는걸 괜히 찢어놓은거 밖에 안된다.

다중성이 적은 방향을 선택하라. 일대다(상대방 리스트로가진상태) 보다는 다대일이 좋다

의존성이 필요없다면 제거하라

패키지 사이의 의존성 사이클을 제거하라

 

배민은 장바구니 로컬에 담는다서버에 저장하지 않는다.

가게(Shop)->메뉴(Menu)->옵션그룹(OptionGroupSpecification)->옵션(OptionSpecification)

주문(Order)->주문항목(OrderLineItem)->주문옵션그룹(OrderOptionGroup)->주문옵션(OrderOption)

유저가 장바구니 담았는데 사장님이 메뉴명, 금액을 바꾼다면? 주문을 했을때 서로 일치여부의 주문 validation이 필요하다.

 

 

2.설계방법

 

설계를 진화시키기위한 출발점은 코드 작성후 의존성 관점에서 설계를 검토하는것이다.

dependency를 종이에 그려봐야한다. 싸이클이 도나? 패키지를 잘못나눴나?

 

 

3. 객체참조로 구현한 연관관계 문제점

 

예시 문제점

 

-객체 참조로 인한 결합도 상승

Order->shop ,서로 의존시 한 클래스 수정시 다른 클래스도 수정해야하는 문제

패키지가 잘못 분해되있거나 의존성의 방향이 잘못되있는경우임

 

-패키지 의존성 사이클 

 

객체참조가 꼭 필요한가???

객체참조는 모든 객체가 참조로 연결될  수 있고 어떤 객체도 접근가능하고 수정가능할 수 있음.

객체참조는 결합도가 가장 높은 의존성임. 어떤 경우라도 이 객체는 같이 있어야된다는 의미

필요한 경우 객체 참조를 끊어야한다

 

1)객체 그룹의 조회 경계가 모호

 

어디까지 조회할것인가? 

수정시 도메인 규칙을 함께 적용할 경계는? (order의 상태를 변경할때 연관된 도메인 규칙을 함께 적용해야하는 객체의 범위는?)

다른말로 트랜잭션의 경계는 어디까지인가?(어떤 테이블에서 어떤 테이블까지 하나의 단위로 잠금을 설정할 것인가?)

 

2)트랜잭션 경합으로 인한 성능 저하

 

연관관계 탐색 전부 할 수 있다할시 메모리상에 있으면 큰 이슈 안되지만 ORM,  DB 직접매핑 하면 성능문제 Lazy loading 이슈

비지니스 로직이 추가될때마다 객체참조하면 된다라는 안일한생각에 아무생각없이 객체 참조 추가하고 객체타면서 수정하면 트랜잭션을 점점 더 길게 느리게 만든다. 거대한 연관객체간의 흐름이 하나의 롱 트랜젝션을 묶어서 업데이트함

 

 

 

4. 객체 결속(Aggregate)과 분리의 기준

 

어떤 객체들을 묶고 어떤 객체들을 분리할 것인가?

 

1)함께 생성되고 함께 삭제되는 객체들을 함께 묶어라

(결합도가 높다는 얘기, 하나의 단위, tx로 묶인다)

샵과 메뉴의 생성시점과 contraint는  다르다. 주문,배송도 다 독립적 so 분리

 

2)도메인 제약사항을 공유하는 객체들을 함께 묶어라

 

3)가능하면 분리하라

 

5. 객체 분리 후 action

 

1)경계안의 객체는 참조를 이용해 접근

 

2)겅계 밖의 객체는 ID를 이용해 접근

 

ID를 이용해서 연관관계 설정,Repository를 통한 연관객체 탐색(약한 결합도)

 

Order->shop

Orders에 private shopId

비지니스 로직은 단방향으로 깔끔하게 보여줄수 있는데 조회로직, 어드민로직 들어가면서 양방향이된다.

 

객체분리 후  객체를 직접 참조하는 로직을 다른 객체로 옮기자

새로운 객체 만들어서 관련 로직을 이동시키자

예전 객체지향 방식에서는 validation 로직 여러 객체에 퍼져 있어서 여러 객체를 오가며 로직을 파악해야했고 응집도가 낮았다.

낮은 응집도의 객체가-> 높은 응집도의 객체로 변경됨(단일책임의 원칙)

때로는 절차지향이 객체지향보다 좋다.

 

3)분리한 그룹은 트랜잭션/조회/비즈니스 제약의 단위임. 그룹  단위의 영속성 저장소 변경 가능

 

분리는 비지니스 룰, 시스템마다 케바케

어떤 시스템은 장바구니와 장바구니 항목을 같은 객체안에 묶을 수 있고 어떤 시스템은 끊을 수 있다. 배민은 동일한업소꺼만 장바구니 넣을 수 있어서 함께 있다.

 

 

 

 

 

 

 

6. 도메인 로직의 순차적실행시 해결책

 

한 도메인에 여러 참조를 사용하며 순차적으로 실행할때

 

1)절차지향적 로직

 

2)도메인 이벤트 퍼블리싱

 

Spring Data Aggregate Abstration 이용(AbstractAggregateRoot)

 

이벤트 등록--save시 실행->이벤트 핸들러->이벤트 실행

 

 

 

7. 패키지 의존성 사이클을 제거하는 3가지 방법

 

1)추상적 중간 객체 만들어서 변환하기

 

변경전

가게(Shop)--------->메뉴(Menu)------>옵션그룹(OptionGroupSpecification)->옵션(OptionSpecification)

각 항목이 대응

주문(Order)-->주문항목(OrderLineItem)-->주문옵션그룹(OrderOptionGroup)->주문옵션(OrderOption)

 

변경후

가게(Shop)--------->메뉴(Menu)------>옵션그룹(OptionGroupSpecification)->옵션(OptionSpecification)

중간층 추가                                                           OptionGroup추가                        Option 추가       

주문(Order)-->주문항목(OrderLineItem)-->주문옵션그룹(OrderOptionGroup)->주문옵션(OrderOption)

 

 

2)의존성 역전

 

인터페이스나 추상클래스넣어서 의존성을 역전시키기

 

-의존성의 역전 원리

 

클래스들이 구체적인거에 의존하지 말고 추상화에 의존해야한다

추상화하면 인터페이스나 추상클래스여야되는 선입견이 있다.

개발쪽에 추상화의 정의는 잘 안 변하는거임

 

 

3)새로운 패키지 추가(같은 패키지에서 분리)

 

의존성에 따라 시스템을 진화시켜라

'프로그래밍 > Programming stuff' 카테고리의 다른 글

몇가지 구현 이야기  (0) 2020.04.12
애플리케이션 아키텍처와 객체지향  (0) 2020.04.12
모나드(Monad)  (0) 2020.03.04
클로저 Closure (computer programming)  (0) 2020.03.04
함수형 프로그래밍  (0) 2020.03.03
Comments