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.*
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).
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)
"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.
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:
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
Mais avoir
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
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 === bookFoundSé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çonSi, 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
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