본문 바로가기

클린한 코드/Clean Code

[클린 코드] 7장. 오류처리

728x90

1. 오류 코드보다 예외를 사용하라

  • 오류가 발생하면 예외를 던지는 것이 코드를 깔끔하게 해준다. (비즈니스 로직이 오류 처리 코드와 뒤섞이지 않는다.)

 

2. try-catch-finally 문부터 작성하라

  • 예외에서 범위를 정의함으로써 try 블록에 들어가는 코드의 본질을 유지하기가 쉽다.

 

3. 미확인 (unchecked) 예외를 사용하라

  • 확인된 (checked) 예외는 OCP(Open Closed Principle)을 위반한다.
    • 하위 메소드에서 checked 예외를 던진다면, 상위 메소드들이 그 예외를 처리하기 위해 1) catch 블록을 추가하거나 2) 선언부에 throw 절을 추가해야 한다.
    • 즉, 모든 함수가 최하위 함수에서 던지는 예외를 알아야 하므로 캡슐화가 깨진다.

 

4. 예외에 의미를 제공하라

  • 오류 메시지에 정보를 담아 예외와 함께 던져 전후 상황을 충분히 설명해라.
  • 실패한 코드의 의도를 파악하려면 호출 스택만으로는 부족하다.

 

5. 호출자를 고려해 예외 클래스를 정의하라

  • wrapper 클래스 (감싸는 클래스)를 이용하자
// 형편없는 코드
ACMEPort port = new ACMEPort(12);

try{
 port.open();
}catch(DeviceResponseException e){
 reportPortError(e);
 logger.log("Device response exception", e);
}catch(ATM1212UnlockException e){
 reportPortError(e);
 logger.log("Unlock exception", e);
}catch(GMXError e){
 reportPortError(e);
 logger.log("Device response exception");
}finally{
 ...
}


// Wrapper 클래스 사용
LocalPort port = new LocalPort(12);

try{
 port.open();
}catch(PortDeviceFailure e){
 reportPortError(e);
 logger.log(e.getMessage(), e);
}finally{
 ...
}

// LocalPort 클래스
public class LocalPort{
 private ACMEPort innerPort;
 
 public LocalPort(int portNumber){
 	innerPort = new ACMEPort(portNumber);
 }
 
 public void open(){
  try{
    port.open();
   }catch(DeviceResponseException e){
    reportPortError(e);
    logger.log("Device response exception", e);
   }catch(ATM1212UnlockException e){
    reportPortError(e);
    logger.log("Unlock exception", e);
   }catch(GMXError e){
    reportPortError(e);
    logger.log("Device response exception");
   }
  }
  ...
 }

 

7. null을 반환하지 마라

  • 오류를 유발하는 행위이다.
  • null을 반환하고 싶다면 그 대신 예외를 던지거나 특수 사례 객체를 반환하라
    • 특수 사례 패턴: 클래스를 만들거나 객체를 조작해 특수 사례를 처리하는 방식
      • 클래스나 객체가 예외적인 상황을 캡슐화해서 처리
// Null 반환
List<Employee> employees = getEmployees();
if(employess!=null){
 for(Employee e: employees){
  totalPay += e.getPay();
 }
}


// Null 반환 X (특수 사례 객체에서 빈 리스트 반환하도록 변경)
List<Employee> employees = getEmployees();
for(Employee e: employees){
  totalPay += e.getPay();
 }

public List<Employee> getEmployees(){
 if(직원이 없다면) return Collections.emptyList();
}

 

8. null을 전달하지 마라

  • 메소드의 매개변수로 null을 전달하지도 말자
  • 호출자가 실수로 null을 넘기면 대부분 프로그래밍 언어는 적절히 처리할 수 있는 방법이 없다.

 

오류 처리를 프로그램의 비즈니스 로직과 분리함으로써 독립적인 추론이 가능해지며 유지보수성도 높아질 것이다.

 

728x90
반응형

'클린한 코드 > Clean Code' 카테고리의 다른 글

[클린 코드] 10장. 클래스  (0) 2024.03.15
[클린 코드] 9장. 단위 테스트  (0) 2024.03.14
[클린 코드] 5장. 형식 맞추기  (0) 2024.03.09
[클린 코드] 3장. 함수  (0) 2024.03.07