|
Trouver une ressource
Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !
Sujet : serialisation: heritage & évolutivité [ Divers / Aide et documentation ] (Guillemouze)
Informations & options pour cette discussion
mardi 15 avril 2008 à 09:41:28 |
serialisation: heritage & évolutivité

Guillemouze
|
Salut tout le monde, je suis sur un probleme de serialisation de mes objets, et je cherche une maniere efficace pour la sauvegarde/chargement. Ma structure est composée d'une liste d'objets heritants tous de la meme classe de base (a travers de multiples niveaux). on pourrai les symboliser comme ca : A / \ B C / \ / \ D E F G
Mon but est de pouvoir sauvegarder les informations de ces objets de maniere optimale (en terme de rapidité), tout en gardant à l'esprit que ces structures changeront a l'avenir: ajout/suppression de champs, ajout de classes intermediaires (pas sur mais possible), ... j'ai donc pensé a la structure suivante: | Id de la classe | Version de la classe | Champs de la classe | Version de la classe mere | Champs de la classe mere | ...
ce qui me donnera par exemple, pour un objet de la classe E | E | 2 | E1 | E2 | 5 | B1 | B2 | B3 | 1 | A1
ou les Xi sont les champs de la classe X, en supposant que la classe E est en version 2, la B en 5 et la A en 1. J'en arrive donc (enfin) a ma question : Que pensez vous de cette structure? est elle fiable, efficace et evolutive? Peut etre avez d'autres idées/suggestions a me soumettre. Merci de vos réactions :)
|
|
|
mardi 15 avril 2008 à 14:20:27 |
Re : serialisation: heritage & évolutivité

Caribensila
|
Salut Guillemouze,
Si j'ai bien compris...
Je reprends ton exemple pour la classe E et je considère une autre classe D (version 3) par exemple. Ca donnera, pour ces deux classes:
| E | 2 | E1 | E2 | 5 | B1 | B2 | B3 | 1 | A1 | D | 3 | D1 | D2 | 5 | B1 | B2 | B3 | 1 | A1
On voit qu'on sauvegardes deux fois les mêmes données (en rouge)... Ce qui n'est pas optimal. De plus, s'il y a changement dans la structure, il faudra peut-être revoir toutes les classes contenant les parties qui auront changé.
Mais ai-je bien compris ton problème?...
|
|
|
mardi 15 avril 2008 à 14:58:14 |
Re : serialisation: heritage & évolutivité

MAURICIO
|
Effectivement c' est ce que j' ai remarqué aussi: peut-être veux tu garder pour chaque "child" la version du parent avec lequel il descend lors de la sauvegarde ..
|
|
|
mardi 15 avril 2008 à 18:17:58 |
Re : serialisation: heritage & évolutivité

Guillemouze
|
non il n'y a pas redondance. B1, B2, A1, ... sont les valeurs des champs (pour l'instance de E qui est en train d'etre sauvée) hérités de A et B
Petit exemple un peu plus concret : Classe Papi - 2 champs: (version 4) - Toto: integer - Titi : word
Classe Maman - 1 champ: (version 2) - Tutu: char
Class Fiston - 1 champ (version 7) - Tata: byte
Class Fiston2 - 0 champs (version 5)
soit une instance de fiston (F1) et une instance de fiston2 (F2) F1 = (Tata=9, Tutu=C, Titi=12, Toto=23); F2 = ( Tutu=E, Titi=21, Toto=512); je sauverai donc pour F1 : ID_FISTON | 7 | 9 | 2 | C | 4 | 12 | 23 pour F2 : ID_FISTON2 | 5 | 2 | E | 4 | 21 | 512 (en rouge les num de version)
Ainsi, si j'ajoute un champ a Maman par exemple (je passe donc en version 3), je sais que si je li une version 2, je lierai le champ "Tutu", si je lis une version superieur, il faudra aussi que je lise le nouveau champ. En gros, la version m'indique l'espace memoire ocuppée par la classe elle meme
procedure Maman.Read(S: TStream); var v: byte; begin S.Read(v, 1); //lecture de la version S.Read(Self.Tutu, 1); if v > 2 then //Seulement a partir de la version 3 S.Read(MonNouveauChamp, 4);
inherited; // a tour du parent de se lire end;
Donc comme tu le dis mauricio, je ne peux pas savoir qu'une sauvegarde de la version X d'une classe correspond a une version Y de sa classe mere (mes classes n'evoluent pas toutes en meme temps).
Ai-je été clair?
|
|
|
mardi 15 avril 2008 à 18:22:02 |
Re : serialisation: heritage & évolutivité

MAURICIO
|
Haa bem oui, mais c' est qui le père de "Fiston" et "Fiston2" ? ^ ^
|
|
|
mardi 15 avril 2008 à 20:34:14 |
Re : serialisation: heritage & évolutivité

florenth
|
Réponse acceptée !
Salut !
Perso, je trouve que ta structure fonctionne bien.
Après, pour l'implémentation dans le code, tu ne donnes pas trop de détails.
Mais j'imagine que la version de chaque classe est bien retournée par une "class function" et que tu utilises bien l'héritage pour sauvegarder et chercher les propriétés ancestrales.
Vu le code que tu donnes, ça a l'air bon, mais j'aurais une toute petite remarque: faire sauvegarder les ancêtres AVANT la classe elle-même. En gros, appeler inherited en tout premier dans les procédures Read ET Write.
Pourquoi ?
Parce que si tu as besoin d'initialisations, ou autre, il est judicieux de s'assurer que les ancêtres ont un contenu cohérent avec ce que tu vas charger.
En effet, si TChild dérive de TParent, une instance de TParent ne peut pas accéder aux membres de TChild alors qu'une instance de TChild peut accéder aux membres de TParent. Et suivant ce que tu fais dans tes procédures, ce détail ne doit pas être négligé (surtout si tes classes évoluent, on ne peut pas prédire ce que va devenir ton code !)
En plus, ça permet facilement de faire sauvegarder ce que tu appelles l'id de classe (qui ne doit être fait qu'une fois par objet sauvé): il suffit de demander à la classe A de le faire ! Par le jeu des inherited, ce sera elle qui sera sauvée en premier alors que dans ton cas, c'est plus dur.
Voila déjà pour ça.
Ensuite, je ne pense pas que tu va pouvoir ajouter des classes intermédiaires dans ta hiérarchie. Dans tous les cas, c'est affreusement galère !
Et j'aurais une autre idée: donner la taille en octets de chaque enregistrement de classe. Car quand tes versions changeront, tu n'auras plus aucun moyen de le savoir. (ex: une classe de version 2 charge un fichier de version 4: il y a des champs en trop mais elle ne peut pas le savoir)
|
|
|
mardi 15 avril 2008 à 20:37:58 |
Re : serialisation: heritage & évolutivité

