2
\$\begingroup\$

I want to create wrapper for boolean type to not use more if statements. Can you tell me that this class make sense?

public final class Bool {

    private boolean value;

    private Bool(boolean value) {
        this.value = value;
    }

    public static final Bool of(boolean value) {
        return new Bool(value);
    }

    public static final Bool ofFalse() {
        return new Bool(false);
    }

    public static final Bool ofTrue() {
        return new Bool(true);
    }

    public OrElse ifTrue(Procedure procedure) {
        if (value)
            procedure.invoke();
        return new OrElse(!value);
    }

    public OrElse ifFalse(Procedure procedure) {
        if (!value)
            procedure.invoke();
       return new OrElse(value);
    }

    public class OrElse {
        private boolean value;

        private OrElse(boolean value) {
            this.value = value;
        }

        public void orElse(Procedure procedure) {
            if (value)
                procedure.invoke();
        }
    }
}

Example usage:

public Bool findElement(String name) {
    for(Element el : elements) {
       if(el.getName().equals(name)) return Bool.ofTrue();
    }
    return Bool.ofFalse();
}


// And now in other place of code I may use:
findElement("el").ifTrue(() -> doSomething).orElse(() -> doSomethingElse)
\$\endgroup\$
2
  • \$\begingroup\$ Is this for production code or just for fun (your motivation is important to answer the question; If it's just for fun, people can focus on design, etc; if it's for production, you should expand on your explanation, otherwise people will just tell you not to do this (performance, readability, etc.))? And can you also post Procedure? And maybe a usage example or unit tests? It would help readers of your question to understand what your code tries to achieve. \$\endgroup\$
    – tim
    Commented Apr 7, 2017 at 13:32
  • \$\begingroup\$ This is for production code. Procedure is my own functional interface which takes no arguments and return no result. \$\endgroup\$
    – Damian U
    Commented Apr 7, 2017 at 13:43

1 Answer 1

3
\$\begingroup\$

Approach

The approach is interesting, but doesn't seem practical or actually useful.

I think that you need more justification for this than simply stating that you want to use less if-statements.

Especially since you essentially still have the if-structure, just with a different syntax:

// your code:
findElement("el").ifTrue(() -> doSomething).orElse(() -> doSomethingElse)

// regular if, one line (which I would not recommend, it's more difficult to read than multi-line):
if (findElement("el")) doSomething; else doSomethingElse;

// standard if:
if (findElement("el")) {
    doSomething;
} else {
    doSomethingElse;
}

If there are other reasons for your approach, you need to make them clear. But this is definitely not a good replacement for general-purpose if statements.

And if you use this throughout a project, you have dependencies to this custom wrapper everywhere. Removing it later will be a lot of work. You will also need to wrap each return value from libraries and the standard APIs (which will be ugly in itself), or your code will consist of a mixture of standard ifs and your approach, which will not help readability.

Readability

Your approach is already more difficult to read than the standard approach, and with anything except a simple function-call, your approach would be even less readable:

// your code:
findElement("el").ifTrue(() -> {doSomething; doSomething2; doSomething3;}).orElse(() -> doSomethingElse; doSomethingElse2;)

// standard:
if (findElement("el")) {
    doSomething;
    doSomething2; 
    doSomething3;
} else {
    doSomethingElse;
    doSomethingElse2;
}

You can of course also make your version multi-line, but that doesn't make matters much better:

findElement("el").ifTrue(() -> {
    doSomething; 
    doSomething2; 
    doSomething3;
}).orElse(() -> {
    doSomethingElse; 
    doSomethingElse2;
})

You are still recreating the if-structure, just with a worse syntax.

Performance

I did not profile your approach, but in many situations, the extra cost of the additional function calls for the simplest of basic expressions will be noticeable.

Misc

  • I would recommend curly brackets even for one-line statements. They do make code easier to read, and can prevent bugs.
  • I would always use this when accessing fields, it makes it clearer where values come from.
  • Do you really need the value field and if in OrElse? I would assume that an else should always be executed.
\$\endgroup\$

Your Answer

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

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