Condition: secondary clauses now use Supplier's to enable short circuiting

This commit is contained in:
Paul Campbell 2018-03-13 17:08:06 +00:00
parent d1ca0b039f
commit efc1705a6c
4 changed files with 88 additions and 58 deletions

View file

@ -21,6 +21,8 @@
package net.kemitix.conditional; package net.kemitix.conditional;
import java.util.function.Supplier;
/** /**
* If-then-else in a functional-style. * If-then-else in a functional-style.
* *
@ -35,7 +37,6 @@ public interface Condition {
* *
* @return the Condition * @return the Condition
*/ */
@SuppressWarnings("avoidinlineconditionals")
static Condition where(final boolean clause) { static Condition where(final boolean clause) {
return clause ? TrueCondition.TRUE : FalseCondition.FALSE; return clause ? TrueCondition.TRUE : FalseCondition.FALSE;
} }
@ -58,7 +59,7 @@ public interface Condition {
* *
* @return the Condition * @return the Condition
*/ */
Condition and(boolean clause); Condition and(Supplier<Boolean> clause);
/** /**
* Logically AND combine the current {@code Condition} with boolean opposite of the clause. * Logically AND combine the current {@code Condition} with boolean opposite of the clause.
@ -67,8 +68,8 @@ public interface Condition {
* *
* @return the Condition * @return the Condition
*/ */
default Condition andNot(final boolean clause) { default Condition andNot(final Supplier<Boolean> clause) {
return and(!clause); return and(() -> !clause.get());
} }
/** /**
@ -78,8 +79,7 @@ public interface Condition {
* *
* @return the Condition * @return the Condition
*/ */
@SuppressWarnings("PMD.ShortMethodName") Condition or(Supplier<Boolean> clause);
Condition or(boolean clause);
/** /**
* Logically OR combine the current {@code Condition} with the boolean opposite of the clause. * Logically OR combine the current {@code Condition} with the boolean opposite of the clause.
@ -88,8 +88,8 @@ public interface Condition {
* *
* @return the Condition * @return the Condition
*/ */
default Condition orNot(final boolean clause) { default Condition orNot(final Supplier<Boolean> clause) {
return or(!clause); return or(() -> !clause.get());
} }
/** /**
@ -115,8 +115,8 @@ public interface Condition {
* *
* @return the Condition * @return the Condition
*/ */
default Condition otherwise(final boolean clause) { default Condition otherwise(final Supplier<Boolean> clause) {
return where(clause); return where(clause.get());
} }
} }

View file

