이 글에서 분류한 기준은 책의 내용을 바탕으로 주관적인 견해로 재정리해본 것입니다.
들어가기 전에
개발을 하다 보면 외부 코드를 사용하는 일이 많은데, 이러한 외부 코드는 우리 코드에 깔끔하게 통합해야만 한다.
이 장에서는 소프트웨어 경계를 깔끔하게 처리하는 기법과 기교를 살펴보도록 한다.
외부 코드 사용하기
긴장으로 인한 시스템 경계의 문제
인터페이스 제공자와 인터페이스 사용자 사이에는 특유의 긴장이 존재한다.
- 패키지 제공자나 프레임워크 제공자는 적용성을 최대한 넓히려 애쓴다.
- 사용자는 자신의 요구에 집중하는 인터페이스를 바란다.
이러한 긴장으로 인해 시스템 경계에서 문제가 생길 요지가 많다.
- 사용자에게 필요하지 않은 기능까지 제공한다는 문제가 있다.
- ex)
java.util.map
에서 Map 사용자라면 누구나 Map 내용을 지우거나 어떠한 객체 유형이라도 추가할 수 있다.
- 인터페이스가 변경되면 수정할 코드가 상당히 많아진다.
- 따라서 Map과 같은 경계 인터페이스를 이용할 때는 이를 이용하는 클래스나 클래스 계열 밖으로 노출되지 안도록 주의해야 한다.
- 잘못된 예) Map 인스턴스를 공개 인수로 넘기거나 반환값으로 사용하는 경우
학습 테스트
- 간단한 테스트 케이스를 작성해 외부 코드를 익히는 것을 말한다.
- 프로그램에 사용하는 방식대로 API를 호출하여 통제된 환경에서 API를 제대로 이해하는지를 확인한다.
- 학습 테스트는 API를 사용하려는 목적에 초점을 맞춘다.
log4j 익히기
자세한 내용은 책을 참고하는 것이 좋다.
내가 이해한 바로는, 우선 라이브러리만 사용하는(우리 쪽 로직에 적용하기 전) 단위 테스트를 만들면서 사용하는 데 필요한 지식을 얻어가는 학습 방법 같다.
- 우선 문서의 첫 부분을 보고 코드를 작성한 후, 테스트를 돌려가면서 오류를 수정하고 다시 문서를 읽어가며 단위 테스트 케이스 몇 개를 작성한다.
- 모든 지식을 독자적인 로거 클래스로 캡슐화한다.
- 그러면 나머지 프로그램은 log4j 경계 인터페이스를 몰라도 된다.
학습 테스트의 비용
- 학습 테스트에 드는 비용은 없다.
- 필요한 지식만 확보할 수 있다.
- 이해도를 높여주는 정확한 실험이다.
- 투자하는 노력보다 얻는 성과가 더 크다.
- 학습 테스트는 패키지가 예상대로 도는지 검증한다.
- 패키지 새 버전이 나온다면 학습 테스트를 돌려 차이가 있는지 확인한다.
- 만약 새 버전이 우리 코드와 호환되지 않으면 학습 테스트가 이 사실을 곧바로 밝혀낸다.
- 패키지의 새 버전으로 이전하기 쉬워진다.
아직 존재하지 않는 코드를 사용하기
아는 코드와 모르는 코드를 분리하는 경계
협업을 할 때, 내가 개발하는 시스템에서 필요한 모듈의 API가 아직 설계되지 않았을 경우가 있다.
- 모듈 API는 다른 팀에서 개발 중이다.
- 이때, 우리가 자체적으로 인터페이스를 정의한 후 구현한다.
- 우리가 인터페이스를 전적으로 통제한다는 장점이 생긴다.
- 코드 가독성이 높아진다.
- 코드 의도가 분명해진다.
- Adapter 패턴으로 API 사용을 캡슐화해 API가 바뀔 때 수정할 코드를 한 곳으로 모은다.
- 모듈 API가 정의된 후, Adabter를 구현해 간극을 메우면 된다.
- 이와 같은 설계는 테스트도 아주 편하다.
깨끗한 경계
- 소프트웨어 설계가 우수하다면 변경하는데 많은 투자와 재작업이 필요하지 않다.
- 통제하지 못하는 코드를 사용할 때는 너무 많은 투자를 하거나 향후 변경 비용이 지나치게 커지지 않도록 각별히 주의해야 한다.
- 경계에 위치하는 코드는 깔끔히 분리하고, 기대치를 정의하는 테스트 케이스를 작성한다.
- 통제가 불가능한 외부 패키지에 의존하는 대신 통제가 가능한 우리 코드에 의존하는 편이 좋다.
- 외부 패키지를 호출하는 코드를 가능한 줄여 경계를 관리해야 한다.
- 새로운 클래스로 경계를 감싸는 방법
- Adapter 패턴을 사용해 우리가 원하는 인터페이스를 패키지가 제공하는 인터페이스로 변환하는 방법