JeuWeb - Crée ton jeu par navigateur
[JS] Boucle for..in Array et ajout de methodes via prototype = conflit?! - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : [JS] Boucle for..in Array et ajout de methodes via prototype = conflit?! (/showthread.php?tid=7068)

Pages : 1 2 3 4 5 6 7 8 9 10 11


RE: [JS] Boucle for..in Array et ajout de methodes via prototype = conflit?! - Xenos - 02-08-2013

Le pattern strategy n'est pas totalement incompatible avec cette notion "atomique". En un sens, on peut "fusionner" deux atomes (Personnage et EspritCombatif dans l'exemple du SdZ), mais on ne peut pas récupérer l'élément "soin". Un peu comme si on pouvait fusionner des atomes, mais pas les scinder, ce qui ne contredit pas la notion d'objet indivisible (deux objets indivisibles n'ont pas de raison de ne pas pouvoir être fusionnés, mais après fusion, on perd la séparation entre ces objets). De l'extérieur de la classe "Personnage", je ne peux pas accéder à l'objet "EspritCombatif". Au mieux, je peux avoir une méthode qui va me renvoyer un objet "EspritCombatif", mais je ne peux pas dire que cet objet "EspritCombatif" était un composant de "Personnage".

Ce qui me gène dans la Bibliothèque pour laquelle on itère sur les Livres, c'est que l'on considère que les Livre renvoyés par la bibliothèque sont ceux que la Bibliothèque contient. A mon sens, dès l'instant où j'ai envoyé le Livre dans la Bibliothèque, j'en "perd" la trace, car je ne suis pas censé savoir comment la Bibliothèque va manipuler ce livre.

(Après, le débat sera sans fin ^^ Je comprend le point de vue que vous avancez, mais je n'aime pas utiliser ce point de vue là, et je préfère avoir des objets "atomiques", même lourds, plutôt que de considérer que les objets et les conteneurs comme la Bibliothèque sont la même chose et fonctionnent pareil)


RE: [JS] Boucle for..in Array et ajout de methodes via prototype = conflit?! - srm - 02-08-2013

Tu préfères mal coder en résumé.
A ta guise Smile


RE: [JS] Boucle for..in Array et ajout de methodes via prototype = conflit?! - niahoo - 02-08-2013

Les quoi le problème avec les dossiers contenant trois voire un seul fichier ... L'important ce n'est pas que l'objet soit petit mais qu'il soit congru. C'est comme pour les fonctions, qui ne doivent faire qu'une seule chose, et bien. Un objet ne doit gérer qu'une seule chose, et bien. Un paragraphe par idée, une idée par paragraphe comme dirait l'autre.

À ce propos, il faut vraiment revoir ta notion de "atomique".

Quand tu envoies un livre dans la bibliothèque, tu en perds la trace. Mais tu peux quand même récupérer le livre a posteriori (sinon la bibliothèque ne sert à rien). Ceci n'est absolument pas incompatible avec ce que je raconte depuis X posts. Encore une fois, pouvoir itérer sur le contenu d'une collection ne remet pas en cause l'encapsulation du moteur de stockage de cette collection et de la fonction dont elle fonctionne.


RE: [JS] Boucle for..in Array et ajout de methodes via prototype = conflit?! - Xenos - 02-08-2013

Citation :tu peux quand même récupérer le livre a posteriori (sinon la bibliothèque ne sert à rien).
Justement, je pense que non (dans le cas d'un objet, pas d'une collection, sachant que je distingue les deux comme je distinguerait un atome d'une molécule).
Si tu prends du sel, et que tu le dissous dans l'eau, tu en perds la trace. Ensuite, tu fais évaporer l'eau (aka, la bibliothèque fait son petit bazar), et tu récupère à nouveau du sel.
Ok, tu auras la même masse (ou quantité) de sel (en supposant que seule l'eau s'est évaporée), mais rien ne te garantis que le sel récupéré est composé des mêmes atomes (pire, des mêmes électrons) que le sel initial.
Mon principe se situe à ce niveau là, en permettant de distinguer un objet "véritable" (ou "pur") comme l'eau saline, d'une simple collection (un sac avec une bouteille d'eau et une salière).

Donc, on ne "récupère pas le livre", mais on récupère un livre.
Peut-être que, oui, c'est "mal codé", au sens où ce n'est pas les conventions usuelles, mais cela devient très agréable à utiliser quand on est en présence de miriades d'objets. Si, par exemple, j'ai une carte de jeu qui, de base, est composée de cases, alors avec un modèle classique, je pourrait ajouter une case, puis la récupérer ensuite. Avec un modèle "atomique", j'ajoute une case, et je récupère une case, mais aucune garantie d'avoir les mêmes. Je peux alors changer, dans le contenu de ma carte, les cases par une fonction continue (heightmap) par exemple. En effet, à ce moment là, la case peut toujours être envoyée à la carte (la fonction continue sera modulée) et elle peut toujours être récupérée (calcul de la hauteur de la heightmap en un point). Mais je n'ai pas la garantie que ce sera la même case.

Quand tu dis "un objet gère une seule chose", il faudrait préciser ce que tu entends par "chose", car si une fonction ne doit faire qu'une seule chose, et qu'un objet ne doit faire qu'une seule chose, je ne vois pas comment un objet pourrait avoir la possibilité de définir plusieurs fonctions (ou méthodes)... Il ferait alors plusieurs "choses" O.o


RE: [JS] Boucle for..in Array et ajout de methodes via prototype = conflit?! - srm - 02-08-2013

On va faire simple Xenos vu que tu comprends rien.
Donne un code, de 50 à 200 lignes qui est codé à ta façon et montre l'utilité et la puissance de ton code.

Et je coderais la même version en objet propre tu comprendras mieux.


RE: [JS] Boucle for..in Array et ajout de methodes via prototype = conflit?! - Xenos - 02-08-2013

Ok.

Voilà donc ce que je propose:
Code PHP :
<?php

/*objet*/
class Livre
{
private
/*string*/ $titre;
private
/*string*/ $texte;
public function
__construct(/*string*/ $p_titre, /*string*/ $p_texte)
{
$this->titre = $p_titre;
$this->texte = $p_texte;
}
public
/*string*/ function getTitre()
{
return (
$this->titre);
}
}

/*conteneur*/
class ConteneurLivre
{
protected
$livres;
public function
__construct(/*array[Livre]*/ $p_livres=array())
{
$this->livres = Array();
foreach (
$p_livres as $clivre)
$this->stack($clivre);
}
public function
stack(/*Livre*/ $p_livre)
{
$this->livres[] = $p_livre;
}
public
/*Livre*/ function unstack()
{
return (
array_pop($this->livres));
}
public
/*Livre*/ function getLivre(/*string*/ $p_titre)
{
foreach (
$this->livres as $key=>$clivre)
{
if (
$clivre->getTitre() == $p_titre)
{
unset(
$this->livres[$key]);
return (
$clivre);
}
}
}
}

/*objet*/
class Bibliotheque
{
private
/*ConteneurLivre*/ $livres;

public function
__construct()
{
$this->livres = new ConteneurLivre();
}
public function
addLivre(/*Livre*/ $p_livre)
{
$this->livres->stack(clone $p_livre);
}
public
/*Livre*/ function getLivre(/*string*/ $p_titre)
{
return (
$this->livres->getLivre($p_titre));
}
}


// Main
$myBook = new Livre('Lorem Ipsum', 'Lorem ipsum dolor sit amet, consectetur adipisicing elit,...');

$bibliotheque = new Bibliotheque();
$conteneur = new ConteneurLivre();

$bibliotheque->addLivre($myBook);
$conteneur->stack($myBook);

$myOtherBook = $bibliotheque->getLivre('Lorem Ipsum');
$myOtherOtherBook = $conteneur->getLivre('Lorem Ipsum');

assert($myBook === $myOtherBook); //false
assert($myBook === $myOtherOtherBook); //true
assert($myOtherBook === $myOtherOtherBook); //false
?>

Dans ce code, j'ai donc une classe Bibliothèque (objet), une "pseudo-classe" ConteneurLivre (conteneur) et une classe "Livre".
Si j'ajoute un livre au conteneur, je peux le récupérer et je suis certain qu'il s'agit du même livre. ConteneurLivre n'est donc, à mon sens, qu'un conteneur, et non un objet (puisque je peux garder la trace de l'objet entre l'appel à "get" et "set").
Si j'ajoute un livre à la bibliothèque, je peux en récupérer ensuite un autre, mais rien ne me garantis qu'il s'agira du même objet (Bibliothèque n'est pas un conteneur).

La première assertion est fausse, car Bibliothèque est un objet, qui donc ne garantie en rien la "consistance" (ou la tracabilité) des objets qu'on lui envoie (les Livre). En revanche, la seconde est vraie car elle utilise un Conteneur qui garantie cette traçabilité (mais qui, en contre partie, n'est pas un véritable "objet" à mon sens puisque je sais où et comment les données Livre circulent à l'intérieur du conteneur).
La troisième est fausse par déduction.

Maintenant, je veux changer la façon dont Bibliothèque stocke ses données:
Code PHP :
<?php

/*objet*/
class Livre
{
private
/*string*/ $titre;
private
/*string*/ $texte;
public function
__construct(/*string*/ $p_titre, /*string*/ $p_texte)
{
$this->titre = $p_titre;
$this->texte = $p_texte;
}
public
/*string*/ function getTitre()
{
return (
$this->titre);
}
public
/*string*/ function getContenu()
{
return (
$this->texte);
}
}


/*objet*/
class Bibliotheque
{
private
/*array[string]*/ $titres;
private
/*array[string]*/ $textes;

public function
__construct()
{
$this->titres = array();
$this->textes = array();
}
public function
addLivre(/*Livre*/ $p_livre)
{
$this->titres[] = $p_livre->getTitre();
$this->textes[] = $p_livre->getContenu();
}
public
/*Livre*/ function getLivre(/*string*/ $p_titre)
{
$index = array_search($p_titre, $this->titres);
unset(
$this->titres[$index]);
unset(
$this->textes[$index]);
return (new
Livre($this->titres[$index], $this->textes[$index]));
}
}


// Main
$myBook = new Livre('Lorem Ipsum', 'Lorem ipsum dolor sit amet, consectetur adipisicing elit,...');

$bibliotheque = new Bibliotheque();
$bibliotheque->addLivre($myBook);
$myOtherBook = $bibliotheque->getLivre('Lorem Ipsum');

assert($myBook === $myOtherBook); //false
?>

Pour alléger, je ne laisse que le code qui aura changé. Ici, l'assertion est toujours "false": j'envoie un Livre dans la Bibliothèque, mais je n'avais pas de garantie de récupérer le même Livre en sortie, et c'est toujours le cas.
Je peux donc modifier à ma guise tout ce que Bibliothèque contient, sans pour autant que cela ne porte préjudice au reste du code. Tandis que s'il s'agit d'un conteneur, comme ce qu'il contient est "exposé" au reste du code, alors je ne peux pas changer tout ce que je veux comme je veux dans le conteneur (car alors, je n'aurai plus la garantie que ce que j'ajoute dans le conteneur puisse être récupéré en sortie).

Si ma Bibliothèque avait "garantie" que je puisse récupérer le Livre que je lui avait envoyé, alors dans le premier cas (code 1), j'aurai eu une assertion "true", et ici, j'aurai maintenant une assertion "false". Pour autant, je n'ai en rien changé ce que Bibliothèque fait (elle prend un livre, ou elle en envoie un et le supprime de sa base).

Donc, dans un conteneur, je ne peux pas changer tout ce que je veux comme je veux, car je prend le risque de perdre l'assertion "$myBook = $conteneur->getLastBook()". En revanche, dans un objet, cette assertion sera toujours fausse car on n'a pas de trace des objets Livre qu'on envoie à la Bibliothèque.

En un sens, pour moi, un "get()" ne renvoie une référence que s'il s'agit d'une méthode d'un Conteneur (qui n'a donc pas le droit de faire quoi que ce soit des objets, si ce n'est les stocker).
Un "get()" sur un objet renvoie obligatoirement une valeur et non une référence et l'objet peut donc faire ce qu'il souhaite avec les objets qu'on lui envoie.


RE: [JS] Boucle for..in Array et ajout de methodes via prototype = conflit?! - niahoo - 02-08-2013

Non une fonction ne fait qu'une seule chose, par exemple enregistrer un livre, récupérer un livre, traduire un livre, etc. Un objet ne **gère** qu'un seule chose, par exemple une collection de livres. C'est plutôt simple comme concept.

Bon et donc pour reprendre ta métaphore sur le sel, excuse moi mais c'est n'importe quoi. Quand je stocke un livre dans une bibliothèque, je veux pouvoir récupérer exactement ce livre, et pas une version dissoute dans l'eau avec l'encre à moitié effacée, des pages d'un autre livre et le dernier chapitre en anglais. non merci.


RE: [JS] Boucle for..in Array et ajout de methodes via prototype = conflit?! - Xenos - 02-08-2013

D'accord pour le distingo Faire / Gérer.

Si tu préfères ainsi fais donc Wink Je préfère de mon coté stocker les objets dans des Conteneurs qui ne font rien d'autre que stocker (ils ne gèrent que le fait de stocker) et envoyer des objets à manipuler à d'autres objets, sans espérer les récupérer exactement après le traitement.


RE: [JS] Boucle for..in Array et ajout de methodes via prototype = conflit?! - niahoo - 02-08-2013

Bon allez, je montre mon code.


$bibliothèque = [];

(02-08-2013, 05:05 PM)Xenos a écrit : Je préfère de mon coté stocker les objets dans des Conteneurs qui ne font rien d'autre que stocker (ils ne gèrent que le fait de stocker)

Je me tue à démontrer que c'est le but d'une bibliothèque

(02-08-2013, 05:05 PM)Xenos a écrit : et envoyer des objets à manipuler à d'autres objets, sans espérer les récupérer exactement après le traitement.

Pourquoi s'infliger cette contrainte. Reste atomique : stockage, pas partage.


RE: [JS] Boucle for..in Array et ajout de methodes via prototype = conflit?! - srm - 02-08-2013

En gros tout ce que tu as dit c'est du bullshit car dans ton exemple tu fais qu'utiliser le pattern adaptateur.
De plus tu le fais mal, sans injection de dépendance, du coup ton code est intestable (au sens test unitaire).