@ -21,6 +21,8 @@
package net.kemitix.conditional; package net.kemitix.conditional;
import java.util.function.Supplier;
/** /**
* A {@code Condition} that has evaluated to {@code false}. * A {@code Condition} that has evaluated to {@code false}.
* *
@ -31,14 +33,13 @@ final class FalseCondition implements Condition {
public static final Condition FALSE = new net.kemitix.conditional.FalseCondition(); public static final Condition FALSE = new net.kemitix.conditional.FalseCondition();
@Override @Override
public Condition and(final boolean clause) { public Condition and(final Supplier<Boolean> clause) {
return FALSE; return FALSE;
} }
@Override @Override
@SuppressWarnings("PMD.ShortMethodName") public Condition or(final Supplier<Boolean> secondClause) {
public Condition or(final boolean secondClause) { return Condition.where(secondClause.get());
return Condition.where(secondClause);
} }
@Override @Override

View file

@ -21,6 +21,8 @@
package net.kemitix.conditional; package net.kemitix.conditional;
import java.util.function.Supplier;
/** /**
* A {@code Condition} that has evaluated to {@code true}. * A {@code Condition} that has evaluated to {@code true}.
* *
@ -31,13 +33,12 @@ final class TrueCondition implements Condition {
public static final Condition TRUE = new net.kemitix.conditional.TrueCondition(); public static final Condition TRUE = new net.kemitix.conditional.TrueCondition();
@Override @Override
public Condition and(final boolean clause) { public Condition and(final Supplier<Boolean> clause) {
return Condition.where(clause); return Condition.where(clause.get());
} }
@Override @Override
@SuppressWarnings("PMD.ShortMethodName") public Condition or(final Supplier<Boolean> secondClause) {
public Condition or(final boolean secondClause) {
return TRUE; return TRUE;
} }

View file

@ -3,6 +3,8 @@ package net.kemitix.conditional;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import java.util.concurrent.atomic.AtomicInteger;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
/** /**
@ -76,9 +78,9 @@ public class ConditionalTest {
public void whereTrueThenDoSomethingAndThenDoSomethingElse() { public void whereTrueThenDoSomethingAndThenDoSomethingElse() {
//when //when
Condition.where(true) Condition.where(true)
.then(thenResponse) .then(thenResponse)
.and(true) .and(() -> true)
.then(otherwiseResponse); .then(otherwiseResponse);
//then //then
assertThatBothResponsesRun(); assertThatBothResponsesRun();
} }
@ -119,7 +121,7 @@ public class ConditionalTest {
public void whereNotFalseThenRuns() { public void whereNotFalseThenRuns() {
//when //when
Condition.whereNot(false) Condition.whereNot(false)
.then(thenResponse); .then(thenResponse);
//then //then
assertThatTheThenResponseRuns(); assertThatTheThenResponseRuns();
} }
@ -128,8 +130,8 @@ public class ConditionalTest {
public void whereNotTrueThenOtherwiseRuns() { public void whereNotTrueThenOtherwiseRuns() {
//when //when
Condition.whereNot(true) Condition.whereNot(true)
.then(thenResponse) .then(thenResponse)
.otherwise(otherwiseResponse); .otherwise(otherwiseResponse);
//then //then
assertThatTheOtherwiseResponseRuns(); assertThatTheOtherwiseResponseRuns();
} }
@ -138,8 +140,8 @@ public class ConditionalTest {
public void whereTrueAndNotFalseThenRuns() { public void whereTrueAndNotFalseThenRuns() {
//when //when
Condition.where(true) Condition.where(true)
.andNot(false) .andNot(() -> false)
.then(thenResponse); .then(thenResponse);
//then //then
assertThatTheThenResponseRuns(); assertThatTheThenResponseRuns();
} }
@ -148,9 +150,9 @@ public class ConditionalTest {
public void whereTrueAndNotTrueThenOtherwiseRuns() { public void whereTrueAndNotTrueThenOtherwiseRuns() {
//when //when
Condition.where(true) Condition.where(true)
.andNot(true) .andNot(() -> true)
.then(thenResponse) .then(thenResponse)
.otherwise(otherwiseResponse); .otherwise(otherwiseResponse);
//then //then
assertThatTheOtherwiseResponseRuns(); assertThatTheOtherwiseResponseRuns();
} }
@ -159,8 +161,8 @@ public class ConditionalTest {
public void whereFalseOrNotFalseThenRuns() { public void whereFalseOrNotFalseThenRuns() {
//when //when
Condition.where(false) Condition.where(false)
.orNot(false) .orNot(() -> false)
.then(thenResponse); .then(thenResponse);
//then //then
assertThatTheThenResponseRuns(); assertThatTheThenResponseRuns();
} }
@ -169,9 +171,9 @@ public class ConditionalTest {
public void whereFalseOrNotTrueThenOtherwiseRuns() { public void whereFalseOrNotTrueThenOtherwiseRuns() {
//when //when
Condition.where(false) Condition.where(false)
.orNot(true) .orNot(() -> true)
.then(thenResponse) .then(thenResponse)
.otherwise(otherwiseResponse); .otherwise(otherwiseResponse);
//then //then
assertThatTheOtherwiseResponseRuns(); assertThatTheOtherwiseResponseRuns();
} }
@ -180,9 +182,9 @@ public class ConditionalTest {
public void whereFalseElseTrueThenOtherwiseRuns() { public void whereFalseElseTrueThenOtherwiseRuns() {
//when //when
Condition.where(false) Condition.where(false)
.then(thenResponse) .then(thenResponse)
.otherwise(true) .otherwise(() -> true)
.then(otherwiseResponse); .then(otherwiseResponse);
//then //then
assertThatTheOtherwiseResponseRuns(); assertThatTheOtherwiseResponseRuns();
} }
@ -191,9 +193,9 @@ public class ConditionalTest {
public void whereFalseElseFalseThenNothingRuns() { public void whereFalseElseFalseThenNothingRuns() {
//when //when
Condition.where(false) Condition.where(false)
.then(thenResponse) .then(thenResponse)
.otherwise(false) .otherwise(() -> false)
.then(otherwiseResponse); .then(otherwiseResponse);
//then //then
assertThatNoResponseRuns(); assertThatNoResponseRuns();
} }
@ -202,8 +204,8 @@ public class ConditionalTest {
public void whereTrueChainedThensBothRuns() { public void whereTrueChainedThensBothRuns() {
//when //when
Condition.where(true) Condition.where(true)
.then(thenResponse) .then(thenResponse)
.then(otherwiseResponse); .then(otherwiseResponse);
//then //then
assertThatBothResponsesRun(); assertThatBothResponsesRun();
} }
@ -212,8 +214,8 @@ public class ConditionalTest {
public void whereFalseChainedThensNothingRuns() { public void whereFalseChainedThensNothingRuns() {
//when //when
Condition.where(false) Condition.where(false)
.then(thenResponse) .then(thenResponse)
.then(otherwiseResponse); .then(otherwiseResponse);
//then //then
assertThatNoResponseRuns(); assertThatNoResponseRuns();
} }
@ -235,22 +237,22 @@ public class ConditionalTest {
private void assertThatTheOtherwiseResponseRan() { private void assertThatTheOtherwiseResponseRan() {
assertThat(otherwiseFlag).as("otherwise response runs") assertThat(otherwiseFlag).as("otherwise response runs")
.isTrue(); .isTrue();
} }
private void assertThatTheThenResponseRan() { private void assertThatTheThenResponseRan() {
assertThat(thenFlag).as("then response runs") assertThat(thenFlag).as("then response runs")
.isTrue(); .isTrue();
} }
private void assertThatTheOtherwiseResponseDidNotRun() { private void assertThatTheOtherwiseResponseDidNotRun() {
assertThat(otherwiseFlag).as("otherwise response does not run") assertThat(otherwiseFlag).as("otherwise response does not run")
.isFalse(); .isFalse();
} }
private void assertThatTheThenResponseDidNotRun() { private void assertThatTheThenResponseDidNotRun() {
assertThat(thenFlag).as("then response does not run") assertThat(thenFlag).as("then response does not run")
.isFalse(); .isFalse();
} }
private void assertThatNoResponseRuns() { private void assertThatNoResponseRuns() {
@ -260,27 +262,53 @@ public class ConditionalTest {
private void when(final boolean clause) { private void when(final boolean clause) {
Condition.where(clause) Condition.where(clause)
.then(thenResponse) .then(thenResponse)
.otherwise(otherwiseResponse); .otherwise(otherwiseResponse);
} }
private void when( private void when(
final boolean firstClause, final boolean firstClause,
final boolean secondClause final boolean secondClause
) { ) {
Condition.where(firstClause) Condition.where(firstClause)
.and(secondClause) .and(() -> secondClause)
.then(thenResponse) .then(thenResponse)
.otherwise(otherwiseResponse); .otherwise(otherwiseResponse);
} }
private void whenOr( private void whenOr(
final boolean firstClause, final boolean firstClause,
final boolean secondClause final boolean secondClause
) { ) {
Condition.where(firstClause) Condition.where(firstClause)
.or(secondClause) .or(() -> secondClause)
.then(thenResponse) .then(thenResponse)
.otherwise(otherwiseResponse); .otherwise(otherwiseResponse);
}
@Test
public void shortCurcuitOr() {
//given
final AtomicInteger atomicInteger = new AtomicInteger();
//when
Condition.where(true)
.or(() -> atomicInteger.compareAndSet(0, 2))
.then(thenResponse);
//then
assertThatTheThenResponseRan();
assertThat(atomicInteger).hasValue(0);
}
@Test
public void shortCurcuitAnd() {
//given
final AtomicInteger atomicInteger = new AtomicInteger();
//when
Condition.where(false)
.and(() -> atomicInteger.compareAndSet(0, 2))
.then(thenResponse);
//then
assertThatTheThenResponseDidNotRun();
assertThat(atomicInteger).hasValue(0);
} }
} }