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 - 03-08-2013

Pour éviter d'utiliser le même mot aprtout:
Opérateur: Objet actif capable de faire des traitements à partir des messages qu'il reçoit, sans que je ne sache comment les traitements sont faits
Message: Ce qui est envoyé par le code utilisateur à l'opérateur
Objet: Elément du message que l'opérateur est en charge de traiter
Conteneur: Objet inerte, recevant un objet et le stockant pour pouvoir le retourner ensuite
X == Y si et seulement si les deux objets ont le même comportement extérieur X.* donnera le même résultat sur X que Y.* donnera sur Y (donc, pas comme Scala le fait)
X === Y si et seulement si les deux objets sont les mêmes, X.* est identique à Y.*


(03-08-2013, 11:42 AM)oxman a écrit : C'est le comportement normal, standard et attendu que book === bookFound.
Dans le cas d'un conteneur (inerte comme une armoire), ok: je mets un truc dans une armoire, je récupère le même truc et pas une copie. Mais pas dans le cas d'un opérateur, sinon, cela "oblige" l'opérateur à stocker l'objet que tu lui as passé, donc, tu sais comment cet opérateur traite le message que tu lui as confié. Si je donne un objet à un humain, je ne sais pas ce qu'il va en faire, et si je lui demande de me le redonner, je ne sais pas s'il va me redonner l'objet ou une copie.


Citation :Si tu sérialises oui tu vas casser book === bookFound
Sérialiser l'objet, c'est du ressort du "comment mon opérateur manipule l'objet que je lui confie", et donc, cela devrait être à l'entière et intégrale liberté de l'opérateur (un conteneur n'est pas un opérateur).
Si je confie l'objet à un conteneur, le conteneur doit me garantir que je peux récupérer le même objet, mais il ne me garantis pas que l'objet sera dans le même état. Si je confie l'objet à un opérateur, il ne me garantis pas que je récupèrerai le même objet (il devrait plutôt garantir le contraire), mais l'objet sera dans le même état (sauf si j'ai demandé à l'opérateur de faire des traitements sur l'objet).


Citation :mais, si tu prévois de sérialiser alors, tu sais que tu ne pourras jamais avoir book === bookFound,
Oui, et donc si je prévois de sérialiser, j'ai un objet actif, et non un Conteneur.

Citation :dans ce cas tu redéfinis === pour que ça fasse une comparaison d'objet selon tes critères.
O.o
Je redéfinis l'opérateur "===" juste parce que j'ai changé le code dans une classe d'un objet? Là, ça me semble être un viol de l'encapsulation. De toute façon, "===" est à considérer comme étant l'opérateur de comparaison strict, qui en gros compare l'adresse mémoire des deux objets (donc, si A === B tfaire A.* ou B.* revient strictement au même)


Citation :Il n'y a pas d'autres façon de faire de toute façon Smile
Si, il y a "empêcher l'utilisateur de faire l'hypothèse qu'après Bibliothèque.add(X) on ait Bibliotheque.get() === X, et l'obliger à ne considérer que Bibliotheque.get() == X (valeurs égales, mais objets différents).


Citation :Je rajouterais que tu mélanges un peu tout je trouve, puisque en programmation on ne s'amuse jamais à comparer les objets ou leur id par référence dans un cas comme ça. Puisque ça ne sert à rien et n'apporte que des problèmes.
Ca, admettons, mais tu contredis ta première phrase:
"C'est le comportement normal, standard et attendu que book === bookFound."
"Comparer" les objets par id/référence n'est pas une fin en soi, mais c'est une hypothèse qui permet de dire "ah, là, j'ai un appel au constructeur de telle classe", et ça, cela fait une différence. Autre exemple: je mets un objet dans mon Conteneur (inerte), et je garde, ailleurs, une référence sur l'objet. Là, pouvoir "comparer", dans la conception du programme, les identifiants des deux objets est essentiels, car on sait alors que les objets pointés par le conteneur peuvent être modifiés ailleurs (et c'est là la clef du problème: le conteneur n'est pas "intègre" en ce sens, et ne peut donc pas traiter les objets vers lesquels ils pointe, mais il peut traiter les pointeurs eux-mêmes qu'il contient).

C'est plus une question de conception que de code lui-même.


Citation :Ton benchmark est faux en plus, voici le bon :
J'ai regardé, et j'ai l'impression qu'à part ajouter un test pour "for + callback", tu n'as rien changé (mais j'ai peut-être raté une ligne?!). Si tel est le cas, le benchmark est juste.
Il ne vise pas à comparer "for + callback: 19" et "forEachCallback: 13", il vise à comparer "forEachCallback: 13" et "forEach: 439".



