본문 바로가기

코딩/JAVA 공부

[객체지향] 의존성을 이용해 설계 진화시키기

프리코스를 진행하면서 객체지향 코드의 이해가 부족한 것을 느꼈다.

그러다 유튜브 알고리즘에 우아한 형제들에서 진행한 우아한 테크 세미나 중 객체지향과 관련된 강의가 있어 한번 들어봤다.

객체지향 그 자체에 대하 알고 싶은 것 도 있었고, 현업에 종사하는 분들은 객체지향을 어떤 식으로 다룰까 궁금함도 있어 강의를 끝까지 봤다.

https://www.youtube.com/watch?v=dJ5C4qRqAgA (강의 링크)

강의 모든 내용을 완벽하게 이해하진 못했지만 내 나름대로 정리해봤다.

 

소프트웨어를 설계할 때 가장 중요한 점은 '의존성'이다.

약간 논란이 될 수 있는 문장일 것 같은데, 적어도 유지보수 측면에선 맞는 말이라 생각했다.

그리고 유지보수는 소프트웨어에서 가장 중요하다 생각하기 때문에.. (이하 생략)

 

즉 의존성을 관리하는 방법에 따라 설계가 바뀔 수 있다.

여기서 의존성이란.

A 클래스가 B 클래스에 의존한 경우, B가 변경될 때 A 도 함께 변경된다.

클래스의 의존성은 총 4가지 경우가 있다.

 

<클래스의 의존성>

1. 연관 관계 (Association)

아래 코드처럼 A에 B로 갈 수 있는 경로가 있는 경우.

이는 협력을 위해 필요한 영구적인 탐색 구조라고 할 수 있다.

즉 연관 관계 = 탐색 가능성 (navigability)이라 할 수 있다.

class A {
	private B b;
}

 

2. 의존 관계 (Dependency)

일시적으로 관계를 맺고 헤어진다. 즉 협력을 위해 일시적으로 필요한 의존성이다.

파라미터, 리턴 타입, 내부에서 new 생성의 경우이다.

class A{
	public B method(B b) {
    	return new B();
    }
}

 

3. 상속 관계 (Inheritance)

클래스를 extends 하는 경우.

 

4. 실체화 관계 (Realization)

인터페이스를 implements 하는 경우.

 

여기서 3, 4 번은 아주 명확한 관계이고 비교적 쉽게 관리 가능하다.

따라서 우리는 1, 2번 의존 관계를 주의 깊게 살피고 관리해야 한다.

패키지의 의존성은 그 구성인 클래스의 의존관계이다.

 

의존성을 관리하는 세 가지 포인트는

1. 양방향 의존성을 피하자

2. 다중성이 적은 방향을 선택하자

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

 

1. 양방향 의존성을 피하자

클래스에서 양방향 의존성은 쉽게 보이며 비교적 피하기 편하다.

그러나 패키지 사이의 양방향 의존성은 발견이 어렵다.

이를 찾기 위한 좋은 방법은 각 클래스, 패키지의 관계를 손으로 그려보는 것이다.

양방향 의존성을 발견했을 때 이를 해결하는 방법은 세 가지가 있다. 

 - 1-1. 중간 객체를 이용해 의존성 사이클 끊기 -> 추상화를 통해!

 - 1-2. 의존성 역전 시기키 (인터페이스, 추상 클래스를 통해)

 - 1-3. 패키지 분리하기

 

2. 다중성이 적은 방향을 선택하자

일대 다

class A {
	private Collection<B> bs;
}

class B {
}

다대 일

class A {
}

class B {
	private A a;
}

이 내용은 깊게 다루지 않아서 잘 이해를 못 했다..

프리 코스에서 이미 일대 다의 관계를 사용해서 설계를 많이 했는데??

레파지토리는 어쩔 수 없이 일대 다의 관계이지 않을까? 이런 경우는 예외인가..?

 

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

데이터 적으로 객체 간 관계가 꼭 필요한 경우가 있다.

그러나 단지 데이터를 줘야 하니 관계를 형성하는 것은 옳지 않다.

객체 사이에서 어떤 메시지를 주는지, 어떤 식으로 협력하는지 생각해보고,

이를 바탕으로 관계를 형성해야 한다.

이 방식을 통해 필요 없는 의존성을 제거할 수 있다.

또, 협력의 방향에 따라 관계가 형성되어야 한다. 런타임의 협력관계를 통해 의존성의 방향을 결정하자.