노개북 - 클린코드 Assignment 09

February 09, 2024

📌 2주차 - Assignment #09

📚 TIL (2024.02.09) - 8장. 경계

🎈 책에서 기억하고 싶은 내용을 써보세요.

시스템에 들어가는 모든 소프트에어를 직접 개발하는 경우는 드물다. 때로는 패키지를 사고, 때로는 오픈 소스를 이용한다. 때로는 사내 다른 팀이 제공하는 컴포넌트를 사용한다. 어떤 식으로든 이 외부 코드를 우리 코드에 깔끔하게 통합해야만 한다. 이 장에서는 소프트웨어 경계를 깔끔하게 처리하는 기법과 기교를 살펴본다.

경계(Boundaries)란?
외부 코드를 내 코드에서 호출하는 부분을 경계(boundaries)라고 한다.

외부 코드 사용하기

인터페이스 제공자와 인터페이스 사용자 사이에는 특유의 긴장이 존재한다. 패키지 제공자나 프레임워크 제공자는 적용성을 최대한 넓히려 애쓴다. 더 많은 환경에서 돌아가야 더 많은 고객이 구매하니까. 반면, 사용자는 자신의 요구에 집중하는 인터페이스를 바란다. 이런 긴장으로 인해 시스템 경계에서 문제가 생길 소지가 많다.

경계 인터페이스를 이용할 때는 이를 이용하는 클래스나 클래스 계열 밖으로 노출되지 않도록 주의한다. 해당 인스턴스를 공개 API의 인수로 넘기거나 반환값으로 사용하지 않는다.

외부 코드를 경계 클래스로 랩핑해서 불필요한 기능을 제한하고 내부 로직에 알맞게 사용하자!

경계 살피고 익히기

외부 코드를 사용하면 적은 시간에 더 많은 기능을 출시하기 쉬워진다. 만약 외부에서 가져온 패키지를 사용하고 싶다면 어디서 어떻게 시작해야 좋을까? 외부 패키지 테스트가 우리 책임은 아니지만, 우리 자신을 위해 우리가 사용할 코드를 테스트하는 편이 바람직하다.

곧바로 우리쪽 코드를 작성해 외부 코드를 호출하는 대신 먼저 간단한 테스트 케이스를 작성해 외부 코드를 익히는 것을 학습 테스트라 부른다. 학습 테스트는 프로그램에서 사용하려는 방식대로 외부 API를 호출한다. 통제된 환경에서 API를 제대로 이해하는지를 확인하는 셈이다. 학습 테스트는 API를 사용하려는 목적에 초점을 맞춘다.

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

학습 테스트는 패키지가 예상대로 도는지 검증한다. 일단 통합한 이후라고 하더라도 패키지가 우리 코드와 호환되리라는 보장은 없다. 패키지 작성자에게 코드를 변경할 필요가 생길지도 모른다. 패키지 작성자는 버그를 수정하고 기능도 추가한다. 패키지 새 버전이 나올 때마다 새로운 위험이 생긴다. 새 버전이 우리 코드와 호환되지 않으면 학습 테스트가 이 사실을 곧바로 밝혀낸다.

학습 테스트를 이용한 학습이 필요하든 그렇지 않든, 실제 코드와 동일한 방식으로 인터페이스를 사용하는 테스트 케이스가 필요하다. 이런 경계 테스트가 있다면 패키지의 새 버전으로 이전하기 쉬워진다. 그렇지 않다면 낡은 버전을 필요 이상으로 오랫동안 사용하려는 유혹에 빠지기 쉽다.

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

경계와 관련해 또 다른 유형은 아는 코드와 모르는 코드를 분리하는 경계다. 때로는 우리 지식이 경계를 너머 미치지 못하는 코드 영역도 있다.

우리가 바라는 인터페이스를 구현하면 우리가 인터페이스를 전적으로 통제한다는 장점이 생긴다. 또한 코드 가독성도 높아지고 코드 의도도 분명해진다.

깨끗한 경계

소프트웨어 설계가 우수하다면 변경하는데 많은 투자와 재작업이 필요하지 않다. 통제하지 못하는 코드를 사용할 때는 너무 많은 투자를 하거나 향후 변경 비용이 지나치게 커지지 않도록 각별히 주의해야 한다.

경계에 위치하는 코드는 깔끔히 분리한다. 또한 기대치를 정의하는 테스트 케이스도 작성한다. 통제가 불가능한 외부 패키지에 의존하는 대신 통제가 가능한 우리 코드에 의존하는 편이 훨씬 좋다. 자칫하면 오히려 외부 코드에 휘둘리고 만다.

외부 패키지를 호출하는 코드를 가능한 줄여 경계를 관리하자. 새로운 클래스로 경계를 감싸거나 ADAPTER 패턴을 사용해 우리가 원하는 인터페이스를 패키지가 제공하는 인터페이스로 변환하자. 어느 방법이든 코드 가독성이 높아지며, 경계 인터페이스를 사용하는 일관성도 높아지며, 외부 패키지가 변했을 때 변경할 코드도 줄어든다.

🎈 오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요.

프로젝트를 하다보면 자연스럽게 패키지나 오픈 소스들을 사용하게 되는데, 해당 코드를 호출하는 부분을 '경계'라고 부른다는 것을 처음 알게 되었다. 패키지를 가져오면서 경계를 깔끔하게 처리하는 방법 등에 대해서는 생각해 본 적이 없었는데, 이번 기회를 통해 기존 코드와 문제가 생기지 않도록 테스트 할 필요가 있다고 생각했다.

🎈 궁금한 내용이나, 잘 이해되지 않는 내용이 있다면 적어보세요.

  • 학습 테스트

    • API, 라이브러리, 프레임워크가 어떻게 동작하는 지 검증하기 위한 테스트
    • 기능 검증을 위한 테스트가 아님
  • 어댑터(adapter 패턴)

    • 한 클래스의 인터페이스를 클라이언트에서 사용하고자 하는 다른 인터페이스로 변환
    • 인터페이스 호환성 문제 때문에 같이 쓸 수 없는 클래스들을 연결해서 사용이 가능하다

학습 테스트를 실질적으로 어떻게 해야 할 지 감이 안온다..😖