53
Lorem Ipsum Dolor A la recherche du code mort AFUP, Paris

A la recherche du code mort

Embed Size (px)

Citation preview

Page 1: A la recherche du code mort

Lorem Ipsum Dolor

A la recherche du code mort

AFUP, Paris

Page 2: A la recherche du code mort

Agenda

❖ Qu'est-ce que du code mort

❖ Code mort classique en PHP

❖ Supprimer le code mort

Page 3: A la recherche du code mort

Conférencier

❖ Damien Seguy

❖ Exakat CTO

❖ Ik ben een boterham

❖ Analyse statique de code PHP : SCAP

Page 4: A la recherche du code mort

Code mort

❖ Le code jamais utilisé

❖ Les résultats jamais utilisés

❖ Le contraire de :

PHP Fatal error: Uncaught Error: Call to undefined function foo()

Page 5: A la recherche du code mort

Code mort

<?php

function foo() {}

$y = rand(0, 12);

echo 'two';

?>

if ($y == 2) {    echo 'deux'; } 

?>

Page 6: A la recherche du code mort

Code mort<?php 

class A implements B {}

interface B {}

?>

<?php interface B implementedBy A,B,C {}

class A {}

?>

Il serait beaucoup mieux de pouvoir écrire

Page 7: A la recherche du code mort

Code mort en PHP

❖ Installation de base

❖ 766 fonctions

❖ 92 classes

❖ 1024 constantes

❖ Éviter de compiler trop d'extensions

❖ Utilisez disable_functions

Page 8: A la recherche du code mort

Pourquoi faire la chasse ?

❖ Les sources sont plus grandes

❖ Le code est moins maintenable

❖ Le code mort est souvent maintenu

❖ Le code est plus lent

❖ Le code mort grandit au fil dutemps

Page 9: A la recherche du code mort

Pourquoi garder le code mort ?

❖ Personne n'a jamais été viré pour l'avoir gardé

❖ Pourquoi corriger ce qui marche bien

❖ Tous les tests passent pour ce code

❖ D'autres parties du code dépendent de ce code

❖ Le code source croit toujours

❖ On a pas le temps pour ça!

Page 10: A la recherche du code mort

Comment rechercher le code mort?

❖ Identifier du code

❖ Rechercher son utilisation et ses impacts

❖ Retirer chacun un par un

❖ Retirer le code mort

Page 11: A la recherche du code mort

Trois types de code mort

❖ Code mort classique

❖ Code mort à la mode PHP

❖ Code mort structurel

Page 12: A la recherche du code mort

Code mort classique

Mort dans toutes les langues

Page 13: A la recherche du code mort

Code inaccessible<?php

if (false) {    print_r($variable); }

