시스템에 들어가는 모든 소프트웨어를 직접 개발하는 경우는 드물다.
때로는 패키지를 사고, 오픈 소스를 이용한다. 때로는 사내 다른 팀이 제공하는 컴포넌트를 사용한다.
어떤 식으로든 이 외부 코드를 깔끔하게 통합해야 한다.
[외부 코드 사용하기]
인터페이스 제공자와 인터페이스 사용자 사이에는 특유의 긴장이 존재한다.
패키지 제공자나 프레임워크 제공자는 적용성을 최대한 넓히려 하는 반면,
사용자는 자신의 요구에 집중하는 인터페이스를 바란다.
한 예로 java.util.Map을 살펴보자. Map은 굉장히 다양한 인터페이스로 수많은 기능을 제공한다.
Map이 제공하는 기능성과 유연성은 확실히 유용하지만, 그만큼 위험도 크다.
- clear() 메서드를 사용하면 누구나 Map 내용을 지울 수 있다.
- Map에 특정 객체 유형만 저장하기로 결정하지만, 실제로 Map은 어떤 객체 유형도 추가 가능하다.
다음은 Map을 좀 더 깔끔하게 사용한 코드다.
public class Sensors {
private Map sensors = new HashMap();
public Sensors getById(String id) {
return (Sensor) sensors.get(id);
}
...
}
경계 인터페이스인 Map을 Sensors 안으로 숨긴다.
따라서 Map 인터페이스가 변하더라도, 나머지 프로그램에는 영향을 미치지 않는다.
제네릭스를 사용하든 안하든 더 이상 문제가 되지 않는다.
Sensors 클래스 안에서 객체 유형을 관리하고 변환하기 때문이다.
Map 클래스를 사용할 때마다 위와 같이 캡슐화하라는 말이 아니다. Map을 여기저기 넘기지 말라는 말이다.
Map과 같은 경계인터페이스를 이용할 때는 이를 이용하는 클래스나 클래스 계열 밖으로 노출되지 않도록 주의하자.
[경계 살피고 익히기]
외부 코드를 익히기는 어렵다. 외부 코드를 통합하기도 어렵다.
그럼 먼저 간단한 테스트 케이스를 작성해 외부 코드를 익히면 어떨까?
짐 뉴커크는 이를 학습 테스트라고 부른다.
학습 테스트는 프로그램에서 사용하려는 방식대로 외부 API를 호출한다.
통제된 환경에서 API를 제대로 이해하는지를 확인하는 셈이다.
[학습 테스트는 공짜 이상이다]
학습 테스트에 드는 비용은 없다. 학습 테스트는 이해도를 높여주는 정확한 실험이다.
학습 테스트를 이용한 학습이 필요하든 그렇지 않든, 실제 코드와 동일한 방식으로 인터페이스를 사용하는 테스트 케이스는 필요하다.
이런 경계 테스트가 있다면 패키지의 새 버전으로 이전하기 쉬워진다.
[아직 존재하지 않는 코드를 사용하기]
경계와 관련해 또 다른 유형은 아는 코드와 모르는 코드를 분리하는 경계다.
다음과 같은 상황이 있었다.
지정한 주파수를 이용해 이 스트림에서 들어오는 자료를 아날로그 신호로 전송하라.
저쪽 팀이 아직 API를 설계하지 않았으므로 구체적인 방법을 몰랐다.
그래서 우리는 구현을 나중으로 미뤘다.
이쪽 코드를 진행하고자 우리는 자체적으로 인터페이스를 정의했다. Transmitter라는 간단한 클래스를 만든 후, transmit라는 메서드를 추가했다. Transmitter 인터페이스는 주파수와 자료 스트림을 입력으로 받았다.
우리가 바라는 인터페이스를 구현하면 우리가 인터페이스를 전적을 통제한다는 장점이 생긴다.
또한 코드 가독성도 높아지고, 코드 의도도 분명해진다.
저쪽 팀은 송신기 API를 정의한 후, TrainsmitterAdapter를 구현해 간극을 메웠다.
ADAPTER 패턴으로 API을 사용을 캡슐화해 API가 바뀔 때 수정할 코드를 한곳으로 모았다.

이와 같은 설계는 테스트도 아주 편하다.
FakeTransmitter 클래스를 사용하면 ConmmunicationController 클래스를 테스트할 수 있다.
[깨끗한 경계]
경계에서는 흥미로운 일이 많이 벌어진다. 변경이 대표적인 예다.
경계에 위치하는 코드는 깔끔히 분리한다. 또한 기대치를 정의하는 테스트 케이스도 작성한다.
외부 패키지를 호출하는 코드를 가능한 줄여 경계를 관리하자.
만약 경계가 필요하다면
- 새로운 클래스로 경계를 감싸거나
- ADAPTER 패턴을 사용해 우리가 원하는 인터페이스를 패키지가 제공하는 인터페이스로 변환하자
'Book Notes' 카테고리의 다른 글
| [개발서적] Clean Code 10. 클래스 (0) | 2025.10.28 |
|---|---|
| [개발서적] Clean Code 9. 단위 테스트 (1) | 2025.10.24 |
| [개발서적] Clean Code 7. 오류 처리 (0) | 2025.10.23 |
| [개발서적] Clean Code 6. 객체와 자료 구조 (1) | 2025.10.22 |
| [개발서적] Clean Code 5. 형식 맞추기 (0) | 2025.10.21 |