开发者

When is better to throw an exception and when is better to return some error log 'object'?

I was wondering how to decide between :

1) If to throw custom exceptions OR

2) return a kind of LOG object that has flags like 'CityNotFound,' 'ReferenceConstraintBroken' etc.

I have been reading the exceptions are expensive. If I just need to know specific details of a process result, to me it sounds more beneficial to have a custom 'process LOG o开发者_运维百科bject' that contains only the necessery information of a process.

So, if I come back to my question:

When is better to throw an exception and when is better to return some error log 'object' ?


Throw an exception to provide more information (type of exception, message, etc.) for proper handling and to signify that:

  1. your code is being used inappropriately / illegally
    1. i.e. against contractual constraints that cannot be enforced during compile time
  2. an alternative to the primary flow has occurred
    1. i.e. you expected an operation to succeed but it failed, like obtaining a resource or connection

I would actually discourage returning "log objects" (i.e. returning an exception object rather than throwing one) as this

  1. results in unnecessary mashes of if statements to check the result AND handle a potential error
    1. all your methods would have to return of a "log object" (or have an out param) or else you cannot "bubble up" the error/exception for scoped handling, resulting in further limitations
  2. loses the helpfulness of try/catch/finally
  3. hurts readability of scope (operation attempt vs error handling vs clean up)

If you want to return "log objects", you should really use boolean returns with methods that makes sense (i.e. FindCity) or methods with an out boolean parameter (i.e. TryFindCity). This way, you don't need to specify flags, but just use the methods whose boolean return allows you to determine the would-be flag value.

EDIT

Per OP's comment, if there is a giant method with numerous possible validation errors, then the giant method should be refactored to call smaller methods that each throw the appropriate exception. The giant method can then simply re-throw each exception or just allow each exception to bubble up if it shouldn't be the one handling it.

If there are validation dependencies that prevent "proper separation", then simply throw a single ValidationException with the proper argument(s). An example of what this class could be is below:

public class ValidationException : Exception {
    private readonly object _Field;
    public object Field { get { return _Field; } }

    public ValidationException(string message) : base(message) { }

    public ValidationException(string message, object field)
        : this(message) {
        _Field = field;
    }
}

Then you can just throw one exception explaining the validation error.


If you're concerned about the performance of exceptions, you could factor towards the "tester-doer" pattern, which can be used to avoid them in most cases (it also makes the code more readable than a try/catch in my opinion).

// Traditional try catch
try
{
    var record = myDb.myTable.Select(primaryKey);

    // do something with record...
}
catch (RecordNotFoundException)
{
    // The record not found in the database... what to do?
}

// Tester-doer pattern
if (myDb.myTable.RecordExists(primaryKey))
{
    var record = myDb.myTable.Select(primaryKey);

    // do something with record...
}
else
{
    // The record not found in the database... what to do?
}

Same result, no exceptions. The cost is you have to write the "RecordExists" function yourself, usually it would be as simple as doing something like return COUNT FROM myTable WHERE PrimaryKey=foo == 1


To turn things on thier head slightly. Consider, do I know how to handle this condition within the function and will the code be called frequently enough to make writing it worth while or, more generally, is this exceptional?

If the case occurs in the routine operation of your function then handle it as part of your return value. If it occurs because your function has been misused or some resource is unavailable throw an exception.


If the caller could have prevented an exception (like knowing that the city doesn't exist), throw an exception. Otherwise return an error.

I would never return a log object. It makes the code unreadable since you have to add if statements and special handling everywhere. It's better to add methods like CheckIfCityExists.


Generally speaking you would return an exception, only when something absolutely unexpected occurs. If its a condition you are aware of and can happen then you should try and handle it either by sending an error code or better still, format your code in smaller fragments,

Example

  1. Method call to check if the City is Found
  2. Proceed to other statements
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