View
78
Download
0
Category
Preview:
Citation preview
Lorem Ipsum Dolor
A la recherche du code mort
AFUP, Paris
Agenda
❖ Qu'est-ce que du code mort
❖ Code mort classique en PHP
❖ Supprimer le code mort
Conférencier
❖ Damien Seguy
❖ Exakat CTO
❖ Ik ben een boterham
❖ Analyse statique de code PHP : SCAP
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()
Code mort
<?php
function foo() {}
$y = rand(0, 12);
echo 'two';
?>
if ($y == 2) { echo 'deux'; }
?>
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
Code mort en PHP
❖ Installation de base
❖ 766 fonctions
❖ 92 classes
❖ 1024 constantes
❖ Éviter de compiler trop d'extensions
❖ Utilisez disable_functions
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
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!
Comment rechercher le code mort?
❖ Identifier du code
❖ Rechercher son utilisation et ses impacts
❖ Retirer chacun un par un
❖ Retirer le code mort
Trois types de code mort
❖ Code mort classique
❖ Code mort à la mode PHP
❖ Code mort structurel
Code mort classique
Mort dans toutes les langues
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
Code inaccessible
<?php
function foo($bar) { for($i = 0; $i < 10; $i++) { $bar *= 2; exit; // ou die $bar += 1; } }
?>
❖ Code inaccessible
Code inaccessible
<?php
function foo($bar) { for($i = 0; $i < 10; $i++) { $bar *= 2; continue; $bar += 1; } }
?>
❖ Code inaccessible
Code inaccessible
<?php
function foo($bar) { for($i = 0; $i < 10; $i++) { $bar *= 2; break 1; $bar += 1; } }
?>
❖ Code inaccessible
Code inaccessible
<?php
function foo($bar) { $bar *= 2; return $bar;
$bar += 1; return $bar; }
?>
❖ Code inaccessible
Code inaccessible
<?php
$bar *= 2; goto END: $bar += 1; exit; end: print $bar;
?>
❖ Code inaccessible
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
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;
?>
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
Code mort à la mode PHPQuelques squelettes dans les placards
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
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; }
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 )
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
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"; }
?>
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"; } }
?>
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"; } }
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,
Code mort structurel
FichiersConstantesVariablesFunctionsClasses InterfacesTraits
Synopsis
❖ Définitions
❖ Usage
❖ Quelques pièges inévitables
❖ Appels dynamiques
Structural dead code
Traits InterfacesClasses FunctionsConstantesFichiers
Traits
<?php
trait t1 { use t2; }
class c { use t1; } ?>
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; } ?>
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; } ?>
Traits<?php
trait t { function setName($name) { $this->name = $this->normalize($name); } }
class bar { use t; private $name = 'aucun';
function normalize($string) {} } ?>
Interfaces
<?php
interface i2 { }
interface i1 implements i2 { }
class c implements i1 { }
?>
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;
?>
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;
?>
Classes
<?php
classes c1 { }
class c2 extends c1 { }
new c2();
?>
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();
?>
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;
?>
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
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
❖ Interfaces, traits puis classes
❖ Commencez avec les positions basses, puis les moins utilisées
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);
?>
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);
?>
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';
?>
Comment repérer du code mort
❖ Connaissance du code
❖ lint
❖ Grep / Chercher
❖ Analyse statique
❖ Logs / error_reporting
❖ Tests unitaires
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
Merci!
@exakathttp://www.exakat.io/http://slideshare.net/dseguy/
Recommended