반응형

 

 

 

📘 7장 :: 오류처리

깨끗한 코드와 오류 처리 사이에도 연관성은 있다.
상당수의 코드는 오류 처리에 좌우되며, 여기저기 흩어진 오류 처리 코드 때문에 실제 코드가 하는 일을 파악하는 것이 불가능해질 수 있다. 따라서 오류 처리는 중요하다.

" 오류 코드보다 예외를 사용하라 "
예외 처리가 없다면 오류 플래그를 설정하거나 호출자에게 오류 코드를 반환해야 한다.
→ 함수를 호출한 즉시 오류를 확인해야 하기 때문에 호출자 코드가 복잡해지고, 잊어버리기 쉽다.
→ 오류 발생 시 예외를 던지면 로직과 오류 처리 코드가 섞이지 않게 되므로 호출자 코드가 깔끔해진다.


" Try-Catch-Finally 문부터 작성하라 "
어떤 면에서 try 블록은 트랜잭션과 비슷하다. try 블록에서 무슨 일이 생기든지 catch 블록이 상태를 일관성 있게 유지해야 하기 때문이다.
따라서, 예외가 발생할 코드를 짤 때는 try-catch-finally 문으로 시작하는 편이 낫다.


" 미확인(unchecked) 예외를 사용하라 "
확인된 예외는 OCP(Open Closed Principle)을 위반한다.
→ 하위 단계에서 코드를 변경하면 상위 단계 메서드 선언부를 전부 고쳐야 한다.(또한 캡슐화도 깨진다)
때로는 확인된 예외도 유용하다. 중요한 라이브러리를 작성한다면 모든 예외를 잡아야 한다. 하지만 일반적인 애플리케이션은 의존성이라는 비용이 이익보다 크다.


" 예외에 의미를 제공하라 "
예외를 던질 때는 오류 메시지에 정보를 담아 예외와 함께 던진다.(전후 상황을 충분히 덧붙인다.)
→ 오류가 발생한 원인과 위치를 찾기가 쉬워진다.


" 호출자를 고려해 예외 클래스를 정의하라 "
오류를 잡아내기 위해 예외 클래스를 정의한다.


" 정상 흐름을 정의하라 "
예외 처리를 통해 코드를 깔끔하게 만들 수 있고 오류를 처리할 수 있지만, 때로는 예외 처리로 인한 중단이 적합하지 않은 때도 있다. 
- 특수 사례 패턴(SPECIAL CASE PATTERN) : 클래스를 만들거나 객체를 조작해(=예외적인 상황을 캡슐화하여) 특수 사례를 처리하는 방식으로, 클라이언트 코드가 예외적인 상황을 처리할 필요가 없어진다.


" null을 반환하지 마라 "
null을 반환하는 코드는 일거리를 늘린 뿐만 아니라 호출자에게 문제를 떠넘긴다.
null확인을 빼먹는다면 애플리케이션 통제 불능에 빠질지도 모른다.
메서드에서 null을 반환하고자 한다면 그 대신 예외를 던지거나 특수 사례 객체를 반환한다.


" null을 전달하지 마라 "
메서드에서 null을 반환하는 방식도 나쁘지만 메서드로 null을 전달하는 방식은 더 나쁘다.
정상적인 인수로 null을 기대하는 API가 아니라면 메서드로 null을 전달하는 코드는 최대한 피한다.

=======================================>>>

깨끗한 코드는 읽기도 좋아야 하고 안정성도 높아야 한다.
그런 면에서 비즈니스 논리와 오류 처리가 잘 분리된 코드를 작성하기 위해 오류 처리는 중요하다.
오류 처리를 프로그램 논리와 분리하면 독립적인 추론이 가능해지며 코드 유지보수성도 크게 높아진다.

*** NullPointException 

 


📘 8장 :: 경계

시스템에 들어가는 모든 소프트웨어를 직접 개발하는 경우는 드물다.
때로는 패키지를 사고, 오픈 소스를 이용한다. 또는 사내 다른 팀이 개발한 컴포넌트를 사용한다.
어떤 식으로든 이러한 외부 코드를 우리의 코드에 깔끔하게 통합해야만 한다.


" 외부 코드 사용하기 "
경계 클래스(인터페이스)를 이용할 때는 이를 사용하는 클래스나 클래스 계열 밖으로 노출되지 않도록 주의한다.


" 경계 살피고 익히기 "
외부 코드의 테스트는 우리의 책임이 아니다. 하지만 우리 자신을 위해 사용할 코드를 테스트하는 편이 바람직하다. 외부 코드를 익히기는 어렵다. 외부 코드를 통합하기도 어렵다.


" 학습 테스트 "
학습 테스트는 우리쪽 코드를 작성해 외부 코드를 호출하는 대신 먼저 간단한 테스트 케이스를 작성해 외부 코드를 익히는 것을 말한다. 따라서 학습 테스트는 API를 사용하려는 목적에 초점을 맞춘다.


" 학습 테스트는 공짜 이상이다 "
학습 테스트에 드는 비용은 없다. 오히려 필요한 지식만 확보하는 손쉬운 방법이며, 이해도를 높여주는 정확한 실험이다. 따라서 투자하는 노력보다 얻는 성과가 크다.


" 아직 존재하지 않는 코드를 사용하기 "
위에서 살펴본 것과 또 다른 경계는 아는 코드와 모르는 코드를 분리하는 경계이다.
우리에게 필요한 경계 인터페이스를 예측하고 미리 설계하여 구현한다면 우리가 인터페이스를 전적으로 통제한다는 장점이 생긴다. 또한 코드의 가독성도 높아지고 코드 의도도 분명해진다.


