9장 - HONGDAE-OBJECT/OOP GitHub Wiki
9장 유연한 설계
8장에서 의존성 관리 기법을 소개 했다.
이장에서는 이 기법을 원칙이라는 관점에서 정리 하겠다.
9장은 총 4개의 파트로 구성 되어 있다
- 개방-폐쇄 원칙
- 생성 사용 분리
- 의존성 주입
- 의존성 역전 원칙
결국 필자가 말하고자 하는 것은 추상화와 적절한 책임을 질 수 있는 객체를 만들어야 된다 라고 생각한다.
1. 개방-폐쇄 원칙
개방 폐쇄 원칙(Open-Closed-Principle)은 한 마디로 요약하면 소프트웨어 개체는 확장에 대해 열려있어야하며 수정에 대해서는 닫혀 있어야한다는 의미이다.

-
컴파일타임 의존성을 고정시키고 런타임 의존성을 변경하라
-
개방 폐쇄 원칙은 결국 컴파일타임에서의 의존성을 변경하지 않고 런타임 의존성을 쉽게 변경할 수 있다.
-
가격할인 정책이 새로운 것이 추가되더라도 우리는 추상화된 인터페이스를 의존하고 있기 때문에 새로운 클래스를 추가함으로써 기존 코드의 변경없이 기능을 확장할 수 있다.
추상화가 핵심이다.
결국 개방 폐쇄 원칙의 핵심은 추상화에 의존하는 것을 의미한다.
추상화에 의존함으로써 구체적인 코드에 강하게 결합되지 않고 이는 유지보수를 용이하게 만들 뿐 아니라 새로운 변경사항에 대해서도 기존코드 변경없이 추상화를 구현하고 있는 새로운 클래스를 추가함으로써 개방폐쇄원칙을 가능하게 한다.
2. 생성 사용 분리
public class Movie {
...
private DiscountPolicy discountPolicy;
public Movie(String title, ...){
...
this.discountPolicy = new AmountDiscountPolicy(...);
}
public Money cacluateMovieFee(Screening screening){
return fee.minus(discountPolicy.calculateDiscountAmount(screenig));
}
}
추상화에만 의존하기 위해서는 구체 클래스의 인스턴스를 생성해서는 안된다.
위 코드에서, Movie 의 할인 정책을 비율 할인 정책으로 변경할 수 있는 방법은, AmountDiscountPolicy 직접 코드를 수정하는 것 뿐이다.
이것은 동작을 추가하거나 변경하기 위해 기존 코드를 수정하도록 만들어서, 개방-폐쇄 원칙을 위반한다.
따라서 생성과 사용을 분리 하여야 한다.
public class Factory {
public Movie cacluateAvatarMovie() {
return new Movie("아바타", ....);
}
}
public class Client {
private Factory factory;
...
}
FACTORY 추가하기
FACTORY를 추가하여 한곳에 있는 책임을 분산 시키게 만들었다.
FACTORY를 사용하면 Movie와 AmountDiscountPolicy를 생성 하는 책임을 모두 FACTORY로 이동 시킬 수 있다.
client는 오직 사용과 관련 된 책임만 지고 있다.
3. 의존성 주입
의존성 주입이란, 외부의 독립적인 객체가 인스턴스를 생성한 후 이를 전달해서 의존성을 해결 하는 방법이다. 의존성 주입에서 의존성 해결 방법은
- 생성자 주입 : 객체 생성 시점에 생성자 통해 의존성 해결
- setter 주입 : 객체 생성 후 세터 메서드로 의존성 해결
- 메서드 주입 : 메서드 실행 시 인자로 의존성 해결
숨겨진 의존성을 나쁘다
숨겨진 의존성이 가지는 가장 큰 문제점은 의존성을 이해하기 위해 코드의 내부의 구현을 이해해야 된다는 것이다.
따라서 숨겨진 의존성은 캡슐화를 위반한다.
의존성 주입은 위의 문제를 깔끔하게 해결한다.
필요한 의존성은 클래스의 퍼블릭 인터페이스에 명시적으로 드러난다.
의존성을 이해하기 위해 내부를 읽을 필요가 없다.
4.의존성 역전의 원칙
public class Movie {
private AmountDiscountPolicy discountPolicy;
}
위 설계가 변경에 취약한 이유는, 요금을 계산하는 상위 정책이 요금을 계산하는데 필요한 구체적인 방법에 의존하기 때문이다.
쉽게 말해, Movie가 하위 클래스인 AmountDiscountPolicy에 의존하는 것이다.
아래 그림의 문제점은 의존성의 방향이 잘못됐다는 것이다.
부모에서 자식이 아닌 자식에서 부모의 방향으로 흘러야 한다.

이 문제의 해결 방안도 추상화이다.

Movie와 AmountDiscountPolicy 모두가 추상화에 의존하도록 수정하면 하위 수준의 클래스의 변경으로 상위 수준의 클래스가 영향을 받는 것을 방지 할 수 있다.
이를 정리 하면
-
- 상위 수준의 모듈은 하위 수준의 모듈을 의존하면 안된다.
-
- 추상화는 구체적인 사항에 의존해서는 안된다.
이를 의존성 역전 원칙이라고 한다.
객체 지향 설계를 위해서는 의존성을 역전시켜야 한다.
그리고 의존성을 역전 시켜야만 유연하고 재사용 가능한 설계를 얻을 수 있다.
5. 유연성에 대한 조언
의존성을 관리 해야 하는 이유는 역할, 책임, 협력의 관점에서 설계가 유연하고 재사용 가능해야 하기 때문이다.
따라서 역할, 책임, 협력에 집중해라.