Вы находитесь на странице: 1из 15

Les liaisons UML implmentes avec PHP

par Julien Pauli (Tutoriaux, articles et confrences PHP et developpement web) (Blog)
Date de publication : 06/07/2010
Dernire mise jour : 18/06/2011

UML dfinit plusieurs liens remarquables entre les classes. La totalit de ces liens pondrs
permet de mesurer ce que l'on appelle le couplage. Savoir lire un diagramme de classes
est aujourd'hui indispensable pour la conception d'une application web. PHP ne fait pas
exception cela, son modle objet tant trs mr et tout fait capable.
Nous allons ici prsenter les diffrentes liaisons, leurs caracteristiques ainsi que
leurs avantages/inconvnients et quand les utiliser.
Association,
hritage,
agrgation,
composition.
Dans cet article, nous allons voir comment utiliser ces liaisons avec PHP.

Les liaisons UML implmentes avec PHP par Julien Pauli (Tutoriaux, articles et confrences PHP et developpement web) (Blog)

I - Hritage................................................................................................................................................................... 3
I-A - Priv - protg............................................................................................................................................... 3
I-B - Hritage multiple - arbre d'hritage............................................................................................................... 4
I-C - Substitution de Liskov....................................................................................................................................5
II - Association............................................................................................................................................................. 7
III - Agrgation............................................................................................................................................................. 9
III-A - Agrgateur automatis............................................................................................................................... 10
IV - Composition........................................................................................................................................................ 11
V - Implmentation.....................................................................................................................................................12
VI - Lecture d'un schma UML................................................................................................................................. 14
VII - Conclusion......................................................................................................................................................... 15

-2Copyright 2010 - . Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images,
etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://julien-pauli.developpez.com/tutoriels/php/liaisons-uml/

Les liaisons UML implmentes avec PHP par Julien Pauli (Tutoriaux, articles et confrences PHP et developpement web) (Blog)

I - Hritage
Une notion que tout le monde connait certainement, nous passerons vite sur sa dfinition. L'hritage se traduit par
un lien fort entre 2 classes dont l'enfant "est un" - "est une sorte de" vis vis de son parent.
Si l'on ne peut pas dire cela, alors il ne s'agit pas d'un hritage. L'hritage vient rapidement l'esprit pour rsoudre
tous les problmes de conception mais il est rarement la solution et il faut l'utiliser avec modration (une profondeur
d'hritage trop importante traduit un problme de conception).
Nous allons voir que l'hritage possde quelques astuces.
En UML, l'hritage se reprsente par une flche blanche gnralement tourne vers le haut.

Hritage
Une classe vhicule

<?php
class Vehicule { }

Un hritage envers vhicule

<?php
require_once 'path/to/Vehicule.php';
class Voiture extends Vehicule { }

Premire notion: l'hritage est un lien fort. Une partie du code du parent va tre port dans l'enfant, celui-ci a donc
besoin de la dfinition de la classe de son parent pour exister d'o l'instruction require.
Le programme
PHPDepend permet une analyse statique de code et la production de
statistique en terme de couplage, de cohsion et d'hritage.
Pour viter d'avoir charger les dpendances manuellement (require), PHP propose des
mcanismes d'autoload passs en revue

dans cet article.

I-A - Priv - protg


Lorsqu'on parle "d'une partie du code qui va tre porte", il s'agit du code non priv. La diffrence de visibilit entre
priv et protg n'a de sens que pour l'hritage.
Tout ce qui est protg (et donc aussi tout ce qui est public) va tre port du parent vers l'enfant automatiquement
alors que ce qui est priv n'est pas port.
L'hritage et le portage de la visibilit prive en PHP
<?php
class A
{
private $foo;

-3Copyright 2010 - . Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images,
etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://julien-pauli.developpez.com/tutoriels/php/liaisons-uml/

Les liaisons UML implmentes avec PHP par Julien Pauli (Tutoriaux, articles et confrences PHP et developpement web) (Blog)

L'hritage et le portage de la visibilit prive en PHP


}

class B extends A { }
var_dump(new B);
/* affiche
object(B)#1 (1) {
["foo":"A":private]=>
NULL
}
*/

Comme on le voit lorsque PHP dump un objet il utilise une notation "nom-attribut":"nom-classe":private et donc le
nom de la classe qui possde l'attribut priv est bien visible. Ce mcanisme permet PHP de srialiser/dsrialiser
des objets (entres autres choses).
Preuve du non-portage de la visibilit prive
<?php
class A
{
private $foo
= 'A';
protected $bar = 'A';

public function dumpPrivate()


{
return $this->foo;
}
public function dumpProtected()
{
return $this->bar;
}

}
class B extends A
{
private $foo
= 'B';
protected $bar = 'B';
}
$b = new B;
echo $b->dumpPrivate();
echo $b->dumpProtected();
/* Affiche
A
B
*/

Le code ci-dessus dmontre que la visibilit prive n'est pas porte dans l'hritage ce qui est le cas de la visibilit
protge.
Bien sr, nous ne parlons pas ici de la visibilit publique accessible partout et qui est porte
dans l'hritage comme la visibilit protge.

I-B - Hritage multiple - arbre d'hritage


En PHP l'hritage multiple n'existe pas : une classe ne peut hriter que d'une et une seule classe. Ainsi l'hritage
doit se rflchir car il reprsente un point de blocage ("attention, je cre un hritage, si dans le futur je veux hriter
d'une autre classe: je ne pourrai plus").
Une des solutions face un problme d'hritage multiple est le design pattern dcorateur.

-4Copyright 2010 - . Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images,
etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://julien-pauli.developpez.com/tutoriels/php/liaisons-uml/

Les liaisons UML implmentes avec PHP par Julien Pauli (Tutoriaux, articles et confrences PHP et developpement web) (Blog)

En revanche on peut allonger l'arbre d'hritage - tant qu'on respecte la relation "est un", souvent vue comme
"gnralisation - spcialisation" - et tant que l'on ne bloque pas l'arbre au moyen du mot-cl final.
Non respect de la relation d'hritage : fatal error
<?php
class A
{
public function foo() { }
}

class B extends A
{
private function foo() { }
}
/* Affiche
Fatal error: Access level to B::foo() must be public (as in class A)
*/

L'exemple ci-dessus brise la relation d'hritage car B hrite de A mais B n'est pas un A car il ne peut pas faire ce que
A sait faire (on ne peut appeler la mthode foo() sur lui mais on le peut sur son pre). Idem si l'on utilise protected
dans le parent et private dans l'enfant.
La rgle d'hritage est simple: l'enfant doit savoir faire tout ce que sait faire le pre et
ventuellement plus, mais en aucun cas moins ("est-un")
Si vous voulez bloquer l'hritage d'une classe (et donc terminer l'arbre d'hritage), PHP vous le permet au moyen
du mot-cl final
Utilisation de final pour bloquer l'hritage
<?php
class A { }
class B extends A { }
final class C extends B { }

class D extends C { } // Fatal error: Class D may not inherit from final class (C)

Dans l'exemple ci-dessus, nous sommes en prsence d'un arbre d'hritage d'une profondeur de 3 niveaux dont le
dernier niveau est final: toute tentative de prolongement de l'arbre via sa branche C se soldera par une erreur fatale
(la classe D dans l'exemple), il reste possible par contre de prolonger l'arbre en recrant une branche partir de B.
L'utilisation de final devant une classe est rare mais peut s'avrer pratique.
final peut tre utilis devant une mthode empchant ainsi sa surcharge dans une classe
fille. Cette utilisation est rare, mais intressant dans des cas trs spcifiques.

I-C - Substitution de Liskov


Le principe de subsitution est clair: Un objet utilisateur de A doit pouvoir manipuler un fils de A sans s'en rendre
compte. Si vous brisez ce principe, PHP vous avertira mais contrairement l'hritage, il n'enverra qu'une erreur de
niveau Strict si vous avez activ ce rapport d'erreur (qui ne l'est pas par dfaut).
Cassure du principe de Substitution de Liskov

<?php
/* indispensable sinon l'erreur n'apparait pas, en gnral
E_STRICT est activ avec E_ALL dans php.ini pour le dveloppement */
error_reporting(E_STRICT);
class A
{
public function foo($a, $b) { }
}

-5Copyright 2010 - . Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images,
etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://julien-pauli.developpez.com/tutoriels/php/liaisons-uml/

Les liaisons UML implmentes avec PHP par Julien Pauli (Tutoriaux, articles et confrences PHP et developpement web) (Blog)

Cassure du principe de Substitution de Liskov


class B extends A
{
public function foo($a, $b, $c) { }
}
/* Affiche
Strict standards: Declaration of B::foo() should be compatible with that of A::foo()
*/

On voit clairement ici qu'un objet (C par exemple) qui utilisait A ne peut pas utiliser B sa place car il devrait alors
passer un paramtre en plus lors de l'appel de la mthode foo() sur celui-ci. Le principe de substitution rejoint celui
de l'arbre d'hritage mais le pousse un peu plus loin.
Dans l'exemple ci-dessus, le simple fait de passer le paramtre additionnel $c en facultatif (c'est--dire en lui donnant
une valeur par dfaut), rend la signature compatible avec celle du parent, et fait ainsi disparaitre l'erreur.
Briser le principe de substitution de Liskov avec une interface gnrera une erreur de
niveau fatal et non plus strict.