" 깨끗한 경계 "
경계에 위치하는 코드는 깔끔히 분리한다. 또한 기대치를 정의하는 테스트 케이스도 작성한다.
이쪽 코드에서 외부 패키지를 세세하게 알아야 할 필요가 없다. 통제가 불가능한 외부 패키지에 의존하는 대신 통제가 가능한 우리 코드에 의존하는 편이 훨씬 좋다.

=======================================>>>

외부 코드를 우리 코드에 사용할 때 특히 더 깔끔하고 가독성 있는 코드를 작성하여 외부 코드와 섞이는 코드의 경계를 뚜렷하게 작성하여야 한다. 또한 외부 코드에 의존하지 않고 스스로 외부 코드를 익히고 테스트하여 그 경계 부분을 잘 다룰 수 있도록 하자.

 


📘 9장 :: 단위 테스트

" TDD 법칙 세 가지 "
1. 실패하는 단위 테스트를 작성할 때까지 실제 코드를 작성하지 않는다.
2. 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다.
3. 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다.

위 세 가지 규칙을 따르면 개발과 테스트가 약 30초 주기로 이루어진다.
테스트 코드와 실제 코드가 함께 나올뿐더러 테스트 코드가 실제 코드보다 불과 몇 초 전에 나온다.
실제 코드와 맞먹을 정도로 방대한 테스트 코드는 심각한 관리 문제를 유발할 수 있다.


" 깨끗한 테스트 코드 유지하기 "
지저분한 테스트 코드나 테스트를 하지 않는 것은 오십 보 백보, 아니 오히려 못하다.
→ 실제 코드가 변경되면 테스트 코드도 변경되어야 하며, 테스트 코드가 더러울수록 변경하기 어려워진다. 경우에 따라 테스트 코드를 짜는 시간이 실제 코드를 짜는 시간보다 오래 걸릴 수도 있고, 지저분한 코드로 인해 테스트를 통과시키기 더 어려워진다.
→ 테스트 코드는 실제 코드 못지않게 중요하다. 테스트 코드는 이류 시민이 아니다. 테스트 코드는 사고와 설계와 주의가 필요하다. 실제 코드 못지 않게 깨끗하게 짜야한다.

" 테스트는 유연성, 유지보수성, 재사용성을 제공한다. "

" 깨끗한 테스트 코드 "
깨끗한 테스트 코드를 위해서는 세 가지가 필요하다. 가독성, 가독성, 가독성.
어쩌면 가독성은 실제 코드보다 테스트 코드에 더더욱 중요하다.(명료성, 단순성, 표현력)
테스트 코드는 최소의 표현으로 많은 것을 나타내야 한다.


" 도메인에 특화된 테스트 언어"


" 이중 표준 "
메모리나 CPU효율과 관련 있는 경우 실제 환경과 테스트 환경은 달라도 문제되지 않는다.


" 테스트 당 assert 하나 "
JUnit으로 테스트 코드를 작성할 때 함수마다 assert문을 단 하나씩만 사용해야 한다.
→ assert문이 하나인 함수는 결론도 하나이기 때문에 테스트 코드를 빠르게 이해하기 쉽다.


" 테스트 당 개념 하나 "
테스트 함수마다 한 개념만 테스트하라, 개념 당 assert문 수를 최소로 줄여라
여러 개념을 하나의 함수에 몰아넣으면 각 절이 거기에 존재하는 이유와 각 절이 테스트하는 개념을 모두 이해해야 한다.


" F.I.R.S.T "
◾ Fast(빠르게) : 테스트는 빨라야 한다. 
테스트 속도가 느리면 자주 테스트할 엄두가 안나고 코드 초반에 문제를 찾아내지 못해 코드 품질이 나빠지기 시작한다.


◾ Independent(독립적) : 각 테스트는 서로 의존하면 안된다.
각 테스트는 실행 순서에 상관없이 독립적으로 실행할 수 있어야 하며, 테스트가 서로에 의존하면 하나가 실패할 때 나머지도 잇달아 실패하므로 결함의 원인을 찾기 어려워진다.


◾ Repeatable(반복가능한) : 테스트는 어떤 환경에서도 반복 가능해야한다.
테스트할 수 없는 환경이 있다면 실패한 이유를 둘러댈 변명이 생기고, 테스트를 수행하지 못하는 상황에 직면할 수 있다.

 

◾ Self-Validating(자가검증) : 테스트는 bool 값으로 결과를 내야한다. 성공 아니면 실패다.

테스트가 스스로 성공과 실패를 가늠하지 않는다면 판단은 주관적이 되며 지루한 수작업 평가가 필요하게 된다.

 

◾ Timely(적시에) : 테스트는 적시에 작성해야 한다.

단위 테스트는 테스트하려는 실제 코드를 구현하기 직전에 구현한다.
실제 코드를 구현한 다음 테스트 코드를 만들면 실제 코드가 테스트하기 어렵다는 사실을 발견할 수도 있고, 테스트가 불가능하도록 실제 코드를 설계할지도 모른다.

=======================================>>>

테스트 코드가 실제 코드의 유연성, 유지보수성, 재사용성을 보존하고 강화하기 때문에 실제 코드보다 더 중요한 역할을 할 수 있다. 따라서 지속적으로 테스트 코드를 관리하자.

세 가지의 TDD 법칙과 FIRST원칙. "테스트 당 개념 하나" 는 함수 파트와 비슷한 내용이다.

 

 

 

 

 

 

반응형

'Book Review' 카테고리의 다른 글

[Clean Code] 클린 코드 10장 ~ 11장 리뷰  (0) 2023.02.03
[Clean Code] 클린 코드 1장 ~ 6장 리뷰  (0) 2023.01.25
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기