Short:
Code Erlang, ok
Code Scala: Library garantie que book === bookFound? C'est Storage qui assure que l'objet même est conservé (même emplacement mémoire), pas Library (et le comportement de Library ne doit pas être dicté par son initialisation via Storage). Ou alors Scala passe tout par référence et là, Ok.
Dans Storage (stocker/déstocker des références), le risque est l'injection: l'objet référencé peut être accéder de l'extérieur. Storage contient des données non fiables et ne devrait donc rien en faire. replace_all_books ne devrait pas être de son ressort: Storage ne peut pas considérer ses propres données comme fiables donc ne peut pas les traiter proprement.
2nd code PHP ne garantis pas que le Livre envoyé à Bibliothèque sera le même que celui récupéré (c'est le boulot de Conteneur ça). Donc si Livre change, Bibliothèque n'est pas "non-fiable" même avec titre/texte seul (sans l'auteur). On pourrait sinon utiliser "detDatas" ou "Serialize".
Idée clef:
Pour Storage, add() === get() mais données internes de Storage non fiables.
Pour un objet pur, add() !== get() mais données internes fiables, donc traitements possibles.
Long
@niahoo: ok! Merci de la tartine, le matin, c'est bienvenue
Effectivement, là, je suis d'accord avec le code. Le livre ne reste pas dans la bibliothèque quand on le récupère, et on traite la bibliothèque dans son ensemble. En revanche, on ne peut donc pas "garantir" que get_livre("Hamlet") va renvoyer le même objet Livre que celui dans add_livre(Bibli, Livre("Hamlet")), puisque sinon, on présupposerai que la Bibliothèque stocke ses Livres de façon "unique" (on présuppose que la Bibliothèque stocke l'objet Livre et non pas une copie, ou ses données sérializées, ou autre).
Et de même, "pour chaque livre contenu dans la bibliothèque" la fonction replace_all_boks va être appliquée, d'accord, mais l'objet Livre auquel la fonction sera appliquée, rien ne me garanti que ce sera le même objet que je récupèrerai en sortie (la Bibliothèque peut donc très bien recevoir le message add_book(Livre), sérializer le Livre sans détruire l'objet d'origine, puis recevoir le message replace_all_books(callback) et pour chaque donnée sérializée, créer l'objet Livre associé, lui appliquer le callback, le resérializer puis le détruire).
Je suis donc pour cette implémentation (puisque get, add et forEach sont effectivement des messages) 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.
Quand au 2nd code, effectivement, Bibliothèque fait le postulat que les données du Livre sont "titre" et "texte". Je devrais en effet changer ces deux méthodes "getTitle" et "getText" pour un "getDatas" ou pour un "Serialize" par exemple. Mais le fait de ne prendre que Titre et Texte n'est pas si buggé en soi, car la Bibliothèque, à mon sens, ne garantis pas le stockage des livres (c'est le Conteneur qui le garantis). L'astuce et la clef est justement là: la garantie fournie par Storage ne se retrouve pas dans Bibliothèque car je n'ai pas l'assurance du fonctionnement de Bibliothèque: je n'ai pas l'assurance que Bibliothèque utilisera Storage. Et à l'inverse, Storage stockant les références aux objets (ou leurs pointeurs), je n'ai alors pas la garantis dans Storage que les objets ne vont pas être changés par un autre bout de code (mais Storage garantis que le Livre sera conservé dans son intégrité).
Si je fais du C/C++, Storage va stocker des pointeurs, mais rien ne me garantis que ces pointeurs pointent encore vers un objet valide (je peux ajouter un objet à Storage qui stocke donc le pointeur, puis détruire l'objet, et Storage a alors un pointeur invalide). Or, si les données de Storage (internes) ne sont pas fiables car modifiables de l'extérieur, Storage ne devrait alors pas les traiter, en aucune façon.
Alors, oui, si je fais "replace_all_books", ce n'est pas Storage qui va traiter les Livres, mais callback. Sauf que du point de vue du code utilisateur, le message est envoyé à Storage, donc, c'est Storage qui fait le traitement pour l'utilisateur... C'est là où je trouve cela litigieux: si "bug" il y a, pour l'utilisateur, cela vient de Storage, alors qu'en fait, Storage ne garanti pas que les données stockées persisteront et seront fiables. Y'a un peu une forme "d'injection" dans Storage, puisqu'il stocke des références à des objets que je peux manipuler du dehors, et donc Storage ne devrait avoir le droit de ne rien faire si ce n'est stocker / déstocker ces références.
@Oxman: Merci aussi pour la tartine.
ok, je pensais que tu parlais du 2nd code.
Sur le code Scala, ce qui me gène alors, c'est que l'on a forcément (book === bookFound), et c'est là où cela me gène car alors je ne peux alors plus utiliser, comme StorageLibrary, une base de données qui sérialiserait l'objet puisque dans un tel cas, on aurait "book != bookFound" car 2 objets différents auront été créés (si on va ras les pâquerettes, on verrait que les pointeurs mémoire vers chaque objet ne sont pas les mêmes). C'est cette information, qui "filtre" hors de StorageLibrary, qui me gène.
C'est comme si, dans une architecture Client - Serveur - Base de données, le Client (Main) demandait son identifiant (Livre) au Serveur (Bibliothèque). Le serveur demande alors l'identifiant à la BDD (Storage). La BDD renvoie un identifiant. Le serveur retransmet ce même identifiant au Client. Le client reçoit alors non pas son identifiant sur le serveur, mais son identifiant sur la BDD. Normalement, le serveur devrait renvoyer une copie de l'identifiant, qui serait alors bel et bien l'identifiant du Client sur le Serveur (même si la valeur est égale, ce n'est pas le même objet, donc ce n'est pas garanti que la valeur sera égale). Si le client fait le test (Serveur.getId() == BDD.getId()), alors il récupère "true" (car les valeurs sont égales) mais s'il fait (Serveur.getId() === BDD.getId()) ou (&Serveur.getId() == &BDD.getId()) il récupère "false", car les objets sont différents.
Or, là, ce qui flotte dans l'air c'est que (book === bookFound) est une garantie fournie par Library (puisque j'attaque Library quand je fais addBook ou getByTitle). Or, cette garantie ne vient de la Library elle même, mais de Storage. Et je ne suis pas censé savoir comment Library a traité le Storage que je lui ai envoyé à sa construction.
Le addBook() == getBook() pour le Storage ne me pose encore pas trop de problème: je sais que Storage prend les objets eux-mêmes, et me les stocke. Mais en ce cas, Storage ne garanti rien sur les objets stockés, puisque le code utilisateur peut créer un objet, le mettre en Storage, puis modifier l'objet et donc l'objet que Storage possède (par "référence") sera aussi modifié. Si Storage ne peut rien garantir sur la fiabilité et l'immuabilité de ce qu'il contient, il ne peut faire aucun traitement lui-même.
Mais pour Library, addBook==getBook vient du Storage. Or, si je reprends les "Good coding Practices" (ok, je ne sais plus d'où elles viennent exactement, mais je les ai récupérées pendant mes cours), j'y lis "Objet usage must not rely on Objet's initialization". Or, le comportement de Library (addBook === getBook) provient de la manière de l'initialiser (avec Storage). Ca, ça me gène. Comme si j'insérai un objet dans mon SGDB et qu'en récupérant l'objet, je suis certain que c'est l'objet inséré et non une copie (alors qu'en fait, c'est bien une copie que je récupère).
Tout ceci n'étant valable que si Scala passe les arguments des appels de fonction par référence et non par valeur.
Code Erlang, ok
Code Scala: Library garantie que book === bookFound? C'est Storage qui assure que l'objet même est conservé (même emplacement mémoire), pas Library (et le comportement de Library ne doit pas être dicté par son initialisation via Storage). Ou alors Scala passe tout par référence et là, Ok.
Dans Storage (stocker/déstocker des références), le risque est l'injection: l'objet référencé peut être accéder de l'extérieur. Storage contient des données non fiables et ne devrait donc rien en faire. replace_all_books ne devrait pas être de son ressort: Storage ne peut pas considérer ses propres données comme fiables donc ne peut pas les traiter proprement.
2nd code PHP ne garantis pas que le Livre envoyé à Bibliothèque sera le même que celui récupéré (c'est le boulot de Conteneur ça). Donc si Livre change, Bibliothèque n'est pas "non-fiable" même avec titre/texte seul (sans l'auteur). On pourrait sinon utiliser "detDatas" ou "Serialize".
Idée clef:
Pour Storage, add() === get() mais données internes de Storage non fiables.
Pour un objet pur, add() !== get() mais données internes fiables, donc traitements possibles.
Long
@niahoo: ok! Merci de la tartine, le matin, c'est bienvenue
Effectivement, là, je suis d'accord avec le code. Le livre ne reste pas dans la bibliothèque quand on le récupère, et on traite la bibliothèque dans son ensemble. En revanche, on ne peut donc pas "garantir" que get_livre("Hamlet") va renvoyer le même objet Livre que celui dans add_livre(Bibli, Livre("Hamlet")), puisque sinon, on présupposerai que la Bibliothèque stocke ses Livres de façon "unique" (on présuppose que la Bibliothèque stocke l'objet Livre et non pas une copie, ou ses données sérializées, ou autre).
Et de même, "pour chaque livre contenu dans la bibliothèque" la fonction replace_all_boks va être appliquée, d'accord, mais l'objet Livre auquel la fonction sera appliquée, rien ne me garanti que ce sera le même objet que je récupèrerai en sortie (la Bibliothèque peut donc très bien recevoir le message add_book(Livre), sérializer le Livre sans détruire l'objet d'origine, puis recevoir le message replace_all_books(callback) et pour chaque donnée sérializée, créer l'objet Livre associé, lui appliquer le callback, le resérializer puis le détruire).
Je suis donc pour cette implémentation (puisque get, add et forEach sont effectivement des messages) 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.
Quand au 2nd code, effectivement, Bibliothèque fait le postulat que les données du Livre sont "titre" et "texte". Je devrais en effet changer ces deux méthodes "getTitle" et "getText" pour un "getDatas" ou pour un "Serialize" par exemple. Mais le fait de ne prendre que Titre et Texte n'est pas si buggé en soi, car la Bibliothèque, à mon sens, ne garantis pas le stockage des livres (c'est le Conteneur qui le garantis). L'astuce et la clef est justement là: la garantie fournie par Storage ne se retrouve pas dans Bibliothèque car je n'ai pas l'assurance du fonctionnement de Bibliothèque: je n'ai pas l'assurance que Bibliothèque utilisera Storage. Et à l'inverse, Storage stockant les références aux objets (ou leurs pointeurs), je n'ai alors pas la garantis dans Storage que les objets ne vont pas être changés par un autre bout de code (mais Storage garantis que le Livre sera conservé dans son intégrité).
Si je fais du C/C++, Storage va stocker des pointeurs, mais rien ne me garantis que ces pointeurs pointent encore vers un objet valide (je peux ajouter un objet à Storage qui stocke donc le pointeur, puis détruire l'objet, et Storage a alors un pointeur invalide). Or, si les données de Storage (internes) ne sont pas fiables car modifiables de l'extérieur, Storage ne devrait alors pas les traiter, en aucune façon.
Alors, oui, si je fais "replace_all_books", ce n'est pas Storage qui va traiter les Livres, mais callback. Sauf que du point de vue du code utilisateur, le message est envoyé à Storage, donc, c'est Storage qui fait le traitement pour l'utilisateur... C'est là où je trouve cela litigieux: si "bug" il y a, pour l'utilisateur, cela vient de Storage, alors qu'en fait, Storage ne garanti pas que les données stockées persisteront et seront fiables. Y'a un peu une forme "d'injection" dans Storage, puisqu'il stocke des références à des objets que je peux manipuler du dehors, et donc Storage ne devrait avoir le droit de ne rien faire si ce n'est stocker / déstocker ces références.
@Oxman: Merci aussi pour la tartine.
ok, je pensais que tu parlais du 2nd code.
Sur le code Scala, ce qui me gène alors, c'est que l'on a forcément (book === bookFound), et c'est là où cela me gène car alors je ne peux alors plus utiliser, comme StorageLibrary, une base de données qui sérialiserait l'objet puisque dans un tel cas, on aurait "book != bookFound" car 2 objets différents auront été créés (si on va ras les pâquerettes, on verrait que les pointeurs mémoire vers chaque objet ne sont pas les mêmes). C'est cette information, qui "filtre" hors de StorageLibrary, qui me gène.
C'est comme si, dans une architecture Client - Serveur - Base de données, le Client (Main) demandait son identifiant (Livre) au Serveur (Bibliothèque). Le serveur demande alors l'identifiant à la BDD (Storage). La BDD renvoie un identifiant. Le serveur retransmet ce même identifiant au Client. Le client reçoit alors non pas son identifiant sur le serveur, mais son identifiant sur la BDD. Normalement, le serveur devrait renvoyer une copie de l'identifiant, qui serait alors bel et bien l'identifiant du Client sur le Serveur (même si la valeur est égale, ce n'est pas le même objet, donc ce n'est pas garanti que la valeur sera égale). Si le client fait le test (Serveur.getId() == BDD.getId()), alors il récupère "true" (car les valeurs sont égales) mais s'il fait (Serveur.getId() === BDD.getId()) ou (&Serveur.getId() == &BDD.getId()) il récupère "false", car les objets sont différents.
Or, là, ce qui flotte dans l'air c'est que (book === bookFound) est une garantie fournie par Library (puisque j'attaque Library quand je fais addBook ou getByTitle). Or, cette garantie ne vient de la Library elle même, mais de Storage. Et je ne suis pas censé savoir comment Library a traité le Storage que je lui ai envoyé à sa construction.
Le addBook() == getBook() pour le Storage ne me pose encore pas trop de problème: je sais que Storage prend les objets eux-mêmes, et me les stocke. Mais en ce cas, Storage ne garanti rien sur les objets stockés, puisque le code utilisateur peut créer un objet, le mettre en Storage, puis modifier l'objet et donc l'objet que Storage possède (par "référence") sera aussi modifié. Si Storage ne peut rien garantir sur la fiabilité et l'immuabilité de ce qu'il contient, il ne peut faire aucun traitement lui-même.
Mais pour Library, addBook==getBook vient du Storage. Or, si je reprends les "Good coding Practices" (ok, je ne sais plus d'où elles viennent exactement, mais je les ai récupérées pendant mes cours), j'y lis "Objet usage must not rely on Objet's initialization". Or, le comportement de Library (addBook === getBook) provient de la manière de l'initialiser (avec Storage). Ca, ça me gène. Comme si j'insérai un objet dans mon SGDB et qu'en récupérant l'objet, je suis certain que c'est l'objet inséré et non une copie (alors qu'en fait, c'est bien une copie que je récupère).
Tout ceci n'étant valable que si Scala passe les arguments des appels de fonction par référence et non par valeur.