Ce qui me gène, c'est ce genre de cas:
Code :
monLivre = new Livre();

Conteneur.add(monLivre); // Conteneur stocke le "pointeur" vers monLivre

monLivre.traduire(); // L'objet auquel Conteneur référence est altéré
//Conteneur ne peut donc pas faire la moindre hypothèse sur son propre contenu.

delete monLivre; // Les données mêmes, valeurs de pointeurs, de conteneur n'ont pas changées
// Mais l'hypothèse sur l'intégrité de ces données a changé
// Conteneur ne peut donc pas traiter ses propres objets

Conteneur.forEach(Livre.traduire); // Là, je fais quoi?
// L'un des pointeurs de conteneur est "mort" et pointe sur rien du tout, alors...?
// Si conteneur doit tester lui-même l'intégrité de ses données alors que lui-même n'y a pas touché,
// alors on viole l'encapsulation: si Conteneur n'a rien fait, ses hypothèses (donc son état) ne changent pas

Conteneur devrait permettre de stocker des objets, puis de les récupérer, mais lors de cette opération, j'ignore tout de l'état de l'objet que je récupère (l'état pouvant être "mort", objet supprimé). Il ne devrait pas permettre de faire la moindre opération sur les objets eux-mêmes (à la rigueur, sur les pointeurs, ok). Dans un tel cas d'ailleurs, si je fais "Conteneur.length", je ne récupère pas 0 (0 objets sont valides dans le conteneur) mais bien 1 (1 donnée, 1 pointeur, se trouve dans le conteneur, je sais pas s'il pointe vers un objet disponible ou pas).
Du coup, le "forEach" sur le Conteneur ne devrait pas porter sur les objets du conteneur, mais sur les valeurs des pointeurs du conteneur. En d'autres mots, ne pas avoir
Code :
void function callback(Livre p_livre)
// ou
public:
void function callback() // p_livre = this
Mais avoir
Code :
void function callback(Livre* p_livre)

Et callback ne peut alors plus être une méthode de l'objet "p_livre", c'est forcément une fonction extérieur, puisque callback traite la donnée du conteneur (le pointeur) et non l'objet pointé par le conteneur (qui peut ne pas exister).

Oui, c'est un point de vue hyper-chiant, et super lourd, ça, je veux bien le reconnaitre et donc, comprendre que ce ne soit pas un point de vue adaptable ou recevable pour tous. Après, est-ce une raison pour l'envoyer à la poubelle, à mon sens non. Car nommer ses variables "x y z" c'est rapide, mais les nommer "LivreEnCoursDeTraitement, LivreEnAttente, LivreCalantLePiano" c'est bien plus explicite et facile à maintenir (mais plus long).

Pas faux, Argorate ^^
Mais j'aime bien ce genre de discussion, cela permet de voir d'autres méthodes de dev que ses propres méthodes, et donc, cela enrichis. D'accord, j'vais pas du jour au lendemain changer mes habitudes (et les autres feront surement de même et garderons les leurs), mais cela ajoute des connaissances à sa BDD personnelle XD


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

Citation :mais je suis alors contre l'idée que "Le Livre que je met via add sera le même que celui que je récupèrerai via get", ce qui serait faire un présupposé sur comment la Bibliothèque fonctionne.

Tu sais seulement que tu récupères un livre identique en tous points. Mais il n'est pas question de parler de références mémoire ou autres truc du styles. Tu n'as ici que des objets non mutables, quand tu modifies un livre, tu ne le fais qu'en copiant un nouveau livre avec certains paramètres changés, par exemple le titre et le texte, et le livre précédant disparaît dans le ventre du GC.


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

Là, dans ce cas, ok d'accord, puisqu'il n'y a plus de risque d'avoir un objet qui serait propriété d'une classe, mais qui pourrait être quand même modifié hors de la classe.


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

Xenos pour commencer apprends à faire des réponse très courtes.
Je me suis trompé sur le === je voulais dire ==
que c'était le comportement normal pour ==.

Dans ton benchmark faux ton foreachCallback fait une itération par for donc dans l'autre cas tu dois aussi faire une itération par for.
Puisque le sujet du benchmark était d'encapsuler le callback ou pas lors d'une itération.

