11-08-2014, 09:50 PM
$a1.foo($a2) { $a2->v } me semble aussi sale, de même que le "private sur le scope que tu veux": un élément privé partagé par différentes classes... Ca sent le gaz et l'usine qui va avec :/
Pas d'accord Oxman: dans le cas de l'attribut publique, on peut écraser la valeur de cet attribut, et y mettre n'importe quoi. Dans le cas du getter seul, on ne peut pas écraser l'attribut. Si on ajoute le setter, celui-ci (via type hinting) peut n'autoriser que certaines classes.
Après, faire un getter qui renvoie l'attribut protégé et un setter sans condition n'est pas différent de faire un attribut publique. La faute, à mon sens, n'est pas de vouloir fuir les attributs publiques, mais de faire des getters et des setters trop laxistes, pas assez restrictifs et qui donc, n'apportent rien.
Oui @niahoo, le code du getter en lui-même ok, ce qui me gène, c'est la formulation qu'on trouverait alors dans la doc, type "getMachinChose(): getter de l'attribut machinChose", qui est la formulation sous-entendue par ton "Le getter te donne du contrôle parce qu'il permet d'avoir un membre privé mais tout de même lisible" (enfin, c'est ce que j'en ai compris). Bref, okay pour le getter en lui-même pas de soucis, mais pas okay pour dire, dans la doc "cette méthode renvoie la valeur de $this.chose", ou "Human::getBrain(): renvoie l'attribut Brain du Human".
J'aime bien mettre des casts inutiles en PHP pour voir clairement ce qu'est retourné par une méthode/fonction: cela évite de fouiller la doc, et en plus, cela assure que l'élément retourné sera bien de ce type. C'est redondant quand on fait un return (int)$objet-toInt(), mais au moins, on est certain que c'est un int qui sera retourné (pratique aussi si on utilise un analyseur de code).
Ah? Le fait qu'il y ai plus de classes, "c'est chiant"? Donc, tu as mis toutes les données de ton PC dans le même fichier (qui doit faire des To de long!) parce que plusieurs fichiers c'est chiant aussi? iffle: Plus de classes, c'est chiant pour avoir une vision d'ensemble et approcher la totalité du projet, mais si c'est bien fait, c'est pas plus mal car cela permet de réduire le code à appréhender.
Si je veux ajouter une fonctionnalité à un projet de 1000Ko en 100 classes, il faudra me farcir au moins une classe, soit 10Ko de code (probablement plus), si j'ai 1000 classes, je réduis potentiellement le code à lire, comprendre puis commiter/merger à seulement 1Ko.
(Oui, PHP permet de faire tout et surtout n'importe quoi ^^)
J'aime pas cet exemple, Oxman, car $metadata dans la function() n'est pas décrit, et parce qu'il devient impossible de changer cette fonction (pas top extensible). Utiliser le DP Command et passer, en paramètre, un objet qui contient la méthode "run($metadata)" me semble plus approprié. Surtout, j'exècre le "use" qui sent l'effet collatéral à plein nez.
Niveau souplesse, on y gagne. Si on fait sauter la dépendance de current() à CommandFactory, on peut même changer la factory, et utiliser autre chose qu'une NullCommand si jamais la classe renvoyée par getClass() est "null" (on peut alors générer un DefaultCommand). Mais on rajoute des classes, donc on limite la vision d'ensemble... ce qui est plutôt bien si on considère l'approche objet et non procédurale Mais c'est moins attrayant pour un p'tit nouveau qui relit le code...
Pas d'accord Oxman: dans le cas de l'attribut publique, on peut écraser la valeur de cet attribut, et y mettre n'importe quoi. Dans le cas du getter seul, on ne peut pas écraser l'attribut. Si on ajoute le setter, celui-ci (via type hinting) peut n'autoriser que certaines classes.
Après, faire un getter qui renvoie l'attribut protégé et un setter sans condition n'est pas différent de faire un attribut publique. La faute, à mon sens, n'est pas de vouloir fuir les attributs publiques, mais de faire des getters et des setters trop laxistes, pas assez restrictifs et qui donc, n'apportent rien.
Oui @niahoo, le code du getter en lui-même ok, ce qui me gène, c'est la formulation qu'on trouverait alors dans la doc, type "getMachinChose(): getter de l'attribut machinChose", qui est la formulation sous-entendue par ton "Le getter te donne du contrôle parce qu'il permet d'avoir un membre privé mais tout de même lisible" (enfin, c'est ce que j'en ai compris). Bref, okay pour le getter en lui-même pas de soucis, mais pas okay pour dire, dans la doc "cette méthode renvoie la valeur de $this.chose", ou "Human::getBrain(): renvoie l'attribut Brain du Human".
J'aime bien mettre des casts inutiles en PHP pour voir clairement ce qu'est retourné par une méthode/fonction: cela évite de fouiller la doc, et en plus, cela assure que l'élément retourné sera bien de ce type. C'est redondant quand on fait un return (int)$objet-toInt(), mais au moins, on est certain que c'est un int qui sera retourné (pratique aussi si on utilise un analyseur de code).
Ah? Le fait qu'il y ai plus de classes, "c'est chiant"? Donc, tu as mis toutes les données de ton PC dans le même fichier (qui doit faire des To de long!) parce que plusieurs fichiers c'est chiant aussi? iffle: Plus de classes, c'est chiant pour avoir une vision d'ensemble et approcher la totalité du projet, mais si c'est bien fait, c'est pas plus mal car cela permet de réduire le code à appréhender.
Si je veux ajouter une fonctionnalité à un projet de 1000Ko en 100 classes, il faudra me farcir au moins une classe, soit 10Ko de code (probablement plus), si j'ai 1000 classes, je réduis potentiellement le code à lire, comprendre puis commiter/merger à seulement 1Ko.
(Oui, PHP permet de faire tout et surtout n'importe quoi ^^)
J'aime pas cet exemple, Oxman, car $metadata dans la function() n'est pas décrit, et parce qu'il devient impossible de changer cette fonction (pas top extensible). Utiliser le DP Command et passer, en paramètre, un objet qui contient la méthode "run($metadata)" me semble plus approprié. Surtout, j'exècre le "use" qui sent l'effet collatéral à plein nez.
// Génère un Command($className) si $className n'est pas null,
// génère une NullCommand sinon
class CommandFactory
{
public function build($className)
{
return ($className === null? new NullCommand(): new Command($className));
}
}
class Command
{
$objects[$alias] = new $entityName();
protected $className;
public function __construct($className)
{
$this->setClassName($className);
}
// Juste pour coller un setter ici
protected function setClassName($className)
{
// Si besoin, ajouter des vérifications sur $className
$this6>className = $className;
}
// Opérations à exécuter
public function run($that, $column, &$objects, $alias)
{
$fields = $that->metadataList[$column['table']]->getFields();
if (isset($fields[$column['name']]['fieldName']) === true)
{
$propertyName = 'set' . ucfirst($fields[$column['name']]['fieldName']);
$iterator = $that->iteratorCurrent[$column['index']];
$objects[$alias]->$propertyName($iterator);
}
}
}
// Commande ne faisant rien
class NullCommand
{
public function run()
{
}
}
class ...
{
public function current()
{
$objects = array();
$commandFactory = new CommandFactory();
foreach ($this->targets as $alias => $columns)
{
foreach ($columns as $column)
{
if (isset($objects[$alias]) === false)
{
$columnTable = $column['table'];
$entityName = $this->entityManager->getClass($columnTable);
$command = $commandFactory->build($entityName);
$command->run($this, $column, $objects, $alias);
}
}
}
return $objects;
}
}
Niveau souplesse, on y gagne. Si on fait sauter la dépendance de current() à CommandFactory, on peut même changer la factory, et utiliser autre chose qu'une NullCommand si jamais la classe renvoyée par getClass() est "null" (on peut alors générer un DefaultCommand). Mais on rajoute des classes, donc on limite la vision d'ensemble... ce qui est plutôt bien si on considère l'approche objet et non procédurale Mais c'est moins attrayant pour un p'tit nouveau qui relit le code...