IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Delphi Discussion :

Chaînage de records génériques


Sujet :

Langage Delphi

  1. #1
    Membre du Club Avatar de CoyotteDundee
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2008
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2008
    Messages : 54
    Points : 47
    Points
    47
    Par défaut Chaînage de records génériques
    Bonjour à toutes et tous,

    Petit problème à soumettre à votre sagacité :
    J'ai créé un record pour les gestion des erreurs dans mon application. Ce record comprend un code d'erreur et un message ainsi qu'un pointeur vers le message d'erreur d'origine. Ceci permet, en chaînant les record, de remonter une erreur depuis le niveau le plus bas vers le GUI....

    Voici la déclaration du record :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
     //---------------------------------------------------------------------------
      //  @classname
      //---------------------------------------------------------------------------
      pChainableIntegerError = ^TChainableIntegerError;
     
      //---------------------------------------------------------------------------
      //  @classname implémente la gestion des erreur chainées ayant un code d'erreur
      // de type entier.
      //---------------------------------------------------------------------------
      TChainableIntegerError = record
      private
        _Parent, _Child: pChainableIntegerError;
      public
        // le code d'erreur
        ErrorCode: integer;
        // Le message associé
        ErrorMessage: string;
     
        // Permet de chaîner les erreurs sous la forma d'une liste doublement chaînée
        procedure Chain( pPreviousError: TChainableIntegerError );
        // permet de réinitialiser l'erreur en supprimant les parents et enfants,
        // en vidant le emssage d'erreur et assignant 0 (zéro) au code d'erreur.
        procedure Clear;
        // Si l'erreur actuelle dispose d'un parent, pvError se voit assigné ce parent et la fonction renvoie True@br
        // Dans le cas contraire, pvError n'est pas modifié et la fonction renvoie False.
        function Parent( var pvError: TChainableIntegerError ): boolean;
        // Si l'erreur actuelle dispose d'un enfant, pvError se voit assigné cet enfant et la fonction renvoie True@br
        // Dans le cas contraire, pvError n'est pas modifié et la fonction renvoie False.
        function Child( var pvError: TChainableIntegerError ): boolean;
      end;
    Tout irait pour le mieux dans le meilleurs des mondes si je ne voulais pas pouvoir changer le type de ErrorCode.
    En effet, j'utilise généralement une énumération pour les codes d'erreur d'un module telle que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     TAaeWmiError = ( weNoError, weNoConnection, weUnknownError );
    Et je n'ai pas une envie folle de ré-écrire un jeu de fonctions pour chaque type de record possible.

    L'idée serait donc de rendre le record générique afin de fixer plus tard le type de ErrorCode.
    Manque de bol, je ne trouve pas la bonne formulation pour Delphi (XE8). :-(

    En effet, en remplaçant "simplement" le record original par sa version générique, Delphi se plaint déjà au niveau de la déclaration du pointeur...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      pChainableIntegerError<T> = ^TChainableIntegerError<T>;
    Je me suis dit" passons nous des pointeurs et déclarons les parent et enfant comme des records..."
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    TChainableIntegerError<T> = record
      private
        _Parent, _Child: TChainableIntegerError<T>;
    La réponse est "E2086 Type 'TChainableIntegerError<T>' is not yet completely defined"
    Selon la doc, il faut passer par la déclaration d'un type pointeur auxiliaire mais Delphi n'accepte pas ma déclaration de pointeur...(cf plus haut)

    Comme il n'est pas possible d'hériter un type record, je ne peux créer un record de base qui serait rendu générique dans un type descendant...

    Donc, si quelqu'un avait idéalement une solution, à défaut une piste de recherche, je suis preneur.
    En vous remerciant déjà de m'avoir lu jusqu'ici

    Coyotte

    ps: En utilisant une classe, il n'y aurait pas de problème... Mais je voudrais un record pour la facilité de gestion. (Pas d'instanciation, libération, ...)

  2. #2
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 457
    Points
    28 457
    Par défaut
    les Generic te crées des type différents, or si je comprend bien ton besoin, tu veux simplement changer l'interprétation de ErrorCode en fonction du contexte

    évidemment au lieu d'un SET tu pourrais utiliser des constantes...

    mais je verrais dans ton cas plutôt un Helper

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    type
      TError = (error0, error1, error2);
     
      TChainableError = record helper for TChainableIntegerError 
        function GetError: TError; inline;
        procedure SetError(Value: TError); inline;
        property Error: TError read GetError write SetError;
      end;
     
    function TChainableError.GetError: TError;
    begin
      Result := TError(ErrorCode);
    end;
     
    procedure TChainableError.SetError(Value: TError);
    begin
      TError(ErrorCode) := Value;
    end;
    ceci dit, l'interprétation de Error sera foireuse si tu n'es pas dans le bon contexte.

    et tu auras sans doute un problème de taille de type...mais il doit être possible de ruser...

  3. #3
    Membre du Club Avatar de CoyotteDundee
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2008
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2008
    Messages : 54
    Points : 47
    Points
    47
    Par défaut
    Bonjour Paul,

    Merci pour la réponse.
    Je vais examiner ta solution... Elle n'offre pas encore la souplesse de la solution (théorique pour le moment) avec les records mais on se rapproche. :-)
    Ce qui est le plus "génant" est qu'il faille écrire une classe de Helper pour chaque type d'erreur.

    De plus, je dois contrôler comment se gèrent les Helpers si plusieurs sont déclarés.
    Si un module qui déclare un helper et appelle une fonction d'un module qui déclare le sien, quel sera le helper actif au retour dans le module d'origine ? Je vais aller me renseigner là-dessus.

    Pour répondre à ta remarque, je n'utilise pas de constante car cela m'obligerait à maintenir une liste des codes d'erreurs utilisés dans toutes les sources... pas glop !

    Merci pour ton aide !

    Coyotte

    ps: Je viens de vite faire un test en essayant de déclarer un helper générique... Las... Delphi n'en veut pas !!!! snif

  4. #4
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par CoyotteDundee Voir le message
    En utilisant une classe, il n'y aurait pas de problème... Mais je voudrais un record pour la facilité de gestion. (Pas d'instanciation, libération, ...)
    Tu pourrais utiliser un Singleton ?

    http://jeremy-laurent.developpez.com...rns/singleton/

  5. #5
    Membre du Club Avatar de CoyotteDundee
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2008
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2008
    Messages : 54
    Points : 47
    Points
    47
    Par défaut
    Hello,

    Non, le singleton n'est pas envisageable puisque je veux pouvoir chaîner mes records ...
    (ben oui, je sais, je suis difficile... )

    Coyotte

  6. #6
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 457
    Points
    28 457
    Par défaut
    Citation Envoyé par CoyotteDundee Voir le message
    Bonjour Paul,

    Merci pour la réponse.
    Je vais examiner ta solution... Elle n'offre pas encore la souplesse de la solution (théorique pour le moment) avec les records mais on se rapproche. :-)
    ? tu as toujours ton record de base, je ne comprend pas ce que tu veux dire

    Citation Envoyé par CoyotteDundee Voir le message
    Ce qui est le plus "génant" est qu'il faille écrire une classe de Helper pour chaque type d'erreur.
    c'est le prix à payer pour faire de la POO sans O

    Citation Envoyé par CoyotteDundee Voir le message
    De plus, je dois contrôler comment se gèrent les Helpers si plusieurs sont déclarés.
    Si un module qui déclare un helper et appelle une fonction d'un module qui déclare le sien, quel sera le helper actif au retour dans le module d'origine ? Je vais aller me renseigner là-dessus.
    le helper le plus proche du code a le dernier mot, mais un helper c'est juste un habillage syntaxique en fait tu pourrais écrire des fonctions que ça serait pareil:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    procedure SetError(var R: TChainableIntegerError; Error: TError);
    function GetError(const R: TChainableIntegerError): TError;
    Citation Envoyé par CoyotteDundee Voir le message
    Pour répondre à ta remarque, je n'utilise pas de constante car cela m'obligerait à maintenir une liste des codes d'erreurs utilisés dans toutes les sources... pas glop !
    il ma manque une étape dans ton raisonnement, admettons que tu ais des TChainableIntegerError spécifiques à chaque unité...comment penses-tu gérer ta pile d'erreur sans savoir ce que doit contenir Error ?!

  7. #7
    Membre du Club Avatar de CoyotteDundee
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2008
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2008
    Messages : 54
    Points : 47
    Points
    47
    Par défaut
    il ma manque une étape dans ton raisonnement, admettons que tu ais des TChainableIntegerError spécifiques à chaque unité...comment penses-tu gérer ta pile d'erreur sans savoir ce que doit contenir Error ?!
    Tout juste !
    La chaîne doit être du même type... Sans quoi je ne peux la traiter uniformément...
    Damned !

    Je vais donc garder mon entier qui reste la solution la plus souple...
    Désolé pour le dérangement et merci pour l'analyse.

    Coyotte

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 6
    Dernier message: 26/01/2003, 14h45
  2. Stocker un record dans un fichier
    Par ushu dans le forum Langage
    Réponses: 7
    Dernier message: 13/12/2002, 16h51
  3. Structure de données de type "RECORD"
    Par chaours dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 30/09/2002, 18h10
  4. Record et TObject
    Par spirale dans le forum Langage
    Réponses: 2
    Dernier message: 13/09/2002, 13h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo