05-06-2015, 09:41 AM
C'est cela.
Je distingue clairement le typage acceptable par une méthode (typehinting) et le typage qui permet à l'algo de réagir différemment (instanceof). Dans ton cas (le 2nd), le typage acceptable et le typage de l'algo sont les mêmes.
Pour moi, c'est mieux, par réutilisabilité et pour le principe de l'open/close, plus d'autres raisons satellites :
• La réutilisabilité est favorisée car il n'existe qu'une seule méthode askGold (qui peut d'ailleurs être typée, par exemple par l'interface Player ou n'importe quelle autre jugée utile): on centralise l'algorithme en un seul endroit (une méthode), et cela évite de répéter du code
• L'open/close car si d'autres discriminations de ce asker sont à ajouter, elles n'impacteront que le code interne de la méthode: aucun changement de classe ni d'interface n'est requis, et aucun impact n'a lieu dans le reste du code (tant que le changement d'algorithme n'impacte pas la doc). On peut même faire ces changements sans toucher au contenu de la méthode existante (s'il est trop complexe, cf l'exemple où elle passe en private).
• Si je n'ai pas besoin, dans mon algo, de différencier Kid et Beggar, la 2nde solution oblige quand même à faire 2 méthodes
• On centralise l'algorithme en un seul lieu: on évite de répéter du code (cf les deux propositions plus bas).
• On peut faire des combinaisons internes: que faire dans le 2nd cas si le demandeur est à la fois un Kid et un Beggar? Il faut ajouter une nouvelle interface? Mais si j'ai 4 types possibles (Kid, Beggar, Stanger, Seller) combinables, il va falloir... 16 interfaces supplémentaires ?!
• Il est du ressort de l'appelé (une seule classe) de faire le tri entre ceux qui demandent de l'or, c'est plus facile à maintenir que de devoir faire le tri au niveau des appelants (multiples, voir même dans d'autres projets).
• Comment faire, dans la 2nd solution, si la classe appelée décide de ne plus réagir différemment pour un typage donné (Beggar)? On garde la méthode Beggar? Ce sera la même que celle de Kid... On la supprime? On casse le code utilisateur.
• On garde la possibilité de bluffer la classe appelée: l'appelant peut lui passer un $object qui est un KidProxy, pour se faire passer pour un Kid
D'ailleurs, j'aurai surement synthétisé de cette façon (en pratique, j'aurai surement fait un return, mais bon):
Je distingue clairement le typage acceptable par une méthode (typehinting) et le typage qui permet à l'algo de réagir différemment (instanceof). Dans ton cas (le 2nd), le typage acceptable et le typage de l'algo sont les mêmes.
Pour moi, c'est mieux, par réutilisabilité et pour le principe de l'open/close, plus d'autres raisons satellites :
• La réutilisabilité est favorisée car il n'existe qu'une seule méthode askGold (qui peut d'ailleurs être typée, par exemple par l'interface Player ou n'importe quelle autre jugée utile): on centralise l'algorithme en un seul endroit (une méthode), et cela évite de répéter du code
• L'open/close car si d'autres discriminations de ce asker sont à ajouter, elles n'impacteront que le code interne de la méthode: aucun changement de classe ni d'interface n'est requis, et aucun impact n'a lieu dans le reste du code (tant que le changement d'algorithme n'impacte pas la doc). On peut même faire ces changements sans toucher au contenu de la méthode existante (s'il est trop complexe, cf l'exemple où elle passe en private).
• Si je n'ai pas besoin, dans mon algo, de différencier Kid et Beggar, la 2nde solution oblige quand même à faire 2 méthodes
• On centralise l'algorithme en un seul lieu: on évite de répéter du code (cf les deux propositions plus bas).
• On peut faire des combinaisons internes: que faire dans le 2nd cas si le demandeur est à la fois un Kid et un Beggar? Il faut ajouter une nouvelle interface? Mais si j'ai 4 types possibles (Kid, Beggar, Stanger, Seller) combinables, il va falloir... 16 interfaces supplémentaires ?!
• Il est du ressort de l'appelé (une seule classe) de faire le tri entre ceux qui demandent de l'or, c'est plus facile à maintenir que de devoir faire le tri au niveau des appelants (multiples, voir même dans d'autres projets).
• Comment faire, dans la 2nd solution, si la classe appelée décide de ne plus réagir différemment pour un typage donné (Beggar)? On garde la méthode Beggar? Ce sera la même que celle de Kid... On la supprime? On casse le code utilisateur.
• On garde la possibilité de bluffer la classe appelée: l'appelant peut lui passer un $object qui est un KidProxy, pour se faire passer pour un Kid
D'ailleurs, j'aurai surement synthétisé de cette façon (en pratique, j'aurai surement fait un return, mais bon):
Code PHP :
<?php
class Conan
{
public askGold($object)
{
$factor = $object instanceof Beggar ? 0.5 : $object instanceof Kid ? 1 : null;
if ($factor != null)
$object->giveGold($this->gold * $factor);
}
}
En return (West):
Code PHP :
<?php
class Conan
{
/**
* Allows $object to ask how much gold Conan has.
* @param $object Who's asking (Conan may lie depending on the asker).
*/
public askGold($object)
{
return $object instanceof Beggar ? $this->gold/2. : $object instanceof Kid ? $this->gold : null;
}
}