다음 책 내용을 정리한 항목입니다
엔터프라이즈 애플리케이션 아키텍처 패턴
구현과 분리된 별도의 패키지에 인터페이스를 정의한다
시스템을 구성하는 부분간의 결합을 줄이면 시스템의 설계를 개선할 수 있다
이를 위해서 좋은 방법은 클래스를 패키지로 그룹화 하고 이들간의 의존성을 제어하는 것이다
주로 사용했던 언어(C#)와 현재 사용중인 언어(java)는 이를 지원해주고 있다
온전히 같지는 않지만 비슷한 행태이다(논리적 분할이냐 물리적 분할이냐 정도?)
what-is-the-difference-between-namespace-and-package
그러나 일반적인 의존성 구조를 위반하고 메서드를 호출해야 하는 경우가 종종 존재한다
예시)
프레임워크 패키지에 넣은 범용 추상 코드에서 특정한 애플리케이션 코드를 호출해야 하는 경우
한 계층의 코드에서 볼 수 없어야 하는 다른 계층의 코드를 호출해야 하는 경우
- 예시) 도메인 코드에서 데이터 매퍼를 호출하는
다른 개발 그룹에서 개발한 함수를 호출해야 하지만 해당 API에 대한 의존성을 원하지 않는 경우
이런 경우 하나의 방법으로 사용될 수 있다.
인터페이스에 대한 의존성이 필요한 클라이언트는 해당 방식을 통해 구현을 전혀 의식하지 않고 작업을 수행할 수 있다. 분리 인터페이스는 게이트웨이를 연결할 수 있는 좋은 위치다
(개인적으로는 인터페이스의 위치를 이동하는 경우에도 종종 사용한다)
적당히(트레이드 오프)를 고민 하자
분리를 함으로 발생할 수 있는 직접적인 의존성 관리는 복잡도를 높일 수 있다
의존성을 제거하려는 경우 또는 여러 독립적 구현을 사용하려는 경우에만 분리 인터페이스를 사용하는 것이 바람직하다.
구현은 해당 인터페이스에 의존하지만 그 반대는 해당되지 않는다
인터페이스와 구현을 별도의 패키지에 넣고 구현 패키지가 인터페이스 패키지에 대한 의존성을 갖게 한다
다른 패키지는 구현 패키지에 의존하지 않고 인터페이스 패키지에 의존할 수 있다.
인터페이스의 구현이 아예 없는 경우는 런타임에 문제가 발생하겠지만 해당 문제는 컴파일 시 둘을 연결하는 별도의 패키지를 사용하거나 구성시 플러그인을 통해서 해결할 수 있다
해당 개념은 인터페이스를 정의할 책임이 클라이언트 패키지(사용하는)에 있다고 생각하면 이해하기 쉽다
근본적으로 클라이언트 패키지는 자신이 정의하는 인터페이스를 구현하는 다른 모든 패키지와 함께 작업한다는 것을 나타낸다
만약 클라이언트 패키지가 여러개인 경우에는 다른 인터페이스를 사용하는 것이 좋다
또한 인터페이스를 정의하는 역할이 클라이언트 패키지 개발자의 책임이 아니라는것을 나타내는 경우에도 이 방법이 좋다
분리 인터페이스는 구현을 인스턴스화 하기가 약간 불편할 수 있으며 일반적으로 구현 클래스의 정보(implemet)가 필요하다. 일반적인 방법은 별도의 팩토리 객체와 팩토리에 대한 분리 인터페이스를 사용하는 것이다(또 늘어난다..)
굳이 이런 플러그인을 사용하고 싶지 않다면 인터페이스와 구현을 모두 인식하는 다른 패키지를 사용해 애플리케이션 시작시 해당 객체를 인스턴스화 할 수도 있다