Pour maintenant répondre à ton gros message (prend bien note des réponses très courtes) :
Reprends mon poste avec mes exemples de codes en Scala et maintenant oublie totalement la notation de référence mémoire, de pointeur etc.
Qui n'a rien à faire ici, puisque dans la problématique de Bibliothèque que tu as posé ça n'a aucun intérêt.

Si cependant tu affirmes que ça à un intérêt, alors explique juste pourquoi simplement et rapidement l'intérêt que ça à sans répondre à autre chose.


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

Quand on parle de redéfinir '===', on parle de changer la méthode de comparaison. Ici oxman utilise .equals à la place. (Il est sympa, s'il t'avait sorti def === ... je sens que ça t'aurait perturbé.

Pourquoi s'embarasser de vérifier si l'objet est une copie ou non. Ici c'est un bouquin qu'on stocke. En toute logique c'est le même bouquin. S'il est dans la biblio il ne doit pas être ailleurs. Tu peux donc lui faire ce que tu veux en dehors et tu te fous complètement de savoir si la biblio te renvoie une copie de l'objet ou non. Tu considères par contre que c'est le meme bouquin et pas une copie du bouquin. Tu mélanges gravement les niveaux d'abstraction. Comme quand tu dis que en C++ le type considère son conteneur comme pouvant buguer. Oui, ça arrive, mais si ton propre code se méfie de lui même t'as pas fini de rajouter des couches de code abscon par dessus ton code fonctionnel.


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

Court... Ok.
J'ai pas compris pour le benchmark: mon sujet était de tester juste forEach(callback) face à forEachCallback().

Citation :S'il est dans la biblio il ne doit pas être ailleurs.
Oui! \o/
Donc "forEach(callback)" avec "function callback(that)" serait illégitime: that est un objet actuellement dans la biblio et accessible de l'extérieur (dans callback()). Et l'appel à "Biblio.add(Livre)" doit donc non pas ajouter directement "Livre", mais une copie de "Livre".

Citation :Tu peux donc lui faire ce que tu veux en dehors [...] Tu considères par contre que c'est le meme bouquin et pas une copie du bouquin.
Considérer que c'est le même bouquin entre ce qui peut être en dehors de la Bibliothèque et ce que la bibliothèque renvoie? Ca contredirai la phrase précédente (ou alors, j'ai pas compris cette phrase-ci).


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

Non tu n'as pas compris ce que niahoo dit.
Il explique que si tu as un livre stocké dans la variable X, une fois que tu l'as ajouté dans ta bibliothèque, si tu modifies X ça ne modifie pas le livre de la bibliothèque.
Tu peux très bien avoir un système d'itération dans ta bibliothèque pour donner accès à tous les livres un à un.
C'est d'ailleurs ce que l'on a avec un .forEach, l'objet est un iterable.


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

Oui, mais alors, on peut se retrouver avec un code comme ceci:

<html>
<head>
<script>function go()
{
// Classe
var k = function()
{
this.value = 0;
this.increment = function()
{
this.value++;
}
}

// Callback
function callback(val)
{
val.increment();
}

// Conteneur
var t = [new k(), new k(), new k()];

console.log(t);
t.forEach(callback);
console.log(t);
}
</script>
</head>
<body onload="go()">

</body>
</html>

Donnant, dans FireBug:
Citation :[Object { value=1, increment=function()}, Object { value=1, increment=function()}, Object { value=1, increment=function()}]
t.htm (ligne 23)
[Object { value=1, increment=function()}, Object { value=1, increment=function()}, Object { value=1, increment=function()}]

Donc, callback a bien modifié les objets qui normalement ne sont contenus que dans "t", et callback est en dehors de la "classe" t. Ca ne viole pas l'encapsulation? Le contenu de t a été altéré par callback, qui est hors de t.


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

Non ça ne viole rien du tout et c'est parfaitement normal.
Et encore heureux que l'on puisse faire ça.

Donc je dis encore heureux qu'il puisse modifier l'objet dans la librairie puisqu'il a demandé l'objet à la librairie pour travailler dessus.
Aucun rapport avec l'encapsulation.


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

Au contraire, moi ça me gène, car du coup si t avait été une classe, il aurait vu ses propriétés modifiées sans être responsable de cette modification, ce qui fait "fuiter" ses données à l'extérieur de la classe. Bon, ça ne "viole" peut-être pas le principe objet, mais je trouve que cela le rend très peu pratique quand le nombre de classes et de dépendances va exploser au fil du projet. Le callback vient faire une "ingérence" dans les objets que contient t.

t me semble plutôt donner l'accès à l'objet que donner l'objet.