3

Say, I have a function, RegisterUser() which takes in an user's registration details such as their username, name and password and registers them if there is no invalid data. For such functions, it is important to report all errors at once, instead of stopping at the very first test at which validation fails.

An exception is probably out of the question here, since the general practice is to immediately throw them once an error is encountered. The only way I could think of doing this is using an integer field where various error values are ORed and returned; however, I haven't really seen this being used anywhere; not to mention the very complicated and confusing code that the handling would require:

rv = RegisterUser(...)
err_msg = []

if (rv != 0) {
  err_msg_lookup_table = ["The username was invalid.", "That username is already taken up.", ...]

  for (i = 1; i < MAX_INT_VAL; i *= 2) {
    if (rv & i == i) {
      err_msg.push(err_msg_lookup_table[log(i, 2)])
    }
  }

  ShowMessage(err_msg)
}

Is there a better way to do it?


This is a dupe but doesn't have answers.

  • What stops you from setting all error information in a throwing object? – BЈовић Oct 5 '16 at 11:59
4

Why not tie your error messages up in a collection in a custom exception, and throw that exception upon completion ? Your receiving code can then catch the exception and iterate the collection to report the errors. I would record the errors separately rather than concatenate them (that sounds like a presentation issue)

An alternative is to use something like a Scala Either structure, which you could return from the method. Your Either implementation would (as the name suggests) return the successful results of that method, or a collection of errors.

2

Building a "validation result" object is a good middle ground, if exceptions get too messy.

public class ValidationResult
{
    public ValidationResult()
    {
        errorMessages = new List<string>();
    }

    public bool IsValid { get; private set; }

    private List<string> errorMessages;

    public IEnumerable<string> ErrorMessages
    {
        get { return errorMessages; }
    }

    public void AddErrorMessage(string errorMessage)
    {
        IsValid = false;
        errorMessages.Add(errorMessage);
    }
}

Then you can build up your validation result as you validate different fields or properties:

ValidationResult result = new ValidationResult();

if (name == null)
    result.AddErrorMessage("The 'Name' field is required");

if (age < 18)
    result.AddErrorMessage("The 'Age' field must be greater than or equal to 18");

return result;

Then you can process those results:

ValidationResult result = x.Validate();

if (result.IsValid)
{
    // Save to database
}
else
{
    // Show result.ErrorMessages to the user
}

Note: My code is in C#, as you didn't specify which language your code examples were written in.

0

As you said the handling is "very complicated and confusing".

My suggestion is that you add a public String[] getErrorMessage() to the class responsible of registering the user.

Take into account though that some errors won't allow further steps to be taken so the list of errors would be incomplete since steps that would have also failed would have not been attempted.

Another option is creating a custom exception, containing all error messages and throwing it at the very last moment. That way calling code would do e.getErrorMessages().

0

Are you going to do anything with the errors other than display them to the user? If not, what I usually do is simply build a string containing the text of all the errors. Like:

StringBuilder errors=new StringBuilder();
if (find_name(new_user_name)) {
  errors.append("User name already in use<br/>";
}
if (password.length==0) {
  errors.append("Password required<br/>");
}
if (prettiness(favorite_color)<20) {
  errors.append("Favorite color is not pretty enough<br/>");
}
... whatever other tests ...
if (errors.length>0) {
  showError(errors);
} else {
  processRegistration();
}

(I put br's after each error here on the idea that we're going to display them on a web page.)

I've had a few cases where I've created a collection of some kind and added the error messages to the collection, but in retrospect this gains nothing. I still have to append the strings together for display.

If you're returning errors from a function, and the caller may try to do something about the errors rather than just display them, that's a whole different story. I'm hard-pressed to think of a time when I've had to do that, but I think then I'd create a collection of error codes, and have the error codes defined as enum's.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.