프로그램을 하나 만들 때 모든 기능을 직접 개발하는 경우는 거의 없다. 라이브러리를 활용하거나 외부 패키지를 불러와 사용하는 경우가 대부분이다. 이러한 상황에서 우리쪽에서 개발하는 코드와 외부의 코드의 경계가 생기기 마련이고 경계를 확실히 하지 않으면 수정할 때 손이 많이 가게 된다. 그래서 애초에 경계를 명확히 나누면서 개발하면 수정을 최소화하면서 유연하게 변화에 대처할 수 있다.
이번 챕터에서는 경계를 만들어야 하는 상황과 해결책을 제시한다.
외부 코드 사용하기
패키지, 프레임워크 제공자는 최대한 많은 사용자들이 범용적으로 사용할 수 있도록 인터페이스를 설계한다. 반면 인터페이스를 사용하는 입장에서는 본인이 필요로 하는 요구사항에 집중하기를 바란다.
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 |
경계챕터의 결론은 외부 패키지를 세세하게 알아야 할 필요가 없다는 것이다.
통제가 불가능한 외부 패키지에 의존성을 낮추고 수정 가능성이 있는 부분을 모아 따로 관리할 수 있도록 구현한다.
'좋은 코드 만들기 > 클린코드' 카테고리의 다른 글
[클린코드] 7. 오류 처리 (0) | 2021.04.25 |
---|---|
[클린코드] 6. 객체와 자료 구조 (0) | 2021.04.25 |
[클린코드] 5. 형식 맞추기 (0) | 2021.04.11 |
[클린코드] 4. 주석 (0) | 2021.03.28 |
[클린코드] 3. 함수 (0) | 2021.03.21 |