Automated code reviews for PHP
I'm exploring an approach to automated code review: it's not as precise as the human-based one, but it scales better.
For example, I heard from the Ideato guys that often they get a 100K lines project to maintain, and don't know where to start analyzing it. Thus they use automated tools to find out which are the most complex points, or the largest packages, or the untested ones.
Other scenarios for automated code review are keeping an eye on a new programmer, or ensuring some minimal coding standard is maintained from the others even if you aren't in the office to enforce it for a while. :)
All in all, automated code reviews, performed with tools instead of with human intellect, can be a starting point to search for the problematic zones of a codebase. Then the human may come in, since they also have to clean up the code: their intervention was already scheduled.
These tools are often the next step to improve a Continuous Integration process, after testing automation and build/deployment tools. In the PHP ecosystem, these tools are slowly maturing and can now be used as defaults in new project.
Mostly we are talking about static analysis performed on the source code, not on the code at execution time. Note that since you run these tools on your machine or on a CI server, you'll never need to look for an hosting service that supports them. I think this is a great factor contributing to their adoption.
PHPUnit code coverage
sudo pear channel-discover pear.phpunit.de sudo pear install phpunit/PHPUnit
PHPUnit is not only useful for testing, but it can leverage xdebug's features (when installed) to generate code coverage reports that tell you how many classes, methods and lines of code are executed by at least a test.
PHPUnit also generate a CRAP (Change Risk Analysis and Prediction) index, which mixes coverage with cyclomatic complexity; this index tells you where are the pain points with an high complexity (many ifs, cycles and method calls) which are not tested appropriately.
sudo pear install PHP_CodeSniffer
PHP_CodeSniffer performs a static analysis to detect violation of coding standards. It's really good on basic points, like line length, wrong indentation, misaligned braces; provided that you agree with it on the definition of code smells.
phpcs may also be run in a pre-commit/pre-push hook in order to stop code that violate basic coding rules from being inserted in the repository.
The issue with phpcs is that it does not contain so many sniffs out of the box, but you can use the Generic, Pear or Zend included standards to detect most of the code smells cited earlier:
phpcs --standard=Generic folder/or/file/path
sudo pear channel-discover pear.pdepend.org sudo pear install pdepend/PHP_Depend
PHP_Depend generates static analysis graphical reports involving for instance relationships between classes. To support the graphical part, I used the php5-imagick ubuntu package, which is simpler to install than the ImageMagick extension provided via PECL.
Graphical reports are easy to analyze by eye, especially when you view a lot of them every day. Two samples of these reports?
- Uncle Bob's abstractness/stability graph for classes (at least I first saw it in Uncle Bob papers.)
- The overview pyramid, containing a summary of the number of methods, classes, lines of code, cyclomatic complexity...
sudo pear channel-discover pear.phpmd.org sudo pear channel-discover pear.pdepend.org sudo pear install --alldeps phpmd/PHP_PMD
PHP Mess Detector leverages the metrics of PDepend to find out pain points, one of the use cases we described earlier; it produces an output in text or XML format. It works at an increased level of abstraction with respect to PDepend and especially to PHP_CodeSniffer.
Here's an example of what phpmd can tell you:
phpmd . text codesize,unusedcode,naming /home/giorgio/code/practical-php-testing-patterns/CustomAssertionTest.php:2 This class has too many methods, consider refactoring it. /home/giorgio/code/practical-php-testing-patterns/CustomAssertionTest.php:93 Avoid unused parameters such as '$speed'. ... # more lines of output
Jenkins Job template
(Jenkins is the name of the free fork of the Hudson Continuous Integration server, after its acquisition by Oracle as part of the Sun's deal.)
Using these tools by hand is possible, but a bit of automation can improve the experience; it will include them in your build process, so that they are executed at each check-in, and the results are published.
Sebastian Bergmann, one of the pioneers of Quality Assurance in the PHP world, has created a Job template for Jenkins which automatically runs all these tools as part of an Ant buildfile (a standard used by Jenkins, which after all is a Java tool).
It has lots of requirements, both as Jenkins plugins and PEAR-based tools available on the machine, but when integrated well the reports we have seen in these article will be automatically regenerated during the build, and hosted by Jenkins on its HTTP server. It would also take a bit of time to complete all the artifacts, but that's why we have a separate server for Continuous Integration, right?