1

I need a solution for decision making chain. There are number of criteria that may return true, false or be inconclusive. A non-functional code (Java) would look like this:

Boolean res = nullValuesCheck(fieldValue, node);
if (res != null) {
    return res;
}
res = typeCheck(node);
if (res != null) {
    return res;
}
res = dictCheck(dict, fieldValue);
if (res != null) {
    return res;
}
return finalCheck(fieldName, fieldValue); //also returns a Boolean

I'm considering creating an extended predicate that would return a nullable Boolean instead of boolean, so that an inconclusive result could be returned.

I tried googling, but found no apparent solution (got lot of mishits on some simple java problems instead). I am wondering whether there exists a pattern, a library maybe, that would handle this problem properly. The problem seems generic and simple to solve and someone must've solved it already. I don't want to reinvent the wheel.

1
  • What you're describing sounds like Trinary Logic, you might be able to find more by searching for that!
    – Rowan
    Sep 28, 2020 at 11:52

4 Answers 4

3

I think you're looking for Optional.or(). As in:

check1()
.or(() -> check2())
.or(() -> check3())
.orElse(false)

Checks return Optional<Boolean>, so Optional.empty() if they don't decide, otherwise they contain the boolean decision. Result of the whole thing is a boolean with the first decision that was not empty, or the default value at the end if all were empty.

1

Your chain is a collection of checks, so why not treat it as such?

public interface ICheck
{
    bool? Execute();
}

public class NullValuesCheck : ICheck
{
    public NullValuesCheck(Value fieldValue, Node node)
    {
        //set fields
    }

    public bool? Execute()
    {
        // use fields
    }
}

public class CheckCollection
{
    public CheckCollection(params ICheck[] checks)
    {
        //save the collection
    }

    public bool? Execute()
    {
        bool? result = null;
        foreach (var check in checks)
        {
            result = check.Execute();
            if (result != null)
            {
                return result;
            }
        }
        return result;
    }
}

// in your code
return new CheckCollection(
    new NullValuesCheck(fieldValue, node),
    new TypeCheck(node),
    //...
).Execute();

That way, you avoid repeating the "check result and execute next if null" logic everywhere you have a chain of checks, and can define your chain in a more OO way. The example above is in C#, but I think the Java implementation would be fairly similar.

1
  • I have no problem making my own implementation, I wanted to know whether an implementation already exists and/or the pattern has na name. But thanks for your time!
    – Dariusz
    Sep 28, 2020 at 12:55
1

It's not quite clear why you need a fancier solution than what you've already sketched out. Is the list of checks long or dynamic or something?

You could return Optional<Boolean> instead of Boolean to make it clear the methods might not return a result. Then you could use Optional.orlike suggested in another answer.

If you have to deal with a long or dynamic list of checks then you could write a function that returns the first present result from a List of Suppliers:

<T> Optional<T> firstPresentResult(List<Supplier<Optional<T>>> suppliers) {
    return suppliers.stream()
            .map(x -> x.get())
            .filter(x -> x.isPresent())
            .findFirst()
            .orElse(Optional.empty());
}

Alternatively you could iterate:

<T> Optional<T> firstPresentResult(List<Supplier<Optional<T>>> suppliers) {
    for (Supplier<Optional<T>> s: suppliers) {
        if (s.get().isPresent()) {
            return s.get();
        }
    }
    return Optional.empty();
}

Then you could feed the method with a list of checks

return firstPresentResult(
        Arrays.asList(
                () -> nullValuesCheck(fieldValue, node), 
                () -> typeCheck(node),
                () -> dictCheck(dict, fieldValue),
                () -> finalCheck(fieldName, fieldValue)
            )
        );
-3

It can be reduced to one expression with

Boolean res;
return ((res= nullValuesCheck(fieldValue, node)) != null)
    ? res
    : ((res= typeCheck(node)) != null)
        ? res
        : ((res= dictCheck(dict, fieldValue)) != null)
            ? res
            : finalCheck(fieldName, fieldValue);
1
  • 6
    I wouldn't do this to my worst enemy.
    – Polygnome
    Sep 28, 2020 at 17:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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