코딩관계론

오류 본문

Clean code

오류

개발자_티모 2023. 5. 20. 21:14
반응형

서론

 코드가 실행되는 환경은 굉장히 불완전합니다. 여러가지 상황을 따져 봤을 때 오류는 불가피하게 발생하게 됩니다.

오류 사례를 신중하게 생각하지 않고는 견고하고 신뢰성 높은 코드를 작성할 수 없다. 따라서 오류의 종류 및 차이점들을 살펴보고 적절하게 처리할 수 있는 방법에 대해서 기술해보고자 한다.

오류의 종류

 1. 복구할 수 있는 오류

  시스템 문제가 아닌, 시스템 외부 환경으로 인해 발생되는 오류이다

 예를 들면 사용자의 입력이 잘못되서 다음 단계를 진행할 수 없거나, 인터넷 연결이 불안정해서 사용자의 요청을 진행할 수 없는 경우이다.

 

 2. 복구할 수 없는 오류

  시스템 오류를 복구할 수 있는 합리적인 방법이 없을 때다, 이러한 오류는 프로그래밍 오류 때문에 발생할 때가 많다. 예를 들면 코드와 함께 추가되어야 하는 리소시가 없거나 잘못된 입력 인수로 호출하는 경우다
 이런 잘못된 경우가 발생하면 우리가 선택할 수 있는 최선의 방법은 신속한 실패와 요란한 실패이다. 이 개념은 글의 후반부를 참고하자

오류를 처리의 담당자  
 

 1. 호출하는 쪽 vs 호출당하는 쪽

  일반적으로, 오류 처리는 호출하는 쪽에서 처리하는 것이 좋습니다. 호출당하는 쪽에서 오류 처리를 담당하면, 해당 함수가 어떻게 사용되고 어디에서 호출되는지에 대한 정보를 알 수 없기 때문에 오류 복구 가능성에 대한 질문에 대답하기 어렵습니다. 


  호출하는 쪽에서 오류 처리를 담당함으로써, 호출 당하는 쪽은 예외를 발생시켜 호출하는 쪽에 오류를 알리는 역할을 수행합니다. 이를 통해 호출하는 쪽은 오류에 적절하게 대응할 수 있습니다.

  예를 들어, 호출하는 쪽에서는 호출된 함수의 반환 값을 확인하고, 오류가 발생한 경우 예외를 처리하거나 오류 메시지를 표시하는 등의 조치를 취할 수 있습니다. 이렇게 함으로써 호출하는 쪽은 호출된 함수가 제대로 수행되었는지를 확인하고, 오류가 발생했을 때 적절한 조치를 취할 수 있게 됩니다.

  또한, 호출하는 쪽에서 오류 처리를 담당하면 호출 당하는 쪽에서 발생하는 오류에 대한 처리 방법을 몰라도 되므로, 모듈 간의 결합도를 낮출 수 있습니다. 이는 유지 보수 및 확장에 유리한 구조를 만들어줍니다.

따라서, 오류 처리를 호출하는 쪽에서 담당하는 것이 프로그래밍에 좋은 방법이라고 할 수 있습니다.

 

견고성 vs 실패

 견고성을 추구하기보다는 실패를 인지하고 처리하는 것이 바람직합니다. 왜냐하면 오류가 발생했을 때 적절한 처리를 통해 프로그램을 계속 진행시키면 더 견고한 코드라고 볼 수 있지만, 오류가 감지되지 않고 이상한 동작이 발생한다면 더 큰 문제를 야기할 수 있기 때문입니다.

 그러면 어떤 방식으로 오류를 알리는 것이 좋을까요? 이를 위해 우리는 오류 처리 방법을 살펴볼 수 있습니다. 일반적으로 실패 지점으로부터 스택 트레이스를 이용하여 오류를 처리합니다. 하지만, 만약 스택 트레이스가 이상한 지점부터 시작된다면 오류 처리가 어려워질 수 있습니다.


신속하게 실패하라

 신속하게 실패하는 것은 가능한 한 문제의 실제 발생 지점으로부터 가까운 곳에서 오류를 나타내는 것이다. 복구할 수 있는 오류의 경우 호출하는 쪽에서 오류로부터 훌륭하고 안전하게 복구할 수 있는 기회를 제공한다. 또한 복구할 수 없는 경우에는 개발자에게 문제를 신속하게 파악하고 해결할 수 있는 기회를 제공한다.

 

요란하게 실패하라

 요란한 실패는 오류가 발생하는데도 불구하고 아무도 모르는 상황을 막고자 하는 것이다. 이를 위한 방법은 예뢰를 발생해 프로그램이 중단되게 하는 것이다. 이를 통해 개발자는 오류를 신속하게 파악하고 수정할 수 있습니다.

 

이러한 방식으로 "신속하게 실패하라"와 "요란하게 실패하라"는 오류를 빠르게 인지하고 처리함으로써 견고한 코드를 구축하는 데 도움이 됩니다. 이는 개발자가 오류를 파악하고 수정하는 시간을 단축시키며, 사용자에게는 안정적인 프로그램 경험을 제공할 수 있습니다.

전달 방법

 1. 명시적 전달 

  코드를 직접 호출한 쪽에서 오류가 발생할 수 있음을 인지할 수 밖에 없도록 하는 것입니다. 그것을 처리하든, 이전 호출자에게 전달하든 , 무시하든 간에 호출하는 쪽에서 오류 처리가 달려있습니다. 또한 무엇을 선택하든 그것은 적근적인 선택의 결과입니다. 오류가 발생할 가능성이 코드 계약에 명확하게 나타나 잇기 때문에 오류를 모르고 넘어갈 가능성은 없습니다

 

예시 코드: 검사 예외

public class DivisionException extends Exception {
    public DivisionException(String message) {
        super(message);
    }
}

public class Calculation {
    public static double divideNumbers(int a, int b) throws DivisionException {
        if (b == 0) {
            throw new DivisionException("Division by zero is not allowed.");
        }
        return (double) a / b;
    }

 장점과 단점


 2. 암시적 전달 

 코드를 호출하는 쪽에 오류를 알리지만, 호출하는 쪽에서 그 오류를 신경 쓰지 않아도 된다. 오류가 발생할 수 있음을 알기 위해서는 문서나 코드를 읽는 등의 적극적인 노력이 필요하며 이것은 코드 계약의 숨겨진 세부 조항이다.

 

 파이썬의 경우 명시적 전달 방법은 불가능하고, 암시적 전달만이 가능하다. 즉 아래의 calculate_division의 try-catch문을 제거하더라도 프로그램의 실행에 문제가 발생하지 않는다. 그렇기 때문에 암시적인 전달인 것이다.

import random

def calculate_division():
    dividend = random.randint(0, 100)
    divisor = random.randint(0, 10)
    
    # 오류 발생 가능성을 암시적으로 호출하는 쪽에 알림
    if divisor == 0:
        raise ZeroDivisionError("Division by zero")
    
    return dividend / divisor

try:
    result = calculate_division()
    print("Division result:", result)
except ZeroDivisionError:
    # 오류를 호출하는 쪽에 알리지만, 신경을 쓰지 않음
    # 오류 처리를 하지 않고 오류를 무시함
    print("An error occurred, but it is ignored.")

 장점과 단점

 3. 요약표

 

 

반응형

'Clean code' 카테고리의 다른 글

코드를 오용하게 어렵게 만들라  (0) 2023.07.10
코드 계약  (0) 2023.05.18
코드 추상화  (0) 2023.05.15
파이썬 데코레이터(Decorator)  (0) 2023.02.26
[Clean code] 클래스  (0) 2023.01.11