콘텐츠로 이동

2023 01 29

2023-01-29

우아한 객체지향

[의존성 (Dependency)]

  • 같이 변경되는 코드를 같이 넣으세요
  • 클래스 사이의 Dependency

    • 연관관계: 협력을 위해 필요한 영구적인 탐색구조
      class A {
          private B b;
      }
      
    • 의존관계: 협력을 위해 일시적으로 필요한 의존성
      class A {
          public B method(B b) {
              return new B();
          }
      }
      
    • 상속관계
      class A extends B {
      }
      
    • 실체화관계
      class A implements B {
      }
      
  • 패키지 사이의 Dependency
    • 패키지에 포함된 클래스 사이의 의존성
    • 딴 패키지 import 들어있으면 의존관계
  • 의존성 TIP
    1. 양방향 의존성을 피하라
      • 싱크 맞추는 상황에서 머리아픔
    2. 다중성이 적은 방향을 선택하라
      • Collection 물고있게하지 말고, 그냥 자식이 부모 바라보게해
    3. 의존성 필요없으면 제거해라
    4. 패키지 사이의 의존성 사이클 제거하기

[설계 개선하기]

  • 설계 개선 TIP
    • 의존성을 그림으로 그려보기
    • 이게 여기에 있는게 맞나?
  • 중간 객체를 이용한 의존성 사이클 끊기

    • 상황
      • shop 패키지: Shop, Menu, OptionGroupSpecification, OptionSpecification
      • order 패키지: Order, OrderLineItem, OrderOptionGroup, OrderOption
      • shop -> order 흐르는 상황을 끊어야함
        class OrderGroupSpecification {
            public boolean isSatisfiedBy(OrderOptionGroup group) {
                return true;
            }
        }
        
        class OptionGroupSpecification {
            public boolean isSatisfiedBy(OrderOption option) {
                return true;
            }
        }
        
    • 중간객체 생성
      • shop 패키지: Shop, Menu, OptionGroupSpecification, OptionGroup, OptionSpecification, Option
      • order 패키지: Order, OrderLineItem, OrderOptionGroup, OrderOption
      • shop은 order 알 필요없게 다 변환해줘!
        class OrderOptionGroup {
            public OptionGroup convertToOptionGroup() {
                return new OptionGroup(name, status);
            }
        }
        
        class OrderOption {
            public Option convertToOption() {
                return Option(name, status);
            }
        }
        
  • 추상화
    • 어떤거에 비해서 어떤건 잘 변하지 않아
    • OptionGroup, Option에는 변하지 않는 정보가 담겨있어
    • 이런것도 추상화야 (DIP의 변형)
    • 인터페이스, 추상클래스만 추상화가 아니라!
  • ORM 사용시 어디까지 조회할 것인가?
    • 싹다 조회하면 lazy loading 오지게 발생함 => 성능문제
    • 수정시 도메인 규칙을 적용할 경계는 어디까지인가? => 트랜잭션 경계문제
      • Shop, Order, Delivery가 주문 한번에 변경해버림...
      • 트랜잭션 경합으로 인한 성능 저하

[객체참조는 꼭 필요한가?]

  • 객체 참조는 결합도가 가장 높은 의존성
  • 객체 참조 필요없으면 끊어!
  • 어떤 객체를 묶고, 어떤 객체를 분리할지에 대한 간단한 경계 규칙 (With Business Rule)
    • 함께 생성되고 함께 삭제되는 객체들을 묶어라
    • 도메인 제약사항을 공유하는 객체들을 함께 묶어라
    • 가능하면 분리하라
    • 트랜잭션/조회를 이 경계에서 같이 관리하자
      • 그룹 단위로 영속성 저장소 변경도 가능!

[컴파일 에러 어찌해결?]

  1. 중간 객체 만들기
    • 절차지향으로 Validation등 묶기
    • 때로는 절차지향 >> 객체지향
    • 의존성 제거
  2. 도메인 이벤트 퍼블리싱
    • 높은 결합도를 느슨하게 끊기 위해 이벤트를 발행하자
    • 이벤트 & 이벤트 리스너
  3. 순환 참조 걸려있으면 패키지 분리하는 것도 방법
    • 사이클 도는거 해결하다보면 도메인을 뚜렷하게 찢을 수 있어!

[의존성과 시스템 분리]

  • 도메인 단위 분리시 주로 의존성 사이클이 존재함
  • 도메인 단위 모듈 = 시스템 분리의 기반
  • Message Broker등을 통해 외부로 이벤트 퍼블리싱도 쉬움
  • MSA + System Event => 트래픽 관리

그래서 Spring Security가...

  • UserDetailsService에서 Authentication을 반환하잖아?
  • 근데 Authentication내의 Principal에 Controller에 넘겨줄 정보 넣어두잖아?
  • 그 넣어둘 정보는 SpringSecurity에서 정의한 객체지?
  • SpringSecurity는 완전 독립적인 친구로 운용할 수 있네
  • MVC에서 정의한 객체를 받아 가져다 쓰면 되는거고!