florenth
|
Tiens, mes dires sont confirmés par Wikipédia:
http://fr.wikipedia.org/wiki/S%C3%A9rialisation#Types_hi.C3.A9rarchiques
|
|
|
mardi 15 avril 2008 à 20:53:15 |
Re : serialisation: heritage & évolutivité

florenth
|
Sinon, si tu cherches en plus la performance (tant au niveau occupation disque que vitesse de lecture/écriture) j'ai une autre solution, radicale cette fois:
- Comme les versions des classes seront les mêmes pour tout le fichier que tu vas écrire, tu écris une fois toutes ces versions au début du fichier. Comme ça:
1. C'est fait une fois pour de bon.
2. Tu gagnes en rapidité et en place.
- Du coup, tu vas devoir faire quelque chose de beaucoup plus complexe sur le plan structural: chaque classe devra être référencée auprès d'une classe de gestion (comme TBitmap et TJpegImage se référencent sur TPicture) qui se chargera de gérer le chargement/sauvegarde de tout ton bazar.
C'est de l'introspection en sorte, mais fait-maison puisque Delphi ne propose rien** pour le faire automatiquement, à la différence de Java et .net.
**: c'est pas très juste (voire complètement faux) car les composants fonctionnent aussi selon ce principe d'introspection (enregistrement dans les dfm) qu'il est tout à fait possible de réutiliser en faisant descendre tes classes de TComponent, en lui faisant surcharger les méthodes adéquates et en utilisant les classes de Delphi faites pour cela (TReader, TWriter, ...)
Il n'y a "juste" pas de compatibilité descendante puisqu'une exception est produite dans ces cas là (mais peut être que tu ne souhaites pas garantir de compatibilité descendante)
Voila, avec ça tu as de quoi pas mal réfléchir !
[d'ailleurs ce problème aurait du être réfléchi AVANT de coder quoi que ce soit !]
|
|
|
mardi 15 avril 2008 à 20:55:01 |
Re : serialisation: heritage & évolutivité

florenth
|
Pardon, je parlais de compatibilité ascendante (cas où on lit un fichier provenant d0une version plus récente) et non pas descendante dans mon dernier paragraphe.
Voir ici: http://fr.wikipedia.org/wiki/Compatibilit%C3%A9_ascendante_et_descendante
|
|
|
mercredi 16 avril 2008 à 00:06:42 |
Re : serialisation: heritage & évolutivité

Guillemouze
|
merci BEAUCOUP florenth pour toutes ces remarques "Mais j'imagine que la version de chaque classe est bien retournée par une "class function" et que tu utilises bien l'héritage pour sauvegarder et chercher les propriétés ancestrales."Non j'ai choisi d'utiliser des constantes dans le code pour gerer chaque version. Cette info de version n'est utilisée que par la classe elle meme pour savoir quoi lire. En clair, seules les methodes Read et Write de la classe utilisent cette info, donc je ne suis pas allé jusqu'a creer une class function. Peut etre vais-je faire une fonction Read[Write]Version pour genericiser tout ca... a voir. par contre il est sur que j'utilise l'heritage, sinon je perd tout l'interet de ce versionning ! "faire sauvegarder les ancêtres AVANT la classe elle-même."
Carrement, tres bonne idée. mes objets n'utilisent aucune donnée de leur parent lorsqu'ils chargent les leurs, mais ca pourrait tres bien arriver. A changer absolument. "En plus, ça permet facilement de faire sauvegarder ce que tu appelles l'id de classe (qui ne doit être fait qu'une fois par objet sauvé): il suffit de demander à la classe A de le faire ! Par le jeu des inherited, ce sera elle qui sera sauvée en premier alors que dans ton cas, c'est plus dur."C'est peut etre la que se trouve le gros probleme de ma conception. En effet, l'id est sauvé qu'une fois par objet, pour la classe la plus profonde. Mais cette action est faite par le superviseur (la liste d'objets). Cela vient du fait qu'il faut que j'appele le bon TClass.Create . Mon code ressemble a peu pres a ca : procedure TSuperviseur.Load(s: TStream); begin while not EndOfStream(s) do begin s.read(id, 1); classe := Self.GetClassOfId(id); MonObjet := classe.Create; MonObjet.Load(s); end; end;
procedure TSuperviseur.Save(s: TStream); begin for i := 0 to self.Count-1 do begin id := Self.GetIdOfClass(self[i].classType); s.write(id, 1); MonObjet.Save(s); end; end;"donner la taille en octets de chaque enregistrement de classe"Ca me semble aussi tres important pour lire des version ulterieures avec un ancien code. "Comme les versions des classes seront les mêmes pour tout le fichier que tu vas écrire, tu écris une fois toutes ces versions au début du fichier"C'est vrai que c'est pas mal, mais un peu trop galere a mettre en place (utilisation de variables globales, ...). Je garde cette idée de coté, mais je ne vais pas la mettre en place pour l'instant (faute de temps un peu aussi). "en utilisant les classes de Delphi faites pour cela (TReader, TWriter, ...) "J'etais parti sur l'etude de ces classes au debut, je pensai les utiliser ou m'en inspirer fortement, mais j'ai laissé ca de coté pour voir si je trouvai pas une autre solution ... que j'ai finalement choisie. En tout cas merci beaucoup pour toutes ces information qui me sont d'une aide precieuse
|
|
|
Cette discussion est classé dans : champs, classe, structure, objets, serialisation
Répondre à ce message
Sujets en rapport avec ce message
Liste d'objets [ par okemobi ]
Bonjour,J'essaie de créer une liste d'objets avec une TList.Hypothèses : - J'ai une classe d'objet TMyClass avec ses propriétés et méthodes, - j'
Structure Message [ par MicLau ]
Bonjour,Je dois envoyer un message via TCPIP d'un ordinateur à un autre. Mon problème est le suivant :Lorsque je concatène 3 champs, Delphi compresse
Image+base de donnée [ par micfrip ]
Bon, j'ai une petite question toute bête... ( c'est probablement tellement bête que je ne l'ai trouvé nulle part ).J'ai une base de donnée Access qui
BDGRID+image [ par micfrip ]
Bon, j'ai une petite question toute bête... ( c'est probablement tellement bête que je ne l'ai trouvé nulle part ).J'ai une base de donnée Access qui
Locate dans un champs Memo [ par erijeux ]
Je cherche a faire un locate sur un champs memo.je ne trouve pas la solution quoique que je fasse j'ai une erreur.Help !!!!!!!! PLEASE !!!!!!!!!!!
Libération de ressources [ par nicolaspennaneach ]
j'ai une application MDI où chaque fenètre enfant possède un thread pour effectuer certaines opérations. Lorsque j'exécute la méthode formclose d'une
classe indy client / serveur [ par norton ]
hello, n'ayant pas la classe TNMUdp je voulais continuer mon prog de jestion de CyberSalle avec le composant indy mais j'aimerai faire ce code en comp
ouvrir un fichier texte [ par kwentinn ]
salut tout le monde,je dois faire un petit prog sensé récupérer des infos à partir d'un fichier texte.Sur chaque ligne du fichier texte, il y a 6 cham
IdTcpServer-Client [ par pfp ]
Je cherche depuis un sacré moment le moyen d'employer les objets IdTcpServer-Client pour faire une petite application simple d'envoi et réception de m
Ecriture dans un fichier binaire [ par ixpichu ]
Salut!!g un petit problème, j'aimerai écrire une structure dans un fichier binaire, je voudrais savoir: -comment je dois déclarer ma structure qui
Livres en rapport
|
Téléchargements
Logiciels à télécharger sur le même thème :
Comparez les prix Nouvelle version
|