9장 유연한 설계

오브젝트의 9장을 요약한 내용 입니다.

개방-폐쇄 원칙

소프트웨어 개체(클래스, 모듈, 함수 등등)는 확장에 대해 열려 있어야 하고, 수정에 대해서는 닫혀 있어야 한다.

여기서 키워드는 '확장'과 '수정'이다. 이 둘은 순서대로 애플리케이션의 '동작'과 '코드'의 관점을 반영한다.

  • 확장에 대해 열려 있다. 애플리케이션의 요구사항이 변경될 때 이 변경에 맞게 새로운 '동작'을 추가해서 애플리케이션의 기능을 확장할 수 있다.

  • 수정에 대해 닫혀 있다. 기존의 '코드'를 수정하지 않고도 애플리케이션의 동작을 추가하거나 변경할 수 있다.

추상화가 핵심이다

개방-폐쇄 원칙의 핵심은 추상화에 의존하는 것이다. 추상화를 사용하면 생략된 부분을 문맥에 적합한 내용으로 채워넣음으로써 각 문맥에 적합하게 기능을 구체화하고 확장할 수 있다.

순수한 가공물에게 책임 할당하기

도메인 모델은 설계를 위한 중요한 출발점이지만 단지 출발점이라는 사실을 명심해야 한다. 실제로 동작하는 애플리케이션은 데이터베이스 접근을 위한 객체와 같이 도메인 개념들을 초월하는 기계적인 개념들을 필요로 할 수 있다.

모든 책임을 도메인 객체에게 할당하면 낮은 응집도, 높은 결합도, 재사용성 저하와 같은 심각한 문제점에 봉착하게 될 가능성이 높아진다. 크레이그 라만은 이처럼 책임을 할당하기 위해 창조되는 도메인과 무관한 인공적인 객체를 PURE FABRICATION(순수한 가공물)이라고 부른다.

어떤 행동을 추가하려고 하는데 이 행동을 책임질 마땅한 도메인 개념이 존재하지 않는다면 PURE FABRICATION을 추가하고 이 객체에게 책임을 할당하라. 따라서 PURE FABRICATION은 표현적 분해보다는 행위적 분해에 의해 생성되는 것이 일반적이다.

도메인 개념을 표현하는 객체와 순수하게 창조된 가공의 객체들이 모여 자신의 역할과 책임을 다하고 조화롭게 협력하는 애플리케이션을 설계하는 것이 목표여야 한다.

의존성 주입

의존성 해결은 컴파일타임 의존성과 런타임 의존성의 차이점을 해소하기 위한 다양한 매커니즘을 포괄한다. 따라서 의존성 주입에서는 의존성을 해결하는 세 가지 방법을 가리키는 별도의 용어를 정의한다.

  • 생성자 주입(constructor injection) : 객체를 생성하는 시점에 생성자를 통한 의존성 해결

  • setter 주입(setter injection) : 객체 생성 후 setter 메서드를 통한 의존성 해결

  • 메서드 주입(method injection) : 메서드 실행 시 인자를 이용한 의존성 해결

의존성 역전 원칙

추상화와 의존성 역전

객체 사이의 협력이 존재할 때 그 협력의 본질을 담고 있는 것은 상위 수준의 정책이다. 어떤 협력에서 중요한 정책이나 의사결정, 비즈니스의 본질을 담고 있는 것은 상위 수준의 클래스다.

상위 수준의 변경에 의해 하위 수준이 변경되는 것은 납득할 수 있지만 하위 수준의 변경으로 인해 상위 수준이 변경돼서는 곤란하다.

의존성 역전 원칙과 패키지

의존성 역전 원칙에 따라 상위 수준의 협력 흐름을 재사용하기 위해서는 추상화가 제공하는 인터페이스의 소유권 역시 역전시켜야 한다.

유연하고 재사용 가능하며 컨텍스트에 독립적인 설계는 전통적인 패러다임이 고수하는 의존성의 방향을 역전시킨다. 전통적인 패러다임에서는 상위 수준 모듈하위 수준 모듈에 의존했다면 객체지향 패러다임에서는 상위 수준 모듈과 하위 수준 모듈이 모두 추상화에 의존한다.

유연성에 대한 조언

유연한 설계는 연성이 필요할 때만 옳다

유연성은 항상 복잡성을 수반한다. 유연하지 않은 설계는 단순하고 명확하다. 유연한 설계는 복잡하고 암시적이다. 특정 시점의 객체 구조를 파악하는 유일한 방법은 클래스를 사용하는 클라이언트 코드 내에서 객체를 생성하거나 변경하는 부분을 직접 살펴보는 것뿐이다.

Last updated