이번 장은 전체적으로 같은 얘기를 하고 있어서 “결론” 으로 전체 내용을 잘 정리해 볼 수 있을 것 같았다.
이번 챕터는 나의 발표순서도 아니니 간단하게 정리해서 이 부분은 블로그 포스팅을 하기로 했다.
간단하지만 중요한 얘기 같다.
하지만 아직……. 회사에서…개발을 안하다 보니… 외부 API 를 사용할 때 어느정도까지 우리만의 인터페이스나 wrapper 클래스를 작성하는 지 까지는 감이 잘 오지 않는다.
결론
내가 원하는 기능을 정의한 오픈 소스들은 이미 많이 존재하고 있다.
이러한 외부 API 를 사용할 경우 시스템 자체에서 다 개발할 필요가 없어 개발 속도가 빨라질 것이다.
하지만 외부 API 를 사용할 경우, 우리의 코드가 상당히 위험해짐에 항상 주의해야 한다!
이 책에서 말하는 “경계” 란 외부 API 를 사용하게 되는 부분을 의미하는 것 같았다. 대표적으로 책에서는 Map 조차도 변경 가능성이 존재하는 대상으로 설명하고 있다(실제로 Java 에 제네릭 이라는 것이 도입 되며 Map 에도 변경이 발생 했었기 때문). 이 Map 을 “경계 인터페이스” 라고 표현하고 있었다.
경계에서는 항상 수많은 변경발생 가능성이 존재한다.
외부 API 에 의존하는 코드가 존재해야 한다면, 이를 “분리” 하는 우리의 경계지점을 만들어야 한다. 그렇게 한다면 향후 외부 API 의 변경이 발생하더라도, 우리의 변경 비용이 지나치게 커지지 않을 수 있기 때문이다.
여기서 “분리” 에는 대표적으로 두 가지 방법이 있다.
- 외부 API 사용을 감싸는 Wrapper Class
- 가장 주의해야 하는 상황은 “우리 코드 여러 곳” 에 대해 “외부 API 에서 제공하는 타입 을 넘기는 코드” 가 만들어지고 있는 상황이다. ( 아마 변경 가능성이 존재하는 코드 범위가 넓어지기 때문에 그런 것 같다)
- 경계 인터페이스와 같은 외부 API 사용이, 특정 클래스를 넘지 않도록 주의할 것을 권하고 있다.
- 따라서 , 별도의 클래스를 정의하여 해당 클래스에서만 외부 API 를 직접 사용하고, 우리 코드에서는 우리가 정의한 클래스만을 사용하는 방법을 제시했다.
// 예시 - 외부에서는 Map 에 대해서는 모른다. Sensors 만을 사용하면 된다 ( 일급 컬렉션 같은 느낌이.. ) public class Sensors { private Map Sensors = new HashMap(); // Map<String, Sensor> 가 되더라도 외부에서는 이를 알 필요 없다 public Sensor getById(String id) { return (Sensor) sensors.get(id); } {
- 우리가 사용하는 형태를 정의한 “우리의 인터페이스” 를 정의하기
- 이를 통해, 아직 외부에서 제공 해 주지 않는 기능을 포함해 우리 코드를 테스트,구현 하는것도 가능해진다.
- 우리가 사용하는 인터페이스를 완벽하게 통제하게 된다.
- Adapter 패턴을 통해 외부 API 사용을 캡슐화 한다
- 인터페이스를 정의 해 두었기에
- 우리의 CommunicationController 에 대한 단위테스트를 작성시, Trasnmitter 에 대한 Fake 객체를 만들어 제공해 줄 수도 있다. → 테스트가 쉽고 편해진다 (엘레강트 오브젝트에서도 이런 내용이 나온다 - 엘레강트 오브젝트에서는 우리가 어떤 기능의 클래스를 만들어야 한다면 무조건 인터페이스를 제공해, 이를 사용하는 측에서 테스트 코드를 쉽게 작성할 수 있도록 하자고도 말하고 있었다 )
- 이렇게 미리 “경계 테스트 케이스” 를 작성해 두었기에, 미래에 외부에서 API 구현체가 실제로 제공되면 올바로 동작하는지 빠르게 검증할 수 있다.
- 예시 구조
그리고 외부 API 를 사용한다면 먼저 학습 테스트를 통해 사용에 대한 이해도를 높이는 것이 필요하다. 뿐만 아니라 “이해도의 정확성” 을 높이는데도 큰 공헌을 한다. 공식문서 등을 읽고 학습 테스트를 작성함으로서 “내가 예상한 대로 동작하는지 확인” 할 수 있기 때문이다. 즉 학습테스트는 “외부 API 를 사용하려는 목적에 초점” 을 맞춘다.
또한 “경계 테스트 케이스”, 즉 “실제로 우리코드가 해당 외부 API 를 사용하는 방식과 동일한 방식으로 외부 API 를 사용하는 테스트 케이스” 를 작성하는 것이 필요하다. 이를 작성할 경우 외부 패키지의 버전 업그레이드와 같은 변화가 발생하였을 때, 여전히 우리 코드에서 문제가 없는지 ( 이전버전과 차이가 있는지 ) 쉽고 빠르게 검증할 수 있다. 결과적으로 “두려워 하지 않고 버전 업그레이드 를 할 수 있어” 져 필요 이상으로 지나치게 낡은 버전의 외부 API 를 계속해서 사용 하는 일은 피할 수 있어진다.