Community

개발자 99% 커뮤니티에서 수다 떨어요!

← Go back
TIL (2022.03.06)
#clean_code
2년 전
945
1

오늘 TIL 3줄 요약

  • 나에게 통제권이 없는 코드와는 최대한 접촉할 일을 줄이자

  • 테스트는 빨리보다 '잘' 짜는 게 중요함을 기억하자

  • 테스트 코드와 실제 코드는 목적이 다르다. 다른 코드 규칙들은 잊어버리자. 테스트 코드에서 제일 중요한 건 가독성!

TIL (Today I Learned) 날짜

2022.03.06

오늘 읽은 범위

8장. 경계 ~ 9장. 단위 테스트

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

  • 경계 인터페이스를 사용할 때에는 클래스로 감싸줌으로써 해당 경계 인터페이스가 전체 프로그램에 끼치는 의도치 않은 영향을 방지하고 프로그램에 필요한 기능만을 추출한다. (p.145)

  • 외부 코드를 사용할 때에는 먼저 자기 프로그램을 작성하는 것이 아니라 간단한 테스트를 작성하여 외부 코드의 사용법을 익히는 학습 테스트를 이용하자. (p. 146)

  • 경계를 최대한 줄이고 그 외의 요소들로부터 분리시킴으로써 프로그램에 대한 통제성을 높이자. 경계를 잘 관리하지 않으면 우리가 통제할 수 없는 영역의 외부 코드에 의해 너무 휘둘릴 수 있다. 최소한 경계 코드는 우리가 통제권을 쥘 수 있다. (p.152)

  • TDD의 세 가지 법칙 : 실패하는 단위 테스트를 작성할 때까지 실제 코드를 작성하지 않는다. / 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다. / 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다. (p.155)

  • 실제 코드가 변경되면 테스트 코드 역시 변경이 필요할 수 있다. 테스트 코드를 복잡하게 마음대로 작성하면 이 과정이 매우 골치아파진다. 따라서 테스트 코드의 품질은 실제 코드만큼이나 중요하다. (p.156)

  • 실제 코드에 유연성, 유지보수성, 재사용성을 제공하는 버팀목이 바로 단위 테스트다. 테스트 케이스가 있으면 버그를 찾아낼 수 있기 때문에 변화를 두려워하지 않아도 된다. (p.157) 

  • 테스트 코드에서 가장 중요한 것은 가독성이다. 깨끗한 테스트 코드가 테스트 코드의 유지보수를 보장하고 잘 작성된 테스트 코드가 실제 코드가 발전할 수 있게 해준다. (p.158)

  • 테스트 코드는 바로 본론에 돌입해 진짜 필요한 자료와 함수만을 사용한다. (p.160)

  • 실제 코드와 테스트 코드는 요구사항이 다르다. 테스트 코드는 가독성을 위해 기존 실제 코드에 적용되는 규칙들을 깨도 되며 리소스가 제한적인 실제 환경과 다르게 메모리, CPU 등에서 제한을 가지지 않는다. (p.162)

  • 테스트 하나당 개념은 하나만 테스트한다. 그리고 개념당 asset문은 최소한으로 사용한다. 만약 하나의 개념을 테스트하는 데 assert문이 2개 이상 필요한 것 같다면 최대한 개념을 잘 쪼개보자. (p.167)

  • 테스트는 FIRST라는 다섯 가지 규칙을 따른다. (p.167)

    1. Fast : 테스트는 빨리 돌아가야 한다. (테스트 시간이 오래 걸리면 테스트를 덜 하게 되고 이는 코드 성능의 저하로 이어진다.)

    2. Independent : 테스트끼리 의존성을 가지면 안 된다. 예를 들어서 한 테스트가 다른 테스트를 준비하면 안 된다. 그렇게 되면 테스트 실패시 원인 추적이 어렵다.

    3. Repeatable : 테스트는 어떠한 환경에서도 돌아갈 수 있어야 한다. (반복 가능해야 한다.)

    4. Self-Validating : 테스트 결과는 무조건 성공, 실패 둘 중 하나다.

    5. Timely : 테스트는 적시, 즉 실제 코드를 작성하기 직전에 작성해야 한다.

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

  • 사실 처음 챕터 제목을 읽었을 때에는 에러 경계같은 내용을 생각했는데 전혀 다른 내용이 나와서 당황했다. 외부 코드를 사용하는 것은 정말 조심해야 하는 영역인 것 같다. 내가 통제권을 가지지 못한 영역이 내 코드 여기저기에 스며들어있다면 가뜩이나 내 프로그램의 목적에 맞춰서 유지보수하기도 힘든데 외부 코드에 의해 이리 휘둘렸다 저리 휘둘렸다 할 테니까. 당연한 말이지만 외부코드가 아니더라도 프로그램의 모든 부분을 잘 쪼개는 것이 참 중요한 것 같다. 오늘 포트폴리오 사이트를 새로 만드는 과정에서 에러 경계의 위치를 고민하다 느낀 점이다. 코드는 분리를 잘 하고 분리한 코드들은 서로 인터렉션을 줄이는 것이 참 중요한 것 같다. 어떻게 보면 먼 과거의 성들을 보는 것 같아서 재미있다. 벽을 굳건하게 세우고 왕래가 필요하면 성문에서 문지기에게 검사받은 후에만 입장할 수 있으니 클래스, 인터페이스와 비슷한 느낌 아닌가? 요즘 사람들에게 '너는 MBTI N이 확실하구나'라는 말을 자주 듣는데 이래서인가 싶다.

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

  • 경계 인터페이스 : 어떠한 메소드에서 Map, List와 같은 자료구조를 반환하거나 공개 API 인수로 넘겨서 클라이언트에서 해당 인터페이스를 사용하는 것을 말한다. 경계 인터페이스는 클라이언트 측에서 예상하지 못한 동작으로 프로그램에 문제를 일으킬 수 가능성이 있다. 이러한 경계 인터페이스를 클래스로 감싸준다면 원하는 기능만을 도출(일부 기능을 직접 사용하던 변환시키던)하고 코드의 직관성 역시 향상시킬 수 있다. 또한 경계 인터페이스 내부가 변화하더라도 그것이 외부에 노출되지 않으며 감싼 클래스만을 수정하면 된다는 장점이 있다.

  • 학습 테스트 : 자신이 개발하지 않은 코드를 사용할 때 테스트하면서 사용법을 익히는 방식을 말한다. 테스트 코드를 작성하고 구체적으로 테스트를 돌리는 과정에서 프로그램의 사용법을 익힐 수 있다. 학습 테스트는 코드의 테스팅이 아니라 학습에 그 목적이 있다는 점이 중요하다. 학습 테스트에서는 프로그램에서 원하는 방식으로 테스트를 작성한다. 이 때 작성한 테스트는 이후에 해당 외부 코드가 변경되었을 때 해당 코드가 자신의 프로그램(+그 기능)과 호환되는지 점검하는데 지속적으로 활용될 수 있다.

  • 어뎁터 패턴 (Adapter Pattern) : 클래스의 인터페이스가 클라이언트에서 사용될 수 있도록 변환(적응)시켜주는 역할을 수행하는 어뎁터가 포함된 디자인 패턴이다. 어뎁터를 활용하면 호환되지 않은 클래스를 사용하거나 여러 클래스, 구조 사이에서 유연한 전환이 가능하다. 

  • BUILD-OPERATE-CHECK 패턴 : 테스트 자료를 만들고(Build), 테스트 자료를 조작하고(Operate), 조작 결과를 확인하는(Check) 테스트 방법으로 given-when-then을 각각 주석으로 활용하는 것이 관례이다.

  • 템플릿 메소드 패턴 (Template-Method Pattern) : 어떤 작업을 처리하는 일부분을 서브 클래스로 캡슐화해 전체 일을 수행하는 구조는 바꾸지 않으면서 특정 단계에서 수행하는 내역을 바꾸는 패턴이다. 즉, 전체적으로는 동일하면서 부분적으로는 다른 구문으로 구성된 메서드의 코드 중복을 최소화 할 때 유용하다.

오늘 읽은 다른사람의 TIL

1 comment