Skip to content

Latest commit

 

History

History
53 lines (40 loc) · 4.17 KB

chapter8.md

File metadata and controls

53 lines (40 loc) · 4.17 KB

8장 경계

해당 챕터에서 경계는 우리 코드와 외부 코드 사이의 경계를 이야기 한다. 시스템의 모든 소프트웨어를 직접 개발하는 경우는 드물다. 이때 사용하는 외부 코드를 우리 코드에 깔끔하게 통합하기 위해 경계를 잘 지어야한다.

외부 코드 사용하기

인터페이스 제공자는 적용성을 최대한 넓히려 애쓴다. 반면 사용자는 자신의 요구에 집중하는 인터페이스를 바란다. 이러한 차이로 시스템 경계에서 문제가 생길 소지가 많다.

다양한 기능을 제공하는 인터페이스는 확실히 유용하지만 그만큼 위험도 크다.

예시로 java.util.Map 인터페이스를 통해 외부에서 사용되는 Sensor를 관리하는 방법에 대해 살펴보자. (java util이기 때문에 java 예시로 작성했습니다.)

// 예시 1
Map sensors = new HashMap();
Sensor s = (Sensor)sensors.get(senserId);

예시1에서 Map을 그대로 사용한다면 Map이 가진 (사용자의 요구와 관련 없는) 다양한 기능들이 외부로 노출되어 문제가 생길 수 있다. 따라서 Map 반환하는 Object를 Sensor 타입으로 제한해야한다. 이때 타입 캐스팅할 책임은 클라이언트에 있다. 하지만 다음과 같은 코드가 한번이 아니라 여러 차례 반복 된다면 깨끗한 코드라 보기 어렵다.

// 예시 2
Map<String, Sensor> sensors = new HashMap<Sensor>();
Sensor s = sensors.get(senserId);

Generics를 사용하여 코드를 작성한다면 첫번째 예시보다 가독성이 좋은 코드를 작성할 수 있다.
하지만 예시2 또한 예시1과 마찬가지로 사용자에게 필요하지 않은 기능까지 제공하는 문제가 존재한다. 또한 Map 인터페이스가 변할 경우, 해당 인스턴스가 있는 코드를 모두 수정해야하는 문제가 발생한다.

// 예시 3
public class Sensors {
    private Map sensors = new HashMap();

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

예시3과 같이 캡슐화를 통해 경계 인터페이스인 MapSensor 안으로 숨긴다면 Map 인터페이스가 변할 경우에도 나머지 프로그램에 영향을 미치지 않는다. 또한 캡슐화를 통해 사용자는 원하는 기능만을 공개할 수 있고 사용자의 코드를 보호할 수 있다.

경계 살피고 익히기

우리는 보통 외부 코드를 사용할때, 문서를 읽으며 사용법을 결정하고 코드를 작성해 의도대로 동작하는지 확인한다. 외부 코드를 익히는 것은 어렵다. 또한 이를 통합하는 것까지 동시에 진행하는 것은 배로 어렵다.

짐 뉴커크(Jim Newkirk)의 학습 테스트 : 간단한 테스트 케이스를 작성하여 외부 코드를 익히는 방법

곧바로 우리 쪽 코드를 작성해 외부 코드를 호출하는 대신, 학습 테스트 방식을 이용하여 외부 코드를 익히는 것이 더 좋다. 학습 테스트는 프로그램에서 사용하려는 방식대로 외부 API를 호출한다. 통제된 환경에서 API를 제대로 이해하는지를 확인하는 것이다.

학습 테스트는 공짜 이상이다.

학습 테스트에 드는 비용은 없다. 오히려 필요한 지식만 확보하는 손쉬운 방법이다.
패키지의 새 버전이 나온다면 학습 테스트를 돌려 차이가 있는지 확인한다. 새 버전이 우리 코드와 호환되지 않으면 학습 테스트가 이 사실을 곧바로 밝혀낸다.

깨끗한 경계

통제가 불가능한 외부 코드에 의존하는 대신 통제가 가능한 우리 코드에 의존하는 편이 훨씬 좋다. 외부 패키지를 호출하는 코드를 가능한 줄이고 새로운 클래스로 경계를 감싸거나 Adapter 패턴을 이용하는 등의 방식을 사용하여 우리가 원하는 인터페이스를 패키지가 제공하는 인터페이스로 변환하자. 이를 통해 코드의 가독성은 높아지고 경계 인터페이스를 사용하는 일관성도 높일 수 있으며 외부 패키지가 변했을 때 우리가 변경해야할 코드도 줄어든다.