경계

외부 코드 사용하기

책너두 5기 16일차

로버트 C. 마틴의 클린코드 p.142 ~ p.150

내용 정리

8. 경계

패키지나 오픈 소스를 사용할 때, 외부 코드를 우리 코드에 깔끔하게 통합해야 한다. 이를 위해 소프트웨어 경계를 깔끔하게 처리해야 한다.

외부 코드 사용하기

인터페이스 제공자는 많은 고객이 사용하길 바라기 때문에 적용성을 넓히지만, 사용자는 자신의 니즈에 집중하는 인터페이스를 바란다. 이 사이에서 문제가 발생한다.

예시 : java.util.Map

사용자는 마음만 먹으면 어떤 객체 유형도 추가할 수 있다. 아래처럼 Sensor라는 객체를 담는 Map을 만든다.

Map sensors = new HashMap();

Sensor 객체가 필요한 코드는 다음 코드를 입력한다.

Sensor s = (Sensor)sensors.get(sensorId);

코드의 가독성을 높이기 위해 Generics를 사용하면 다음과 같이 바뀐다.

1
2
3
Map<String, Sensor> sensors = new HashMap<Sensor>();
...
Sensor s = sensors.get(sensorId);

여전히 Map<String, Sensor>가 사용자에게 필요하지 않은 기능까지 제공할 뿐더러, Map 인스턴스를 여기저기 넘길 경우 수정할 때 힘들어진다. 다음과 같이 작성하면 해결할 수 있다.

1
2
3
4
5
6
7
public class Sensors {
    private map sensors = new HashMap();

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

Map 클래스를 사용할 때 마다 캡슐화하라? => X

Map이나 유사한 경계 인터페이스를 여기저기 넘기지 말라 => O

경계 살피고 익히기

타사 라이브러리의 사용법이 분명치 않을 때는? 시간을 들여 문서를 읽은 후 우리 코드를 작성해 작동을 확인하고 디버깅한다.

학습 테스트 : 곧바로 우리쪽 코드를 작성해 외부 코드를 후촐하는 대신 먼저 간단한 테스트 케이스트를 작성해 외부 코드를 익힌다.

log4j 익히기

학습 테스트의 예시로 log4j패키지를 사용해 보자. “hello”를 출력하는 테스트 케이스를 작성한다.

1
2
3
4
5
@Test
public void testLogCreate() {
    Logger logger = Logger.getLogger("MyLogger");
    logger.info("hello");
}

실행하면 Appender라는 것이 필요하다고 뜬다. 문서를 읽어보면 ConsoleAppender라는 클래스가 있다고 하니 생성하여 다시 테스트한다.

1
2
3
4
5
6
7
@Test
public void testLogAddAppender() {
    Logger logger = Logger.getLogger("MyLoggger");
    ConsoleAppender appender = new ConsoleAppender();
    logger.addAppender(appender);
    logger.info("hello");
}

이제 Appender에 출력 스트림이 없다고 뜬다. 구글링을 통해 고쳐보면?

1
2
3
4
5
6
7
8
9
@Test
public void testLogAddAppender() {
    Logger logger = Logger.getLogger("MyLoggger");
    logger.removeAllAppenders();
    logger.addAppender(new ConsoleAppender(
    	new PatterLayout("%p %t %m%n"),
    	ConsoleAppender.SYSTEM_OUT));
    logger.info("hello");
}

이제 작동한다.

여기서 ConsoleAppender.SYSTEM_OUT인수를 제거하면? => 아무 문제 없음

PatternLayout 제거하면? => 다시 출력 스트림 없다는 오류 발생

이런 방법으로 하나씩 방법을 익혀가는 방식이다.

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

필요한 지식만 확보하는 손쉬운 방법이고 이해도를 높여주는 정확한 실험이다. 이를 통해 새로운 버전의 패키기자 나올때마다 울 ㅣ코드와 호환되는지 밝혀낼 수 있다. 그 결과 새 버전으로 이전하기 쉬워진다.

아직 존재하지 않는 코드를 사용하기

다른 팀, 부서에서 담당하는 부분의 코드에 대해 모르는 상태 일때, 우리가 바라는 대로 간단한 ㄴ인터페이스를 구현한다. 이후 다른 팀에서 코드를 작성하고 API를 정의하면 우리가 작성한, 필요로 하는 것을 추가하면 된다.

읽고 나서

정확히 작성되는 코드에 대해서는 여전히 언어 떄문인지 감이 잘 오지 않는다.. ㅠ 그래도 존재하지 않는 코드에 대해서는 도움이 됐다. 나도 팀 프로젝트를 하다보면 아직 다른 팀원이 작성하지 못한 부분으로 인해서 곤란할 때가 많은데 미리 내가 필요로하는 방식으로 간략하게 정의함으로서 서로에게 도움이 될 수 있을 것 같다.