if (0) {     // Gros morceau de code   // fonctionnalité en développement // code avec bug} ?>

❖ Débogage de mon grand-père

Page 14: A la recherche du code mort

Code inaccessible

<?php

function foo($bar) {    for($i = 0; $i < 10; $i++) {      $bar *= 2;             exit; // ou die      $bar += 1;    } }

?>

❖ Code inaccessible

Page 15: A la recherche du code mort

Code inaccessible

<?php

function foo($bar) {    for($i = 0; $i < 10; $i++) {     $bar *= 2;             continue;      $bar += 1;    } }

?>

❖ Code inaccessible

Page 16: A la recherche du code mort

Code inaccessible

<?php

function foo($bar) {    for($i = 0; $i < 10; $i++) {      $bar *= 2;             break 1;      $bar += 1;    } }

?>

❖ Code inaccessible

Page 17: A la recherche du code mort

Code inaccessible

<?php

function foo($bar) {    $bar *= 2;        return $bar;

   $bar += 1;    return $bar; }

?>

❖ Code inaccessible

Page 18: A la recherche du code mort

Code inaccessible

<?php

$bar *= 2; goto END: $bar += 1;        exit;  end: print $bar;

?>

❖ Code inaccessible

Page 19: A la recherche du code mort

Unreachable code

<?php

$bar = 2; goto END;   class X {    const ONE = 1; }

exit;  END: print $bar . X::ONE; ?>

❖ Code inaccessible

❖ Mais pas les définitions

Page 20: A la recherche du code mort

Variables inutilisées<?php 

$uneFois = "Bonjour AFUP";

?>

❖ Les variables mythiques 'utilisées une fois'

❖ 75% des sources contiennent des variables

❖ Global ou local à un contexte

❖ Attention aux imports en masse $_GET/_POST

<?php 

echo $utiliséUneFois;

?>

Page 21: A la recherche du code mort

Variables inutiles

<?php  

function foo() {   $a = "Bonjour AFUP";    //more code    $a = "Bonjour PHP Tour";    //more code   $a .= " et les autres";  }

?>

❖ Variables uniquement écrites

❖ Dans une fonction

❖ Variables uniquement lues sont OK, mais méritent de l'attention

Page 22: A la recherche du code mort

Code mort à la mode PHPQuelques squelettes dans les placards

Page 23: A la recherche du code mort

Clause default dans switch()<?php   

switch($x) {        case '1' :             break;        default :             break;        default :             break;        case '2' :             break;    }   

❖ PHP 7.0+ : Fatal error

❖ l'ordre des 'case' n'est pas important

Page 24: A la recherche du code mort

Le cas des cases

❖ Switch() utilise ==

❖ Les valeurs sont transtypées

switch($x) {        case 1 :             break;        case 0+1 :             break;        case '1' :             break;        case true :             break;        case 1.0 :             break;        case $y :             break;    }   

Page 25: A la recherche du code mort

Les index des tableaux

<?php

$a = [ true  => 1,         1.0  => 2,         1.1  => 3,         4,        "1.4" => 5,        2  => 6];         print_r($a);

?>

❖ Uniquement int et string

❖ Attention aux mélanges entre les index fixes et auto-générés.

Array ( [1] => 3 [2] => 6 [1.4] => 5 )

Page 26: A la recherche du code mort

Le code mort s'exhibe<?php

try {    doSomething(); } catch (NotAnException $e) {

} catch (MyExxeption $e) {

} catch (\Exception $e) {

} catch (MyException $e) {

}

❖ Classes inexistantes

❖ Non-exceptions

❖ Ordre des exceptions, de spécifique à général

❖ Simplement ignorée

Page 27: A la recherche du code mort

Instanceof

❖ La cible est l'espace de noms courant

<?php

class MaClass {}

$o = new MaClass();

if ($o instanceof MaClass) {    print "MaClass est trouvée\n"; }

?>

Page 28: A la recherche du code mort

Instanceof

❖ La cible est l'espace de noms courant

❖ Attention à l'ajout d'espaces de noms

<?php

namespace { class MyClass {} }

namespace X { $o = new \MyClass();

if ($o instanceof MyClass) {     print "Found MyClass\n"; } }

?>

Page 29: A la recherche du code mort

Instanceof

❖ Noms completsdans leschaînes

namespace { class MyClass {} }

namespace X { $o = new \MyClass();

$a = '\\X\\MyClass'; if ($o instanceof $a) {     print "Found MyClass with \$a\n"; } }

Page 30: A la recherche du code mort

Typehint

❖ Les typehint ne sont pas vérifiés

❖ On peut vérifier les typehint à l'exécution

<?php

class foo {}

$o = new foo();

function bar(fooo $a) {}

bar($o); ?>

PHP Fatal error: Uncaught TypeError: Argument 1 passed to bar() must be an instance of fooo, instance of foo given,

Page 31: A la recherche du code mort

Code mort structurel

FichiersConstantesVariablesFunctionsClasses InterfacesTraits

Page 32: A la recherche du code mort

Synopsis

❖ Définitions

❖ Usage

❖ Quelques pièges inévitables

❖ Appels dynamiques

Page 33: A la recherche du code mort

Structural dead code

Traits InterfacesClasses FunctionsConstantesFichiers

Page 34: A la recherche du code mort

Traits

<?php

trait t1 {    use t2; }

class c {    use t1; } ?>

Page 35: A la recherche du code mort

Traits

❖ Utilisées dans les 'use' de classes

❖ Utilisées dans les 'use' de traits

❖ Utilizes dans les appels de méthode statiques, ou de propriétés statiques

<?php

trait t1 {    use t2; }

class c {    use t1; } ?>

Page 36: A la recherche du code mort

Traits

❖ Facile à repérer : appels statique

❖ En espace de noms, avec des alias

❖ Les dépendances locales conduisent à plus de code mort

<?php 

use t1 as t3;

trait t1 {     use t2;  } 

class c {     use t3;  }  ?>

Page 37: A la recherche du code mort

Traits<?php

trait t {    function setName($name) {      $this->name = $this->normalize($name);   } }

class bar {    use t;    private $name = 'aucun';

   function normalize($string) {} } ?>

Page 38: A la recherche du code mort

Interfaces

<?php

interface i2 { }

interface i1 implements i2 { }

class c implements i1 { }

?>

Page 39: A la recherche du code mort

Interfaces

❖ Utilisée dans

❖ les classes

❖ les interfaces

❖ les constante statiques

❖ Les instanceof, catch et type hint

<?php 

interface i2 { const konst = 3; }

interface i1 implements i2 { } 

class c implements i1 { } 

echo i2::konst;

?>

Page 40: A la recherche du code mort

Interfaces

❖ Peuvent finir en chaînes

❖ Peuvent hériter des parents

<?php 

interface i2 { const konst = 3; }

interface i1 implements i2 { } 

$interfaceName = 'i2';

if ($object instanceof $interfaceName) {}

echo i1::konst;

?>

Page 41: A la recherche du code mort

Classes

<?php

classes c1  { }

class c2 extends c1 { }

new c2();

?>

Page 42: A la recherche du code mort

Classes❖ Utilisées dans

❖ Les autres classes

❖ les appels statiques

❖ constantes, propriétés, méthodes

❖ les appels normaux

❖ instanceof, catch, typehint

❖ les instantiations : new

<?php

class c1  { }

class c2 extends c1 { }

new c2();

?>

Page 43: A la recherche du code mort

Classes

❖ new a / new a()

❖ Appels dynamiques un peu partout

❖ Gestion des mots spéciaux : parent, self, static

<?php

class foo {    const ONE = 1;    const TWO = self::ONE + 1; }

class bar extends foo {    const THREE = parent::TWO + self::ONE; }

$class = 'bar'; $o = new \bar;

?>

Page 44: A la recherche du code mort

Classes

❖ Dépendances circulaires

❖ S'applique aussi aux traits et aux interfaces

<?php 

class foo extends bar {     const TWO = bar::ONE + 1;  } 

class bar extends foo {     const ONE = bar::ONE; } 

?>PHP Fatal error: Class 'bar' not found

Page 45: A la recherche du code mort

Classes

❖ Dépendance circulaire vicieuse

<?php 

class foo {     const ONE = 1;     const TWO = bar::ONE + 1;  } 

class bar {     const ONE = foo::TWO; } 

echo bar::ONE;

PHP Fatal error: Uncaught Error: Cannot declare self-referencing constant 'foo::TWO' on line 12

Page 46: A la recherche du code mort
Page 47: A la recherche du code mort

❖ Interfaces, traits puis classes

❖ Commencez avec les positions basses, puis les moins utilisées

Page 48: A la recherche du code mort

Functions

❖ Utilisées dans les appels de fonction

❖ Dépend des espaces de noms, et les alias

❖ Utilises dans les fonctions natives array_map(),…

<?php

function foo() {}

array_map('foo', $array);

?>

Page 49: A la recherche du code mort

Constantes❖ Définies avec const, define

❖ Insensible à la casse, parfois

❖ Les constant() dynamiques

❖ Espaces de noms, alias

❖ Utilisées dans les expressions statiques

❖ Encore des dépendances vicieuses

<?php 

define(ONE, 1, true);

const TWO = ONE + 1; 

$constant = 'TWO'; echo constant($constant);

?>

Page 50: A la recherche du code mort

Inclusions

❖ include/require, /_once

❖ new() parce que autoload()

❖ Constantes statiques, propriété statiques, appels de méthodes statiques

❖ L'ordre est important, car les inclusions s'exécutent

<?php 

include 'file.php';

?>

Page 51: A la recherche du code mort

Comment repérer du code mort

❖ Connaissance du code

❖ lint

❖ Grep / Chercher

❖ Analyse statique

❖ Logs / error_reporting

❖ Tests unitaires

Page 52: A la recherche du code mort

Quand chasser le code mort?❖ Comme relaxation quotidienne

❖ Ma meilleure journée de programmation fut la suppression de 200 classes

❖ trigger_error($msg, E_USER_DEPRECATED) et debug_backtrace()

❖ Sentez en vous la puissance du code vivant

Page 53: A la recherche du code mort

Merci!

@exakathttp://www.exakat.io/http://slideshare.net/dseguy/