Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
27 / 27
CodeMetrics
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
2 / 2
7
100.00% covered (success)
100.00%
27 / 27
 extractShortName(Vertex $v)
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
5 / 5
 getCardinal()
100.00% covered (success)
100.00%
1 / 1
5
100.00% covered (success)
100.00%
22 / 22
<?php
/*
 * Mondrian
 */
namespace Trismegiste\Mondrian\Analysis;
use Trismegiste\Mondrian\Graph\Algorithm;
use Trismegiste\Mondrian\Graph\Vertex;
/**
 * CodeMetrics analyses a graph and counts number of vertices per type
 * Design Pattern : Decorator
 *
 * Metrics are usefull to fast evaluate what kind of project you have
 * to refactor. But it is not a guide where you have to go. Of course
 * a project with a 50/50 ratio in interfaces/classes can be a good thing
 * but if classes are used in parameters of methods instead of interfaces,
 * interfaces are not really usefull. It's easy to fake good metrics.
 *
 * This analyser also counts where methods are declared first in the
 * inheritance tree. A good point can be that you have low count of
 * method first declared in class. This can mean you can decouple your
 * concrete classes (remember LSP)
 *
 * From my experience, it's better to have dirty code in loosely coupled
 * classes than beautiful code in highly coupled classes, because your beautiful
 * code does not stand a chance against the entropy of changing.
 *
 * Dirty code can be refactored, even in paralell process, if you have loosely
 * coupling.
 *
 * In short : Bad coding practices has bad metrics
 * but good metrics does not means good coding practices.
 * That's why I didn't push too far these statistics.
 *
 * See the others tool to find out where the coupling is.
 */
class CodeMetrics extends Algorithm
{
    /**
     * Extract the class name of a vertex to get a printable result
     *
     * @param Vertex $v
     * @return string
     */
    private function extractShortName(Vertex $v)
    {
        $result = 'Unknown';
        if (preg_match('#([^\\\\]+)Vertex$#', get_class($v), $match)) {
            $result = $match[1];
        }
        return $result;
    }
    /**
     * Makes the statistics on the code
     *
     * @return array hashmap of stat
     */
    public function getCardinal()
    {
        $card = array(
            'Class' => 0,
            'Interface' => 0,
            'Trait' => 0,
            'Impl' => 0,
            'Method' => 0,
            'Param' => 0,
            'MethodDeclaration' => array('Class' => 0, 'Interface' => 0, 'Trait' => 0)
        );
        $vertex = $this->graph->getVertexSet();
        foreach ($vertex as $v) {
            $type = $this->extractShortName($v);
            $card[$type]++;
            if (in_array($type, ['Class', 'Interface', 'Trait'])) {
                foreach ($this->graph->getSuccessor($v) as $succ) {
                    $succType = $this->extractShortName($succ);
                    if ($succType == 'Method') {
                        $card['MethodDeclaration'][$type]++;
                    }
                }
            }
        }
        return $card;
    }
}