우아한 테크 세미나 - 우아한 객체지향을 듣고 정리한 내용이다.
A - - - - - - - - - → B
B가 변경될 때 A도 함께 변경
B클래스 내부가 변경되더라도 A 클래스가 변경되지 않을 수도 있다.
Dependency란 변경에 의해 영향을 받을 수 있는 가능성
연관관계 (Association)
class A {
private B b;
}
의존관계
class A {
public B method(B b) {
return new B();
}
}
상속관계
class A extends B {
}
실체화 관계
class A implements B {
}
패키지에 포함된 클래스 사이의 의존성
클래스에서 import에 다른 패키지가 나오면 그 패키지끼리 dependency가 있다고 보면 됨
/**
* 양방향
*/
class A {
private B b;
// B클래스의 setter 메소드를 콜하게 됨. A-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 B b;
public void setA(B b) {
this.b = b;
}
}
class B {
}
/**
* One-To-Many
*/
class A {
private Collection<B> b;
}
class B {}
/**
* Many-To-One
*/
class A {}
class B {
private A a;
}
정말 불필요하다면 제거하는 것이 좋다.
패키지 사이의 양방향 의존은 반드시 피해야 한다.
무조건 변경을 중점으로 하여 코드를 배치하는 것이 원칙이다.
관계의 방향
= 협력의 방향
= 의존성의 방향
연관관계
@Entity
@Table(name = "ORDERS")
public class Order {
@ManyToOne
@JoinColumn(name="SHOP_ID")
private Shop shop;
}
@Entity
@Table(name = "SHOPS")
public class Shop {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="SHOP_ID")
private Long id;
}
@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;
}
의존관계
연관관계의 코드 구현 중 하나인 객체참조에는 문제점이 있다.
객체 참조의 문제점
모든 것이 다 연결되어있는게 문제..
어떤 객체라도 다 접근 가능하고, 어떤 객체라도 함께 수정 가능하기 때문이다.
객체 참조는 결합도가 가장 높은 의존성, 필요한 경우 객체 참조를 모두 끊어야함
간단한 규칙
이를 결정하는 것이 도메인 룰 (도메인 관점에서 어떤 데이터를 같이 처리해야할지 결정 필요)
경계 안의 객체는 같이 묶어주는 편이 좋다.
경계 밖의 객체는 ID를 이용해 접근할 수 있도록 한다. (Repository를 통한 탐색)
객체 참조로 설명하는 편이 객체간의 메시지를 통한 협력을 표현하기 좋기 때문인데, 실무에서는 성능 이슈 등 현실적인 제약으로 분리를 하는 것이 더 좋다.
때로는 절차지향이 객체 지향보다 좋을 때가 있다..
해결 방법
위의 세 가지 중 어떤 것을 고를지는 판단에 따라 다르다. (trade-off 필요)
도메인 이벤트를 사용하여 도메인 단위를 분리하게 된다면 의존성 사이클이 제거됨
도메인 단위로 분리가 된다면 도메인 이벤트를 통해 협력을 하게 되고 시스템을 분리하기가 쉬워진다.
시스템을 쪼갤 때 의존성을 확인한 다음에 의존성 사이클을 분리하는 기법을 통해 분리하고 쪼개야 한다.
디자인 패턴 스터디를 하면서 연관관계 의존성에 대한 내용을 이해하기 어려워 검색하던 중 우아한 테크 세미나를 듣게 되었다.
책을 보거나 강의를 듣다보면 자주 '이렇게 구현했을 때 오히려 더 복잡하지 않나..?', '실무에서 진짜 이렇게 쓰는건가' 라고 의문이 들었던 적이 많았는데, 실무에서 사용하는 예제를 가지고 (비록 엄청나게 단순화했지만) 객체 지향이 모두 정답이 아니다. 실무에서는 trade-off가 필요하다. 라는 내용을 들으니 뭔가 정리되는 느낌을 받았다. 객체 지향의 사실과 오해 라는 책도 꼭 읽어봐야겠다.