Why does this code have high cyclomatic complexity - or is it a bug in PHPMD in Jenkins?

8.8k views Asked by At

I'm trying to understand how Cyclomatic Complexity works and how I can avoid the warnings. Yes, I understand that the goal of writing code is not to avoid arbitrary warnings, but I'd at least like to know what's going on so I can decide if the code I'm seeing is good or bad.

I have a function that looks like:

protected function update($uuid, $data, $householdUuid, $androidId) {
    $household = $this->householdService->getHouseholdByUuid($householdUuid);

    $this->updatePeriod($household, $data);
    $this->updateNickname($household, $data, $androidId);
    $this->updateDateOrder($household, $data);
    $this->updateCurrency($household, $data);
    $this->updateAccounts($household, $data);

    $household->save();
    return $this->respondUpdated();
}

This gets flagged as having a cyclomatic complexity of 10. How is that possible? From the documentation, I would count this as a 1. The only possibility is that PHPMD is descending down into the various method calls.

But if that's so, then I have no way to "fix" this method. Generally I would reduce the complexity of a method by extracting out smaller helper methods. This method got refactored into those various update() methods already, to eliminate a bunch of conditional updating that happens. The original method had a cyclomatic complexity of 10 as well, and the refactor did nothing.

Or maybe the problem is simpler -- I'm running PHPMD through a continuous integration set up with Jenkins. Could there be an issue where PHPMD is not using the most recent code? I have had somewhat similar issues where it will flag a class as having too many lines, after I had already refactored the class below the line number limit.

2

There are 2 answers

2
Steven Scott On BEST ANSWER

I might think that each function call is what is adding the +1 to the complexity, since it is technically a pass through the code, but it should not do this according to the documentation. Even the definition for Cyclomatic Complexity does not support this count.

I would think this is a bug in PHP Mess Detector, as the PHP_CodeSniffer complexity calculation does not give a 10 on this.

0
spm On

I think its a bug. I haven't isolated it - but I collapsed one of my functions to {return false} and re-ran the jenkins job. I still had an NPath complexity of 4000 (ish). When I ran phpmd from the command line it correctly calculated it.

Looking into it a bit more, phpmd relies on pdepend, and pdepend does some caching. If you run pdepend directly you can specify "memory" or "file" caching in a config. But I don't know how or if its possible to influence how phpmd uses it. I thought perhaps restarting jenkins would clear things - but it doesn't. Once my function has been marked as 'overly complex' - that seems to stay with it.

There are a few issues in the phpmd repo on github about caching. But its all a bit vague. If I isolate it as a reproducible bug and not some quirk of my setup, Ill submit a bug report.