In a project using spring reactor, we have detected that the real complexity of the reactive code is not detected by our static analysis tools. At the moment we are using a combination of PMD, Checkstyle, Spotbugs and SonarQube, but none of them is able to detect "complex reactive code".
Is there any other tool out there that can take into account the new reactive and stream APIs in Java?
Just some very simple examples that are considered to have cyclomatic complexity 0 could be:
// EXAMPLE 1: Optional usage for avoiding null field checks
int activeSensors = Optional.of(sensorData).map(SensorData::getActiveCount).orElse(0);
// EXAMPLE 2: Stream API usage for replacing iterations and conditionals
list.stream().filter(Objects::nonNull).forEach(item -> do_something(item));
// EXAMPLE 3: Reactive API
Flux<Float> historyValuesFlux = Mono.justOrEmpty(sensorData)
.filter(Objects::nonNull)
.flatMapMany(data -> Flux.fromIterable(data.getHistoryPoints()))
.filter(Objects::nonNull)
.map(SensorHistoryPoint::getValue);
In the three cases, the "classic equivalent" code has a higher complexity value, so our concern is that the actual complexity of the code is being hidden by the new syntaxis. And this means that our estimations of the code mantainability are wrong, and they will worsen with time.
list.forEach(System.out::println)
has lower complexity thanfor(Object o: list) System.out.println(o);
. Don’t confuse with computational complexity or “what does this code actually do”, as when you refactor the code to make it more maintainable, you don’t change the purpose of the code, i.e. in my example, a linear iteration is unavoidable. – Gilboa