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

C# Discussion :

Dans la structure d'un Objet on met des Id ou des Objet ?


Sujet :

C#

  1. #1
    Membre expérimenté

    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    1 377
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 377
    Points : 1 628
    Points
    1 628
    Par défaut Dans la structure d'un Objet on met des Id ou des Objet ?
    Bonjour,

    Je voulais avoir votre avis sur une petite problématique, qui n'a pas de solution miracle je suppose. Mais qui doit bien avoir ces règles.

    Dans une structure d'un objet en C# en l'occurrence, on a besoin parfois d'avoir une référence à un autre objet (classique ). Ma question est : Est ce qu'on met une référence à l'objet ? Son identifiant uniquement ? Ou ça dépend ?

    Un exemple classique, dans un objet transaction, on a une référence au client et au fournisseur.
    Si notre besoin est de voir la liste des transactions pour un client (dans le cas d'une appli Web ou le client dans son espace veut voir sa liste de transaction). Dans la partie BackOffice, nous devant interroger la base et crée nos objets transactions qui vont bien ... Mais alors quel sera la structure de notre objet Transaction ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Class transaction{
    int IdClient;
    int IdFournisseur;
    DateTime date;
    ...
    }
    ou encore

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Class transaction{
    Client client;
    Fournisseur fournisseur;
    DateTime date;
    ...
    }
    Je crains les réponses "ça dépend les cas", certes ça dépends mais il doit bien avoir des régles ou des théories ou disant simplement des bonnes pratiques ?

    On m'a dit des fois qu'il n y a pas de question conne, parfois j'en suis pas si sûre

    Merci à ceux qui me liront et m'aideront à dormir un peu plus éclairé.

  2. #2
    Membre averti
    Inscrit en
    Octobre 2005
    Messages
    400
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 400
    Points : 444
    Points
    444
    Par défaut
    Perso j'utilise la deuxième option dans un cas similaire. En faites je vais même un peu plus loin. Dans l'objet client j'aurai une liste de transaction, et dans mon objet transaction un objet client.

    Si tu gère bien la chose, ton client ne sera chargé en mémoire qu'une seule fois, car les objets son passé par référence.

    Par exemple, lorsque tu récupère une liste de transactions pour un client dans la base, tu dois récupérer le client qu'une seule fois et l'affecter à chacun de tes objets.

    Mais alors il n'est pas vraiment censé de dire que c'est la meilleure solution. Car dans ce cas tu n'a plus accès à l'identifiant du client sauf si tu fais la reqête. Par exemple, imagine un cas ou tu ne veux pas les infos du client, mais que seul l'identifiant te suffit, bah t'es obligé de tout charger.

  3. #3
    Membre émérite Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Points : 2 925
    Points
    2 925
    Par défaut
    C'est loin d'être une question conne à mon avis. Dans un cas, c'est une classe de gestion qui fera le lien ; dans l'autre, le lien est directement dans les objets métier.

    Dans l'équipe où je suis arrivé, l'un des projets était codé en mettant uniquement les Ids. Avantage : si on a une classe de cache contenant une liste (ou un dico, pour de meilleures perfs) de factures et un autre de client, return monCache.GetClientById(facture.IdClient) renvoie un objet du cache, dont on est sûr qu'il est à jour. Mais ça fait faire un parcours de conteneur.
    Dans un autre projet, je suis passé à des liaisons par référence : la principale contrainte, c'est que si le cache doit être mis à jour au cours de la vie de l'appli indépendamment de l'utilisateur, on peut se retrouver avec des objets métiers qui se référencent les uns les autres alors mêmes qu'ils ont été remplacés dans le cache...

    Autrement dit, là où une gestion par Id permet de faire moncache[objet.Id] = objet sans souci, c'est à dire qu'en cas d'update on peut se contenter de remplacer l'ancien objet par le nouveau, il ne faut pas remplacer une référence par une autre dans le cache ; ça oblige à faire des fonctions "Update" sur les objets métier.

    Sans compter qu'un client charge son cache avec des données fournies par un BDD ou un serveur métier, qui lui travaille la plupart du temps par Id ; si un objet Facture référence un objet Client, il faut d'abord charger le cache de clients avant le cache de factures...

    Donc, d'expérience, une réponse qui va te plaire : ça dépend Je continue mon projet en bossant par références, mais je regrette de pas avoir plus utilisé ADO.Net (qui bosse par id, d'ailleurs).

  4. #4
    Membre expérimenté
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Points : 1 561
    Points
    1 561
    Par défaut
    Les deux méthodes sont bonnes, et on choisi l'une ou l'autre en fonction contexte uniquement.

    Seul le context permet de savoir quelle méthode sera la plus intéressante.
    Par nature, le fait de détenir la référence d'un autre objet, fait que si tu dois t'y référé, c'est facile et rapide
    monObjet.refExterne.propAutreObjet = ...;
    par exemple.

    Ceci convient typiquement s'il s'agit d'une classe instanciée par l'objet détenteur.
    Dans le cadre d'un Client et d'une Facture, ce type de liaison n'est pas la plus efficace, et de toute facon ne colle pas avec la nature persistante des données manipulées.

    En général quand il s'agit d'une liaison entre objets métiers qui ont une persistance en base de données, on stockera plutot l'Id, car c'est au Manager (BLL) de gérer l'instanciation et les instances des objets métiers à proprement dit.
    L'intérêt de ne conserver que l'Id, et d'invoquer le manager pour obtenir l'instance le moment venu, c'est que tu n'a plus à te soucier de savoir si ta référence est valide ou non... comment instancier l'objet... de plus, tu n'a plus à te soucier de l'ordre de chargement des données.

    En effet, les contraintes d'intégrité relationnelle dans la base de données, ne sont pas "systèmiques" dans ton programme, ainsi si tu charge tes factures avant les clients... aucun problème... si tu fait le contaire aucun problème non plus. Si en revanche tu met clairement la référence plutot que l'identifiant... tu es obligé de les charger dans l'ordre et surtout de t'assurer qu'en mémoire à chaque instant, tous les clients dont on a les factures sont en mémoire, dans le cas ou tu ne conserve que l'Id, rien n'oblige à conserver en mémoire l'instance du client conceré par la facture quand on en a pas besoin.
    De plus dans le cas de cette persistance, charger l'objet métier est plus simple, tu le charge directement en provenance de la base sans te demander à quelle référence lier ton instance... car cette donnée est typiquement dynamique, et géré a l'exécution... alors que l'id elle est une données connue avant l'exécution et qui persiste dans le temps, meme après exécution.

  5. #5
    Membre émérite Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Points : 2 925
    Points
    2 925
    Par défaut
    cinemania exprime mieux ma pensée que moi-même, je l'en remercie

    J'ajoute quand même que ça dépend de la nature de la relation entre deux objets. Si c'est une notion d'appartenance forte (ex : une voiture a quatre roues), je trouverais ça dommage d'avoir un cache de voitures d'un côté, un cache de roues de l'autre, et passer par un manager pour faire le lien, d'autant plus si on suppose qu'une voiture ne change pas de roue au cours de la vie de l'appli.

    Je ne sais pas si la perf est une contrainte suffisante : même si le cache est indexé (DataTable avec PK, dico quelconque), je ne sais pas si faire des parcours systématiques est coûteux.

    Cela doit être un problème battu et rebattu, d'autant plus qu'il n'est pas du tout spécifique à C#

  6. #6
    Membre confirmé
    Inscrit en
    Juin 2007
    Messages
    459
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 459
    Points : 553
    Points
    553
    Par défaut
    Je vois qu'il s'agit d'une application web. Si tu utilises les objets plutôt que les identifiants, fais très attention à la gestion de ta session si elle est associée à une base Sql par exemple. La sérialisation peut devenir très vite pénalisante dans le cas de fortes charges.
    Cela peut être un argument pour le choix d'une solution basée sur les identifiants.

  7. #7
    Membre expérimenté
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Points : 1 561
    Points
    1 561
    Par défaut
    un parcours de cache est tjs plus couteux que d'avoir directement l'instance.

    meme dans le cas d'un dico implanté comme une hashtable, en supposant que ta recherche soit toujours en O(1), cas miracle où ton algo de hashcode est parfait et qu'il rende à chaque fois une valeur "unique".
    et bien cette recherche bien qu'en O(1) est plus lente qu'un accès à l'instance elle meme, et oui car dans le cas de la recherche... tu fait d'abord le calcul du code de hashage puis tu fait la recherche.

    en ce qui concerne la voiture on est d'accord qu'en mémoire, il est préférable d'avoir directement la référence vers chacune des roues, plutot que de manipuler leur identifiant, mais cela dépend du contexte aussi.
    mais dans ce cas, on sais également qu'il n'y a pratiquement pas variance de la référence, a moins de crever ou que les pneus soient lisses, mais ca n'arrive pas tous les jours... pour une facture et un client, bien qu'une facture soit établie et immuable, et qu'un client soit générallement établi et immuable, il est plus difficile là de se prononcer en faveur de la référence plutot que l'identifiant.

    pour bien choisir il faut aussi tenir compte de la volumétrie des données en mémoire, si tu rappatrie l'intégralité de ta base en mémoire, pour les cas ou il n'y a pas variation de la liaison entre deux objets pendant leur cycle de vie en mémoire, tu peux opter pour une référence. Si en revanche il y a variance, il est préférable d'avoir juste l'identifiant.
    si par contre tu ne rappatrie qu'une infine partie des informations, conserver l'identifiant plutot que la référence est préférable.
    mais là aussi cette règle peut être enfreinte au cas par cas (exemple de la voiture)

  8. #8
    Membre expérimenté

    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    1 377
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 377
    Points : 1 628
    Points
    1 628
    Par défaut
    Bonjour,

    Merci beaucoup à tous pour vos réponses.

    Moi jusqu'ici dans mon application actuel j'utilisais les ID (sauf dans un cas ou y a dépendance très fortes). Et ce qui m'a poussé à me poser cette question entre autres c'est que j'ai dans un objet plusieurs ID et dans le cas ou on veut afficher ces informations, il est obsolète d'afficher des ID à l'utilisateur. Il faudrait alors faire autant de requêtes à la base que d'ID présent dans l'objet.

    Pour être concret si je reprends l'exemple de la transaction ... Si on imagine qu'il y a un ID client, un ID fournisseur, un ID produit, un ID distributeur ... Quand l'utilisateur veut afficher cette transaction, je dois récupérer ces données, en tout cas au moins le nom du fournisseur, le nom complet du produit, le nom et l'adresse du distributeur (donc autant d'objet à récupérer que d'ID finalement).

    Il est vrai qu'il n y a pas de solution idéal et compte tenu des arguments que vous avez présenté, je suis réconforté quand au choix que j'ai fais. Mais je ne peux m'empêcher de me poser la question, est ce que malgré les désavantages que j'ai cité dans mon exemple, la solution des ID reste la meilleur dans ce cas de figure.

    En tout cas je vous remercie encore pour vos réponses.

Discussions similaires

  1. Réponses: 3
    Dernier message: 04/02/2010, 11h30
  2. Mettre des textures et des couleurs sur les objets
    Par MaTtaW dans le forum PhysX et APEX
    Réponses: 5
    Dernier message: 31/07/2009, 17h42
  3. Structure dans une Structure : Pointeur ou Objet?
    Par TNT89 dans le forum Langage
    Réponses: 11
    Dernier message: 13/07/2009, 19h53
  4. [Conception] Stocker un objet java dans une structure java
    Par m3allem001 dans le forum Langage
    Réponses: 2
    Dernier message: 19/03/2009, 08h41
  5. Réponses: 12
    Dernier message: 25/04/2007, 11h36

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