try/catch en cascade, bonne pratique ou pas ?

Eléphant du PHP | 479 Messages

24 avr. 2009, 10:05

Salut à tous,

Je me mets au subtilités de PHP5 et de la POO sur le tard et l'utilisation des try/catch m'intéresse énormément mais je ne sais pas si je m'y prends correctement.
Pour schématiser, j'ai un objet qui instancie un autre objet en son sein et dans chaque méthode de chaque objet, j'ai un try/catch.

Exemple :

Code : Tout sélectionner

<?php class Voiture { function Roule() { global $moteur; // Assumons que le moteur est instancié ailleurs try { if ($moteur->Tourne() == FALSE) throw new Exception(); } catch (Exception $e) { throw new Exception(); } } } // Script principal try { $voiture = new Voiture(); $voiture->Roule(); } catch (Exception $e) { // Traitement de l'exception } ?>
En gros, dans le traitement de la méthode Roule() de ma classe Voiture, je suis obligé de balancer une exception pour la répercuter dans le try/catch appelant (celui du script principal), car si je ne le fais pas, aucune exception ne sera remarquée par le script principal si une erreur survient dans la méthode Tourne() de la classe Moteur.
En gros, est-ce une pratique correcte de cascader les try/catch entre les différents objet et/ou existe-t-il une meilleure méthode ?

Merci d'avance !

Greg

Eléphant du PHP | 217 Messages

24 avr. 2009, 13:33

Bonjour,
le mieux est de ne lever que des exceptions dans tes objets sans les intercepter, mais des exceptions personnalisées.
Par exemple pour la classe Voiture tu auras une classe VoitureException.
Pour la classe Velo une classe VeloException etc...

cela te permettra une meilleur gestion des erreurs dans ton script principal afin d'effectuer des opérations en fonction de l'exception :
try
{
    $voiture = new Voiture();
    $velo = new Velo();
    $voiture->roule();
    $velo->roule();
}
catch(VoitureException $e)
{
    //traitement exception voiture ici
}
catch(VeloException $e)
{
     //traitement exception vélo ici
}
catch(Exception $e)
{
    // traitement exception generique ici
}

Eléphant du PHP | 479 Messages

24 avr. 2009, 14:15

Ca sous-entend qu'il faut que je crée autant d'exceptions personnalisées que j'ai de classes, non ?
Est-ce que ça résoud aussi le problème de l'exception en cascade ?

ViPHP
ViPHP | 4674 Messages

05 mai 2009, 10:51

Hey :),

Il est préférable d'avoir une exception par erreur ou par groupe d'erreur, donc VoitureException, MoteurException etc. (sachant que MoteurException pourrait étendre VoitureException par exemple, selon ta conception bien sûr).

Les exceptions en cascade, ce n'est pas un problème si les exceptions ont un sens (d'où l'utilité de les regrouper correctement).

Enfin, la déclaration en global du moteur est très sale … à revoir absolument ;-).
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Eléphant du PHP | 70 Messages

05 mai 2009, 10:58

Petite optimisation :

- Tu crées 2 instances d'Exception pour une seule erreur.

catch (Exception $e) 
{ 
      throw new Exception(); 
} 

Il te suffit de renvoyer $e qui est déjà une Exception.

try 
{ 
      if ($moteur->Tourne() == FALSE) throw new Exception(); 
} 
catch (Exception $e) 
{ 
      throw $e; 
} 

Concernant les exceptions personnalisées (VoitureException, ...), celà dépend de la complexité de l'application.
Je ne le fais seulement que pour les grosses applications.

Eléphant du PHP | 479 Messages

06 mai 2009, 22:57

HyWan> Je sais que le global n'est pas très propre, surtout dans ce cas là. Dans la pratique, j'utilise un global pour une classe gérant les accès à MySQL, car je ne veux pas gérer une nouvelle connexion pour chaque objet devant utiliser MySQL. Si tu as une autre méthode, ça m'intéresse énormément.

ViPHP
ViPHP | 3300 Messages

06 mai 2009, 23:02

une classe statique pour mysql ca serait mieux qu'un global tout sale
Fait du php depuis que ca existe ou presque :)

ViPHP
AB
ViPHP | 5818 Messages

06 mai 2009, 23:13

une classe statique pour mysql ca serait mieux qu'un global tout sale
++ http://www.journaldunet.com/developpeur ... ry-1.shtml

EDIT : Et viva el Barça :D

ViPHP
ViPHP | 4674 Messages

07 mai 2009, 09:58

Deux solutions :
• la première serait un singleton (constructeur privé, mémorisation de l'objet dans la classe, obtention de l'objet via une méthode statique) ;
• la seconde serait un registre statique abstrait, c'est à dire une classe qui enregistre tout et n'importe quoi, donc peut-être ton objet MySQL.

Si tu as des questions, n'hésites pas !
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Eléphant du PHP | 479 Messages

02 juin 2009, 09:13

Merci pour vos réponses.
Dans mon cas, vu que je n'envisage (pour l'instant) que MySQL comme SGBD, je vais plutôt utiliser un singleton ... heureusement que vous êtes là pour me rappeler de lointains et obscurs cours de POO, car ça fait longtemps que je n'avais pas pratiqué ! ;-)