8장: 경계

시스템에 들어가는 모든 코드를 직접 개발하는 경우는 드물다. 외부 코드를 많이 사용하며, 이를 우리 코드에 깔끔하게 통합해야만 하는데. 이 장은 소프트웨어 경계를 깔끔하게 처리하는 기법에 대해 설명한다.

외부 코드 사용하기(144p)

패키지 제공자, 프레임워크 제공자는 적용성을 최대한 넓히려 애쓴다. 더 많은 환경에서 돌아가야 더 많은 고객이 구매하니까!

하지만 사용자는 자신에 요구에 집중하는 인터페이스를 바란다. 이런 긴장으로 인해 시스템 경계에서 문제가 생길 소지가 많다.

예시: Java의 Map

Map이 제공하는 기능성과 유연성은 확실히 유용하지만 그만큼 위험도 크다. Map은 객체의 유형을 제한하지 않기 때문에 마음만 먹으면 어떤 유형도 추가할 수 있기 때문이다.

Map sensors = new HashMap();
Sensor s = (Sensor)sensors.get(sensorId);

위의 코드는 Map이 반환하는 Object를 올바른 유형으로 변환할 책임을 클라이언트에게 지운다. 코드가 동작은 할 테지만 분명 깨끗한 코드는 아니다.

Map<String, Sensor> sensors = new HashMap<Sensor>();

Sensor s = sensors.get(sensorId);

위의 코드는 그래도 코드 가독성을 크게 높였지만, Map 자체가 사용자에게 필요하지 않은 기능까지 제공한다는 문제는 해결하지 못한다.

해결책

public class Sensors {
  private Map sensors = new HashMap();

  public Sensor getById(String id) {
    return (Sensor) sensors.get(id);
  }
}

경계 인터페이스인 Map을 Sensors 안으로 숨긴다. 따라서 Map 인터페이스가 변하더라도 나머지 프로그램에는 영향을 미치지 않는다! (물론 위와 같이 Map을 항상 캡슐화하라는 것이 아니다. Map을 여기저기 넘기지 말자는 것이다.)

경계 살피고 익히기(146p)

외부 코드를 익히기는 어렵다. 외부 코드를 통합하기도 어렵다. 다르게 접근한다면, 곧바로 우리쪽 코드를 작성해 외부 코드를 호출하는 대신 먼저 간단한 테스트 케이스를 작성해 외부 코드를 익히면 어떨까? 이를 학습 테스트라고 한다.

학습 테스트는 프로그램에서 사용하려는 방식대로 외부 API를 호출한다. 통제된 환경에서 API를 제대로 이해하는지를 확인하는 셈이다.

학습 테스트는 공짜 이상이다 (149p)

학습 테스트에 드는 비용은 없다. 오히려 필요한 지식만 확보하는 손쉬운 방법이며, 이해도를 높여주는 정확한 실험이다.

학습 테스트는 패키지가 예상대로 도는지 검증한다. 일단 통합한 이후라고 하더라도 패키지가 우리 코드와 호환되리라는 보장은 없다. 또한 패키지가 새 버전이 나올 때마다 호환이 되지 않거나 하는 새로운 위험이 생긴다. 학습 테스트는 이를 곧바로 밝혀낼 수 있다.

아직 존재하지 않는 코드를 사용하기 (150p)

경계와 관련해 또 다른 유형은 아는 코드와 모르는 코드를 분리하는 경계이다. 때로는 우리 지식이 경계를 너머 미치치 못하는 코드 영역도 있다.

깨끗한 경계 (151p)

경계에 위치하는 코드는 깔끔히 분리한다. 또한 기대치를 정의하는 테스트 케이스도 작성한다. 통제가 불가능한 외부 패키지에 의존하는 대신 통제가 가능한 우리 코드에 의존하는 편이 훨씬 좋다.

외부 패키지를 호출하는 코드를 가능한 줄여 경계를 관리하자.

Last updated