programing tip

예외 또는 오류 코드에 대한 규칙

itbloger 2020. 7. 30. 10:07
반응형

예외 또는 오류 코드에 대한 규칙


어제 저는 어떤 오류보고 방법이 바람직한 지 동료와 격렬한 토론을 벌였습니다. 주로 애플리케이션 계층 또는 모듈 간의 오류보고를위한 예외 또는 오류 코드 사용법에 대해 논의했습니다.

오류보고를 위해 예외를 던지거나 오류 코드를 반환할지 여부를 결정하기 위해 어떤 규칙을 사용합니까?


높은 수준의 물건에서 예외; 하위 수준의 오류 코드

예외의 기본 동작은 스택을 풀고 프로그램을 중지하는 것입니다. 스크립트를 작성하고 사전에없는 키를 사용하는 경우 오류 일 가능성이 있으며 프로그램을 중지하고 보자 그것에 대해 모두 알고 있습니다.

그러나 가능한 모든 상황에서 동작을 알아야 하는 코드를 작성하는 경우 오류 코드가 필요합니다. 그렇지 않으면 함수의 모든 줄에서 발생할 수있는 모든 예외를 알아야 그 기능을 알 수 있습니다 ( 이것이 얼마나 까다로운 지 알기 위해 항공사접지 한 예외를 읽으십시오 ). 모든 상황 (행복하지 않은 상황 포함)에 적절하게 반응하는 코드를 작성하는 것은 지루하고 어렵지만, 이는 오류 코드를 전달하는 것이 아니라 오류가없는 코드를 작성하는 것이 지루하고 어렵 기 때문입니다.

Raymond Chen Joel모두 예외를 사용하는 것에 대해 웅변적인 주장을했습니다.


나는 일반적으로 예외가 더 문맥 정보가 많고 오류를보다 명확하게 프로그래머에게 전달할 수 있기 때문에 예외를 선호합니다.

반면에 오류 코드는 예외보다 가벼우 나 유지하기가 어렵습니다. 실수로 오류 검사를 생략 할 수 있습니다. 모든 오류 코드가있는 카탈로그를 유지 한 다음 결과를 켜서 발생한 오류를 확인해야하기 때문에 오류 코드를 유지하기가 더 어렵습니다. 오류 범위가 도움이 될 수 있습니다. 관심있는 유일한 것이 오류가 있는지 여부 만 확인하는 것이 더 간단하기 때문입니다 (예 : 0보다 크거나 같은 HRESULT 오류 코드는 성공 및 0보다 작은 것은 실패입니다). 개발자가 오류 코드를 확인하도록 프로그램 적으로 강제하지 않기 때문에 실수로 생략 할 수 있습니다. 반면, 예외는 무시할 수 없습니다.

요약하면 거의 모든 상황에서 오류 코드보다 예외를 선호합니다.


나는 예외를 선호하기 때문에

  • 그들은 논리의 흐름을 방해
  • 더 많은 기능을 제공하는 클래스 계층 구조의 이점
  • 올바로 사용되면 광범위한 오류를 나타낼 수 있습니다 (예 : InvalidMethodCallException도 LogicException입니다. 두 가지 모두 런타임에 감지해야하는 버그가있는 경우 발생합니다)
  • 그것들은 오류를 향상시키는 데 사용될 수 있습니다 (즉, FileReadException 클래스 정의는 파일이 존재하는지 또는 잠겨 있는지 여부를 확인하는 코드를 포함 할 수 있습니다)

함수 호출자는 오류 코드를 무시할 수 있습니다. 예외는 적어도 어떤 식 으로든 오류를 처리하도록 강요합니다. 그들의 처리 버전이 빈 캐치 핸들러 (한숨)를 가지고있는 경우에도 마찬가지입니다.


오류 코드에 대한 예외는 의심의 여지가 없습니다. 오류 코드와 마찬가지로 예외에서와 동일한 이점을 얻을 수 있지만 오류 코드의 단점 없이도 더 많은 이점을 얻을 수 있습니다. 예외에 대한 유일한 노크는 약간 더 많은 오버 헤드가 있다는 것입니다. 그러나이 시대에는 거의 모든 응용 분야에서이 오버 헤드가 무시할만한 수준으로 간주되어야합니다.

다음은 두 기술을 논의, 비교 및 ​​대조하는 기사입니다.

더 읽을 거리를 제공 할 수있는 좋은 링크가 있습니다.


나는 두 모델을 섞지 않을 것입니다 ... 오류 코드를 사용하는 스택의 한 부분에서 예외를 사용하는 상위 부분으로 이동할 때 하나에서 다른 모델로 변환하기가 너무 어렵습니다.

예외는 "메소드 또는 서브 루틴이 요청한 작업을 수행하지 못하게하거나 방해하는 모든 것"에 대한 예외입니다. ... 불규칙성 또는 비정상적인 상황 또는 시스템 상태 등에 대한 메시지를 다시 전달하지 마십시오. 반환 값 또는 참조를 사용하십시오. (또는 밖으로) 매개 변수.

예외는 메소드의 기능에 의존하는 시맨틱으로 메소드를 작성 (및 활용) 할 수있게합니다. 즉, Employee 오브젝트 또는 Employee List를 리턴하는 메소드를 입력하여이를 수행 할 수 있으며이를 호출하여 사용할 수 있습니다.

Employee EmpOfMonth = GetEmployeeOfTheMonth();

오류 코드를 사용하면 모든 메소드가 오류 코드를 리턴하므로 호출 코드에서 사용할 다른 것을 리턴해야하는 경우 해당 데이터로 채워지도록 참조 변수를 전달하고 해당 값에 대한 리턴 값을 테스트해야합니다. 모든 함수 또는 메소드 호출에서 오류 코드를 처리하고 처리하십시오.

Employee EmpOfMonth; 
if (getEmployeeOfTheMonth(ref EmpOfMonth) == ERROR)
    // code to Handle the error here

각 메소드가 하나의 간단한 작업을 수행하도록 코드를 작성하는 경우 메소드가 원하는 목표를 달성 할 수 없을 때마다 예외를 처리해야합니다. 예외는이 방법으로 오류 코드보다 훨씬 풍부하고 사용하기 쉽습니다. 코드가 훨씬 깨끗합니다. "일반"코드 경로의 표준 흐름은 메소드가 원하는 작업을 수행 할 수있는 경우에만 엄격하게 사용할 수 있습니다. 그런 다음 코드를 정리하거나 처리합니다. 메소드가 성공적으로 완료되지 못하게하는 나쁜 일이 발생하는 "예외"환경은 일반 코드에서 분리 될 수 있습니다. 또한 예외가 발생한 위치를 처리 할 수없고 스택에 UI로 전달해야하는 경우 (또는 더 나쁜 경우, 중간 계층 구성 요소에서 UI 로의 연결을 통해) 예외 모델을 사용하면 님'


과거에는 오류 코드 캠프에 참여했습니다 (C 프로그래밍이 너무 많았습니다). 그러나 지금 나는 빛을 보았다.

예, 예외는 시스템에 약간의 부담입니다. 그러나 코드를 단순화하여 오류 수 (및 WTF)를 줄입니다.

따라서 예외를 사용하고 현명하게 사용하십시오. 그리고 그들은 당신의 친구가 될 것입니다.

부수적으로. 어떤 방법으로 어떤 예외를 던질 수 있는지 문서화하는 법을 배웠습니다. 불행히도 이것은 대부분의 언어에서 필요하지 않습니다. 그러나 올바른 수준에서 올바른 예외를 처리 할 가능성이 높아집니다.


깨끗하고 명확하며 올바른 방법으로 예외를 사용하는 것이 번거로운 상황이있을 수 있지만 대부분의 예외는 명백한 선택입니다. 예외 처리가 오류 코드를 능가하는 가장 큰 이점은 두 가지 이유로 중요한 실행 흐름을 변경한다는 것입니다.

예외가 발생하면 응용 프로그램이 더 이상 '정상적인'실행 경로를 따르지 않습니다. 이것이 매우 중요한 첫 번째 이유는 코드 작성자가 잘못되고 나쁘게 진행되지 않으면 프로그램이 중단되고 예측할 수없는 일을 계속하지 않기 때문입니다. 오류 코드가 확인되지 않고 잘못된 오류 코드에 대한 응답으로 적절한 조치를 취하지 않으면 프로그램은 수행중인 작업을 계속 수행하고 해당 조치의 결과가 무엇인지 누가 알 수 있습니다. 프로그램이 '무엇이든'수행하는 것이 매우 비싸 질 수있는 상황이 많이 있습니다. 회사가 판매하는 다양한 금융 상품에 대한 성과 정보를 검색하여 해당 정보를 중개인 / 도매 자에게 제공하는 프로그램을 고려하십시오. 문제가 발생하고 프로그램이 계속 진행되면 잘못된 성능 데이터를 브로커와 도매업자에게 배송 할 수 있습니다. 나는 다른 사람에 대해 모른다. 그러나 나는 내 코드로 인해 회사가 왜 7-figures 가치의 규제 벌금을 얻었는지 설명하는 VP 사무실에 앉아있는 사람이되고 싶지 않습니다. 고객에게 오류 메시지를 전달하는 것이 일반적으로 '실제'로 보일 수있는 잘못된 데이터를 제공하는 것이 바람직하며, 후자의 상황은 오류 코드와 같이 훨씬 덜 공격적인 접근 방식을 사용하기가 훨씬 쉽습니다.

