Comment relire du code pourri sans se fatiguer
AFUP, Paris, 2016
Agenda
Comment appréhender du code
L'analyse statique pour PHP
La session dont vous êtes le héros
Un projet à relire
On ne sait pas ce que ca fait
On ne l'a jamais vu
On ne l'execute pas
On ne connait pas ses auteurs
Peut-on se former une opinion ?
Comment relire du code?
Relire est humainement possible et artisanal
Les tests unitaires sont peu adaptés à la relecture
L'analyse dynamique est peu adaptée à la relecture
Il faut explorer le code
ne pas se contenter des situations actuelles
Conférencier
Damien Seguy
Exakat CTO
Ik ben een boterham
Analyse statique de code PHP : SCAP
Le code est structuré
Le code est une base de données structurée
Les outils pour l'analyser sont l'analyse statique
Migration PHP 7.0->7.1
Inco
mpa
tible
Nouv
eaut
és
PHP LINT
php -l <fichier.php>
Execution parallele :
jakub-onderka/php-paralell-lint
Différentes versions de PHP : 7.0, 7.1, 7.2, 5.6, 5.5
Checked 5982 files in 28.4 seconds Syntax error found in 4 files
------------------------------------------------------------ Parse error: /vendor2/symfony/symfony/src/Symfony/Component/Validator/Constraints/False.php:22 20| * @api 21| */ > 22| class False extends IsFalse 23| { 24| } Fatal error: Cannot use 'False' as class name as it is reserved ------------------------------------------------------------ Parse error: /vendor2/symfony/symfony/src/Symfony/Component/Validator/Constraints/Null.php:22 20| * @api 21| */ > 22| class Null extends IsNull 23| { 24| } Fatal error: Cannot use 'Null' as class name as it is reserved ------------------------------------------------------------ Parse error: /vendor2/symfony/symfony/src/Symfony/Component/Validator/Constraints/True.php:22 20| * @api 21| */ > 22| class True extends IsTrue 23| { 24| } Fatal error: Cannot use 'True' as class name as it is reserved ------------------------------------------------------------ Parse error: /vendor_user/windid_client/src/windid/service/base/WindidUtility.php:93 91| $imageInfo = @getimagesize($file); 92| $exts = array('1'=>'gif', '2'=>'jpg', '3'=>'png'); > 93| if (!isset($exts[$imageInfo[2]])) continue; 94| $ext = $exts[$imageInfo[2]]; 95| $filename = rand(1000,9999). '.'.$ext; Fatal error: 'continue' not
PHP LINT - 7.0/1/2
Checked 5982 files in 29.7 seconds Syntax error found in 1 file
------------------------------------------------------------ Parse error: /vendor2/mockery/mockery/tests/Mockery/MockingVariadicArgumentsTest.php:52 50| abstract class TestWithVariadicArguments 51| { > 52| public function foo(...$bar) 53| { 54| return $bar; Unexpected '.', expecting '&' or variable (T_VARIABLE)
PHP LINT - 5.5
PHP LINT - 5.6Checked 5982 files in 31 seconds No syntax error found
PHP LINT
Pas compatible avec PHP 7.0 +
Pas compatible avec PHP 5.5-
Utilise Symfony
@getimagesize ? vendor2 ?
5982 fichiers
Calcul de métriques
PHPloc, PHPmetrics, PHP MD
Donne des notes d'ensemble au code
Complexité cyclomatique, nombre de LOC…
PHPLOC Directories 1143 Files 5982
Size Lines of Code (LOC) 835199 Comment Lines of Code (CLOC) 252075 (30.18%) Non-Comment Lines of Code (NCLOC) 583124 (69.82%) Logical Lines of Code (LLOC) 195283 (23.38%) Classes 178062 (91.18%) Average Class Length 29 Minimum Class Length 0 Maximum Class Length 3141 Average Method Length 4 Minimum Method Length 0 Maximum Method Length 879 Functions 1477 (0.76%) Average Function Length 1 Not in classes or functions 15744 (8.06%)
Cyclomatic Complexity Average Complexity per LLOC 0.30 Average Complexity per Class 10.82 Minimum Class Complexity 1.00 Maximum Class Complexity 1177.00 Average Complexity per Method 2.65 Minimum Method Complexity 1.00 Maximum Method Complexity 387.00
[...]
PHPLOC Dependencies Global Accesses 2158 Global Constants 1738 (80.54%) Global Variables 31 (1.44%) Super-Global Variables 389 (18.03%) Attribute Accesses 50986 Non-Static 49206 (96.51%) Static 1780 (3.49%) Method Calls 113735 Non-Static 103683 (91.16%) Static 10052 (8.84%)
Structure Namespaces 851 Interfaces 693 Traits 11 Classes 5245 Abstract Classes 301 (5.74%) Concrete Classes 4944 (94.26%) Methods 39581 Scope Non-Static Methods 37468 (94.66%) Static Methods 2113 (5.34%) Visibility Public Methods 31500 (79.58%) Non-Public Methods 8081 (20.42%) Functions 1185 Named Functions 306 (25.82%) Anonymous Functions 879 (74.18%) Constants 2658 Global Constants 361 (13.58%) Class Constants 2297 (86.42%)
PHPMetrics
PHPMetrics
Revue de code automatisée
Relecture du code par une application
regex relit PHP
Extraction de points intéressants
Fonctionnement par mots clé
PHP7cc
php7ccFile: /vendor_user/windid_client/wind/convert/WindGeneralConverter.php > Line 33: PHP 4 constructors are now deprecated public function WindGeneralConverter($sourceLang = '', $targetLang = '', $forceTable = false) { }
File: /vendor2/symfony/symfony/src/Symfony/Component/Validator/Constraints/Null.php > Line 22: Reserved name "null" used as a class, interface or trait name class Null extends \Symfony\Component\Validator\Constraints\IsNull { }
File: /vendor_user/windid_client/wind/filter/WindHandlerInterceptorChain.php > Line 61: Function argument(s) returned by "func_get_args" might have been modified func_get_args();
File: /vendor_user/windid_client/wind/http/session/handler/WindSessionHandler.php > Line 156: Check that callbacks that are passed to "session_set_save_handler" and return false or -1 (if any) operate correctly session_set_save_handler(array($this, 'open'), array($this, 'close'), array($this, 'read'), array($this, 'write'), array($this, 'destroy'), array($this, 'gc'));
File: /vendor_user/windid_client/wind/security/WindMcryptCbc.php > Line 31: Removed function "mcrypt_cbc" called mcrypt_cbc(MCRYPT_DES, $key, $string, MCRYPT_ENCRYPT, $iv); > Line 49: Removed function "mcrypt_cbc" called mcrypt_cbc(MCRYPT_DES, $key, $string, MCRYPT_DECRYPT, $iv);
Total : 83 rapports
php7cc
composer require sstale/php7cc
Fonctionne avec des regex et des mots clés
Migration PHP 7
5982 fichiers en 69.275 secondes
Revue de code automatisée
Relecture du code
Extraction de points intéressants
Fonctionnement par AST
PHP7mar, Phan, exakat
Revue de code automatisée
PHP 5 / 7 Calisthenics ClearPHP
Performance
AST
<?php
class Foo { function bar($arg) { return \StrToUpper($arg + 2); } }
$foo = new Foo(); $foo->bar(__FILE__);
?>
Sémantique et définitions
PHP7mar : nikic/php5-ast
PHAN : ext/ast (PHP 7 only)
Exakat : AST en base de données
SonarQube : AST maison
PHPstorm : AST interne à l'IDE
Sémantique et définitions
Suppression espaces, commentaires, documentations
Suppression des délimiteurs
( ) { } [ ] " ' ` ; :
Capacité à relier définitions et usage
PHANsrc/Org/OrgBundle/Controller/OrgController.php:12 PhanTypeMismatchArgument Argument 1 (data) is bool but \Org\OrgBundle\Controller\OrgController::createJsonResponse() takes array defined at src/Topxia/WebBundle/Controller/BaseController.php:120
Total : 13315 résultats1235 issues
vendor_user/windid_client/wind/mail/protocol/WindPop3.php:186 PhanUndeclaredTypeParameter Parameter of undeclared type \baoolean
276 issues
vendor_user/windid_client/wind/base/WindFactory.php:325 PhanTypeArraySuspicious Suspicious array access to bool
184 issues
vendor2/imagine/imagine/lib/Imagine/Image/AbstractLayers.php:49 PhanParamSignatureMismatch Declaration of function get($offset) should be compatible with function get(int $offset) : \Imagine\Image\ImageInterface defined in vendor2/imagine/imagine/lib/Imagine/Image/LayersInterface.php:97
src/Classroom/ClassroomBundle/Controller/ClassroomAdminController.php:84 PhanUndeclaredMethod Call to undeclared method \Classroom\ClassroomBundle\Controller \ClassroomAdminController::createErrorResponse
1919 issues
808 issues
PHAN [PhanRedefineFunction] => 31 [PhanTypeMismatchForeach] => 31 [PhanUndeclaredClassInstanceof] => 32 [PhanDeprecatedFunction] => 43 [PhanUndeclaredClassConstant] => 49 [PhanUndeclaredTypeProperty] => 60 [PhanParamSignatureMismatchInternal] => 79 [PhanUndeclaredClassCatch] => 94 [PhanParamTooMany] => 101 [PhanUndeclaredFunction] => 102 [PhanTypeMissingReturn] => 126 [PhanStaticCallToNonStatic] => 164 [PhanTypeArraySuspicious] => 184 [PhanTypeMismatchDefault] => 194 [PhanNonClassMethodCall] => 202 [PhanUndeclaredTypeParameter] => 276 [PhanUndeclaredConstant] => 417 [PhanUndeclaredVariable] => 432 [PhanTypeMismatchProperty] => 530 [PhanUndeclaredMethod] => 808 [PhanTypeMismatchArgumentInternal] => 854 [PhanUndeclaredClassMethod] => 1082 [PhanTypeMismatchReturn] => 1236 [PhanTypeMismatchArgument] => 1716 [PhanParamSignatureMismatch] => 1840 [PhanUndeclaredProperty] => 2485
53 analyses
PHANsrc/Classroom/Service/Classroom/Tests/ClassroomReviewServiceTest.php:227 PhanDeprecatedFunction Call to deprecated function \Classroom\Service\Classroom\Tests\ClassroomReviewServiceTest::setExpectedException()
defined at vendor/phpunit/phpunit/src/Framework/TestCase.php:466
43 issues
Avantages PHP 7
Type hint, return type hint, scalaires
Phan comprend les annotations PHPDOC
Le code dynamique reste difficile à analyser
Flow Control diagram
Diagramme de flux de contrôle
Basé sur l'AST, inclut le suivi de la séquence
Outil de base pour RIPS
<?php $x = source(); if ($x < 10) { $y = $x + 1; $x = corrige($y); } else { $y = $x; }
Flow Control Graph
$x = source();
if ($x < 10)
$y = $x + 1;
$x = corrige($y);
$y = $x;
PHP
Exit
ElseThen
<?php $x = source(); if ($x < 10) { $y = $x + 1; $x = corrige($y); } else { $y = $x; }
Program Dependency Graph
$x = source();
if ($x < 10)
$y = $x + 1;
$x = corrige($y);
$y = $x;Depend de $x
Depend de $x
Depend de $y
Depend de $x
Depend de $x
Depend de $x
<?php $x = source(); if ($x < 10) { $y = $x + 1; $x = corrige($y); } else { $y = $x; }
Et PHP dans tout ça?
La majorité des analyses portent sur des concepts informatiques
Il existe des analyses qui portent sur PHP lui-même
Les pratiques courantes
Les spécificités du langage
Analyses Exakat function __destruct() { throw …} : 0,5%
substr($a, 2, 4) == 'abc' : 1 %
function foo($a, $a, $a) {} : 1%
!!(expression) : 7%
$a ? $b ? $c : $d : $e ; 20%
foreach($a as &$b) {} : 21%
if (strpos($a, $b)) {} : 51 %
include('file.php') : 51%
Guide de code propre
Bonnes pratiques
maison, PSR, calisthenics, d'autres techno
Les mantras de code
Le manuel
Les guides de migration
PHP
Liste defonctionnalitésutilisées
PHP
Liste d' extensionsutilisées
Et mon application ?
Découvrez les inventaires
Liste des valeurs utilisées dans le code
Liste des entiers, décimaux, chaines, tableaux
Liste de noms de classes, interfaces, variables, méthodes
Les erreurs
Chaines utiliséesdans les die, exitet new Exception
Les variables
$orderBy 685 $token 690 $response 721 $paginator 752 $temp 828 $params 891 $value 925 $type 955 $thread 968 $order 982 $member 1042 $classroom 1115 $limit 1222 $start 1320 $currentUser 1334 $userId 1352 $file 1391 $data 1408 $i 1494 $lesson 1504 $sql 1528 $courseId 1626 $key 1716 $fields 2214 $result 2600 $course 2742 $request 3219 $id 3529 $conditions 3870 $user 4505
271 variables utilisées 1 fois
Les classesOrderServiceTest 2 FileController 2 ClassroomDataTag 2 LiveCourseController 2 UploadFileController 2 NoteController 2 BlockController 2 OrderLogDaoImpl 2 OpenCourseController 2 FileFilter 2 CourseOrderController 2 Member 2 CoinController 2 ThreadServiceTest 3 BaseProcessor 3 MobileController 3 UserController 3 CategoryDaoImpl 3 CourseReviewController 3 TeacherController 3 AlipaySubmit 3 ThreadServiceImpl 3 ThreadPostDaoImpl 3 AlipayNotify 3 ThreadDaoImpl 3 CourseController 5 DefaultController 5 DefaultControllerTest 5 Configuration 6
Les comparaisons
none 9 vip 10 .. 10 yes 10 material 11 coin 11 created 11 teacher 12 closed 12 error 13 1 14 RMB 15 0 16 paid 16 lesson 18 liveOpen 19 trend 19 cloud 19 ok 20 Coin 21 classroom 22 video 25 self 25 testpaper 27 success 32 live 32 course 39 published 43 _empty_ 71 POST 237
Chaines utilisées dans une comparaison$a == 'ok'
On compte juste les b
Pour aller plus loin
Deptrac
Vérifie que les classes restent bien dans leurs couches
Deptrac traque les dépendances entre classes qui doivent rester indépendantes
Configuré manuellement
Pour aller plus loinLe code dynamique
40% du code est en fait statique
Transpilage : https://github.com/jaytaph/Transphpile
PHP inspections : Intégrées à l'éditeur phpStorm
sensio labs insight : SCA pour le framework
Intégrer l'analyse statique dans son IC
Liste des SCAP citésDeptrac
Exakat
PHP7mar
Phan
PHP Inspections
Phploc
PHPMD
PHP 7 cc
PHPmetrics
RIPS
Transphpile
Edusoho