(Working Effectively with Legacy Code) 014. Dependencies on Libraries Are Killing Me

Dependencies on Libraries Are Killing Me

프로젝트 내의 모든 코드를 개발자들이 직접 작상했다면 모든 제어권을 쥐고 있을 것이다.

하지만 실무에서는 유명하고 검증된 라이브러리를 쓰는 경우가 대다수이다.

라이브러리를 통해서 개발기간을 단축하거나, 검증된 기능을 바로 쓸 수 있는 장점이 있기 때문이다.

하지만 코드 전반에 걸쳐 무분별하게 라이브러리를 사용하여 의존도를 높이게 되면 (비용 등의 이유로)라이브러리의 변경이 어려워져 울며 겨자먹기로 계속 쓸 수 밖에 없는 경우가 발생할 수 있다.

모든 실체 클래스에 대해서 인터페이스를 정의하여 매우 쓰기 편한 라이브러리도 있지만,

실체 클래스만 제공하면서 final 혹은 sealed 로 정의되어있거나

C++ 라이브러리의 중요 함수가 virtual로 정의되어있지 않아서 테스트시 위장 객체를 사용할 수 없는 경우도 있다.

이런 경우엔 라이브러리의 클래스들을 포장하는 포장 클래스를 작성하는 것이 최선이다.

좋은 설계를 강제하는 언어 기능과 테스트 코드를 작성하기 위해 수행하는 것에는 근본적으로 대립 관계가 존재한다.

가장 널리 알려진 것은 일회성의 딜레마(once dilemma) 이다.

시스템 내의 어떤 클래스의 객체가 한 개만 존재한다고 가정할 경우, 위장 객체를 사용하기는 어렵다.

이 싱글턴을 다루기 위해 이용할 수 있는 정적 set 메서드 도입 기법 등의 의존 관계 제거 기법들을 사용할 수 없는 경우도 존재하며, 어떤 경우에는 싱글턴 클래스를 포장하는 방법만이 유일한 해결책일 수도 있다.

또 다른 문제는 제한적 재정의 딜레마(restricted override dilemma) 가 있다.

일부 객체 지향 언어에서는 모든 메서드가 가상 함수거나, 기본적으로 가상 함수지만 가상 함수가 아닌 것처럼 만들 수 있는 언어도 있으며, 명시적으로 키워드르 부여해야만 가상 함수로 선언되는 경우도 있다.

이처럼 다양한 객체 지향 언어의 권장 사항은 가급적 많은 메서드를 가상 함수가 아닌 함수로 만드는 것이었다.

권장 사항인만큼 타당한 면이 없는 건 아니지만, 이는 감지와 분리를 적용하기 어렵게 만드는 부작용이 있다.

이러한 문제는 public 메서드의 실제 코드는 가상 함수로 정의하되, 배포 환경에서는 비가상 함수로 정의하는 방법으로 해결하면 된다.