We frequently have objects that perform multi-part operations/tasks. An example would be refreshing internal state of a list of objects based on a query of the file system and reading data from the found files. These things are also often long running, and tend to be performed in background threads (we do a lot of Swing work, but I think this sort of thing would apply to multi-tier apps as well).
In this sort of operation, it's quite possible that part of the operation would fail (i.e. unable to read 5 or 6 of the 5000 files that we are processing). In this case, it would be inappropriate to throw an exception, but we still want to provide the user with feedback about what didn't happen, etc...
We've always used ad-hoc approaches here (e.g. logging, or have the operation return a list of exceptions), but I've decided to crack down and really think this through.
One motivating concept is Validation (jgoodies has a good implementation). The idea here is that when validating the values in a form or data structure, you construct a ValidationResults object, which can contain ValidationResult objects. Each ValidationResult has a state (OK, WARN, ERROR) as well as descriptive text (and other things as necessary).
I am highly tempted to just use the Validation framework as-is for task results.
Another option would be to expose the current operation result state of the task as a bound property (probably using a GlazedLists event list).
I was wondering if anyone else has any opinions/experience with this sort of thing, or what design patterns may have evolved to deal with long running tasks that can have sub-tasks that may fail, or not quite complete perfectly (i.e. the WARN state) ?
EDIT: Clarification on purpose of the question
A lot of folks have suggested logging the problems and telling the user to check with an administrator. To clarify the problem a bit, consider an application like Eclipse. If the build process had warnings or errors, and Eclipse just gave an error dialog saying 'there were problems, check the logs', I think the user would be less than satisfied.
Presenting the user with a list of the current warnings and errors is a much more interactive solution, and provides the user a mechanism for quickly evaluating and addressing the issues.
The two approaches that we'd tried so far have been:
- Logging and tossing a dialog box at the end of the process
- Exposing a property containing the exceptions that have occured
We are trying to move away from option 1 b/c of the user experience.
Option 2 feels extremely ad-hoc to me. It certainly works, but I'm trying to find a good, standardized methodology for addressing this situation.
Exceptions are good for routines that have 'stop the world' failures (the routine either succeeds or fails in some way), and throwing exceptions is a very nice cross-cutting mechanism for handling those situations.
But when a routine doesn't fall into a simple pass/fail categorization, things get a bit fuzzy - the routine itself can partially succeed.
So, is it better to pass in a 'ProblemListener' that we report issues to? Or is it better to have the routine return a list of problems? Or have the object expose a property of issues from the last run of the routine?
There are many potential solutions - I'm wondering if anyone has experience with trying these, and have they found a best practice (and what reasons they accept or reject a given approach)?