[CleanCode] 3주차 - 7장, 8장, 9장 10장
7장 오류처리
8강 경계
✅ 외부코드 사용하기
Map 과 같은 경계 인터페이스를 이용할 때
👉 이를 사용하는 클래스나 클래스 계열 밖으로 노출되지 않도록 주의할 것.
👉 Map 인스턴스를 공개 API의 인수로 넘기거나 반환값으로 사용하지 않는다
✅ 경계 잘피고 익히기
외부코드를 사용하면 적은 시간에 더 많은 기능을 출시하기 쉬워짐.
하지만 외부코드를 익히기도, 통합하기도 어렵다.
따라서 먼저 간단한 테스트 케이스를 작성해 외부 코드를 익히는 것 추천
학습 테스트
학습테스트 : 프로그램에서 사용하려는 방식대로 외부 api를 호출(통제된 환경에서 api를 제대로 이해하는지를 확인하는 셈)
👉학습 테스트는 api를 사용하려는 목적에 초점을 맞춘다
✅ 학습테스트는 공짜 이상이다
학습테스트에 드는 비용은 없다 -> 이해도를 높여주는 정확한 실험이다
투자하는 노력보다 얻는 성과가 더 큼
✅ 아직 존재하지 않는 코드를 사용하기
아는 코드와 모르는 코드 분리하기
✅ 깨끗한 경계
경계에 위치하는 코드는 깔끔히 분리한다. 기대치를 정의하는 테스트 케이스도 작성한다
외부 패키지를 호출하는 코드를 가능한 줄여 경계를 관리할 것
9장. 단위테스트
✅ tdd 법칙 3가지
1. 실패하는 단위테스트를 작성할 때까지 실제 코드를 작성하지 않는다
2. 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위테스트를 작성한다
3. 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다
위 3가지 규칙을 따르면 개발과 테스트가 대략 30초 주기로 묶임
👉 깨끗한 테스트 코드 유지하기
👉 테스트 코드가 복잡할수록 실제코드를 짜는 시간보다 테스트 케이스를 추가하는 시간이 더 걸리기 십상
👉 하지만 테스트 코드는 실제 코드 못지 않게 중요함
👉 실제 코드 못지않게 깨끗하게 짜야한다
✅ 테스트는 유연성, 유지보수성, 재사용성을 제공한다
테스트케이스가 없다면 모든 변경이 잠정적인 버그다
깨끗한 테스트코드=가독성!
가독성을 높이려면? > 명료성, 단순성, 풍부한 표현력
✅ 도메인에 특화된 언어
흔히 쓰는 스스템 조작 api를 사용하는 대신 API 위에 함수와 유틸리티를 구현한 뒤 그 함수와 유틸리티를 사용하므로 테스트코드를 짜기도 읽기도 쉬워짐
이렇게 구현한 함수와 유틸리티는 테스트코드에서 아용하는 특수 API가 됨.
테스트를 구현하는 당사자와 나중에 테스트를 읽어볼 독자를 도와주는 테스트 언어
✅ 이중표준
테스트 API 코드에 적용하는 표준은 실제 코드에 적용하는 표준과 확실히 다름
간결하고 표현력이 풍부해야하지만 실제 코드만큼 효율적인 필요는 없다
✅ 테스트당 assert하나
JUnit으로 테스트 코드를 짤 땐 함수마다 assert 문을 단 하나만 사용해야함 = > assert 문이 단 하나인 함수는 결론이 하나라 코드를 이해하기 쉽고 빠름
✅ 테스트당 개념 하나
테스트 함수마다 한 개념만 테스트 할 것
잡다한 개념을 연속으로 테스트 하는 긴 함수는 피한다
✅ FIRST 법칙
Fast
테스트는 빨라야함
Independent
각 테스트는 서로 의존하면 안됨
Repeatable
테스트는 어떤 환경에서도 반복가능해야함
Self-Validating
테스트는 부울 값으로 결과를 내야함
Timely
테스트는 적시에 작성해야함
단위테스트는 테스트하려는 실제 코드를 구현하기 직전에 구현할 것
10장 클래스
✅ 캡슐화
변수와 유틸리티 함수는 가능한 공개하지 않는 편이 낫지만 반드시 숨겨야하는 법칙은 없음
때로는 변수나 유틸리티 함수를 protected로 선언해 테스트 코드에 접근을 허용하기도 함
✅ 클래스는 작아야한다
클래스 이름은 해당 클래스 책임을 기술해야함
간결한 이름이 떠오르지 않는다면 클래스 크기가 너무 커서 그렇다
✅ 단일 책임 원칙 : 클래스나 모듈을 변경할 이유가 하나, 단 하나 뿐이어야한다는 원칙
응집도:클래스는 인스턴스 변수 수가 작아야한다. 각 클래스 매서드는 클래스 인스턴스 변수를 하나 이상 사용해야함. 일반적으로 메서드가 변수를 더 많이 사용할수록 메서드와 클래스는 응집도가 더 높다
✅ 응집도를 유지하면 작은 클래스 여럿이 나옴
네 변수를 클래스 인스턴스 변수로 승격한다면 새 함수는 인수가 필요없다.
👉 그만큼 함수를 쪼개기 쉬워짐!
큰 함수를 작은 함수 여럿으로 쪼개다 보면 종종 작은 클래스 여럿으로 쪼갤 기회가 생긴다. 그러면서 프로그램에 점점 더 체계가 잡히고 구조가 투명해진다.
✅ 변경하기 쉬운 클래스
대다수의 시스템은 지속적인 변경이 가해진다
변경할 때마다 시스템이 의도대로 동작하지 않을 위험이 따른다
깨끗한 시스템은 클래스를 체계적으로 정리해 변경에 수반하는 위험을 낮춤
✅ 변경으로부터 격리
요구사항은 변하기 마련이므로 코드도 변하기 마련이다.
따라서 상세한 구현에 의존하는 클라이언트 클래스는 구현이 바뀌면 위험에 빠진다.
👉 따라서 인터페이스와 추상 클래스를 사용해 구현이 미치는 영향을 격리한다.
상세한 구현에 의존하는 코드는 테스트가 어려움
시스템의 결합도를 낮추면 유연성과 재사용성도 더욱 높아짐!
(결합도가 낮다=각 시스템 요소가 다른 요소로부터 그리고 변경으로부터 잘 격리도어 있다는 의미)