Say we have a function that changes the password for a user on a system in an MVC application.
public JsonResult ChangePassword (string username, string currentPassword, string newPassword) { switch (this.membershipService.ValidateLogin(username, currentPassword)) { case UserValidationResult.BasUsername: case UserValidationResult.BadPassword:
membershipService.ValidateLogin() returns a UserValidationResult enumeration, which is defined as:
enum UserValidationResult { BadUsername, BadPassword, TrialExpired, Success }
As a defensive programmer, I would ChangePassword() method described above to throw an exception if there is an invalid UserValidationResult value from ValidateLogin() :
public JsonResult ChangePassword (string username, string currentPassword, string newPassword) { switch (this.membershipService.ValidateLogin(username, currentPassword)) { case UserValidationResult.BasUsername: case UserValidationResult.BadPassword: // abort: return JsonResult with localized error message // for invalid username/pass combo. case UserValidationResult.TrialExpired // abort: return JsonResult with localized error message // that user cannot login because their trial period has expired case UserValidationResult.Success: break; default: throw new NotImplementedException ("Unrecognized UserValidationResult value."); // or NotSupportedException() break; } // Change password now that user is validated }
I have always considered a pattern similar to the last fragment to be superior to best practice. For example, what if one developer receives a requirement that now that users are trying to log in, if for this reason they should first contact the business? Thus, the definition of UserValidationResult updated as follows:
enum UserValidationResult { BadUsername, BadPassword, TrialExpired, ContactUs, Success }
The developer changes the body of the ValidateLogin() method to return a new enum value ( UserValidationResult.ContactUs ), if applicable, but forgets to update ChangePassword() . Without exception, in the switch, the user is still allowed to change his password when their attempt to enter the system should not be checked first!
Is it just me, or is it default: throw new Exception() good idea? I saw this a few years ago, and always (after he did it) suggested that this is best practice.