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 :

Débuter avec l'architecture 3 tiers


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Février 2006
    Messages
    102
    Détails du profil
    Informations forums :
    Inscription : Février 2006
    Messages : 102
    Par défaut Débuter avec l'architecture 3 tiers
    Bonjour,
    après de nombreuses lectures où je trouve différentes réponses, je tente ma chance sur le forum pour avoir des éclaircissements.
    je développe une application en suivant une architecture 3 tiers.
    De ce que j'ai compris:
    la couche UI ne traite que l'interface graphique
    la couche BLL fait le lien entre les deux couches et traite les objets métiers
    la couche DAL ne traite que les accès à la base.

    Par contre, je ne comprends pas bien ce que la DAL doit renvoyer concrètement. Vaut-il mieux renvoyer une datatable ou équivalent qui sera traitée par la couche BLL pour créer ses objets UserBLL? ou bien renvoyer une liste d'objets de la couche BLL correspondante?
    Si demain je rajoute une ou plusieurs colonnes dans ma table utilisateurs, pour les prendre en compte, je ne voudrais pas intervenir dans toutes les couches pour l'instanciation de mon objet, seulement sur la couche BLL. Après peut être aussi sur ma couche DAL suivant la requête

    Pour être plus concret voici un exemple sur lequel je suis parti:

    ma DAL
    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
     
    public class userDAL{
        public userDAL(){ ... };
     
        public List<UserBLL> getUsersFromDB(){
              List<UserBLL> users = new List<UserBLL>();
              String req = " SELECT name,firstName FROM ....";
              using....{
                  using(MySqlDataReader myReader = myCmd.ExecuteReader()){
    		    while(myReader.Read()){
                            UserBLL u = new UserBLL();
                            u.Name = myReader["name"].toString();
                            u.FirstName = myReader["firstName"].toString();
                            users.add(u);
    		    }
                   }
              }
              return users;
        }
     
    }
    ma BLL:
    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
     
    public class userBLL{
        public String userName {get;set;}
        public String userFirstName {get;set;}
     
        public UserBLL(String name, String firstName){
            this.userName  = name;
            this.userFirstName  = firstName;
        }
     
        public static List<UserBLL> getList(){
            UserDAL users = new UserDAL();
            return users.getUsersFromDB();
        }
    }
    mon ui:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public MainForm(){
        List<UserBLL> myUsers = UserBLL.getList();
        ....
    }
    Je vous remercie pour vos bons conseils.

  2. #2
    Membre émérite Avatar de Momoth
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2013
    Messages
    318
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2013
    Messages : 318
    Par défaut
    Bonjour,

    Citation Envoyé par kstou2001 Voir le message
    Par contre, je ne comprends pas bien ce que la DAL doit renvoyer concrètement. Vaut-il mieux renvoyer une datatable ou équivalent qui sera traitée par la couche BLL pour créer ses objets UserBLL? ou bien renvoyer une liste d'objets de la couche BLL correspondante?
    L'architecture en couche "de base" possède une quatrième brique qui est le Domain Model. Il s'agit de tes objets métiers qui vont transiter entre tes couches. En général, quand on ne veut pas se casser la tête, on fait des objets qui respecte le même modèle que celui de ta base de donnée et on les fait transiter dans toutes les couches. Note que faire cela est une mauvaise pratique qui atteins facilement ses limites dès qu'on commence à complexifier le bousin. Perso, je trouve que cela reste une excellente approche de l'architecture en couche.

  3. #3
    Membre confirmé
    Inscrit en
    Février 2006
    Messages
    102
    Détails du profil
    Informations forums :
    Inscription : Février 2006
    Messages : 102
    Par défaut
    Merci pour cette intervention. J avais deja vu ca pour le domain model mais je n ai pas encore saisi l interet. En utisant une classe domain model quel serait l interet de la classe userBLL.
    Au lieu d avoir mon objet metier au sein de cette classe, j instancierai un objet de la classe domain model.

    Et si je comprends bien ma database doit retourner des objets metiers ?

  4. #4
    Membre émérite
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2005
    Messages
    562
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2005
    Messages : 562
    Par défaut
    Bonjour,

    Si on veut se concentrer sur les 3 couches, qui restent de mon point de vue 'la base', et sans certain model on rajoutera en effet une couche avec dedans les DTOs, en gros c'est une classe calquée sur une table en bdd avec tout en get;set; et pas de logique métier dedans ...etc

    Donc pour rester sur 3 couches, si on veut être synthétique, c'est comme tu l'as dit on a UI, BLL et DAL. Et UI utilise DAL pour obtenir BLL.
    Donc pour faire simple et rendre les choses bloquantes (en plus d'être une bonne pratique je trouve) tu mets la couche DAL et BLL dans des dll déférentes. Ainsi, UI doit référencer BLL et DAL, et DAL doit référencer BLL et c'est tout. Surtout pas de référence à DAL dans BLL... Bon maintenant à toi de voir si tu veux mettre UI dans une dll qui sera appelée dans une appli, ou si UI est finalement directement l'appli elle même.

    J'ai regardé vite fait ton code, dans BLL je tique direct sur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    public static List<UserBLL> getList()
    {
            UserDAL users = new UserDAL();
            return users.getUsersFromDB();
    }
    Là tu as une jolie référence de ta DAL dans ta BLL, et c'est référence n'est pas forcément utile... En tout cas on peut faire mieux , en se calquant sur le pattern repository...
    Tu te mets ainsi une épine dans le pied, puisque imagine que ta source de donnée chance (tu passes de Sql server à un fichier plat par exemple), il faudra que tu recodes une DAL pour obtenir tes données depuis un fichier... il faudra alors que tu modifies toutes tes classes dans la BLL pour aller chercher la bonne DAL...

    Voila ce que je te propose :
    DAL
    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
     
    public interface IUserDAL
    {
    	IEnumerable<UserBLL> getUsersFromDB();
    }
     
    public class UserDAL_SQL : IUserDAL
    {
     
        private  UserDAL_SQL (){ ... };
     
        public IEnumerable<UserBLL> IUserDAL.getUsersFromDB()
    	{
              List<UserBLL> users = new List<UserBLL>();
              String req = " SELECT name,firstName FROM ....";
              using....{
                  using(MySqlDataReader myReader = myCmd.ExecuteReader()){
    		    while(myReader.Read()){
                            UserBLL u = new UserBLL();
                            u.Name = myReader["name"].toString();
                            u.FirstName = myReader["firstName"].toString();
                            users.add(u);
    		    }
                   }
              }
              return users;
        }
     
    }
    UI
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public MainForm()
    {
        IUserDAL repoUser = new UserDAL_SQL();
     
        List<UserBLL> myUsers = repoUser.getList();
        ....
    }
    Ainsi si tu as besoin d'une autre DAL, alors tu n'auras qu'a faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public MainForm()
    {
        IUserDAL repoUser = new UserDAL_Txt();
     
        List<UserBLL> myUsers = repoUser.getList();
        ....
    }
    et c'est tout...

    pour ta question :
    Par contre, je ne comprends pas bien ce que la DAL doit renvoyer concrètement. Vaut-il mieux renvoyer une datatable ou équivalent qui sera traitée par la couche BLL pour créer ses objets UserBLL? ou bien renvoyer une liste d'objets de la couche BLL correspondante?
    Je comprends pas ce qui t'embête, car ta DAL retourne bien des objets métiers (userBLL dans ton cas) et c'est ce qu'on lui demande. Bon si tu rajoute une 4eme couche c'est surement différent...
    Je te conseillerais plutôt de retourner un IEnumerable<T> ainsi ta liste retournée ne pourra pas être modifiée en dehors de la DAL... enfin on est un peu hors sujet là .

    Bon code,
    J@ck.

  5. #5
    Membre confirmé
    Inscrit en
    Février 2006
    Messages
    102
    Détails du profil
    Informations forums :
    Inscription : Février 2006
    Messages : 102
    Par défaut
    Donc pour rester sur 3 couches, si on veut être synthétique, c'est comme tu l'as dit on a UI, BLL et DAL. Et UI utilise DAL pour obtenir BLL.
    Donc pour faire simple et rendre les choses bloquantes (en plus d'être une bonne pratique je trouve) tu mets la couche DAL et BLL dans des dll déférentes. Ainsi, UI doit référencer BLL et DAL, et DAL doit référencer BLL et c'est tout.
    Par contre tu contredis tous les tutos que j'ai vu? Normalement BLL est l'intermediaire entre UI et DAL. ui ne dialogue qu'avec BLL

    Tu te mets ainsi une épine dans le pied, puisque imagine que ta source de donnée chance (tu passes de Sql server à un fichier plat par exemple), il faudra que tu recodes une DAL pour obtenir tes données depuis un fichier...
    Justement, il est prévu plus tard de migrer vers un autre SGDB.

    Je comprends pas ce qui t'embête, car ta DAL retourne bien des objets métiers (userBLL dans ton cas) et c'est ce qu'on lui demande. Bon si tu rajoute une 4eme couche c'est surement différent...
    Moi ça ne m'embête pas, je me dis juste que vu que je suis au niveau de la DAL, je ne dois peut être pas retourné un objet métier mais une "sortie brute" de ma requête qui sera exploitée par la BLL.

  6. #6
    Membre éclairé
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Avril 2005
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2005
    Messages : 64
    Par défaut
    bonjour,
    à mon avis il te faut une 4e couche transversale composée de TDOs( classe avec propriétés uniquement) et des interfaces pour l'indépendance entre couches
    ains les dépendances seront

    UI ->TDO,DAL,BLL
    BLL-> TDO
    DAL->TDO

    TDO:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    public class UserTDO
    {
    public string UserName{get;set;}
    public string UserFirstName{get;set;}
    } 
     
    public interface IUserDAL
    {
            Enumerable<UserTDO> GetFromDB();
    }
    DAL:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    public class UserDAL_SQL:IUserDAL
    {
         public Enumerable<UserTDO> GetFromDB()
         {
                var lst=new List<UserTDO>();
                var req="select * from ....";
                .....
         }
    }
    BLL:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    public class UserBLL
    {
         private readonly IUserDAL _dal;
     
         public UserBLL(IUserDAL dal)
         {
              _dal=dal;
          }
         public Enumerable<UserTDO> GetFromDB()
         {
             _dal.GetFromDB();
         }
    }
    UI:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
     public main()
    {
         var bll=new UserBLL(new UserDAL_SQL());
         var lst=bll.GetFromDB();
         ....
    }
    si vous voullez changer de base de donnée il suffit de changer l'instance de la DAL dans UI

  7. #7
    Membre émérite
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2005
    Messages
    562
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2005
    Messages : 562
    Par défaut
    Citation Envoyé par kstou2001 Voir le message
    Par contre tu contredis tous les tutos que j'ai vu? Normalement BLL est l'intermédiaire entre UI et DAL. ui ne dialogue qu'avec BLL
    Oui c'est fort possible En faite j'ai longtemps utilisé l'archi 3 couche comme tu le proposais, avec plein de méthode static dans la BLL qui appel la DAL.
    C'est bien mais comme je te le dis on peut faire mieux, en tout cas dès que j'ai appliqué la 3 couches version repository, tout est devenu plus simple et plus claire, après je te fais pars de mon expérience, sans doute que d'autres en auront eu d'autres qui sont tout aussi valable.
    Par exemple pour moi, mettre une 4ème couche, ce serait plutôt une couche service ...
    @Amri_Daly te propose une DTO, ok, c'est déjà un peu mieux que ta proposition dans le sens ou il a réduit le lien entre BLL et DAL dont je parlais plutôt, mais je la trouve, pour mes besoins en tout cas, trop 'compliquée' (pas taper hein) mais c'est surement parce que je n'ai jamais essayé une telle archi. Peu être à tord mais je pense qu'une couche DTO n'est vraiment utile que lorsque l'on utilise des choses comme Entity Framework...

    Citation Envoyé par kstou2001 Voir le message
    Justement, il est prévu plus tard de migrer vers un autre SGDB.
    Alors fais bien attention (mais ça semble bien parti ) et fais toi 2 3 tests de changement de DAL. Par exemple je fais souvent une DAL version "jesuisunbourrinjemetstoutendure" qui me retourne toujours les mêmes choses codées en dur. Puis je m'attaque à une vraie DAL par SQL. Et pour passer d'une à l'autre, ça, je pense que l'on sera tous d'accord pour dire qu'il ne doit y avoir qu'une ligne à changer...

    Citation Envoyé par kstou2001 Voir le message
    Moi ça ne m'embête pas, je me dis juste que vu que je suis au niveau de la DAL, je ne dois peut être pas retourné un objet métier mais une "sortie brute" de ma requête qui sera exploitée par la BLL.
    Oui possible, mais pourquoi pas un object métier directement serait un frein ou une limitation ? c'est ce que l'on veut obtenir ...
    Si je schématise un peu ma façon de faire : Mon repository vas utiliser une factory ou un constructeur présent dans la BLL pour instancier mes objects métiers et va affecter les valeurs propriétés etc ... tout ce qu'il faut pour que mes object métiers soit à l'image de ma Bdd. Je n'ai pas enfreint de grandes règles de la POO en faisant ça, la logique des couches est conservée, je suis SOLID et DRY

    Intéressante en tout cas, maintenant à toi de trouver le modèle qui correspond les plus à tes besoins.

    J@ck.

Discussions similaires

  1. Architecture 3-tiers avec Asp.NET
    Par tawaha2010 dans le forum ASP.NET
    Réponses: 4
    Dernier message: 19/05/2012, 22h34
  2. architecture n-tiers : BLL et BO avec Power AMC
    Par Barbette dans le forum UML
    Réponses: 0
    Dernier message: 19/05/2010, 17h44
  3. architecture 3-tiers avec swing
    Par Med_Aymen dans le forum AWT/Swing
    Réponses: 4
    Dernier message: 13/03/2010, 21h47
  4. Réponses: 9
    Dernier message: 10/03/2008, 10h44

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