1

I am developing a (Java) library providing an API to read a file in a specific format into an object. The format is basically a map, and specifies valid values for some of the keys, and valid types for values for others.

E.g., the value for colour may only be one of red, green or blue, while the key date must be provided in YYYY-MM-DD format.

Also, the file in this format must have a specific name.

Obviously, the API could be used with invalid data, e.g., a file of the wrong name, or a file containing invalid values, e.g., colour: orange or date: last year.

Additionally, the API will have to deal with scenarios such as non-existing files, files in completely different formats, etc.

Are there best practices for this kind of scenario? E.g., should I throw runtime exceptions for the latter kind of issues (other format, file not found, I/O exception) that I catch during the read, and custom exceptions for the other issues (invalid file name/values)?

Or should I return some sort of result object wrapping, e.g., the data object when it is valid and has been successfully read, or a list of error messages collected during the read when something went wrong? (Should the respective other fields then be null or contain an empty value?)

4

Exceptions exist for a reason. The reason is to be able to signal that a method cannot fulfil its documented purpose. If your input data do not conform to the standard that the method has published, then this is absolutely a reason to raise an exception.

The alternative (return a type-conformant, but special value that the caller has to remember to check for) is inferior in every respect. It is easier to misuse (just forget the error check). It is harder to read: the error-checking code muddles the semantics of every call to the method, while a catch FormatException is pretty explicit about what it does. It is easier to delegate error handling to a place more suited for it (just let the exception bubble up).

In short, this is a textbook case for the kind of unexpected, unfixable event that exceptions were invented for. Use them; accept no substitute.

  • 1
    Well, TryParse() and the like exist for a reason: They are easier to use and more efficient if failure to parse is expected and will be handled immediately. – Deduplicator Feb 5 '18 at 21:30
0
  1. You ask:

    Or should I return some sort of result object wrapping, e.g., the data object when it is valid and has been successfully read, or a list of error messages collected during the read when something went wrong? (Should the respective other fields then be null or contain an empty value?)

    This highly depends on your use case. If you can do something useful with data parsed before an error occurred or if they are useless because not the whole file could be parsed.

  2. runtime exceptions vs. checked exceptions:

    This is source of highly emotional discussions. You will find plenty of arguments for both on the www.

My opinion on this case is:

  • No matter what you / or others think, try to make the whole library behave similarly.
  • If you are free in your decision, set up a meeting with the whole developer team to come up with a design decision that will then be used as a standard by the whole team
  • I prefer to use RuntimeExceptions but if not handling the error at all makes no sense, You may consider a checked exception.
-1

I absolutely support Kilian's answer: If your reader can't completely fulfill its task, throw an exception.

Then there's the question which exception class to use. Short answer: the exception class doesn't matter.

What do you expect your library users to do with your failure notice (= exception)? Typically, they want to

  • log the exception
  • inform the user
  • try some alternative (incl. retries)

Logging doesn't care about the exception class, just provide a decent message, and the logging will be fine.

Informing the user in a user-friendly way while giving specific information about the exception is close to impossible, as it needs a complete mapping of all exception types to friendly messages. So I bet most applications either wrap the exception class and message into some template text, or just give a message like "Error when executing xy". So, what's important here is again the message.

Trying some alternative is something I can hardly imagine with a file reader library. In theory, an application might have a second, fallback file that it could read in case the first attempt fails, but I wouldn't expect that. And if the first attempt fails, the application would try the second one anyway, no matter what the failure reason was. Once again, the exception type hardly matters.

Retrying the call that failed can make sense if the exception implies some temporary problem. So, here application code is interested in knowing about that, maybe by introducing a base exception class like RetryableException. If you see a situation where a retry has a good chance to succeed, do it that way (but I don't see that with a file reader).

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.