-6Copyright 2010 - . Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images,
etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://julien-pauli.developpez.com/tutoriels/php/liaisons-uml/

Les liaisons UML implmentes avec PHP par Julien Pauli (Tutoriaux, articles et confrences PHP et developpement web) (Blog)

II - Association
L'association est une utilisation ponctuelle ou permanente d'une mthode d'un objet au sein d'un autre.

Association

Association ponctuelle
Si l'utilisation est permanente, l'inclusion de la classe utilise est obligatoire. Dans le cas contraire elle pourra tre
charge l'utilisation et le trait UML devient alors pointill.
Une association permanente

<?php
require_once 'path/to/Log.php';
class Data
{
public function __construct()
{
Log::write('text');
// ...
}
// ...
}

Ici, ds la cration de l'objet Data la classe Log va tre utilise, elle est donc absolument ncessaire. On aurait pu
imaginer d'autres cas identiques fonctionnellement : toutes les mthodes de Data utilisent Log par exemple.
Une association ponctuelle

<?php
class Data
{
public function foo(Log $l)
{
$l->method();
// ...
}
public function bar() { }
}

-7Copyright 2010 - . Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images,
etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://julien-pauli.developpez.com/tutoriels/php/liaisons-uml/

Les liaisons UML implmentes avec PHP par Julien Pauli (Tutoriaux, articles et confrences PHP et developpement web) (Blog)

Dans le cas ci-dessus, on peut utiliser l'objet Data sans jamais avoir besoin de Log (on peut par exemple n'appeller
que la mthode bar() et jamais foo()).
Il s'agit donc d'une association mais ponctuelle. On aurait pu imaginer d'autres exemples o une mthode de Data
utilise la classe Log en l'incluant plutt que d'en recevoir un objet via une mthode.
Rappel: PHP n'a pas besoin de connaitre la dfinition de la classe lorsqu'on type
un paramtre de mthode sur cette classe-l. Aucune instruction require n'est donc
ncessaire.

-8Copyright 2010 - . Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images,
etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://julien-pauli.developpez.com/tutoriels/php/liaisons-uml/

Les liaisons UML implmentes avec PHP par Julien Pauli (Tutoriaux, articles et confrences PHP et developpement web) (Blog)

III - Agrgation
L'agrgation est une association particulire dans laquelle un objet est encapsul dans un autre avec possibilit
d'entre-sortie. C'est une association permanente mais plus prcise qui se traduit par la prsence de getters/setters.
On l'utilise pour effectuer de la dlgation de responsabilits et de l'tude de variabilits/communalits.
En UML, la relation est caractrise par un losange blanc qui va de l'objet agrgant vers l'objet agrg. On traduit
l'agrgation par une relation "a un", "est compos d'un", "utilise les services d'un".

Agrgation
Une agrgation simple en PHP
<?php
class Log
{
protected $file;

public function setFile(File $file)


{
$this->file = $file;
}
public function getFile()
{
return $this->file;
}
public function event($priority, $message)
{
if ($this->file) {
$this->file->write(sprintf("Priority: %d, message: %s", $priority, $message));
}
}

}
class File
{
public function write($message) { }
}

Il est trs important de noter que bien que les 2 objets soient lis, ils ne le sont que si on le dsire et si l'on prend la
peine de les construire et les assembler la main (principe de l'inversion de contrle).
C'est LA diffrence avec la relation de composition (chapitre suivant). Dans notre exemple, l'objet agrg File est
partageable et les accesseurs get/set de Log permettent de partager ou de rcuprer l'objet.
Ici il s'agit de set/get : la cardinalit est donc de 1: l'objet Log ne peut possder en lui
qu'un et un seul objet File. En gnral on matrialise cela sur le schma UML directement
en indiquant la cardinalit prs de la relation. Personnelement je prfre utiliser des
conventions : si la cardinalit avait t de plusieurs (plusieurs objets File peuvent tre
ajouts/retirs Log), alors j'aurais crit des mthodes addFile() et removeFile() et non
get/set qui laissent suggrer "un et un seul".

-9Copyright 2010 - . Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images,
etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://julien-pauli.developpez.com/tutoriels/php/liaisons-uml/

Les liaisons UML implmentes avec PHP par Julien Pauli (Tutoriaux, articles et confrences PHP et developpement web) (Blog)

III-A - Agrgateur automatis


Crer toutes les mthodes get/set des agrgats dans une classe peut devenir pnible. A titre d'exemple voici une
utilisation des mthodes magiques et de la Reflection en PHP pour crer une agrgateur automatis en interceptant
les appels de mthodes set/get.
La classe agrgateur
class Agregator
{
public function __call($meth, $args)
{
if (preg_match("#(g|s)et(\w)+#", $meth, $matches)) {
list(,$getOrSet,$class) = $matches;
try {
$param = new ReflectionProperty($this, $paramName = strtolower(substr($meth, 3)));
} catch(ReflectionException $e) {
$this->fail("Unknown attribute", $e);
}
if (!$param->isPublic()) {
switch ($getOrSet) {
case 'g':
return $this->$paramName;
break;
case 's':
if (array_key_exists(0, $args) && $args[0] instanceof $paramName) {
$this->$paramName = $args[0];
}
return $this;
break;
}
}
$this->fail("Aggregate attribute should not be public", $e);
}
}

private function fail($message, Exception $e = null)


{
throw new RuntimeException($message, null, $e);
}

Dans cette exemple, une mthode __call() est utilise pour intercepter les appels aux mthodes get*() ou set*().
On analyse ensuite le paramtre pass ces mthodes et on regarde si dans la classe il existe un attribut non public
ayant le mme nom (par exemple setA(new A)). Si c'est le cas on s'execute, sinon on renvoie une erreur.
Ce type d'artefact "magique" est utilis sous une forme dforme dans certains
frameworks comme Zend Framework ou Symfony.
L'exemple montr ci-dessus n'est l qu' titre de dmonstration de la flxibilit de PHP, il
n'est pas utilis dans des cas rels car il apporte de nombreux inconvnients.

- 10 Copyright 2010 - . Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images,
etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://julien-pauli.developpez.com/tutoriels/php/liaisons-uml/

Les liaisons UML implmentes avec PHP par Julien Pauli (Tutoriaux, articles et confrences PHP et developpement web) (Blog)

IV - Composition
La composition est une agrgation non-partageable (non-isolable). Concrtement, cela signifie que comme pour
l'agrgation, un objet va tre contenu dans un autre. La diffrence est qu'il n'y a aucun moyen de crer l'objet contenu,
ni de le rcuprer.

Composition
Exemple de composition

<?php
require_once 'path/to/File.php';
class Log
{
protected $file;
public function __construct($path)
{
$this->file = new File($path);
}
public function event($priority, $message)
{
$this->file->write(sprintf("Priority: %d, message: %s", $priority, $message));
}

}
class File
{
public function write($message) { }
}

La composition se reconnait par rapport l'agrgation par l'absence de get/set (non-partageable) et par la prsence
d'un "new" au sein d'une classe (ou d'une fabrique).
Dans l'exemple ci-dessus, la cration d'un objet Log entraine la cration d'un objet File (celle-ci peut cependant tre
diffre) et surtout la destruction de l'objet Log entraine la destruction de l'objet File le composant.
La composition est peu recommande car elle rend le couplage trop fort, elle est l'inverse
du principe d'inversion de contrle et rend ainsi les programmes difficilement testables.

- 11 Copyright 2010 - . Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images,
etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://julien-pauli.developpez.com/tutoriels/php/liaisons-uml/

Les liaisons UML implmentes avec PHP par Julien Pauli (Tutoriaux, articles et confrences PHP et developpement web) (Blog)

V - Implmentation
L'implmentation est une liaison qui fait intervenir une classe et une interface. Une classe implmente une interface.
La relation se dcrit comme "permet", "admet", "a la capacit de".
Contrairement l'hritage, une classe peut implmenter autant d'interfaces qu'elle le souhaite. Une implmentation
n'est pas un hritage, mme si a y ressemble dans la forme.
C'est un lien fort qui ncessite l'inclusion du code de l'interface dans le code de la classe l'implmentant (prsence
d'une instruction require). En UML, cela se traduit par la mme flche qu'un hritage, mais le trait est discontinu.

Implmentation
Une interface quelconque

<?php
interface Vendable
{
function vendre($nb);
}

Implmentation

<?php
require_once 'path/to/Vendable.php';
class Produit implements Vendable
{
public function vendre($nb) { }
public function foobar() { }
}

Si une classe implmente 2 interfaces dfinissant une mme mthode, il y a alors conflit,
PHP renverra une erreur fatale et vous demandera de vous arranger (renommer une
mthode par exemple).
Conflit d'interfaces
interface Foo
{
function baz();
}
interface Bar
{
function baz();
}
class A implements Foo, Bar
{
public function baz() { }
}
/* Affiche
Fatal error: Can't inherit abstract function Bar::baz() (previously declared abstract in Foo)
*/

- 12 Copyright 2010 - . Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images,
etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://julien-pauli.developpez.com/tutoriels/php/liaisons-uml/

Les liaisons UML implmentes avec PHP par Julien Pauli (Tutoriaux, articles et confrences PHP et developpement web) (Blog)

Bien que ce soit rarement utilis, une interface peut hriter (extends) d'une autre et la
surcharger ou la complter.

- 13 Copyright 2010 - . Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images,
etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://julien-pauli.developpez.com/tutoriels/php/liaisons-uml/

Les liaisons UML implmentes avec PHP par Julien Pauli (Tutoriaux, articles et confrences PHP et developpement web) (Blog)

VI - Lecture d'un schma UML


Entrainons-nous la lecture d'un diagramme de classes UML simplifi dans lequel n'apparaissent que des relations.

Schma gnral
A la lecture de ce schma simplifi nous pouvons affirmer (chaque mot des phrases ci-aprs est rflchi) :
1
2
3
4

La classe "principale" est Magasin, on peut lui passer une Personne et des Consommables ;
Il existe 2 types concrts de Personne : Client et Anonyme ;
Il existe 2 types abstraits de Consommable, Service et Produit chacun ayant des sous-types concrts ;
Le Magasin gre un Ticket.

Attention "un" et "des". Si c'est "un" et qu'il s'agit d'une agrgation, des mthodes get/set seront prsentes. Si c'est
"des", pour une agrgation toujours, alors des mthodes add/remove seront prsentes.
"On peut lui passer" dfinit l'agrgation, en revanche "Foo gre un Bar" laisse suggrer une composition de Bar
dans Foo.

- 14 Copyright 2010 - . Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images,
etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://julien-pauli.developpez.com/tutoriels/php/liaisons-uml/

Les liaisons UML implmentes avec PHP par Julien Pauli (Tutoriaux, articles et confrences PHP et developpement web) (Blog)

VII - Conclusion
Les liaisons UML dans les diagrammes de classes sont trs importantes. La comprhension d'un systme
d'information orient objet se dcompose en 2 parties: la comprhension de la responsabilit de chaque objet ET la
manire dont cet objet est li au systme gnral. Exactement comme en mcanique, ou de manire plus gnrale
en "tude de systmes" (dans notre cas informatique).
UML est un langage de modlisation permettant de dessiner des schmas reprsentant une partie prcise d'un
systme informatique. Il existe des tonnes de schmas, pas que le diagramme de classes mme si celui-ci est le
plus utilis.
Il existe aussi des logiciels de modlisation, certains sont capables de gnrer le squelette du code partir du
diagramme de classes. Cette utilisation est peu rpandue dans le monde PHP, mais trs utilise en Java ou encore
en C++.
Notre rubrique gnrale UML
Les patterns de tests avancs avec PHPUnit

- 15 Copyright 2010 - . Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images,
etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://julien-pauli.developpez.com/tutoriels/php/liaisons-uml/