본문 바로가기

# Development/Methodologies

[클린 코드] 에러 핸들링

클린 코드: 에러 핸들링

1. 오류 코드 보다는 예외(Exception)을 사용한다.

try, except를 사용하면 오류인지 확인하는 불필요한 로직을 줄일 수 있다.

### as-is
from enum import Enum 

class ErrorCodes(Enum):
    VALUE_ERROR="VALUE_ERROR"

def we_can_raise_error():
    ...
    return ERROR_CODES.VALUE_ERROR

def use_ugly_function():
    result = we_can_occur_error()
    if result == ErrorCodes.VALUE_ERROR:
        # 처리 코드
    ...
### to-be
def we_can_raise_error():
    if ...
        raise ValueError("에러 발생")

def use_awesome_function():
    try:
        we_can_occur_error()
        ...
    except ValueError as e:
        # 에러 처리 로직

2. 예외 클래스를 잘 정의한다.

class CustomException(Exception):
    ...

class WithParameterCustomException(Exception):
    def __init__(self, msg, kwargs):
        self.msg = msg
        self.kwargs = kwargs
    
    def __str__():
        return f"message {self.msg} with parameter {self(self.kwargs)}"

raise WithParameterCustomException("문제가 있습니다", {"name": "grab"})

3. 에러 핸들링

같은 수준의 로직은 한곳으로 모아 Exception 처리한다.

### as-is
def act_1():
    try:
        we_can_raise_error1()
        ...
    except:
        #handling

def act_2():
    try:
        we_can_raise_error2()
        ...
    except:
        #handling

def act_3():
    try:
        we_can_raise_error3()
        ...
    except:
        #handling

# 에러가 날 지점을 한눈에 확인할 수 없습니다. 
# act_1이 실패하면 act_2가 실행되면 안 된다면? 핸들링하기 어려워집니다.
def main():
    act_1()
    act_2()
    act_3()
### to-be
def act_1():
    we_can_raise_error1()
    ...

def act_2():
    we_can_raise_error2()
    ...

def act_3():
    we_can_raise_error3()
    ...

# 직관적이며 에러가 날 지점을 확인하고 처리할 수 있습니다.
# 트랜잭션같이 한 단위로 묶여야하는 처리에도 유용합니다.
def main():
    try:
        act_1()
        act_2()
        act_3()
    except SomeException1 as e1:
        ...
    except SomeException2 as e2:	
        ...
    except SomeException2 as e3
        ...
    finally:
        ...

 

** 핸들링하는 법

# GOOD
def use_awesome_function():
    try:
        we_can_raise_error()
        ...
    except Exception as e:
        logging.error(...) # Error Log 남기기
        notify_error(...) # 예측 불가능한 외부 I/O 이슈라면 회사 내 채널에 알리기(이메일, 슬랙 etc)
        raise OtherException(e) # 만약 이 함수를 호출하는 다른 함수에서 추가로 처리해야 한다면 에러를 전파하기
    finally:
        ... #에러가 발생하더라도 항상 실행되어야 하는 로직이 있다면 finally 문을 넣어주기

 

<참고>

  1. https://yansfil.github.io/awesome-class-materials/
  2. https://dojang.io/mod/page/view.php?id=2389

'# Development > Methodologies' 카테고리의 다른 글

[REST API] API 문서 작성  (0) 2023.06.14
[성능 테스트] Throughput(TPS), Latency  (0) 2023.02.02
[클린 코드] 클래스  (0) 2023.01.31
[클린 코드] 함수  (0) 2023.01.31