Clean Code(클린 코드) | 로버트 C. 마틴 | 인사이트- 교보ebook

애자일 소프트웨어 장인 정신, 나쁜 코드도 돌아는 간다. 하지만 코드가 깨끗하지 못하면 개발 조직은 기어간다. 매년 지저분한 코드로 수많은 시간과 상당한 자원이 낭비된다. 그래야 할 이유

ebook-product.kyobobook.co.kr

코드

https://github.com/rkwhr0010/clean_code/tree/main/src

변경 사항은 git history 참고

시스템에 들어가는 모든 소프트웨어를 직접 개발하는 경우는 드물다.

어떤 식으로든 외부 코드(대표적인 것은 라이브러리) 사용한다.

외부 코드와 우리 코드 소프트웨어 경계를 깔끔이 처리하는 것은 대단히 중요하다.

 

외부 코드 사용하기

인터페이스 제공자/사용자 관점 괴리

제공자는 적용성을 최대한 넓히려 한다. 많은 환경에서 구동돼야 많이 구매하니까

사용자는 자신이 필요한 기능에 특화된 인터페이스를 원한다.

 

예시 java.util.Map

 

많은 기능을 제공한다.

clear() 모든 내용을 지우는 기능인데 누구나 호출 가능하다.

 

예시

    //지네릭스 없던 시절 예시
    Map sensors = new HashMap();
    Sensor s = (Sensor) sensors.get(sensorsId);

특정 객체 유형을 저장하고 싶지만, 강제할 방법이 없고, 특히 꺼냈을 타입이 Object 사용자에게 형변환 책임을 준다.

 

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

지네릭스 도입으로 형변환의 책임은 없어졌다.

 

여전히 clear() 같은 위험한 메서드를 제한할 없다.

 

프로그램에서 Map<String, Sensor> 인수로 여기저기 넘긴다면,

만약 Map인터페이스가 변경될 경우 영향받는 코드가 분명 많을 것이다.

 

//맵 레퍼 클래스
public class Sensors {
  private final Map sensors = new HashMap();
  public Sensor getById(String id) {
    return (Sensor) sensors.get(id);
  }
  //불필요한 기능을 제거할 수 있다. 이 경우는 인터페이스가 없다...
  //프록시로 구현해(대신 인터페이스 구현 필요)
  //불필요한 기능을 예외를 던지도록 구현할 수 있다.
}

 

경계 인터페이스은  Map Sensors 안으로 숨긴다.

 

경우 만약 Map 인터페이스가 변한다고 해도, 이를 사용하는 클라이언트 코드는 변경이 없다.

Sensors 인터페이스 처럼 완충 역할을 하기 때문이다.

또한, 불필요한 인터페이스를 감출 있다. 제어권은 Sensors에게 있다.

 

Map 같은 경계 인터페이스를 ㅣ요하는 클래스나 클래스 계열 밖으로 노출되지 않도록 한다.

 

경계 살피고 익히기

빠른 개발을 위해 외부 패키지를 사용한다.

외부 패키지 테스트는 우리 책임은 아니지만, 사용할 코드는 테스트해야 한다.

 

만약 타사 라이브러리 사용법이 분명치 않다고 가정

보통 API문서를 것이다. 그리고 코드를 작성해 라이브러리 동작을 확인한다.

버그가 발생하면, 우리 버그인지 라이브러리 버그인지 찾아내기도 한다.

 

처럼 외부 코드는 익히기 어렵다. 우리 코드와 통합도 어렵다.

 

곧바로 우리쪽 코드를 작성해 외부 코드를 호출하는 대신

먼저 간단한 테스트 케이스를 작성해 외부 코드를 익히는 거슬 학습 테스트 한다.

 

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

학습 테스트 비용은 없다. 어차피 API 익혀야 하기 때문이다.

오히려 학습 테스트로 얻는 성과가 크다.

 

학습 테스트는 외부 패키지가 예상대로 도는지 검증한다.

학습 테스트 이후 우리 코드와 통합을 했다.

 

시간이 지나 외부 패키기에 버전이 나왔다. 반드시 버전이 우리 코드랑 호환된다는 보장이 없어 변경할 수가 없다.

학습 테스트가 있다면, 호환이 되지 않아도 학습 테스트로 바로 있다.

 

중요한 것은 학습 테스트가 필요하든 말든, 어차피 실제 코드와 동일한 방식으로 인터페이스를 사용하는 테스트 케이스가 필요하다.

 

깨끗한 경계

늦던 빠르건 변경은 반드시 찾아온다.

경계 사이에서 변경이 발생했을 , 경계 사이 설계가 우수하면 변경에 많은 비용이 필요하지 않다.

통제하지 못하는 코드(주로 jar 묶인 외부 라이브러리) 바로 사용하면, 향후 변경 비용이 커진다.

 

경계에 위치하는 코드는 깔끔히 분리해야 한다.(주로 외부 라이브러리)

그리고 내가 원하는 동작에 대한 테스트 케이스를 작성한다.

이렇게 만들어진 테스트 케이스를 기반으로 우리가 통제할 있는 인터페이스를 정의한다.

외부 패키지에서 불필요한 기능은 감추고, 우리가 필요로 하는 기능만 인터페이스로 추상화한다.

 

외부 패키지를 호출하는 코드를 가능한 줄여 경계를 관리해야 한다.

외부 패키지를 새로운 클래스로 감싸거나

Adapter 패턴을 이용해 우리가 원하는 인터페이스로 변환해야 한다.

 

이렇게 되면, 경계 인터페이스는 우리가 통제할 있으며, 코드 모양이 표준화된다.

그리고 외부 패키지 변경 발생 , 경계 코드가 곳으로 모였기 때문에 변경할 코드도 줄어든다.

 

'IT책, 강의 > 클린코드(Clean Code)' 카테고리의 다른 글

10장 클래스  (1) 2024.01.15
9장 단위 테스트  (1) 2024.01.08
7장 오류 처리  (0) 2023.12.25
6장 객체와 자료 구조  (1) 2023.12.18
5장 형식 맞추기  (0) 2023.12.11

+ Recent posts