Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

The title is a bit vague so I'll try to elaborate.

I have a function

makeFoo(int bar) -> returns Foo or throws Exception.

I also have a batch version of this

makeFoos(int[] bars) -> returns Foo[]

which basically loops through bars and runs makeFoo() on them.

Issue is, if while running makeFoos(), makeFoo() throws an Exception, what do I do? I don't want to break out of makeFoos() because I want to continue processing the rest of the bars. But also, I want to retain the Exception that was thrown.

My initial solution is, instead of returning Foo[], I return Result<Foo>[]. Where Result is a wrapper class:

class Result<T>:
    T data;
    Exception e;

Is there a better way that I can approach this?


Edit: Apologies if this is considered a duplicate post, but I posted a more general version of this question here: Result Object vs. Exceptions

share|improve this question

3 Answers 3

Return an array of Optional. That aside, you might want to consider better collections than arrays; they're quite cumbersome, especially since they don't implement Iterable or Collection.

EDIT: For catching the type of the error, your Result<T> is a good starting point, but I wouldn't expose both fields like that (I assume you only did that to get the idea accross.) Result, or as it's known in functional languages, Either, is only marginally different from Optional, so your final design should have roughly the same API. In particular, you definitely want to implement flatMap so you can easily chain computations on Results without having to do this:

Result<T1> result1 = foo();
if (result1.isValue()) {
    T1 value1 = result1.getValue();
    Result<T2> result2 = bar(value1);
    if (result2.isValue()) {
        T2 value2 = result2.getValue();
        Result<T3> result3 = baz(value2);
        if (result3.isValue()) {
            ...
        } else {
            result3.getError();
        }
    } else {
        result2.getError();
    }
} else {
    result1.getError();
}

Normally I'd say you might want to parametrize the Result type over the type of error too, since you may not always want to return an exception, but with Java's practically non-existent type inference it'd just make the whole thing even more cumbersome.

You might want to look at this question for an alternative to implementing Result's API that doesn't involve calling getValue() if and only if isValue() returns true.

share|improve this answer
    
Optionals are an interesting... Paradigm (or whatever you might call it) but it won't work as it is for me since I'd like to retain the exception thrown, or at least the error message associated with it. Also I am, already using collections, I just wanted to use arrays as a short form of asking my question. Thanks for the advice tho! –  kennyg Jul 7 at 22:44
    
Returning a typed object like Result<> is fine. This is exactly the principle behind Java 8's new Optional. When you use your custom wrapper object, you can be more free in edit/modify things the way you want –  InstructedA Jul 8 at 3:22

The simple apporach is to just fail when one of the bars fail. But if you want to process the entire list of bars, then you will need a more complex object that contains arrays like:

  • SuccessfulFoos[]
  • FailedBars[]

FailedBars would be a composite object and would encapsulate the error information as well. SuccessfulFoos would just be a Foo since no error occurred.

share|improve this answer
    
This seems almost more complex than my original approach? As now I have to return (and process) a pair of arrays, and of different types... –  kennyg Jul 7 at 22:46
    
Your asking to keep track of the successes and failures, so yes, both type of objects are returned. If one is processing a batch, certainly knowing what items succeeded and/or failed would be important. –  Jon Raynor Jul 8 at 17:40

In all honesty, I like your answer best. The return array should be the same size as the input array, so you can easily determine which inputs resulted in which outputs. You can also loop through the results array and check to see if the exception is null or not, and if not, then process the result.

Another way to do this would be to pass in an array that has the input parameters, the output result, and an exception all in one area. In that case, you could return the number of exceptions (or non-exceptions, or the first exception), and you could get a quick check on if everything worked. For example:

class BatchedFoo
{
    int i;
    Foo data;
    Exception e;
}

makeFoos(BatchedFoo []) -> returns int
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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