Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does code look when you don't use exceptions to control flow?

Tags:

c#

exception

I've taken the advice I've seen in other answered questions about when to throw exceptions but now my APIs have new noise. Instead of calling methods wrapped in try/catch blocks (vexing exceptions) I have out argument parameters with a collection of errors that may have occurred during processing. I understand why wrapping everything in a try/catch is a bad way to control the flow of an app but I rarely see code anywhere that reflects this idea.

That's why this whole thing seems so strange to me. It's a practice that is supposedly the right way to code but I don't see it anywhere. Added to that, I don't quite understand how to relate to client code when "bad" behavior has occured.

Here's a snippet of some code I'm hacking around with that deals with saving pictures that are uploaded by users of a web app. Don't sweat the details (it's ugly), just see the way I've added these output parameters to everything to get error messages.

public void Save(UserAccount account, UserSubmittedFile file, out IList<ErrorMessage> errors)
{
    PictureData pictureData = _loader.GetPictureData(file, out errors);

    if(errors.Any())
    {
        return;
    }

    pictureData.For(account);

    _repo.Save(pictureData);
}

Is this the right idea? I can reasonably expect that a user submitted file is in some way invalid so I shouldn't throw an exception, however I'd like to know what was wrong with the file so I produce error messages. Likewise, any client that now consumes this save method will also want to find out what was wrong with the overall picture saving operation.

I had other ideas about returning some status object that contained a result and additional error messages but that feels weird. I know having out parameters everywhere is going to be hard to maintain/refactor/etc.

I would love some guidance on this!

EDIT: I think the user submitted files snippet may lead people to think of exceptions generated by loading invalid images and other "hard" errors. I think this code snippet is a better illustration of where I think the idea of throwing an exception is being discouraged.

With this I'm just saving a new user account. I do a state validation on the user account and then I hit the persistent store to find out if the username has been taken.

public UserAccount Create(UserAccount account, out IList<ErrorMessage> errors)
{
    errors = _modelValidator.Validate(account);

    if (errors.Any())
    {
        return null;
    }

    if (_userRepo.UsernameExists(account.Username))
    {
        errors.Add(new ErrorMessage("Username has already been registered."));
        return null;
    }

    account = _userRepo.CreateUserAccount(account);

    return account;
}

Should I throw some sort of validation exception? Or should I return error messages?

like image 350
Nick Swarr Avatar asked May 28 '09 03:05

Nick Swarr


People also ask

Should you use exceptions as the control flow?

One of these common bad practices is using exceptions as the control flow. This should be avoided for two reasons: It reduces the performance of your code as a response per unit time, and it makes your code less readable. Let's start by looking at how one can use an exception as the control flow by viewing the following example code.

Why should I avoid using exceptions in my code?

This should be avoided for two reasons: It reduces the performance of your code as a response per unit time, and it makes your code less readable. Let's start by looking at how one can use an exception as the control flow by viewing the following example code. The business case for the code is:

What is the control flow of a program?

The control flow of a program is the order in which the statements are executed. Normal control flow runs from top to bottom of a file. An exception breaks the normal flow and stops the program. A stopped program can no longer interact with the user. Luckily JavaScript provides a way to anticipate and handle exceptions. 17.3.2.

What is the use of exception in JavaScript?

They are a universal control flow construct. In some languages, they are the only universal control flow construct. JavaScript, for example, has neither Continuations nor GOTO, it doesn't even have Proper Tail Calls. So, if you want to implement sophisticated control flow in JavaScript, you have to use Exceptions.


1 Answers

Despite the performance concerns, I think it's actually cleaner to allow Exceptions to be thrown out of a method. If there are any exceptions that can be handled within your method, you should handle them appropriately, but otherwise, let them bubble up.

Returning errors in out parameters, or returning status codes feels a bit clunky. Sometimes when faced with this situation, I try to imagine how the .NET framework would handle the errors. I don't believe there are many .NET framework methods that return errors in out parameters, or return status codes.

like image 57
Andy White Avatar answered Nov 13 '22 14:11

Andy White