We currently have a sensitive discussion going in the company that touches on a couple of old primary opinion based discussions. Nevertheless, I would like to discuss the case in this forum to establish some sensible code guidelines. Let's assume we have the following two classes of non-modifiable legacy classes:
public class SomeValue {
private String value;
public SomeValue(final String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
public class SomeCondition {
private SomeValue a;
private SomeValue b;
public SomeCondition(final SomeValue a, final SomeValue b) {
this.a = a;
this.b = b;
}
public boolean isA() {
return a != null;
}
public boolean isB() {
return b != null;
}
public String getAOrBValue() {
if (isA()) {
return a.getValue();
}
if (isB()) {
return b.getValue();
}
return null;
}
}
Now, in discussion is the best style for a method that checks whether any of a or b is set and returns its value (prioritizing a). The two versions on offer are those:
Version 1:
protected String getValue(final List<SomeCondition> conditions) {
if (isNotEmpty(conditions)) {
for (SomeConditions conditions : condition) {
if (condition.isA())) {
return a.getValue();
}
if (condition.isB()) {
return b.getValue();
}
}
}
return "default";
}
Critics of this version say, the returns inside several if statements being contained in a for loop not only hide else statements but also a break statement. If one tried to have one return at the end of the method, one would see all this hidden complexity definitely forcing one to refactor. If one had to bugfix this method, one would be in serious trouble.
Version 2:
protected String getValue(final List<SomeCondition> conditions) {
return conditions
.stream()
.map(this::getAOrBValue)
.filter(match -> match != null)
.findFirst()
.orElse("default");
}
Critics of this version say, this code is hard to read since it misuses java streaming api to handle something that usually would be covered by simple for and if statements. Also, the filtering algorithm is harder to understand since it is distributed over two classes.
I am aware that part of this discussion is primary opinion based. Nevertheless, I feel that there are some firmly established programming conventions that could help us, decide which of the two styles we want to make official in our code guidelines. Can anybody shed some light on the matter?