좋은 코드 만들기/클린코드

[클린코드] 8. 경계

개발새발 2021. 5. 2. 14:40
반응형

프로그램을 하나 만들 때 모든 기능을 직접 개발하는 경우는 거의 없다. 라이브러리를 활용하거나 외부 패키지를 불러와 사용하는 경우가 대부분이다. 이러한 상황에서 우리쪽에서 개발하는 코드와 외부의 코드의 경계가 생기기 마련이고 경계를 확실히 하지 않으면 수정할 때 손이 많이 가게 된다. 그래서 애초에 경계를 명확히 나누면서 개발하면 수정을 최소화하면서 유연하게 변화에 대처할 수 있다.

 

이번 챕터에서는 경계를 만들어야 하는 상황과 해결책을 제시한다.

 

외부 코드 사용하기

패키지, 프레임워크 제공자는 최대한 많은 사용자들이 범용적으로 사용할 수 있도록 인터페이스를 설계한다. 반면 인터페이스를 사용하는 입장에서는 본인이 필요로 하는 요구사항에 집중하기를 바란다.

 

java에서 제공하는 java.util.Map을 예로 들어 보자.

Map에서는 Generics를 제공하는데 아래와 같이 코드를 작성할수 있다.

1
2
3
4
Map<String, Sensor> seonsors = new HashMap<Sensor>();
...
Sensor s = sensors.get(seonsorId);
 
cs

Generics는 위에서 언급한대로 최대한 많은 사용자들이 범용적으로 사용할 수 있도록 설계되었다. 

 

반면 사용하는 입장에서는 위와 같이 코드를 작성할 경우 Map인터페이스가 변할 경우 Map<String, Sensor>를 사용하는 모든 코드에 수정이 들어가야 한다는 문제가 발생한다.

 

따라서 Map을 사용할때 아래와 같이 Sensors 클래스 안에 숨겨주면 Map인터페이스가 변하더라도 나머지 프로그램에는 영향을 끼치지 않는다.

1
2
3
4
5
6
7
8
9
public class Sensors {
    private Map seonsors = new HashMap();
    
    public Sensor getById(String id) {
        return (Sensor) sensors.get(id);
    }
}
 
cs

 

 

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

아직 존재하지 않는 인터페이스를 사용해아할 때에는 Adapter패턴을 사용하여 Fake class를 만들어두고 개발을 진행하면 될 것 같다. 아래의 예는 Transmitter라는 하위 시스템은 아직 존재하지 않는 코드이기 때문에 사용하는 입장(Communication Controller)에서는 인터페이스를 통해 추상화 해둔다.

 

 

 Fake Transmitter로 개발을 진행하거나 테스트를 한 뒤 Transmitter API가 완성되면 Transmitter Adapter로 갈아 끼우면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public interface Transimitter {
    public void transmit(Frequency freq, Stream stream);
}
 
public class FakeTransmitter implements Transimitter {
    ...
    public void transmit(Frequency freq, Stream stream) {
        return;
    }
    ...
}
 
public class TransmitterAdapter implements Transimitter {
    ...
    public void transmittransmit(Frequency freq, Stream stream) {
        useTransmitterAPI(freq, stream);
    }
    ...
}
 
public class CommunicationController {
    ...
    public void commuicateWithTransmitter() {
        //Transmitter transmitter = new FakeTransmitter();
        //transmitter.transmit(freq, stream);
 
        Transmitter transmitter = new TransmitterAdapter();
        transmitter.transmit(freq, stream);
 
    }
    ...
}
cs

 

 

 

경계챕터의 결론은 외부 패키지를 세세하게 알아야 할 필요가 없다는 것이다.

통제가 불가능한 외부 패키지에 의존성을 낮추고 수정 가능성이 있는 부분을 모아 따로 관리할 수 있도록 구현한다.

반응형