Is there any cyclomatic complexity calculator that takes into account Java stream and reactive APIs? [closed]
Asked Answered
R

0

8

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.

Radiotherapy answered 9/1, 2020 at 15:15 Comment(7)
I'd argue that this code is, in fact, significantly less complex to read than "classical" code. Creating this in the classical way would result in a nasty forest of for loops and ifs, but this is pretty easy to follow.Puett
@SebastianLenartowicz That doesn't help measure complexity. In any case, I've had a go at rewriting those examples in classic style, and they're much more understandable. They'd be even more understandable if they didn't use nulls. There's rarely much advantage in stream style, and reactive seems to be about moving state from stack to heap (fibres look like they may make that pointless in future as far as I can work out). / So, counting the use of streams/reactive libraries is a good way of measuring this particular accidental complexity.Felicio
@TomHawtin-tackline that’s a great indicator that cyclomatic complexity is not the same as readability or understandability.Gilboa
Well, apart from readability, there are other aspects that get impacted by code complexity, as the testing effort requirements and the risk of having defects. For us, these two points are the main reasons for having code complexity under control. However, we are entering into the subjective area here. The relevance of code complexity is not the same for everybody, after all.Radiotherapy
Cyclomatic complexity is a metric of the source code, not of what invoked methods may do behind the scenes. Yes, this implies that breaking source code into smaller units, hiding complexity is a way to solve the issue of high complexity. So list.forEach(System.out::println) has lower complexity than for(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
@Holger, you are right. Computational and cyclomatic complexities are different concepts. I guess we are looking for a way to measure the computational complexity here, with the "calculation scope" restricted to isolated methods. I don't know if there is any tool that can do something like this in the market, but probably there are not.Radiotherapy
I am afraid that this question is not a good fit for SO because it is asking to recommend a software. However maybe the question about how cyclomatic complexity should be affected by streams / functional programming might be relevant – or maybe better for Software Engineering?Slating

© 2022 - 2024 — McMap. All rights reserved.