[OOP]우아한 객체지향

우아한테크세미나의 우아한객체지향 정리

클래스 의존성의 종류

1. 연관관계 (Association)

class A {
    private B b;
}
  • 영구적인 관계

2. 의존 관계 (Dependency)

class A {
    public B method(B b) {
        return new B();
    }
}
  • 파라미터에서 사용하는 타입 또는 메서드 안에서 생성하는 인스턴스 타입
  • 일시적인 관계

3. 상속 관계 (Inheritance)

class A extends B {
}

4. 실체화 관계 (Realization)

class A implements B {
}

패키지 의존성

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

양방향 의존성을 피하라

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;
    }
}

다중성이 적은 방향을 선택하라

  • 일대다 대신에
class A {
    private Collection<B> bs;
}

class B {
}
  • 다대일이 좋음
class A {
}

class B {
    private A a;
}

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

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

  • 코드의 변경이 영향을 미치는 범위를 기준으로 생각!

관계의 방향 = 협력의 방향 = 의존성의 방향

  • 연관관계
    • 협력을 위해 필요한 영구적인 탐색 구조
    • 어떤 객체에서 어떤 객체로 빈번하게 가는 경우
    • 탐색 가능성
    • 두 객체 사이에 협력이 필요하고 두 객체의 관계가 영구적이라면 연관관계를 이용해 탐색 경로 구현
    • 일반적으로 객체 참조를 이용해서 구현
  • 의존관계
    • 협력을 위해 일시적으로 필요한 의존성
    • 파라미터, 리턴타입, 지역변수

구현 시작하기

  • 메시지를 결정하고 메서드를 만든다

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

  • 협력을 위해 필요하지만 두 객체 사이의 결합도가 높아짐
  • 어디까지 조회할 것인가?
    • ORM의 경우 Lazy Loading 문제 발생
    • 객체 그룹의 조회 경계가 모호
      • 어디까지 읽으면 되는지에 대한 가이드가 없음
  • 수정 시 도메인 규칙을 함께 적용할 경계는?
    • = 트랜잭션 경계는 어디까지인가?
  • 객체 참조는 결합도가 가장 높은 의존성
    • 객체 참조 끊기!!

객체 참조 끊기

Repository를 통한 탐색(약한 결합도)

@Entity
@Table(name = "ORDERS")
public class Order {
    @Column(name="SHOP_ID")
    private Long shopId
}

Shop shop = shopRepository.findById(order.getShopId());

@Entity
@Table(name="SHOPS")
public class Shop {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="SHOP_ID")
    private Long id;
}

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

  • 함께 생성되고 함께 삭제되는 객체들을 함께 묶어라
  • 도메인 제약사항을 공유하는 객체들을 함께 묶어라
  • 가능하면 분리하라

패키지 의존성 객체 끊기 3가지 방법

1. 중간 객체를 새로 생성. 새로운 객체로 변환

2. 의존성 역전

3. 새로운 패키지 추가

도메인 단위 모듈 = 시스템 분리의 기반

참조