Partage
  • Partager sur Facebook
  • Partager sur Twitter

Relation en c#

    22 mars 2011 à 11:00:03

    Bonjour,

    Je cherche à savoir comment coder une relation d'agrégation et une relation de composition en c#. J'ai essayé de trouver des réponses claires sur le net mais rien de vraiment concret.

    Merci d'avance de m'éclaircir quelque peu par l'exemple, et aussi comment on les différencie. :)
    • Partager sur Facebook
    • Partager sur Twitter
      22 mars 2011 à 20:21:39

      La différence est assez ténue. En général la distinction entre composition et agrégation se situe au niveau de la durée de vie entre l'aggrégat et l'objet aggrégé : s'il y a une dépendance entre leur durée de vie c'est une composition, sinon c'est une agrégation.
      Dans des langages OO où la destruction des objets doit se faire explicitement (comme en C++), cela a des conséquences assez lourdes sur l'implémentation. Mais on n'a pas ce problème en C#. ;)

      En fait la différence se situera plutôt au niveau de l'accessibilité (publique ou privée) de la référence vers l(es) objet(s) aggrégé(s). En effet, une autre façon de voir la distinction entre composition et agrégation est d'observer si la relation entre un aggrégat et ses objets aggrégés est nécessaire au niveau du service (interface publique) exposé par l'aggrégat, ou au niveau de l'implémentation de ce service. Dans le cas d'une agrégation, la relation entre les objets est généralement publique; dans le cas d'une composition, elle concernera souvent l'implémentation et sera donc plutôt privée. On rencontre parfois des compositions publiques, mais il y a un risque de violer la loi de Demeter en faisant cela.

      Voyons ça avec un exemple: je propose de modéliser le processus de rédaction et de validation des tutos du Site du Zero. :p

      On suppose qu'on a les classes et interfaces suivantes :

      public class Tutoriel
      {
          // plen de champs qui constituent un tutoriel
          // ...
      }
      
      public interface IListeDeTutoriels
      {
          IEnumerable<Tutoriels> TutorielsEnAttente { get; }
          void SoumetNouveauTutoriel(Tutoriel tuto);
          Tutoriel ObtientProchainTutoAValider();
          void ValideTutoriel(Tutoriel tuto, bool ok, List<string> remarques);
      }
      
      public class Membre
      {
          // plein de champs communs à tous les membres du SdZ
          // ...
      }
      
      public interface IRedacteur
      {
          IListeDeTutoriels ListeDeTutoriels { get; set; }
          void RegigeTutoriel();
      }
      
      public interface IValidateur
      {
          IListeDeTutoriels ListeDeTutoriels { get; set; }
          void ValideTutoriel();
      }
      

      Ceci définit les services qui sont nécessaires pour pouvoir rédiger et valider des tutos. On voit que des relations sont nécessaires à ces services : les rédacteurs et validateurs doivent pouvoir alimenter et consommer la liste des tutos en attente et doivent donc interagir avec elle. Il n'y a pas de notion de subordination ici, donc il s'agit de simples associations.

      Voyons une implémentation possible de IListeDeTutoriels:

      public class ListeDeTutoriels : IListeDeTutoriels
      {
          private Queue<Tutoriel> _tutorielsEnAttente;
      
          public IEnumerable<Tutoriel> TutorielsEnAttente // agrégation
          {
              get { return _tutorielsEnAttente; } 
          } 
          
          public void SoumetNouveauTutoriel(Tutoriel tuto)
          {
              _tutorielsEnAttente.Enqueue(tuto);
          }
      
          public Tutoriel ObtientProchainTutoAValider()
          {
              return _tutorielsEnAttente.Dequeue();
          }
      
          public void ValideTutoriel(Tutoriel tuto, bool ok, List<string> remarques)
          {
              // rendre le tuto visible par tous les membres
              // ...
          }
      }
      

      Il y a une relation d'agrégation entre la liste et les tutos qu'elle contient : la "durée de vie" des tutos ne dépend pas de celle de la liste. Cette relation est publique, en effet la liste doit permettre d'ajouter ou retirer des tutos et de consulter les tutos en attente.

      Observons une implémentation de rédacteur:

      public class Toto : Membre, IRedacteur
      {
          public IListeDeTutoriels ListeDeTutoriels { get; set; } // association
      
          public void RegigeTutoriel()
          {
              Tutoriel nouveauTutoriel = new Tutoriel();
      
              // remplir le tuto avec plein de trucs intéressants
              //...
      
              // c'est fini, on le soumet pour qu'il soit validé :
              this.ListeDeTutoriels.SoumetNouveauTutoriel(nouveauTutoriel);
          }
      }
      

      La méthode RedigeTutoriel est appelée on ne sait pas trop quand, ça n'a pas d'importance ici. Il faut veiller par contre à ce que la référence vers la liste des tutos à alimenter ait été initialisée correctement au préalable pour que Toto sache quoi faire avec son super nouveau tuto. Pas grand chose d'intéressant à voir ici.

      Voyons le cas d'un validateur :

      public class Orwell : Membre, IValidateur
      {
          private class Esclave
          {
              public bool AuBoulot(Tutoriel tuto, out List<string> remarques)
              {
                  // valider le tuto pour le maitre
                  // ...
              }
          }
      
          private Esclave _monEsclavePerso = new Esclave(); // composition
      
          public IListeDeTutoriels ListeDeTutoriels { get; set; } // association
      
          public void ValideTutoriel()
          {
              Tutoriel tutorielAValider = this.ListeDeTutoriels.ObtientProchainTutoAValider();
      
              // valider le tutoriel;
              List<string> remarques;
              bool ok = _monEsclavePerso.AuBoulot(tutorielAValider, out remarques);
      
              // et voilà le travail !
              this.ListeDeTutoriels.ValideTutoriel(tutorielAValider, ok, remarques);
          }
      }
      

      Eh oui, j'ai un esclave personnel qui fait le boulot à ma place. :D Comment, vous ne le saviez-pas ? C'est normal, c'est privé ! :ange: Cet esclave n'existe que pour moi, il est à moi et j'en fais ce que je veux. Et je suis le seul à savoir où il est planqué, donc si je meurs, il mourra aussi (de faim). :diable:

      La relation Maitre-Esclave est une relation de composition qui concerne la manière dont je réalise le service de validation que j'expose à la communauté (dans toute ma générosité), donc son implémentation. Elle ne fait pas partie du service lui-même.
      Il pourrait y avoir plusieurs esclaves plutôt qu'un seul, ça resterait une composition.


      Voici une façon de mettre tout ce petit monde en pratique:

      IListeDeTutoriels listeDeTutos = new ListeDeTutoriels();
      
      IRedacteur toto = new Toto();
      toto.ListeDeTutoriels = listeDeTutos;
      
      IValidateur orwell = new Orwell();
      orwell.ListeDeTutoriels = listeDeTutos;
      
      toto.RegigeTutoriel();
      orwell.ValideTutoriel();
      

      Donc pour résumer:
      -> Agrégation entre IListeDeTutoriels et les Tutoriels : La liste est alimentée par des tutos instanciés ailleurs, et ceux-ci sont ensuite extraits pour continuer leur vie autre part. On ne sait pas ce qui doit advenir des tutos de la liste si la liste est détruite, l'interface n'imposant pas de les détruire.
      -> Composition entre Orwell et Esclave : L'objet Esclave est instancié par l'objet Orwell (on aurait pu placer l'instanciation dans le constructeur). L'esclave ne peut survivre sans le maître. :p Note: Ici j'ai défini la classe Esclave comme étant privée au sein de la classe Orwell, mais de manière générale ça peut être une classe publique extérieure à la classe qui l'utilise (par exemple si la même classe Esclave est utilisée par plusieurs validateurs).

      Voilà, j'espère que cet exemple aura permis de voir la différence entre association, agrégation et composition... Et j'espère que tout le monde aura compris qu'il n'est pas à prendre au pied de la lettre, sinon je vais avoir les Droits de l'Homme sur le dos :p
      • Partager sur Facebook
      • Partager sur Twitter

      Relation en c#

      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
      • Editeur
      • Markdown