简体   繁体   中英

Would it be appropriate to throw exceptions for login/register errors?

At first for my login/register form in C#, I had created enumerations for the login errors and the register errors, so that the login method returned an enumeration and if it was for example "LoginErrors.None" then the program continued. However I was wondering if it would be more appropriate to throw exceptions, ie an ArgumentNullException if the username parameter is " " or null.

What is most appropriate in this situation?

Exceptions are generally not used for validation purposes. You should validate any of your login errors yourself.

Exceptions are slow and don't serve any better purpose than your own validation, so it sounds like you did it right the first time.

Bad practice. Try to validate as exceptions are never made for these purposes. Go for validations

I think i'm very aligned to this answer here:

https://stackoverflow.com/a/52322/2740778

Catch exceptions at rare or exceptional scenarios. Validating an user, or checking empty inputs, etc are all common stuff to deal with.

IMO i think that the language provides enough flux control without the usage of Exceptions for this goal.

First of all, if the login name is null probably is a bug because I don't think that an input from the UI could store a null value. Something could be wrong in some layer on top of your login code.

For above case, and only for that case, I would throw an ArgumentNullException . In my case, I would use code contracts .

Anyway, I'll give you a hint: I would turn login information into a class, and I would implement the specification pattern to validate it. Also, see how I implement parameter and return value validation using code contracts (design by contract) :

public class UserLogin
{
     public string Name { get; set; }
     public string Password { get; set; }
}

public class UserLoginSpec
{
       // This could be a simplified way of storing broken rules,
       // where keys are the affected resource or property by the
       // rule, and the value, a human-readable description of what
       // happened with the broken rule...
       public Dictionary<string, string> BrokenRules { get; } = new Dictionary<string, string>();

       public bool IsSatisfiedBy(UserLogin login)
       {
            Contract.Requires(login != null);

            if(string.IsNullOrEmpty(login.Name))
                 BrokenRules.Add("Name", "Name cannot be empty");

            if(string.IsNullOrEmpty(login.Password))
                 BrokenRules.Add("Password", "Password cannot be empty");

            // The spec is passed if no broken rule has been added
            return BrokenRules.Count == 0;
       }
}

public class UserLoginResult
{
      public UserLoginResult(UserLoginSpec spec)
      {
            Contract.Requires(spec != null);

            Successful = spec.BrokenRules.Count == 0;
            Errors = spec.BrokenRules;
      }

      public bool Successful { get; private set; }
      public Dictionary<string, string> Errors { get; private set; }
}

Now your authentication method would look as follows:

public UserLoginResult Authenticate(UserLogin login)
{
     Contract.Requires(login != null);
     Contract.Ensures(Contract.Result<UserLoginResult>() != null);

     UserLoginSpec loginSpec = new UserLoginSpec();

     if(loginSpec.IsSatisfiedBy(login))
     {
          // Actual code to validate user's credentials here
     }

     return new UserLoginResult(loginSpec);
}

Now you can go further and generalize this solution, or add more collected data in your result classes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM