[개발 도서] Clean Code :: 8장 - 경계 Map 정리

Jihyoung·2021년 7월 26일
0

Clean Code

목록 보기
3/11
post-thumbnail

📕 외부 코드 사용하기

  • 제공자 : 적용성을 최대화 하려 함
  • 사용자 : 자신의 요구에 집중하는 인터페이스를 바람

이런 긴장으로 시스템 경계에서 문제가 생길 수 있다.

Map은 아래와 같이 굉장히 다양한 인터페이스로 수많은 기능을 제공한다.

💻 Map이 제공하는 메소드
- clear() void - map 
- containsKey(Object key) boolean - Map
- containsValue(Object value) boolean - Map
- entrySet() set - Map
- equals(Object o) boolean - Map
- get(Object key)Object - Map
- getClass() Class<? extends Object> - Object
- hashCode() int - Map
- isEmpty() boolean - Map
- keySet() Set - Map
- notify() void - Object
- notifyAll() void - Object
- put(Object key, Object value) Object - Map
- putAll(Map t) void - Map
- remove(Object key) Object - Map
- size() int - Map
- toString() String - Object
- values() Collection - Map
- wait() void - Object
- wait(long timeout) void - Object
- wait(long timeout, int nanos) void - Object

📍 Map을 이용한 예시 : 사용하는데 따를 수 있는 위험

  1. clear() 메서드 사용으로 예상치 않게 지울 수 있다.

  2. Map 에 특정 객체 유형만 저장하기로 결정했을 때, Map(Generics 지원 이전의)은 유형을 제한하지 않기 때문에 사용자가 예상치 않은 객체를 추가할 위험도 있다.

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

이러한 문제점은 Generics 지원 이후 해결되었다.

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

📗 경계 살피고 익히기

타사 라이브러리를 가져올 경우 아래의 과정을 거친다.

  1. 문서를 읽으며 사용법을 결정
  2. 코드를 작성해 라이브러리가 예상대로 동작하는지 확인
  3. 디버깅 (반복)

그러나 위와 같은 방법으로 외부 코드를 빠르게 익히고 통합하기엔 어려움이 있다. 따라서 '학습 테스트' 의 방법을 사용한다.

학습 테스트는 우리쪽 코드를 먼저 작성하고, 우리쪽 코드(통제된 환경)에 따라 테스트 케이스를 작성하여 외부 코드를 익히는 방법이다. 이 방법을 통해 외부 API를 사용할 수 있다.


📙 log4j 익히기 -> 무엇을 전달하려는지 모르겠음..

아파치의 log4j 패키지를 사용하여 log4j의 구조를 파악한다.

@Test
public void testLogCreate() {
  Logger logger = Logger.getLogger("MyLogger");
  logger.info("hello");
}
//Appender 필요
//ConsoleAppender 생성
@Test
public void testLogAddAppender() {
  Logger logger = Logger.getLoger("MyLogger");
  ConsoleAppender appender = new ConsolAppender();
  logger.addAppender(appender);
  logger.info("hello");
}
//Appender에 출력 스트림이 없음
//출력 스트림 생성
@Test
public void testLogAddAppender() {
  Logger logger = Logger.getLoger("MyLogger");
  logger.removeAllAppenders();
  logger.addAppender(new ConsoleAppender(new PatternLayout("%p %t %m%n"),
                                         ConsoleAppender.SYSTEM_OUT));
  logger.info("hello");
}

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

학습 테스트는 아래와 같은 이점을 제공한다

  • 이해도를 높여준다.
  • 패키지가 예상대로 도는지 확인 가능하다.
  • 패키지의 새 버전이 나온다면 학습 테스트를 통해 차이를 검증 가능하다.
    : 코드의 호환성을 확인 가능하다.

학습 테스트의 사용 여부와 관계없이, 실제 코드와 같은 방법으로 인터페이스를 테스트 할 수 있는 방법이 필요하다. 이러한 경계 테스트를 통해 패키지를 새 버전으로 이전하기 쉬워지기 때문이다.


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

경계에는 아는 코드와 모르는 코드를 분리하는 경계의 유형이 있다. 지금 알지 못하는 코드 영역을 개발할 때도 경계는 유용하게 사용된다.

모르는 부분의 시스템과의 경계를 예측하고 해당 부분에서 먼 곳부터 구현을 하라.
즉, 아는 부분의 필요한 인터페이스를 우선적으로 정의, 구현하고 분리시켜고 후에 간극을 좁히는 작업을 해라. 그 경우 해당 영역에 대한 통제가 가능해지고, 테스트도 간편하게 진행할 수 있게 된다.


📕 깨끗한 경계

경계에서는 '변경'이 빈번하게 일어난다. 따라서 경계에 위치하는 코드는 깔끔하게 분리한다. 또한 외부 패키지에 의존하기 보다는 통제가 가능한 우리 코드에 의존하는 것이 좋다.

외부 패키지를 호출하는 코드를 가능한 줄여 경계를 관리하자. 앞서 본 예시에서처럼 새로운 클래스로 경계를 감싸거나, Adapter 패턴을 사용하자.

이를 통해 코드 가독성과 일관성이 높아지고, 외부 패키지가 변했을때 변경할 코드도 적어진다.


🧩 더 공부할 부분

📚 Reference

  • Clean Code : 애자일 소프트웨어 장인 정신
profile
로그를 생활화

0개의 댓글