Best Practice Return Value vs Exception vs Enum [closed]

主宰稳场 提交于 2020-01-01 04:18:10

问题


I am trying to find out the advantages and disadvantages for a method with multiple result values.

For example I'm using a login-method. If the login was successful, it will pass, otherwise I need to know why it failed.

1. Return true or false (Not enough information)

bool Login(string user, string password);

2. Return true, if it was successful, otherwise throw an exception

public class UnknownUserException : Exception { }
public class WrongPasswordException : Exception { }
bool Login(string user, string password);

3. Return nothing. Throw an exception, if it wasn't successful

public class UnknownUserException : Exception { }
public class WrongPasswordException : Exception { }
void Login(string user, string password);

4. Return an enum value

enum LoginResult
{
    Successful
    UnknownUser,
    WrongPassword
}
LoginResult Login(string user, string password);

"Login" is just one example case. I would like to know what the advantages and disadvantages of the different implementations is, and for which cases they are more or less appropriate.


回答1:


Of course it depends on the certain situation but let me provide a couple of my subjective comments here:

  1. I'm sure such cases should be avoided. The name of the method points that it just performs any operation like "Login". According to the method name we can't expect any result here. Is you'd like the method to return bool value it's much better to name it like IsLoggedIn(userName). In addition you'll never know if you need to extend the set of values being returned. So the enum is much better here also taking in account that the aim of the value is reflected in the enum name rather than simple bool.

  2. The same as above. Exceptions here help to stop the whole execution hierarchy (which can of course contain more than 1 method in call stack) instead of just returning the result and let the caller to make appropriate decision. More flexible solution as for me. In the current case I'd use exceptions for parameters validation only. Situations like "wrong user name/password" are not exceptional. They are normal from the use cases point of view. null parameter or wrong parameter format are exceptional cases.

  3. If you don't need the method to return a value, that is the way to go. Do not forget you shouldn't use exceptions as a navigation. I mean UserSuccessfullyCreatedException or so.

  4. As I mentioned above, that is the best way as for me. The single point is not to place validation exceptions as a enum values. You have exceptions for it.

So enum result plus exceptions for validation is a way to go.

If you'd like to collect all the errors during the method execution you'll probably like to create special LoginOperationResult class to wrap all the information (including validation errors` occured during the method execution.

class OperationResult
{
    public OperationStatus Status { get; set; }

    public IEnumerable<ValidationError> Errors { get; set; }
    // or list of exceptions
}

class LoginOperationResult : OperationResult
{
    // Login result specific data.
}

enum OperationStatus
{
    Success,
    Denied,
    ValidationFailed,
    // etc.
}



回答2:


You'll get more opinionated answers, If I were doing I'll combine 3 & 4. Throw LoginFailedException with an enum saying why.

void Login(string user, string password);//Or return a bool(redundant though)

class LoginFailedException : ApplicationException
{
    public LoginFailReason Reason {get; private set;}
    public LoginFailedException(LoginFailReason reason)
    {
       this.Reason = reason;
    }
}

enum LoginFailReason
{
    UnknownUser,
    WrongPassword
}

Reason to choose exception option: Assume you choose return value only approach, users of your api(may be client, or other developers) can get a chance to overlook the API.

instance.Login(user, password);
var accountInfo = instance.GetAccountInfo();//Assuming logged in; going to explode

Who knows they have to do like this

if(instance.Login(user, password) == LoginResult.Successful))
{
    var accountInfo = instance.GetAccountInfo();
}

So, IMO throw exception in face saying I can't process your login request due to so and so reason. Make it simple.




回答3:


Definitely not exceptions. A failed login is hardly an "exceptional" case and it just a normal course of logic for the application. If you use an exception then you'll always have to wrap logging in with an exception handler for no other reason than to handle the case of a failed login. That seems like the very definition of using exceptions for logic flow, which isn't right.

If you need to return specific information (which isn't always necessary from a login function, but might be in your case), #4 seems reasonable. You could take it a step further and make it an object:

public class LoginResult
{
    // an enum for the status
    // a string for a more specific message
    // a valid user object on successful login
    // etc.
}

Or, depending on the logic for it, an immutable struct instead of a class. (Make sure the struct is immutable, mutable structs are just asking for trouble.) The point being that you can apply all sorts of logic and functionality on the result object itself, which seems to be the direction you're heading.




回答4:


I usually use this approach in my projects:

signature:

bool TryLogin(string username, string password, out User user);

usage:

User user;
if(userService.TryLogin(username, password, out user)))
{
    // do stuff with user
}
else 
{
    // show "login failed"
}

You could expand this to return your Enum:

signature:

enum LoginResult
{
    Successful
    UnknownUser,
    WrongPassword
}

LoginResult TryLogin(string username, string password, out User user);

usage:

User user;
LoginResult loginResult;
if((loginResult = userService.TryLogin(username, password, out user)) == LoginResult.Successful)
{
    // do stuff with user
}
else 
{
    // do stuff with loginResult
}


来源:https://stackoverflow.com/questions/22807483/best-practice-return-value-vs-exception-vs-enum

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!