PhpMetrics

Détecter les anomalies de conception d'un code PHP

www.phpmetrics.org - @Halleck45

Jean-François Lépine

@Halleck45

  • Consultant en assurance qualité
  • Créateur de PhpMetrics, MutaTesting, BehatWizard...
  • http://blog.lepine.pro

Analyse statique ?

Vision de PhpMetrics

Simple à utiliser
Facile à comprendre
Riche

Quelques métriques à surveiller

  • Absence de cohésion des méthodes
  • Couplage
  • Complexité cyclomatique
  • Indice de maintenabilité
  • Complexité du système

Absence de cohésion des méthodes (LCOM)

Chemin 1

Chemin 2

La classe possède probablement 2 responsabilités

 

=violation du Single responsability principle

Couplage entre les classes

  • Afferent coupling :
    nombre de classes affectés par la classe
  • Efferent coupling :
    nombre de classes dont la classe reçoit les effet

Afferent coupling

Le PNEU est utilisé par plein de VOITURES

=La classe Pneu a un afferent coupling élévé

 

Pour être bénéfique aux voitures, le pneu doit être très très stable, résistant et solide

 

=la classe Pneu doit avoir un CRAP faible, une complexité faible et une couverture forte

Efferent coupling

La VOITURE utilise un chassis, un frein, des pneus, un moteur...

= la classe Voiture a un efferent coupling élevé

 

Pour éviter les problèmes de maintenance et d'évolutivité, il doit être possible de changer facilement le modèle du pneu.

 

=la classe voiture doit avoir une cohésion faible avec ses composants

Complexité cyclomatique et interval de Myer

function foo() { 
    $a = 1; 
    $b = array(); 
    if($a == 1) { 
        foreach($b as $value) {}
    } 
 
    switch($a) { 
        case 1: 
            break; 
        case 2: 
            break; 
    } 
}

Nombres de points de décisions dans le code

 

ccn = (1 + 4) = 5

 

directement lié aux cas de tests unitaires à réaliser

Interval de Myer

function foo() { 
    $a = 1; 
    $b = array(); 
    if($a == 1 || $a == 2) { 
        foreach($b as $value) {}
    } 
 
    switch($a) { 
        case 1: 
            break; 
        case 2: 
            break; 
    } 
}

La complexité cyclomatique ne tient pas compte:

  • du niveau d'imbrication (if dans des boucles)
  • des opérateurs logiques

ccn:(ccn+nb opérateurs)

interval = 5:6

distance = 1

une distance supérieure à 10 est très mauvais signe

Métriques d'Halstead

fournit une note sur :

  • l'effort pour implémenter le code
  • la difficulté d'accès du code
  • le temps de lecture du code
  • basé sur la richesse (volume de variables) et la complexité logique (nombre d'opérateurs)
  • formule basée sur un fondement empirique (valeur "en dur" pour un "développeur normal")

Indice de maintenabilité

basée sur les métriques d'Halstead et la complexité cyclomatique

> 85
Très bon

 

> 65
code maintenable

 

< 65
code peu évolutif / maintenable

Cas pratique

Symfony Console (master)

Installation

wget https://github.com/phpmetrics/PhpMetrics/releases/download/v2.0.0-rc/phpmetrics.deb
sudo dpkg -i phpmetrics.deb
brew install phpmetrics
sudo yaourt install -S phpmetrics

Mac

Debian, Ubuntu

ArchLinux

composer require "phpmetrics/phpmetrics:v2.0.0-rc"

partout

Lancer l'analyse

phpmetrics \
    report-html=<dossier-du-rapport-html> \
    <dossier-des-sources>
phpmetrics --report-html=/tmp/report symfony-console/

Taille & volume

Taille & volume

Orienté objet

Taille & volume

Orienté objet

Complexité

Taille & volume

Orienté objet

Complexité

Probabilité de bugs

Taille & volume

Orienté objet

Complexité

Probabilité de bugs

Défauts de conception

Un peu de couleurs

Aperçu général

Taille du code

Complexité et défauts

Programmation orientée objets

Relations

Couplage

Défauts de conception

Symfony\Component\Console\Application

Grosse mais pas incohérente

Algorithmes complexes, durs à lire et à comprendre

Bugs probables (doit être testée)

PhpMetrics ne remplace pas les humains

Il faudrait auditer manuellement

Symfony\Component\Console\Application

Symfony\Component\Console\Helper\Table

Symfony\Component\Console\Input\ArgvInput

Symfony\Component\Console\Helper\QuestionHelper

Symfony\Component\Console\Input\InputDefinition

...

Tout doit être ponderé

Selon le rôle / la couche du composant

ccn(controlleur) != ccn(classe métier)

Se référer aux autres projets

http://blog.lepine.pro/industrialisation/bornes-pour-les-indicateurs-et-metriques/

J'ai besoin d'aide

  • Traduction
  • Amélioration de la doc
  • Nouveaux plugins (Git, PHPUnit...)
  • ...

Merci !

des questions ?

@Halleck45

https://goo.gl/uuIcWR

ForumPHP 2016 - clinique sur PhpMetrics

By Jean-François Lépine

ForumPHP 2016 - clinique sur PhpMetrics

Logiciel d'analyse statique en PHP

  • 1,003