Clean Code 내용 정리 - 3
#
7장. 오류 처리깨끗한 코드와 오류 처리는 연관성이 존재한다.
#
오류 코드보다 예외를 사용하기오류가 발생 시 예외를 던지는 방법이 논리와 오류 처리 코드가 뒤섞이지 않아 코드가 더 깔끔해진다.
#
Try-Catch-Finally 문부터 작성하기예외가 발생할 코드를 짤 경우에는 try-catch-finally 문으로 시작하는 것이 좋다.
#
미확인(unchecked) 예외를 사용하기확인된 예외는 몇 가지 장점을 제공하지만, 반드시 필요하지는 않다.
- 확인된 오류가 치르는 비용에 대해서 잘 생각해보아야 한다.
- 확인된 예외는 OCP(Open Closed Principle)를 위반한다.
- Ex) 확인된 예외를 던졌으나, catch가 세 단계 위에 있다면 모든 선언부에 예외가 필요하다. 대규모 시스템에서는 힘들다.
#
예외에 의미를 제공하기- 예외를 던질 때 전후 상황을 충분히 덧붙일 때, 오류가 발생한 원인과 위치를 찾을 수 있다.
- 오류 메시지에 정보(실패한 연산 이름, 실패 유형)등을 함께 던진다.
- 로깅 기능을 통해 충분한 정보를 제공하자.
#
호출자를 고려해 예외 클래스를 정의하기오류를 잡아내는 다양한 방법이 존재한다.
외부 API를 사용할 때는 감싸기 기법을 사용하는 것은 좋은 방법이다.
예외 클래스가 하나만 있어도 되는 경우가 많다.
더 나아가, 한 예외는 잡아내고 다른 예외는 무시해도 되는 경우에는 여러 예외 케이스를 사용하는 것도 방법이다.
#
정상 흐름을 정의하기특수 사례 패턴을 사용하기
- 클래스나 객체로 예외적인 상황을 캡슐화하여 처리할 수 있음
#
null을 반환하지 말기null에 대한 과한 확인은 문제가 될 수 있다. 즉, 예외나 특수 사례 패턴이 더 좋은 경우가 많다.
#
null을 전달하지 말기인수에 null이 넘어가지 않는 정책이 있다면, 많은 실수를 줄일 수 있다.
#
결론.- 깨끗한 코드는 읽기도 좋아야 하지만, 안정성도 높아야 한다.
- 오류 처리를 프로그램 논리와 분리해 독자적인 사안으로 고려하면 튼튼하고 깨끗한 코드 작성이 가능
#
8장. 경계시스템에 들어가는 모든 소프트웨어를 직접 개발하는 경우는 드물다.
#
외부 코드 사용하기인터페이스 제공자와 사용자 사이에는 이해관계가 들어간다. 제공자는 최대한 적용성을 늘리기를 원하지만, 사용자는 자신의 요구에 집중하는 인터페이스를 희망한다.
즉, Map
과 같은 경계 인터페이스를
사용할 때는 이용하는 클래스나 계열 밖으로 노출되지 않도록 주의해야 한다.(캡슐화도 한 방법)
#
경계를 살피고 익히기- 외부 코드를 사용하면 적은 시간에 많은 기능을 넣을 수 있는 장점이 존재.
- 그러나, 테스트를 해서 진행하는 방법이 바람직하다.
- 이러한 간단한 테스트 케이스를 사용해 익히는 방법을 학습 테스트라고 부른다.
#
log4j 익히기로깅을 직접 구현하기보다는 아파치의 log4j 패키지를 사용하자.
간단한 예시 코드는 다음과 같다.
#
학습 테스트는 공짜 이상- 학습 테스트에 드는 비용은 없으며, 필요한 지식만 확보하는 손쉬운 방법
- 투자하는 노력보다 얻는 성과가 더 크다
- 패키지가 새 버전이 나오면 학습 테스트를 돌려 예상대로 나오는지 체크한다.
#
아직 존재하지 않는 코드를 사용하기- 아는 코드와 모르는 코드(미완성 코드)를 분리하기
- 바라는 인터페이스를 구현하면 우리가 인터페이스를 전적으로 통제할 수 있다는 장점을 얻을 수 있음.
- 이러한 설계는 테스트에서도 편하다.
#
깨끗한 경계경계에서는 다양한 문제가 발생할 수 있다.
따라서.
- 통제 못하는 코드를 사용하는 경우에는 비용이 적게 구성해야 한다.
- 경계에 위치한 코드는 깔끔하게 분리한다.
- 외부 패키지에 의존하는 대신, 통제 가능한 우리 코드에 의존한다
- 외부 패키지 호출 코드를 가능한 줄여서 경계를 관리한다
#
9장. 단위 테스트제대로 된 테스트가 필요하다.
#
TDD 법칙 세가지- 실패하는 단위 테스트를 작성할 때까지 실제 코드를 작성하지 않다.
- 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다.
- 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다.
위 규칙을 잘 지키면, 테스트 코드와 실제 코드가 같이 나온다.
#
깨끗한 테스트 코드 유지하기코드가 망가지기 시작하면 망가진다. 따라서, 테스트 코드는 실제 코드 못지않게 중요하게 짜야한다.
#
테스트는 유연성, 유지보수성, 재사용성을 제공한다.- 단위 테스트는 코드에 유연성, 유지보수성, 재사용성을 제공하는 기둥이 된다.
- 테스트 케이스가 있다면 많은 공포를 해결할 수 있다.
- 테스트 코드가 지저분해질수록 실제 코드도 지저분해진다.
#
깨끗한 테스트 코드- 가독성 : 명료성, 단순성, 풍부한 표현력
#
도메인에 특화된 테스트 언어- 도메인에 특화된 언어(DSL)도 좋은 방법이다.
#
이중 표준- 단순, 간결, 표현력이 풍부, 그러나 꼭 효율적인 필요는 없다.
#
테스트 당 assert 하나- Assert 문은 하나가 좋지만, 때로는 여러 개를 써도 된다. (단, 최대한 줄여야 한다.)
Tip) Assert문.
정해진 조건에 맞지 않을 때 프로그램을 중단. ex) assert(표현식)
- 테스트 함수마다 한 개념만 테스트
#
F.I.R.S.T- Fast(빠르게) : 테스트는 빠르게 돌아야 한다.
- Independent(독립적으로) : 각 테스트는 서로 의존하면 안 된다.
- Repeatable(반복 가능하게) : 테스트는 어떤 환경에서도 반복 가능해야 한다.
- Self-Validating(자가 검증하는) : 테스트는 부울(bool) 값으로 결과를 내야 한다.
- Timely(적시에) : 테스트는 적시에 작성해야 한다.
#
결론- 테스트 코드는 실제 코드의 유연성, 유지보수성, 재사용성을 보존하고 강화해야 한다.
- 도메인 특화 언어(DSL, Domain Specific Language)를 구성하면 테스트 코드가 짜기 쉬워진다.
#
10장. 클래스#
클래스 체계추상화 단계는 순차적으로 내려간다.
- public, private, 비공개 인스턴스 변수 순으로 진행된다.
#
캡슐화꼭 유지해야 하는 것은 아니나, 캡슐화를 푸는 방법은 최후의 수단입니다.
#
클래스는 작아야 한다.하나의 클래스는 적은 책임을 얻어야 한다.
즉, 클래스 설명은 if, and, or, but 등의 단어를 제외하고 25 단어 내외로 가능해야 한다.
#
단일 책임 원칙(SRP, Single Responsibility Principle)- 클래스나 모듈을 변경할 이유가 하나뿐이어야 한다는 원칙.
- 객체 지향 설계에서 더우 중요한 개념이다.
#
응집도- 클래스는 인스턴스 변수 수가 적어야 한다.
- 각 클래스 메서드는 클래스 인스턴스 변수를 하나 이상 사용해야 한다.
- '함수를 작게, 매개변수 목록을 짧게'라는 전략으로 진행하고, 응집도가 높아지도록 새로운 클래스로 분리한다.
#
응집도를 유지하면 작은 클래스 여럿으로 구성된다.클래스가 응집력을 잃으면 쪼개야 한다.
3가지 룰을 사용한다.
- 리팩터링한 프로그램은 좀 더 길고 서술적인 변수 이름을 사용
- 리팩터링한 프로그램은 코드에 주석을 추가하는 수단으로 함수 선언과 클래스 선언을 활용
- 가독성을 높이기 위해 공백을 추가하고 형식을 맞춤
#
변경하기 쉬운 클래스대표적으로 수정하기 어려운 코드가 SQL 클래스이다. 잠재적으로 수정되는 여지를 남기는 것이 좋다.
#
변경으로부터 격리- 구체적인 클래스와 추상 클래스의 사용이 중요하다. 즉, 인터페이스와 추상 클래스가 중요하다.
- 시스템의 결합도를 낮추면 유연성과 재사용성이 높아지고 각 요소를 이해하기 쉬워진다.
- 이는 클래스 설계 원칙(DIP, Dependency Inversion Principle)을 따르는 클래스를 지킬 수 있다.
- DIP : 상세한 구현이 아니라 추상화에 의존한다는 원칙