내가 예외를 좋아하고 정상적인 실행을 깨는 두 번째 이유는 '정상적인 일이 일어나고 있습니다'라는 논리를 '뭔가 잘못 된 논리'와 분리하는 것이 훨씬 쉽고 쉽다는 것입니다. 나에게 이것은 :

try {
    // Normal things are happening logic
catch (// A problem) {
    // Something went wrong logic
}

... 이보다 바람직합니다.

// Some normal stuff logic
if (errorCode means error) {
    // Some stuff went wrong logic
}
// Some normal stuff logic
if (errorCode means error) {
    // Some stuff went wrong logic
}
// Some normal stuff logic
if (errorCode means error) {
    // Some stuff went wrong logic
}

예외에 관한 다른 작은 것들도 있습니다. 함수에서 호출되는 메소드 중 하나에 오류 코드가 리턴되었는지 여부를 추적하기위한 많은 조건부 논리를 보유하고 오류 코드를 더 높은 값으로 리턴하는 것은 많은 보일러 플레이트입니다. 실제로, 그것은 잘못 될 수있는 많은 보일러 판입니다. 나는 프레드가 쓴 'Fresh-out-of-college'프레드가 쓴 if-else-if-else 문장의 쥐 둥지를 만드는 것보다 대부분의 언어의 예외 시스템에 대해 훨씬 더 많은 믿음을 가지고 있으며, 할 일이 훨씬 더 많습니다. 쥐의 둥지를 검토하는 코드보다 내 시간.


둘 다 사용해야합니다. 문제는 각각을 사용할시기를 결정하는 것입니다 .

예외가 명백한 몇 가지 시나리오 가 있습니다 .

  1. 어떤 상황에서 당신은 오류 코드와 함께 아무것도 할 수 없어 , 당신은 단지 호출 스택의 상위 레벨에서 그것을 처리 할 필요가 대개 오류, 사용자 또는 가까운 프로그램 디스플레이 뭔가를 기록. 이러한 경우 오류 코드를 사용하면 오류 코드를 수준별로 수동으로 버블 링해야하므로 예외 처리가 훨씬 쉽습니다. 요점은 이것이 예상치 못한 다루기 힘든 상황을위한 것입니다.

  2. 그러나 상황 1 (예기치 않고 처리 할 수없는 일이 발생하지 않는 경우) 에 대해서는 상황 정보를 추가 할 수 있으므로 예외가 도움이 될 수 있습니다 . 예를 들어 하위 수준의 데이터 도우미에서 SqlException이 발생하면 하위 수준 (오류의 원인이 된 SQL 명령을 알고 있음)에서 해당 오류를 포착하여 해당 정보를 캡처하고 추가 정보로 다시 던질 수 있습니다. . 여기에 마법의 단어를 주목하십시오 : 다시 던지고 삼키지 마십시오 . 예외 처리의 첫 번째 규칙 : 예외를 삼키지 마십시오 . 또한 외부 캐치에는 전체 스택 추적이 있고 로그를 기록 할 수 있으므로 내부 캐치에는 아무것도 기록 할 필요가 없습니다.

  3. 어떤 상황에서는 일련의 명령이 있으며, 명령 중 하나라도 실패 하면 복구 할 수없는 상황 (발생해야 함) 또는 복구 가능한 상황인지에 관계없이 자원을 정리 / 폐기 (*)해야합니다. 로컬 또는 호출자 코드에서 처리하지만 예외는 필요하지 않습니다. 분명히 각 방법마다 오류 코드를 테스트하고 finally 블록에서 정리 / 처리를 수행하는 대신 모든 명령을 한 번에 시도하는 것이 훨씬 쉽습니다. 노트는 것을 제발 당신이 (당신이 원하는 아마 인) 거품까지 오류를 원한다면, 당신도 그것을 잡을 필요가 없습니다 - 당신은 정리 / 처분에 대한 마지막을 사용 - 당신이 원하는 경우에만 캐치 / retrow를 사용한다 상황에 맞는 정보를 추가합니다 (총알 2 참조).

    한 가지 예는 트랜잭션 블록 내의 일련의 SQL 문입니다. 다시 말하지만, 이것은 또한 "처리 할 수없는"상황입니다. 조기에 잡기로 결정한 경우에도 (맨 위까지 버블 링하는 대신 로컬로 처리) 여전히 최상의 결과가 모든 것을 중단하거나 적어도 중단하는 것이 치명적인 상황 입니다 과정의 일부.
    (*) on error goto이전 Visual Basic에서 사용한 것과 같습니다.

  4. 생성자에서는 예외 만 throw 할 수 있습니다.

호출자 CAN / SHOULD가 어떤 조치를 취하는 일부 정보를 리턴하는 다른 모든 상황에서 리턴 코드를 사용하는 것이 더 나은 대안 일 수 있습니다. 여기에는 예상되는 모든 "오류"가 포함됩니다. 아마도 이들은 즉시 호출자가 처리해야하며 스택에서 너무 많은 레벨을 버블 링 할 필요가 없기 때문입니다.

물론 예상되는 오류를 예외로 처리하고 즉시 한 단계 위의 catch를 수행 할 수 있으며 try catch에서 모든 코드 행을 포함하고 가능한 각 오류에 대해 조치를 취할 수도 있습니다. IMO, 이것은 더 장황하기 때문일뿐만 아니라, 특히 발생할 수있는 예외는 소스 코드를 읽지 않고는 명확하지 않으며, 깊은 방법에서 예외가 발생하여 보이지 않는 gotos를 생성 할 수 있기 때문에 나쁜 설계입니다 . 코드를 읽고 검사하기 어려운 여러 개의 보이지 않는 종료점을 만들어 코드 구조를 손상시킵니다. 다시 말해 예외를 흐름 제어 사용해서는 안됩니다다른 사람들이 이해하고 유지하기가 어렵 기 때문입니다. 테스트를 위해 가능한 모든 코드 흐름을 이해하기가 훨씬 어려울 수 있습니다.
다시 : 올바른 정리 / 처리를 위해 아무것도 잡지 않고 시험 사용을 할 수 있습니다 .

리턴 코드에 대한 가장 인기있는 비판은 "누군가 오류 코드를 무시할 수 있지만 같은 방식으로 누군가도 예외를 삼킬 수 있다는 것입니다. 두 가지 방법 모두에서 예외 예외 처리가 쉽지만 오류 코드 기반 프로그램을 작성하는 것이 훨씬 쉽습니다. 예외 기반 프로그램을 작성하는 것보다 어떤 이유 하나는 (이전의 모든 오류를 무시하기로 결정하면. 그리고 on error resume next), 당신은 쉽게 리턴 코드와 함께 그렇게 할 수 당신은 시도-이나 저전압의 상용구를 많이하지 않고 그렇게 할 수 없습니다.

리턴 코드에 대한 두 번째로 가장 인기있는 비판은 "거품이 어렵다"는 것입니다. 그러나 사람들은 예외가 회복 불가능한 상황에 대한 것이며 오류 코드는 그렇지 않다는 것을 이해하지 못하기 때문입니다.

예외와 오류 코드를 결정하는 것은 회색 영역입니다. 재사용 가능한 일부 비즈니스 메소드에서 오류 코드를 가져 와서 예외로 랩핑하여 정보를 추가 할 수도 있습니다. 그러나 모든 오류가 예외로 발생해야한다고 가정하는 것은 디자인 실수입니다.

그것을 요 ​​약하기:

  • 나는 예기치 않은 상황에 처했을 때 예외를 사용하고 싶습니다. 할 일이 많지 않으며 대개 큰 코드 블록이나 전체 작업 또는 프로그램을 중단하고 싶습니다. 이것은 예전의 "오류 고토"와 같습니다.

  • 발신자 코드가 조치를 취할 수있는 상황이 예상 될 때 리턴 코드를 사용하고 싶습니다. 여기에는 대부분의 비즈니스 방법, API, 유효성 검사 등이 포함됩니다.

예외와 오류 코드의 이러한 차이점은 예상치 못한 치명적인 상황에 대해 "공황"을 사용하고 규칙적인 예상 상황은 오류로 반환되는 GO 언어의 설계 원칙 중 하나입니다.

그러나 GO에 대해서는 다중 반환 값 도 허용 하는데, 이는 오류와 다른 것을 동시에 반환 할 수 있기 때문에 반환 코드 사용에 많은 도움이됩니다. C # / Java에서는 매개 변수, Tuples 또는 (내가 좋아하는) Generics를 사용하여 열거 형과 결합하면 호출자에게 명확한 오류 코드를 제공 할 수 있습니다.

public MethodResult<CreateOrderResultCodeEnum, Order> CreateOrder(CreateOrderOptions options)
{
    ....
    return MethodResult<CreateOrderResultCodeEnum>.CreateError(CreateOrderResultCodeEnum.NO_DELIVERY_AVAILABLE, "There is no delivery service in your area");

    ...
    return MethodResult<CreateOrderResultCodeEnum>.CreateSuccess(CreateOrderResultCodeEnum.SUCCESS, order);
}

var result = CreateOrder(options);
if (result.ResultCode == CreateOrderResultCodeEnum.OUT_OF_STOCK)
    // do something
else if (result.ResultCode == CreateOrderResultCodeEnum.SUCCESS)
    order = result.Entity; // etc...

내 메소드에 가능한 새로운 리턴을 추가하면 모든 호출자가 스위치 명령문에서 해당 새 값을 커버하는지 여부를 확인할 수도 있습니다. 예외를 제외하고는 실제로 그렇게 할 수 없습니다. 리턴 코드를 사용하면 일반적으로 가능한 모든 오류를 미리 알고 테스트합니다. 예외를 제외하고는 일반적으로 어떤 일이 일어날 지 모릅니다. 제네릭 대신 예외 내에서 열거 형을 감싸는 것이 대안이지만 (각 메서드가 throw 할 예외 유형이 분명한 한) IMO는 여전히 나쁜 디자인입니다.


여기 울타리에 앉아 있을지 모르지만 ...

  1. 언어에 따라 다릅니다.
  2. 어떤 모델을 선택하든 사용 방법에 일관성을 유지하십시오.

파이썬에서는 예외를 사용하는 것이 표준 관행이며 내 예외를 정의하게되어 매우 기쁩니다. C에서는 예외가 전혀 없습니다.

In C++ (in the STL at least), exceptions are typically only thrown for truly exceptional errors (I virtually never see them myself). I see no reason to do anything different in my own code. Yes it's easy to ignore return values, but C++ doesn't force you to catch exceptions either. I think you just have to get into the habit of doing it.

The code base I work on is mostly C++ and we use error codes almost everywhere, but there's one module that raises exceptions for any error, including very unexceptional ones, and all the code that uses that module is pretty horrible. But that might just be because we've mixed exceptions and error codes. The code that consistently uses error codes is much easier to work with. If our code consistently used exceptions, maybe it wouldn't be as bad. Mixing the two doesn't seem to work so well.


Since I work with C++, and have RAII to make them safe to use, I use exceptions almost exclusively. It pulls error handling out of the normal program flow and makes the intent more clear.

I do leave exceptions for exceptional circumstances though. If I'm expecting that a certain error is going to happen a lot I'll check that the operation will succeed before performing it, or call a version of the function that uses error codes instead (Like TryParse())


Method signatures should communicate to you what the method does. Something like long errorCode = getErrorCode(); might be fine, but long errorCode = fetchRecord(); is confusing.


My reasoning would be if you are writing a low-level driver that really needs performance, then use error codes. But if you're using that code in a higher-level application and it can handle a bit of overhead, then wrap that code with an interface which checks those error codes and raises exceptions.

In all other cases, exceptions are probably the way to go.


My approach is that we can use both, i.e. Exceptions and Errors codes at the same time.

I'm used to define several types of Exceptions (ex: DataValidationException or ProcessInterruptExcepion) and inside each exception define a more detailed description of each problem.

A Simple Example in Java:

public class DataValidationException extends Exception {


    private DataValidation error;

    /**
     * 
     */
    DataValidationException(DataValidation dataValidation) {
        super();
        this.error = dataValidation;
    }


}

enum DataValidation{

    TOO_SMALL(1,"The input is too small"),

    TOO_LARGE(2,"The input is too large");


    private DataValidation(int code, String input) {
        this.input = input;
        this.code = code;
    }

    private String input;

    private int code;

}

In this way i use Exceptions to define category errors, and error codes to define more detailed info about the problem.


Exceptions are for exceptional circumstances - ie, when they are not part of the normal flow of the code.

It's quite legitimate to mix Exceptions and error codes, where error codes represent the status of something, rather than an error in the running of the code per se (e.g. checking the return code from a child process).

But when an exceptional circumstance occurs I believe Exceptions are the most expressive model.

There are cases where you might prefer, or have, to use error codes in place of Exceptions, and these have been adequately covered already (other than other obvious constrains such as compiler support).

But going in the other direction, using Exceptions allows you to build even higher level abstractions to your error handling, that can make your code even more expressive and natural. I would highly recommend reading this excellent, yet underrated, article by C++ expert Andrei Alexandrescu on the subject of what he calls, "Enforcements": http://www.ddj.com/cpp/184403864. Although it's a C++ article the principles are generally applicable, and I have translated the enforcements concept to C# quite successfully.


First, I agree with Tom's answer that for high-level stuff use exceptions, and for low-level stuff use error codes, as long as it is not Service Oriented Architecture (SOA).

In SOA, where methods may be called across different machines, exceptions may not be passed over the wire, instead, we use success/failure responses with a structure like below (C#):

public class ServiceResponse
{
    public bool IsSuccess => string.IsNullOrEmpty(this.ErrorMessage);

    public string ErrorMessage { get; set; }
}

public class ServiceResponse<TResult> : ServiceResponse
{
    public TResult Result { get; set; }
}

And use like this:

public async Task<ServiceResponse<string>> GetUserName(Guid userId)
{
    var response = await this.GetUser(userId);
    if (!response.IsSuccess) return new ServiceResponse<string>
    {
        ErrorMessage = $"Failed to get user."
    };
    return new ServiceResponse<string>
    {
        Result = user.Name
    };
}

When these are used consistently in your service responses it creates a very nice pattern of handling success/failures in the application. This allows easier error handling in async calls within services as well as across services.


I would prefer Exceptions for all error cases, except when a failure is an expectable bug-free result of a function that returns a primitive datatype. E.g. finding the index of a substring within a larger string would usually return -1 if not found, instead of raising a NotFoundException.

Returning invalid pointers that might be dereferenced (e.g. causing NullPointerException in Java) is not acceptable.

Using multiple different numerical error codes (-1, -2) as return values for the same function is usually bad style, as clients might do a "== -1" check instead of "< 0".

One thing to keep in mind here is the evolution of APIs over time. A good API allows to change and extend failure behavior in several ways without breaking clients. E.g. if a client error handle checked for 4 error cases, and you add a fifth error value to your function, the client handler may not test this and break. If you raise Exceptions, this will usually make it easier for clients to migrate to a newer version of a library.

Another thing to consider is when working in a team, where to draw a clear line for alldevelopers to make such a decision. E.g. "Exceptions for high-level stuff, error codes for low-level stuff" is very subjective.

In any case, where more than one trivial type of error is possible, the source code should never use the numeric literal to return an error code or to handle it (return -7, if x == -7 ...), but always a named constant (return NO_SUCH_FOO, if x == NO_SUCH_FOO) .


If you work under big project, you can't use only exceptions or only error codes. In different cases you should use different approaches.

For example, you decide to use exceptions only. But once you decide to use async event processing. It is bad idea to use exceptions for error handling in this situations. But use error codes everywhere in application is tedious.

So my opinion that it is normal to use both exceptions and error codes simultaneous.


For most applications, exceptions are better. The exception is when the software has to communicate with other devices. The domain I work in is industrial controls. Here errors codes are preferred and expected. So my answer is that it does depend on the situation.


I think it also depends on whether you really need information like stack trace from the result. If yes, you definitely go for Exception which provide object full with lots of information about problem. However, if you are just interested in result and don't care why that result then go for error code.

e.g. When you are processing file and face IOException, client might interested in knowing from where this was triggered, in opening file or parsing file etc. So better you return IOException or its specific subclass. However, scenario like you have login method and you want to know it was successful or not, there either you just return boolean or to show correct message, return error code. Here Client is not interested in knowing which part of logic caused that error code. He just know if its Credential invalid or account lock etc.

Another usecase I can think of is when data travels on network. Your remote method can return just error code instead of Exception to minimize data transfer.


My general rule is:

  • Only one error could appear in a function: use error code (as parameter of the function)
  • More than one specific error could appear: throw exception

Error codes also don't work when your method returns anything other than a numeric value...

참고URL : https://stackoverflow.com/questions/253314/conventions-for-exceptions-or-error-codes

반응형