Comment relire du code pourri sans se fatiguer

Post on 23-Jan-2017

70 views 1 download

Transcript of Comment relire du code pourri sans se fatiguer

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

Merci! https://joind.in/talk/dd616

http://exakat.io/ - @exakat