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 :

Problème de modélisation d'interfaces


Sujet :

C#

  1. #1
    Membre éclairé Avatar de touftouf57
    Profil pro
    Développeur .NET
    Inscrit en
    Décembre 2007
    Messages
    362
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2007
    Messages : 362
    Par défaut Problème de modélisation d'interfaces
    Bonjour à tous,

    Cela fait quelques temps que je me triture le crâne sur la conception d'une bibliothèque d'interfaces.

    Le problème est que certaines de mes interfaces renvoient des collections d'interfaces.

    Prenons un cas concret.

    Vous êtes d'accord avec moi sur le fait qu'une banque contient des comptes bancaires.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     interface IBanque
        {
            IList<ICompteBancaireBase> ComptesBancaires{ get; set; }
        }
    Jusque la tout est ok.

    Depuis un compte bancaire, on peut connaitre l'entreprise à qui il appartient.
    Tout comme depuis une entreprise, on peut connaitre ses comptes bancaires.
    Nous avons donc une relation bilatérale IEntreprise et ICompteBancaire.

    Maintenant, l'entreprise peut être la notre, tout comme cela peut-être un client, un fournisseur. Pour plus de simplicité, nommons les autres entreprises : EntrepriseTierce

    Vous serez aussi d'accord avec moi sur le fait que nous ne pouvons pas réaliser les mêmes opérations sur les comptes bancaires de notre entreprise et ceux d'une entrepriseTierce.

    J'ai donc voulu rendre mon interface IEntreprise générique, pour qu'elle ne renvoie que des IComptesBancairesTiers lorsque c'est une instance de IEntrepriseTierce et qu'elle ne renvoie que des IComptesBancaires pour l'instance de IMonEntreprise.

    C'est la qu'intervient mon problème, je suis confronté au concept de covariance et contravariance.

    Lorsque je manipule une IEntreprise, je voudrais pouvoir obtenir la collection des ComptesBancaires de cette entreprise et peu importe si c'est la mienne ou une tierce.
    Cependant, lorsque je manipule MonEntreprise lorsque je récupère ses comptes bancaires, il ne faut pas que cette collection puisse contenir une compte bancaire tier.
    A l'inverse, les comptes bancaires d'une IEntrepriseTierce ne doit contenir que des comptesBancairesTiers.

    Mais puisque j'ai rendu mon interface IEntreprise générique, je doit savoir si c'est une collection de ICompteBancaire ou ICompteBancaireTiers lorsque je récupère les comptes bancaires d'une IEntreprise.

    Donc comment définissez-vous vos interfaces dans ce genre de relations?

    Je vous remercie de votre aide.

  2. #2
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Bonjour.

    Première règle : éviter de se retrouver dans ce genre de situation. Le système de types de C# a beau être plus riche que la moyenne il reste limitatif, comme tous les typages forts, et peut facilement nous envoyer dans le mur si nous nous acharnons. Évidemment ici on ne peut pas éviter la situation dans son intégralité, l'approche est la bonne, mais je t'invite à avancer avec prudence et accepter parfois des compromis (perte d'informations de typage, redondance du code, et autres joyeusetés) pour éviter de te retrouver avec des constructions génériques abominables.

    Cet avertissement préalable étant formulé, il y a deux solutions :
    * Retourner un IEnumerable pour bénéficier de la covariance. IEnumerable<Enfant> peut être implicitement assigné à un IEnumerable<Parent>. Quand c'est possible mieux vaut privilégier cette voie.

    * Conserver des listes/collections et utiliser des wrappers (ListWrapper<TSource, TDestination>). Ce qui, à moins d'utiliser des structures en lecture seule, ouvre tout un tas de problème puisque le consommateur peut tenter d'ajouter un mauvais type à la collection, opération apparemment légitime d'après l'interface mais en réalité non-supportée par le type sous-jacent. Or, souvent, l'accès en écriture n'est nécessaire qu'aux réalisons concrètes de ces interfaces, qui peuvent référencer directement les mises en oeuvre (implémentations/classes) de ces interfaces. L'exemple typique est le cas où l'accès en écriture n'est requis que par la mise en oeuvre du motif factory. Si c'est le cas, mieux vaut n'exposer qu'un IEnumerable au niveau de l'interface.


    Enfin dans les deux cas il faut souvent déclarer explicitement tout ou partie de l'implémentation de l'interface. BanqueRouge peut par exemple avoir besoin d'exposer une propriété ComptesBancaires retournant une IList<CompteBancaireRouge> plutôt qu'une IList<ICompteBancaire>. Dans ce cas les deux versions peuvent coexister au sein d'une classe grâce à la mise en oeuvre (implémentation) explicite de l'interface. Ce qui permet par exemple de déclarer une propriété renvoyant IEnumerable au niveau de l'interface et d'ajouter un alter ego renvoyant IList au niveau la classe.

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par DonQuiche Voir le message
    * Retourner un IEnumerable pour bénéficier de la covariance. IEnumerable<Enfant> peut être implicitement assigné à un IEnumerable<Parent>. Quand c'est possible mieux vaut privilégier cette voie.
    Encore mieux, si tu es en 4.5 : IReadOnlyList<T>. C'est également covariant, et c'est plus pratique à manipuler.

  4. #4
    Membre Expert Avatar de sisqo60
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2006
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Février 2006
    Messages : 754
    Par défaut
    Bonjour,

    Citation Envoyé par touftouf57 Voir le message
    Vous êtes d'accord avec moi sur le fait qu'une banque contient des comptes bancaires.
    Oui et non, mais si je peux me permettre, un banque contient une liste de Personnes physiques (PP)/Personnes morales(PM), qui tous on une liste de produits et services bancaires (comptes, assurances, forfaits téléphonique etc...). Les PP/PM ont tous des rôles : client, fournisseur etc...

    Je pense que tu simplifies à l’extrême une modélisation vraiment très complexe.

  5. #5
    Membre éclairé Avatar de touftouf57
    Profil pro
    Développeur .NET
    Inscrit en
    Décembre 2007
    Messages
    362
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2007
    Messages : 362
    Par défaut
    Citation Envoyé par sisqo60 Voir le message
    Bonjour,

    Oui et non, mais si je peux me permettre, un banque contient une liste de Personnes physiques (PP)/Personnes morales(PM), qui tous on une liste de produits et services bancaires (comptes, assurances, forfaits téléphonique etc...). Les PP/PM ont tous des rôles : client, fournisseur etc...

    Je pense que tu simplifies à l’extrême une modélisation vraiment très complexe.
    Je suis d'accord avec toi. Cependant, le périmètre de l'application que je dois "préparer" s'arrête à ça. L'objectif est de générer des fichiers XML SEPA.
    Donc pas de prise en compte d'assurances, forfaits et tout le toutim.

  6. #6
    Membre éclairé Avatar de touftouf57
    Profil pro
    Développeur .NET
    Inscrit en
    Décembre 2007
    Messages
    362
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2007
    Messages : 362
    Par défaut
    Bon,

    j'ai tenté de suivre vos conseils, mais apparemment je vais encore trop loin, ce qui me mène dans le mur évoqué par DonQuiche.

    Auriez-vous des exemples "d'implémentation" de ce "problème" dans vos besaces?

    Je suis limité au framework 4.0, donc le IReadOnly est à proscrire.

    Merci

  7. #7
    Expert confirmé

    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2006
    Messages
    3 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2006
    Messages : 3 580
    Par défaut
    bsr

    peut-etre qu'il faut reprendre le problème à la base et écrire dans un premier temps l'ensemble des "méthodes" dont tu as besoin...

    ensuite, une fois que tu auras à plat ton système te fournissant les informations, tu pourras voir quelles informations pourraient être agrégées et regroupées (avec des critères éventuels ou pas)...

    Par expérience, j'ai toujours tendance à produire une solution qui réponds à mon besoin... et si j'ai du budget, du temps, j'esssaye de rendre son utilisation de plus en plus agréable par de la factorisation, etc... mais toujours, dans un premier temps, répondre au besoin pour lequel je suis payé...

    Et à quoi bon faire une usine à gaz et se massacrer la tête si au final, une solution comportant plus d'interface fonctionne...

    Et parfois, la simplification n'apporte rien de bon si ce n'est une gestion plus complexe d'un coté de la chaine !!!

Discussions similaires

  1. Problème de modélisation avec Case Studio
    Par soso78 dans le forum Décisions SGBD
    Réponses: 6
    Dernier message: 15/06/2006, 18h13
  2. Problème de modélisation
    Par Tyler Durden dans le forum Décisions SGBD
    Réponses: 2
    Dernier message: 10/06/2006, 16h18
  3. Problème de conception d'interface
    Par Djangogol dans le forum AWT/Swing
    Réponses: 4
    Dernier message: 28/04/2006, 09h12
  4. [Class/PHP/Postgres] Problème de modélisation...
    Par k-reen dans le forum PostgreSQL
    Réponses: 4
    Dernier message: 27/02/2003, 08h49

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