Last active
December 16, 2019 16:42
-
-
Save joshiraez/1d99004dc2afb93fa2c9f4738401f594 to your computer and use it in GitHub Desktop.
How to assert on a list of boolean functions/predicates/flags that all match without making it messy as hell.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Is common to use all matching functions. Whichever you need to check if a list of flags are set, | |
//if some conditions meet, even if all the fields are equal in a equals function, you need to do an all match. | |
//Many people would do this, but, please, do not do this. Specially if the set of conditions is large. | |
if (conditionA()) { | |
if (conditionB()) { | |
if (conditionC()) { | |
return true; | |
} | |
} | |
} | |
return false; | |
//I used an alternative in Java, but I thought it was not good enough. Knowing that some languages | |
//and the Stream API have an allMatch() method. | |
boolean allTrue = true; | |
allTrue = allTrue && conditionA(); | |
allTrue = allTrue && conditionB(); | |
... | |
// If I don't have autoformat I could do this too | |
boolean allTrue = conditionA() | |
&& conditionB() | |
&& conditionC() | |
&& ...(); | |
//I don't like these because I have 2 big problems: | |
// * I can't construct the list dinamically from a set of different conditions | |
// * Boileplaterish, and weak to autoformat tools or tab evangelist. Also, very prone to erros from copying. | |
// * Not obvious to someone that don't know logic math | |
// I could diminish this just making a function called "allMatch" and putting whatever inside, it wouldn solve | |
// the problem altogether eliminating mess from the code and making it more legible... | |
// But where the hell to put that function? If this were Kotlin, I could at least make an extension function | |
// on List<Boolean> or something of the sort, but I can't. In top of that, this is not Kotlin, son I'd add complexity | |
// to the code adding an Utils class in *someplace* that now all the team must know where is to call it. | |
// MEEEEH. Although this is the best solution by far, there is just absolutely no excuse to create a single file | |
// and the burden of knowledge associated to it for a single file. | |
// Some good solutions I discovered thanks to Stack Overflow were stuff like this. | |
return !Arrays.asList( | |
conditionA(), | |
conditionB(), | |
... | |
).contains(false); | |
//I don't like that you have to negate it, so it is not apparent a first glance what it does. It would be better if I could | |
// do something like not.contains(false) or .allAre(true) | |
// You could do it in a stream too, but there is no way to make the predicate something like Predicate.identity(). | |
// There isnt' also a BooleanStream with specialized reducers like IntStream. Fuck. You have to use Boolean:booleanValue. | |
return Stream.of( | |
conditionA(), | |
conditionB(), | |
... | |
).allMatch(Boolean::booleanValue); | |
//Alternative | |
return Stream.of( | |
conditionA(), | |
conditionB(), | |
... | |
).allMatch(v -> v); // Even less explanatory. And someone will try to put Function.identity() in there and fail at it for some time too. | |
// And even so, when those solutions make it much, MUCH more legible and concise, it still is worse than having | |
// a named function with a correct name that directly conveys its purpose :( | |
// Soooo open questions | |
// Any better ways to do it? | |
// If you would do a file in Java, where would you put it? Or you wouldn't create a specific file? | |
// When are extensions functions coming to Java? :D (this is hard being a really static typed language, but one can wish). |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment