클린 코드 - 8장 경계
06 Sep 2021Intro
초서-독서 한 내용을 그대로 적는 곳이기 때문에 책을 읽지 않은 분들이 보기에 맥락이 애매할 수 있습니다.
초서 : 책을 읽는데 그치는 것이 아닌 손을 이용해 책의 중요한 내용을 옮겨 적음으로써 능동적으로 책의 내용을 수용하고 판단하여 새로운 지식을 재창조하는 과정. 메타인지 학습법
Index
- 들어가면서
- 1장 깨끗한 코드
- 2장 의미 있는 이름
- 3장 함수
- 4장 주석
- 5장 형식 맞추기
- 6장 객체와 자료 구조
- 7장 오류 처리
- 8장 경계 «
- 9장 단위 테스트
- 10장 클래스
- 11장 시스템
- 12장 창발성(創發性)
- 13장 동시성
- 14장 점진적인 개선
- 15장 JUnit 들여다보기
- 16장 SerialDate 리팩터링
- 17장 냄새와 휴리스틱
8장 경계
시스템에 들어가는 모든 소프트웨어를 직접 개발하는 경우는 드물다. 때로는 패키지를 사고, 때로는 오픈 소스를 이용한다. 어떤 식으로든 이 외부 코드를 우리 코드에 깔끔하게 통합해야만 한다. 외부 코드와 자신의 코드 사이의 경계를 깔끔하게 처리하는 기법과 기교를 살펴보자.
외부 코드 사용하기
- 프레임워크(외부) 제공자
적용성을 최대한 넓히려 애씀. - 사용자
자신의 요구에 집중하는 인터페이스를 바람.
위와 같이 둘 간의 서로 다른 요구때문에 시스템 경계에서 문제가 발생하게 된다.
예를 들어 java.util.Map
은 다양한 인터페이스로 수많은 기능을 제공한다.
Map
이 제공하는 기능성과 유연성은 확실히 유용하지만, Map
을 사용하여 기능을 제공하는 제공자의 취지대로 올바르게 사용할 지는 확신하기 어렵다.
Map sensors = new HashMap();
...
Sensor s = (Sensor) sensors.get(sensorId);
Map
이 반환하는 Object
를 올바른 유형으로 변환할 책임은 Map
을 사용하는 클라이언트에 있다.
하지만 의도가 분명히 드러나지 않으며 깨끗한 코드라 보기 어렵다.
위 문제를 제네릭스를 사용하여 해결해보자.
Map<String, Sensor> sensors = new HashMap();
...
Sensor s = sensors.get(sensorId);
위 방법은 Map
이 ‘사용자에게 필요하지 않은 기능까지 제공한다’ 는 문제는 해결하지 못한다.
(clear()
, put()
과 같은 기능에 대한 통제)
프로그램에서 Map
인스턴스를 여기저기로 넘긴다면 추후 수정할 코드가 상당히 많아지게 된다.
public class Sensors {
private Map sensors = new HashMap();
public Sensor getById(String id) {
return (Sensor) sensors.get(id);
}
...
}
위 코드는 Map
을 Wrapper 클래스로 감싸 Map
의 사용방식을 감추고 기능을 통제한다.
제네릭스의 사용 여부는 Sensors
안에서 결정한다. 이와같은 방식이 주는 이점은 다음과 같다.
- Wrapper 클래스 안에서 객체 유형을 자체적으로 관리하고 변환한다.
- 프로그램에 필요한 인터페이스만 제공한다.
- 코드는 이해하기 쉽지만 오용하기는 어렵다.
경계 살피고 익히기
외부 패키지 테스트는 우리 책임은 아니다. 하지만 우리 자신을 위해 우리가 사용할 코드를 테스트하는 편이 바람직하다. 외부 코드를 익히기 위해 학습 테스트라는 것을 이용한다.
학습 테스트란 외부 코드를 호출하는 대신 먼저 간단한 테스트 케이스를 작성해 외부 코드를 익히는 방법이다. 학습 테스트는 프로그램에서 사용하려는 방식대로 외부 API를 호출한다. 통제된 환경에서 API를 제대로 이해하는지를 확인하는 셈이다. (학습테스트는 API를 사용하려는 목적에 초점을 맞춘다)
학습 테스트는 공짜 이상이다
학습 테스트에 드는 비용은 없다. 오히려 필요한 지식만 확보하는 손쉬운 방법이다. 패키지 새 버전이 나온다면 학습 테스트를 돌려 차이가 있는지 확인한다. 학습 테스트는 패키지가 예상대로 도는지 검증하는 역할을 한다. 즉, 새 버전이 우리 코드와 호환되지 않으면 학습 테스트가 이 사실을 곧바로 밝혀낸다.
아직 존재하지 않는 코드를 사용하기
경계와 관련해 또 다른 유형은 아는 코드와 모르는 코드를 분리하는 경꼐이다. 때로는 우리 지식이 경계를 너머 미치지 못하는 코드 영역도 있다. 이때는 자체적으로 (경계 너머의 코드)인터페이스를 정의한 후 Adapter 패턴을 사용하여 간극을 매운다.
깨끗한 경계
소프트웨어 설계가 우수하다면 변경하는데 많은투자와 재작업이 필요하지 않다. 통제하지 못하는 코드를 사용할 때는 너무 많은 투자를 하거나 향후 변경 비용이 지나치게 커지지 않도록 각별히 주의해야 한다.
- 경계에 위치하는 코드는 깔끔히 분리한다.
- 기대치를 정의하는 테스트 케이스를 작성한다.
- 외부 패키지를 호출하는 코드를 가능한 줄여 경계를 관리한다.
- 들어가면서
- 1장 깨끗한 코드
- *2장 의미 있는 이름
- 3장 함수
- 4장 주석
- 5장 형식 맞추기
- 6장 객체와 자료 구조
- 7장 오류 처리
- 8장 경계 «
- 9장 단위 테스트
- 10장 클래스
- 11장 시스템
- 12장 창발성(創發性)
- 13장 동시성
- 14장 점진적인 개선
- 15장 JUnit 들여다보기
- 16장 SerialDate 리팩터링
- 17장 냄새와 휴리스틱