1. Traits : de la théorie à la pratique
Rendez-vous AFUP
15 décembre 2010
Paris
La Cantine
Frédéric Hardy
frederic.hardy@mageekbox.net http://blog.mageekbox.net @mageekguy
2. Traits : de la théorie à la pratique
À propos du conférencier
● Frédéric Hardy.
● 35 ans, marié, 3 enfants.
● Développeur PHP depuis plus de 10 ans.
● Participe au développement du langage depuis
plus de 5 ans.
● Contributeur et développeur de plusieurs
projets libres.
● Architecte logiciel chez PMSIpilot à Lyon.
3. Traits : de la théorie à la pratique
Déroulement de la conférence
● Prés-requis
● Résumé de la théorie
● Cas pratique
● Performances
● Comment tester un trait ?
● Les inconvénients
● Conclusion
● Questions
4. Traits : de la théorie à la pratique
Pré-requis
● PHP ≥ 5.next
● En attendant la sortie de 5.next, il faut utiliser la
version de développement de PHP :
# svn export http://svn.php.net/repository/php/php-src/trunk
# cd path/to/trunk
# ./buildconf
# ./configure
# make
● Pour installer la version de développement ou
remplacer la version installée :
# make install
5. Traits : de la théorie à la pratique
Résumé de la théorie
● Les traits sont :
– Une évolution du modèle objet de PHP.
– Une alternative à l'héritage multiple et au mixin.
● Ils permettent d'éviter la duplication de code.
– Via le « copier/coller » de méthodes lors de la
compilation.
● La résolution des conflits est de la
responsabilité du développeur.
6. Traits : de la théorie à la pratique
Cas pratique
● Atoum
– Framework de tests
unitaires.
– Utilise à plein PHP 5.3
● Fonctions anonyme.
● Fermetures.
– Simple et intuitif.
● Interface fluide.
● Aucune configuration.
● Exécution directe.
7. Traits : de la théorie à la pratique
Comment tester le code suivant ?
<?php
namespace vendorproject;
class myClass {
public function readFile($file) {
$content = file_get_contents($file);
if ($content === false) {
throw new exception('Unable to read file ' . $file);
}
return $content;
}
}
...
?>
Cas pratique
8. Traits : de la théorie à la pratique
Il y a plusieurs solutions
● Utiliser un système de fichiers :
– réel.
– virtuel.
● Utiliser un objet :
– Bouchon.
– Adaptateur.
Cas pratique
9. Traits : de la théorie à la pratique
Atoum utilise l'adaptateur
● L'adaptateur est souple :
– Les « fonctions » deviennent « programmables ».
– Le développeur a le contrôle total.
● L'adaptateur est générique :
– Il fonctionne avec toutes les fonctions PHP.
● Il permet de contrôler l'ensemble des fonctions
PHP sans développement supplémentaire.
● Il est simple à mettre en œuvre.
Cas pratique
10. Traits : de la théorie à la pratique
Le code du test unitaire
<?php
...
class myClassTest extends atoumtest {
public function testReadFile() {
$myClass = new vendorprojectmyclass();
$myClass->setAdapter($adapter = new atoumadapter());
$adapter->file_get_contents = false;
$this->assert
->exception(function() use ($myClass, & $file) {
$myClass->readFile($file = uniqid());
}
)
->isInstanceOf('runtimeException')
->hasMessage('Unable to read file ' . $file)
;
}
}
...
?>
Cas pratique
11. Traits : de la théorie à la pratique
Le code de la classe testée
<?php
...
class myClass {
public function setAdapter(atoumadapter $adapter) {
$this->adapter = $adapter;
return $this;
}
public function getAdapter() {
return $adapter;
}
public function readFile($file) {
$content = $this->adapter->file_get_contents($file);
...
}
}
...
?>
Cas pratique
12. Traits : de la théorie à la pratique
Les conséquences sur le modèle objet
● Il est impossible de prédire les classes qui
devront recourir à l'adaptateur.
● Il faut donc dupliquer au besoin dans les
classes qui utilise l'adaptateur le code des
méthodes :
– setAdapter(atoumadapter $adapter).
– GetAdapter().
Cas pratique
13. Traits : de la théorie à la pratique
Et si on tirait un trait sur la duplication ?
● Via la définition d'un trait « adapter ».
– Injectable en fonction des besoins.
● Il n'y a plus de duplication de code.
– La maintenance est simplifiée.
– Les possibilités d'évolution sont augmentées.
Cas pratique
14. Traits : de la théorie à la pratique
Définition du trait
<?php
namespace mageekguyatoumtraits;
use mageekguyatoum;
trait adapter {
public function setAdapter(atoumadapter $adapter) {
$this->adapter = $adapter;
return $this;
}
public function getAdapter() {
return $this->adapter;
}
}
?>
Cas pratique
15. Traits : de la théorie à la pratique
Utilisation du trait
● Suppression dans les classes concernées de
– setAdapter().
– getAdapter().
● Utilisation du trait dans les classes concernées.
<?php
...
abstract class test implements observable, countable
{
use atoumtraitsadapter;
...
}
...
?>
Cas pratique
16. Traits : de la théorie à la pratique
Quelques remarques
● Un trait est considéré comme une classe.
– L' « autoloading » est donc activé si un trait n'est
pas défini lorsqu'il est appelé.
● Les traits sont compatibles avec les espaces de
noms.
● L'appel à un trait via use peut se faire à
l'endroit de son choix dans une classe.
● Un trait ne peut hériter d'un autre trait.
● Une classe ne peut hériter d'un trait.
Cas pratique
17. Traits : de la théorie à la pratique
Performances
● Sans trait :
> Total tests duration: 2.17 seconds.
> Total tests memory usage: 25.75 Mb.
> Running duration: 10.87 seconds.
> Success (63 tests, 264 methods, 3980 assertions) !
● Avec trait :
> Total tests duration: 2.15 seconds.
> Total tests memory usage: 28.25 Mb.
> Running duration: 11.00 seconds.
> Success (63 tests, 264 methods, 3980 assertions) !
Cas pratique
18. Traits : de la théorie à la pratique
Comment tester un trait ?
● Un trait ne peut être instancié, il n'est donc pas
testable par lui-même.
● Il doit être injecté dans un classe.
– Il est donc testable par transitivité.
● Tout comme les méthodes privées et protégées.
● Le support d'un trait par un classe peut être
testé à l'aide de l'API d'introspection de PHP.
19. Traits : de la théorie à la pratique
Les traits et l'API d'introspection
● reflectionClass::isTrait().
● reflectionClass::getTraits().
● reflectionClass::getTraitNames().
● reflectionClass::getTraitAliases().
Comment tester un trait ?
20. Traits : de la théorie à la pratique
Exemple d'utilisation
# vi path/to/reflection.php
<?php
$class = new reflectionClass('mageekguyatoumtest');
$traits = $class->getTraits();
var_dump($traits);
foreach ($traits as $trait) {
var_dump($trait->getMethods());
}
?>
Comment tester un trait ?
21. Traits : de la théorie à la pratique
Résultat de l'exemple
# path/to/php5.4 path/to/reflection.php
array(1) {
["mageekguyatoumtraitsadapter"]=>
&object(ReflectionClass)#57 (1) {
["name"]=>
string(30) "mageekguyatoumtraitsadapter"
}
}
array(2) {
[0]=>
&object(ReflectionMethod)#56 (2) {
["name"]=>
string(10) "setAdapter"
["class"]=>
string(30) "mageekguyatoumtraitsadapter"
}
...
}
Comment tester un trait ?
22. Traits : de la théorie à la pratique
Tester un trait avec Atoum
<?php
...
class test extends atoumtest {
public function testClass() {
$this->assert
->class($this->getTestedClassName())
->useTrait('mageekguyatoumtraitsadapter')
->trait('mageekguyatoumtraitsadapter')
->hasMethod('setAdapter')
->hasMethod('getAdapter')
;
}
public function testSetAdapter() {...}
public function testGetAdapter() {...}
}
...
?>
Comment tester un trait ?
23. Traits : de la théorie à la pratique
Les inconvénients
● Les traits augmentent l'empreinte mémoire.
● L'intégration dans les IDE n'est pas encore
effective.
● La relecture du code est plus « laborieuse ».
● Ils ne sont disponibles qu'à partir de PHP ≥ 5.4
alors que PHP 5.3 n'est pas encore
démocratisé.
24. Traits : de la théorie à la pratique
Conclusion
● Les traits sont une évolution du modèle objet de PHP :
– Qui permet de supprimer la duplication de code
– Via un mécanisme de « copier/coller » à la compilation
– Sous le contrôle du développeur
– Simple à mettre en œuvre
– Testable via l'instrospection
– Mais consommatrice de mémoire
– Et qui n'est pas supporté par les IDE.
– Ce qui peut compliquer l'audit du code.
– Et qui n'est pas encore officiellement disponible.
25. Traits : de la théorie à la pratique
Questions ?
25
26. Traits : de la théorie à la pratique
Références
● http://wiki.php.net/rfc/horizontalreuse
● http://9elements.com/io/?p=28
● http://blog.mageekbox.net/?post/2010/05/17/Et-si-on-tirait-des-traits
26
27. Traits : de la théorie à la pratique
Remerciements
● Merci à Stephan Marr, pour avoir implémenté
les traits dans PHP.
● Merci à l'AFUP pour son invitation.
● Merci à PMSIpilot de m'avoir permis de faire
cette conférence.
Cette conférence est maintenant terminée, vous pouvez reprendre une activité normale.
frederic.hardy@mageekbox.net http://blog.mageekbox.net @mageekguy
27