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

VB.NET Discussion :

Programmation vb.NET multicouche IHM, BPL, DAL, BEL ? [Débutant]


Sujet :

VB.NET

  1. #21
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Février 2003
    Messages
    2 198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2003
    Messages : 2 198
    Par défaut
    Dans les recommandation de codage les propriétés elles sont nottés en CamelCase

    Pour la dal je pense à un truc du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    Public Class DalUser
     {
    private _connectionString
     
    #Region "Constructeurs"
        Sub New(connectionString As String)
    {
    _connectionString = connectionString;
    }
     
        End Sub
    #End Region
    L'idée de faire une classe principale, et des classes dérivés n'est pas mal non plus

  2. #22
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Février 2003
    Messages
    2 198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2003
    Messages : 2 198
    Par défaut
    Citation Envoyé par kheironn Voir le message
    ...
    Tu peux très découper ton programme en couche en faisait des repertoires différents et sans utiliser de dll mais je ne vois pas ce que ca apporte de vouloir éviter 3 dll...

    De plus même si tu ne changes jamais de bd, d'IHM, le modèle en couche permet d'implémenter plus rapidement un changement, d'implémenter de nouvelles règles à l'endroit le plus approprier

  3. #23
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2011
    Messages : 63
    Par défaut
    Citation Envoyé par BenoitM Voir le message
    Dans les recommandation de codage les propriétés elles sont nottés en CamelCase

    Pour la dal je pense à un truc du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    Public Class DalUser
     {
    private _connectionString
     
    #Region "Constructeurs"
        Sub New(connectionString As String)
    {
    _connectionString = connectionString;
    }
     
        End Sub
    #End Region
    L'idée de faire une classe principale, et des classes dérivés n'est pas mal non plus
    Quelque chose reste flou pour moi :

    Si on écrit ce code, il va bien falloir instancier un objet DALUser avec en paramètre la chaine de connexion non ? C'est pas grave dans ce cas ? Là c'est plus écrit "en dur" ?
    Au passage, que signifie de manière concrete "en dur" ?

  4. #24
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Février 2003
    Messages
    2 198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2003
    Messages : 2 198
    Par défaut
    On appelle codé en dur (hardcodé)(HardCoding) quand une variable est écrite dans le code
    (cf variable static, toutes déclaration de chaine de caractère "toto")
    Et donc pour changer la valeur de cette variable tu dois recompiler le code.

    Il y a 2 problèmes avec ta technique.
    1) Tu écrits en dur 25 fois la même chaine de connection. Le nom de serveur change. tu dois aller modifier 25 endroit en esperant ne pas en oublier un, ne pas avoir fait une faute de frappe dans un des 25 endroits
    2) Ta chaine de connection est écrit en dur, et donc tu dois recompiler le programme si tu dois changer la connection string

    Pour eviter de coder en dur, on utilise l'AppConfig, ainsi si tu dois modifier le nom du serveur il suffit d'éditer le fichier de configuration avec un notepad

    De plus la DAL permet l'access au donnée mais elle n'a pas besoin de savoir où sont stocker les données.

  5. #25
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2011
    Messages : 63
    Par défaut
    Citation Envoyé par BenoitM Voir le message
    On appelle codé en dur quand une variable est écrite dans le code
    (cf variable static, toutes déclaration de chaine de caractère "toto")
    Et donc pour changer la valeur de cette variable tu dois recompiler le code.

    Il y a 2 problèmes avec ta technique.
    1) Tu écrits en dur 25 fois la même chaine de connection. Le nom de serveur change. tu dois aller modifier 25 endroit en esperant ne pas en oublier un, ne pas avoir fait une faute de frappe dans un des 25 endroits
    2) Ta chaine de connection est écrit en dur, et donc tu dois recompiler le programme si tu dois changer la connection string

    Pour eviter de coder en dur, on utilise l'AppConfig, ainsi si tu dois modifier le nom du serveur il suffit d'éditer le fichier de configuration avec un notepad

    De plus la DAL permet l'access au donnée mais elle n'a pas besoin de savoir où sont stocker les données.
    OK, j'ai compris. Je vais me pencher sur l'AppConfig. Thank's !

  6. #26
    Membre émérite Avatar de kheironn
    Homme Profil pro
    Chef de projets technique C# / MVC / .Net
    Inscrit en
    Février 2007
    Messages
    823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projets technique C# / MVC / .Net
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2007
    Messages : 823
    Par défaut
    Citation Envoyé par shurikeNzL Voir le message
    Moi tu sais, on m'impose cette architecture alors j'éxécute, après est-ce que je suis pour ou contre, je ne pense pas pouvoir me prononcer vu mon faible niveau en programmation .
    Je l'ai bien compris.

    comme je le disais, c'est très à la mode cette façon de faire. Il y a une tendance à l'uniformisation des façons de faire et penser.

    Comme toujours, celui qui te donne ton travail à toujours raison
    Tu devrais demander pourquoi on t'impose cette architecture, ce qu'elle t'apporte...
    Tu devrais avoir une réponse du genre : "séparer les traitements et les responsabilités dans le but d'interchangeabilité des couches (d'où plusieurs dll)".

  7. #27
    Membre émérite Avatar de kheironn
    Homme Profil pro
    Chef de projets technique C# / MVC / .Net
    Inscrit en
    Février 2007
    Messages
    823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projets technique C# / MVC / .Net
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2007
    Messages : 823
    Par défaut
    Citation Envoyé par BenoitM Voir le message
    Tu peux très découper ton programme en couche en faisait des repertoires différents et sans utiliser de dll mais je ne vois pas ce que ca apporte de vouloir éviter 3 dll...
    C'est bien ce qui je disais, il y a un formatage des développeurs...
    La séparation des couches en dll doit avoir une raison technique d'être. Dans un framework comme .Net, c'est tout à fait évident ; sinon, nos projets n'auraient qu'une référence à .Net et basta. Dans un projet de gestion bidon comme on en fait tant, cela se discute plus. Le découpage en dll est là pour pouvoir utiliser un fonctionnement modulaire et pour réutiliser ce qui est fait, selon les besoins d'un ENSEMBLE d'applications. (pour plus d'info voir un urbaniste info). Si ton appli est stand-alone, inutile de le faire; sauf dans le cas éventuel d'une future évolution qui ne viendra jamais puisque la fin du monde est pour 2112
    Les choses ne doivent pas être faites parce que c'est joli et que tous les ânes les font, mais parce qu'IL Y A UNE RAISON, UN BESOIN !
    Maintenant, je le répète, il faut voir l'ensemble des choses ! C'est ça le taf de l'architecte !
    Citation Envoyé par BenoitM Voir le message
    De plus même si tu ne changes jamais de bd, d'IHM, le modèle en couche permet d'implémenter plus rapidement un changement, d'implémenter de nouvelles règles à l'endroit le plus approprier
    Tu confonds dll et couche. Comme je le disais, tu peux avoir 250 couches dans une seule dll.
    Ensuite, le découpage en couches peut finir par être plus lourd qu'autre chose. Tu as une DAL, une BL, des DTO et une IHM. Pour certaines modifs, tu vas toucher - contrairement à ce que tu dis - à QUATRE emplacements (voir plus) afin de les faire. N-tiers N'EST PAS la seule architecture valable ! Elle contredit même les canons POO qui préconisent des objets complets, comme les POCO, qui ont données et intelligence. Ces derniers regroupent donc BL et EL voir DAL s'ils ne sont pas "Persist Ignore".
    Personnellement, j'aime bien avoir des objets de ce type qui ont des tas de méthodes pour travailler. Ils ont souvent les méthodes save et load qui vont bien et font appel à une classe (issus d'une autre dll pour le coup) qui sait gérer les db grâce aux classes DB... de .Net, ancêtre de Sql..., Oracle..., etc. et à une reconnaissance du provider de ma db. Je passe à cette classe le nom de la sp ou le sql de la requête, les paramètres, et hop, ça roule.

    Pour conclure, je ne dis pas que cette archi CLASSIQUE n-tiers est mauvaise. J'explique qu'elle est au centre du formatage des jeunes générations de développeurs qui ont pour dogme ce mode de pensée. Selon les besoins je l'utilise aussi.

    il faudrait que je retrouve l'article qui explique tout ça, histoire de vous faire comprendre d'où je tire mes arguments...

  8. #28
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 101
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 101
    Par défaut
    Attention au "francisation" des termes !

    IHM (Interface Homme Machine) -> user interface (UI).
    BPL (Business Process Layer) -> Business Logic Layer (BLL)
    BEL (Business Entity Layer) -> Business Logic Layer (BLL)
    DAL (Data Access Layer) ok

    Rappelons qu'un objet à pour but de regrouper données et méthodes !
    Architecturer son code est important, j'ai eu beaucoup de collègue qui avait du mal à comprendre les notions de "responsabilité d'une classe" qui détermine quelles méthodes vont dans quelle classe !
    Et la dessus, on peut rapidement faire n'importe quoi !

    Dans ton exemple de code, la Séparation BPL et BEL n'est pas liée à une architecture par couche mais plutôt un pseudo-modèle MVC, le BPL servant de Controller entre la BEL (Modèle) et l'IHM (Vue)

    L'amalgame entre ces deux concepts architecturaux est fréquent !
    Comme souvent le MVC s'articule autour d'un modèle muliti-couche, cela se comprend, mais c'est fait oublier que le MCV est avant tout un ensemble de Pattern permettant de mieux gérer ses couches !

    Surtout qu'il ne faut pas forcément globalisé le MVC et N-Tiers, on peut trouver des chaques couche des mini-couches, en fonction du point vue que l'on prend, on peut aussi considérer l'architecture d'un progiciel de différentes manière

    j'ai participé à une application Web (un générateur d'application à base de XML, à la limite d'être un FrameWork), l'ensemble du projet était multi-couche, les basiques IHM (Browser), BEL (POO en PHP), Zend pour le FrameWork DAL

    Mais chaque couche pouvait être considérée un module lui-même divisé en couche
    IHM => HTML pour la présentation, un modèle objet codé en JS\AJAX, le DAL étant le serveur web echangeant des objets JSON (effectivement pour le client, la partie serveur pouvaient s’apparenter à un SGBD par sa structure et sa conception)
    Je peux te dire que mon collègue de l'époque c'était laché sur le JS, il avait conçu un modèle objet encapsulant les objets JSON, la partie cliente sur ce coup là était très riche en terme d'architecture (cela pour répondre à des fonctionnalité très avancées complètement configurable)

    Pour la partie PHP, idem, il y a le BEL en PHP mais pour lui la présentation c'est plus que de l'IHM avec un Browser, les WebService ou Import\Export de Fichier étaient aussi considérés comme des Vues\Controller, au lieu de présenter du HTML+AJAX, cela générait du SOAP, REST, CSV, XML ... des vues de différents formats !


    Une architecture par couche sans appliquer de design-pattern n'a pas un grand intérêt car au final, soit la séparation Vue-Modèle devient trop faible (par facilité) ou alors devient inutilement alambiqué à cause de mauvaise inter-dépendance entre les couches !

    Souvent la vue (IHM) n'est qu'une coquille vide avec un ensemble de listener\event handler qui fait appel au pseudo-Controller (BPL) pour manipuler les entités (sans le faire directement)
    Dans le cas d'une IHM client lourd, très vite, la facilité fait que l'on utilise directement la BEL, surtout si il n'y a pas un fort besoin d'avoir des présentations multiples.

    BPLAjouter, BPLSupprimer, doivent-elle être en dehors de l'objet user ?
    Quelle est la raison de mettre ces fonctions en dehors ?
    Tu peux instancier un objet, ce dernier fourni une méthode Save et se sérialize
    Idem, tu peux très bien avoir une méthode Delete dans l'objet, et il supprime de la DB via le DAL

    Tu peux très bien faire une classe User qui gère un seul user
    Souvent dans les modèle MVC comme Rails, implicitement Users est une collection de User ...
    Du coup, Users est-il du BEL ou BPL, dans ton code en exemple c'est du BPL ...
    Le modèle est donc réparti dans User (BEL) et Users (BPL), n'est-ce pas maladroit ?

    Il existe en Java, PHP, Delphi des FrameWork d'Objet Persistant, c'est souvent l'objet qui gère sa propre lecture\écriture\suppression (via les objets du FrameWork par héritage, composition ou délégation)

    La Notion de FrameWork est très important, certains imposent une philosophie particulière interprétant les concepts de POO et Pattern un peu librement !
    Il est difficile d'avoir une réponse à absolue à ce type de problème, car le FrameWork et le langage influence la méthode de travail !

    Pour VB.NET, il y a le FrameWork .NET certe, mais je parle surtout du FrameWork de ta société, leur propre architecture, souvent c'est plus une bibliothèque d'objet fait pour tel et tel besoin qui manque de cohérence
    Vu qu'ils t'imposent une séparation multi-couche, c'est qu'ils ont déjà conçu des applications avec ces méthodes, c'est curieux que n'ait pas déjà un FrameWork interne sur lequel te greffer !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  9. #29
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Février 2003
    Messages
    2 198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2003
    Messages : 2 198
    Par défaut
    Citation Envoyé par kheironn Voir le message
    Ensuite, le découpage en couches peut finir par être plus lourd qu'autre chose. Tu as une DAL, une BL, des DTO et une IHM. Pour certaines modifs, tu vas toucher - contrairement à ce que tu dis - à QUATRE emplacements (voir plus) afin de les faire. N-tiers N'EST PAS la seule architecture valable ! Elle contredit même les canons POO qui préconisent des objets complets, comme les POCO, qui ont données et intelligence. Ces derniers regroupent donc BL et EL voir DAL s'ils ne sont pas "Persist Ignore".
    Personnellement, j'aime bien avoir des objets de ce type qui ont des tas de méthodes pour travailler. Ils ont souvent les méthodes save et load qui vont bien et font appel à une classe (issus d'une autre dll pour le coup) qui sait gérer les db grâce aux classes DB... de .Net, ancêtre de Sql..., Oracle..., etc. et à une reconnaissance du provider de ma db. Je passe à cette classe le nom de la sp ou le sql de la requête, les paramètres, et hop, ça roule.
    Si j'ai une règle business "Prix ne peut pas etre supérieur à 1000€" je n'aurai qu'un endroit à changer
    Si j'ajoute un paramètre à ma fonction, je devrais peut-être changer mes 4 couches mais au moins je n'oublierai pas dans l'écran X d'ajouter ce paramètre car mes écrans définissent plusieurs fois le même comportement

    Je ne pense pas que le modèle en couche interdit le POCO et vice versa.
    Certaines règles ne sont pas définisable dans le POCO. Exemple un client X ne peut acheter pour plus de Y €

    Et le POCO n'interdit pas d'avoir un modèle en couche pour Sauver les donner.
    Ce n'est pas parce que ton objet Etudiant contient Save() que tu es obliger de definir la requete dans cette méthode

  10. #30
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 101
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 101
    Par défaut
    Sans parler des contraintes\CHECK fourni par la DB !

    Beaucoup d'application déportent l'intelligence du modèle dans les Triggers\SP de la DB !
    niveau conception disons que
    mais niveau performance
    La dessus, il faut être réaliste, la généricité ou la [in]perfection du code, cela à un coût, il faut savoir faire des compromis sans être non plus trop dans le "on the fly"

    SQL Server ou Oracle fournissent tant de possibilité à ce sujet, que cela déborde très souvent ! Au final, la couche métier ne se résume qu'à un appel de procédure !

    Normalement, en modèle en couche, on a pas besoin de modifier toutes les couches, si tu rajoutes une nouvelle règle de gestion, la modification dans la BEL suffit, une petite exception refusant le Save remontant qu'à la vue ... et le tour est joué !

    Certaines règles ne sont pas définisable dans le POCO. Exemple un client X ne peut acheter pour plus de Y €
    Tout dépend comment tu le modélise !

    Est-ce client qui achète ou est-ce une commande que l'on facture tout en vérifiant que la disponibilité en stock et le crédit du compte client !


    Citation Envoyé par BenoitM Voir le message
    Et le POCO n'interdit pas d'avoir un modèle en couche pour Sauver les donner.
    Ce n'est pas parce que ton objet Etudiant contient Save() que tu es obliger de definir la requete dans cette méthode
    Je dirais même qu'il ne devrait pas y avoir des SQL dans la méthode Save, cette dernière doit passer l'objet à un sérialisateur (celui pouvant être DB, Fichier XML, ...), le sérialisateur ne connait pas l'objet et l'utilise de façon purement générique via la Reflexion (RTTI) qui fournisse les propriétés sérializables, les clés de mise à jour, les contraintes, les relations, les objets devant être implicite mis à jour au passage ...

    Encore une fois, tout dépend du choix de Framework de Persistance !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  11. #31
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2011
    Messages : 63
    Par défaut
    Citation Envoyé par shurikeNzL Voir le message
    J'ai une table T_USER, avec les champs ID, Nom, Prenom, Age, et Ville.
    Je veux à partir de mon IHM (une winform toute bête avec les champs ID, Nom, ...) ajouter un utilisateur à ma BDD.

    Comment m'y prendre pour programmer avec ces couches IHM, BPL, DAL, et BEL ?
    OK, ça c'est fait.
    Mais maintenant, mettons qu'on utilise une interface WinForm quelque peu différente :
    Un datagridview pour afficher les colonnes de notre table excepté ID.

    Si je veux supprimer un enregistrement dans la table de la BDD en se basant sur l'ID à partir d'un bouton supprimer, comment faire ?

    En clair, je suis l'utilisateur du programme, j'ai ma fenetre avec un joli datagridview qui m'affiche les enregistrements de la table. Je selectionne une ligne, et clique sur supprimer.

    Comment mon programme fait-il la liaison entre la ligne que j'ai selectionné et la ligne qu'il doit supprimer dans la BDD ?

  12. #32
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2011
    Messages
    70
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2011
    Messages : 70
    Par défaut
    Je ne m'y connais pas trop en couche, donc je ne sais pas ou placer le code dans ton cas. Mais personnelement je met une colonne "Identifiant" dans mes datagridview mais non visible.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Me.DGV.Columns("Ma Colonne").Visible = False
    Ainsi, tu as accé à l'identifiant sans l'afficher à l'utilisateur, à voir si il n'y a pas mieux :p

  13. #33
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2011
    Messages : 63
    Par défaut
    Citation Envoyé par Maniz Voir le message
    Je ne m'y connais pas trop en couche, donc je ne sais pas ou placer le code dans ton cas. Mais personnelement je met une colonne "Identifiant" dans mes datagridview mais non visible.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Me.DGV.Columns("Ma Colonne").Visible = False
    Ainsi, tu as accé à l'identifiant sans l'afficher à l'utilisateur, à voir si il n'y a pas mieux :p
    Je pense que je vais être forcé de faire ça vu que je ne vois pas comment faire autrement ^^.

    Mais je me demande si au lieu d'amener ma datasource direct dans le datagridview s'il ne serait pas possible d'amener une liste d'objet User dans mon datagridview. Ca se fait ça ?

  14. #34
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    Oui oui, tu peux faire cela.

    Perso, j'me suis mis à la programmation en couche y a pas longtemps non plus et j'ai ceci dans la ma couche DAL par exemple :

    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 Function GetUsersByName(ByVal name As String) As List(Of User)
            users = New List(Of User)
            ConnectDB()
     
            sql = 'la requête qui va bien
            ds = Cnx.DoSelect(sql)
            If ds.Tables.Count > 0 Then
                For Each row As DataRow In ds.Tables(0).Rows
                    users.Add(New User("les arguments qui vont bien"))
                Next
            End If
            DisconnectDB()
     
            Return users
        End Function
    Je récupère donc bien une liste d'objets de type User et j'affecte cette liste à la propriété Datasource de mon Datagridview.


    Sinon, j'aimerais profiter de ce topic pour m'assurer d'avoir bien compris le bazar (c'est nouveau pour moi aussi).

    Dans la couche BEL, j'ai mis les différents objets métier dont l'application a besoin.
    Dans la couche DAL, j'ai les fonctions d'accès DB qui retourne les objets de la BEL.
    Dans la couche BLL, j'ai les fonctions qui seront utilisées par la couche graphique pour avoir accès aux objets métiers.

    Est-ce juste jusque là ?

    Du coup, je m'interroge sur un truc. Dans une de mes classes d'objets, je fais appel à une fonction de la couche DAL. Est-ce correct ? Si non, où cet appel est-il sensé se faire ? Je ne donne pas d'exemple concret volontairement car j'aimerais connaître la réponse "théorique" (ce qui devrait être fait idéalement).

    Merci d'avance,

    Griftou.

    EDIT : Je crois que je viens de comprendre. Je pense que ça doit aller dans la couche BLL mais j'attends tout même la confirmation de personnes avec plsu d'XP dans le domaine ^^

  15. #35
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2011
    Messages : 63
    Par défaut
    Citation Envoyé par griftou Voir le message
    Dans une de mes classes d'objets, je fais appel à une fonction de la couche DAL. Est-ce correct ?
    J'ai pas plus d'experience que toi, mais il me semble que que déjà à la base, la BEL ne référence aucune couche et que donc il est normalement impossible d'appeler une fonction de l'IHM, BLL ou DAL.

    IHM référence la BPL et la BEL
    BPL référence la DAL et la BEL
    DAL référence la BEL uniquement.
    BEL ne référence aucune couche sinon on aurait un problème de référence circulaire.

    Que l'on me corrige si je dis faux.

  16. #36
    Membre émérite Avatar de kheironn
    Homme Profil pro
    Chef de projets technique C# / MVC / .Net
    Inscrit en
    Février 2007
    Messages
    823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projets technique C# / MVC / .Net
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2007
    Messages : 823
    Par défaut
    Oui, c'est ça dans le cas de cette architecture 4 couches.

    Citation Envoyé par BenoitM Voir le message
    Si j'ajoute un paramètre à ma fonction, je devrais peut-être changer mes 4 couches
    Je pensais entre autre à ce type de modif en parlant de devoir changer à x endroits...

    Mais j'insiste, le découpage en couche est une architecture parmi d'autres. Une série de pattern qu'il faut connaitre et respecter pour ne pas tomber dans les antipatterns si coûteux. (Mon préféré étant le spaghetti.

    Ce qu'il faut c'est avoir une architecture adaptée au besoins réelles et ne pas faire du N-tiers parce que c'est joli !


    D'ailleurs les deux derniers projets sur lesquels j'ai travaillé étaient découpés en dll fonctionnelles s'appuyant sur des dll de framework, etc... 64 dll dans un projet ne signifie pas 64 couches ! Il y avait 2 DAL, 2 IHM, des batch, et des tas de dll métier/framework

  17. #37
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    Je vais quand même donner un exemple concret pcq j'ai du mal .

    Hop, un peu de code pour commencer :
    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    Imports System.ComponentModel
     
    Public Class Parties
        Inherits List(Of Partie)
     
        Implements INotifyPropertyChanged
        Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
     
        Private Sub NotifyPropertyChanged(ByVal info As String)
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
        End Sub
     
        Public Overloads Sub Add(ByVal partie As Partie)
            MyBase.Add(partie)
            NotifyPropertyChanged("ListParties")
        End Sub
     
        Public Overloads Function Find(ByVal id As Integer) As Partie
            For Each elem As Partie In Me
                If elem.Id = id Then
                    Return elem
                End If
            Next
            Return Nothing
        End Function
     
        'Public Overloads Function Remove(ByVal partie As Partie) As Boolean
        '    If Not DAL_Partie.DeletePartie(partie) Then
        '        Throw New Exception("Impossible de supprimer cette partie")
        '        Return False
        '    Else
        '        Return MyBase.Remove(partie)
        '    End If
        'End Function
     
    End Class
     
    Public Class Partie
        Implements IComparable(Of Partie)
        Protected Function CompareTo(ByVal other As Partie) As Integer _
          Implements IComparable(Of Partie).CompareTo
            If TypeOf other Is Partie Then
                Dim temp As Partie = CType(other, Partie)
                Return Me.ordre.CompareTo(temp.Ordre)
            End If
     
            Throw New ArgumentException("L'objet n'est pas d'un type valide.")
        End Function
     
        Private _id As Integer
        Public Property Id As Integer
            Set(value As Integer)
                _id = value
                Me.Status = e_status.Updated
            End Set
            Get
                Return _id
            End Get
        End Property
     
        Private _ordre As Integer
        Public Property Ordre As Integer
            Set(value As Integer)
                _ordre = value
                Me.Status = e_status.Updated
            End Set
            Get
                Return _ordre
            End Get
        End Property
     
        Private _textes As Textes
        Public Property Textes As Textes
            Set(value As Textes)
                _textes = value
                Me.Status = e_status.Updated
            End Set
            Get
                Return _textes
            End Get
        End Property
     
        Public Property Status As e_status
        Public Enum e_status As Integer
            UpToDate = 1
            Created = 2
            Updated = 3
        End Enum
     
     
        Public Sub New(ByVal id As Integer, ByVal ordre As Integer, ByVal textes As Textes) 'ByVal nom As String
            Me.Id = id
            Me.Ordre = ordre
            Me.Textes = textes
            Me.Status = e_status.UpToDate
        End Sub
     
        Public Sub New(ByVal ordre As Integer, ByVal textes As Textes) 'ByVal nom As String
            Me.Ordre = ordre
            Me.Textes = textes
            Me.Id = 0
            Me.Status = e_status.Created
        End Sub
     
    End Class
    Ma question portait donc sur la portion de code en commentaire.
    Me rendant compte qu'il me manque donc une couche pour faire les choses "correctement", j'ai créé ceci :

    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    Public Class BLL_Partie
     
        Public Shared Function GetPartieById(ByVal id As Integer) As Partie
            Return DAL_Partie.GetPartieById(id)
        End Function
     
        Public Shared Function GetAllParties() As Parties
            Return DAL_Partie.GetAllParties
        End Function
     
        Public Shared Function UpdatePartie(ByVal partie As Partie) As Boolean
            Return DAL_Partie.UpdatePartie(partie)
        End Function
     
        Public Shared Function DeletePartie(ByVal partie As Partie) As Boolean
            Return DAL_Partie.DeletePartie(partie)
        End Function
     
        Public Shared Function NewPartie(ByVal partie As Partie) As Boolean
            Return DAL_Partie.NewPartie(partie)
        End Function
     
        Public Shared Function CommitUpdates(ByVal parties As Parties) As Boolean
            Dim result As Boolean = False
            Dim ordre As Integer = 0
            For Each elem As Partie In parties
                If elem.Ordre = ordre Then
                    Throw New Exception("Chaque partie doit avoir un numéro d'ordre unique.")
                    Return result
                Else
                    ordre = elem.Ordre
                End If
            Next
            For Each partie As Partie In parties
                Select Case partie.Status
                    Case Global.Evolution.Partie.e_status.Updated
                        If DAL_Partie.UpdatePartie(partie) Then
                            partie.Status = Global.Evolution.Partie.e_status.UpToDate
                        Else
                            Throw New Exception("Partie avec l'id " & partie.Id.ToString & " non mise à jour.")
                        End If
     
                    Case Global.Evolution.Partie.e_status.Created
                        If DAL_Partie.NewPartie(partie) Then
                            partie.Status = Global.Evolution.Partie.e_status.UpToDate
                        Else
                            Throw New Exception("Partie avec le texte FR """ & partie.Textes.Find(2).Texte & """ non crée.")
                        End If
                End Select
            Next
            Return result
        End Function
     
        Public Shared Function Remove(ByVal partie As Partie) As Boolean
            If Not DAL_Partie.DeletePartie(partie) Then
                Throw New Exception("Impossible de supprimer cette partie")
                Return False
            Else
                Return Parties.Remove(partie) 'le problème est sur cette ligne...
            End If
        End Function
    End Class
    N.B. : Avant, les appels à la couche DAL se passaient directement dans l'évènement des contrôles graphiques .

    Seulement je cale sur le fonction Remove (la dernière). Lorsque sur l'interface, l'utilisateur choisit une partie dans la liste qui lui est affichée et qu'il clique sur le bouton supprimer, je souhaite donc faire appel à cette fonction. Elle même fera donc appel à la fonction DeletePartie se trouvant dans la couche DAL mais ensuite, il faut que je retire la partie choisie par l'utilisateur de la liste.
    Le problème est que je n'ai pas accès à l'objet parties depuis la couche BLL (aussi appelée BPL si j'ai suivi). Je pourrais éventuellement passé cet objet en paramètre de la fonction mais je ne trouve pas ça élégant ^^

    Que feriez-vous à ma place ?

    Griftou.

  18. #38
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2011
    Messages : 63
    Par défaut
    Citation Envoyé par griftou Voir le message
    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
     
    Public Function GetUsersByName(ByVal name As String) As List(Of User)
            users = New List(Of User)
            ConnectDB()
     
            sql = 'la requête qui va bien
            ds = Cnx.DoSelect(sql)
            If ds.Tables.Count > 0 Then
                For Each row As DataRow In ds.Tables(0).Rows
                    users.Add(New User("les arguments qui vont bien"))
                Next
            End If
            DisconnectDB()
     
            Return users
        End Function
    Dis moi, la variable ds est de quel type ? et quel est le rôle de Cnx et son type ? Merci .

    Pas facile la prog en couche .

  19. #39
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    Citation Envoyé par shurikeNzL Voir le message
    Dis moi, la variable ds est de quel type ? et quel est le rôle de Cnx et son type ? Merci .

    Pas facile la prog en couche .
    Pour ds, c'est un dataset.

    Pour Cnx, c'est plus compliqué ^^.
    En fait, au tout début que j'ai commencé le .NET (sur VS2003 à l'époque), je galérais sévère avec les accès DB.

    Alors quand j'ai eu réussi à faire qqch qui tourne, j'en ai fait une dll à laquelle je passe qqes paramètres pour pouvoir me connecter la db et faire des requêtes.

    Cnx est une instance de cette dll (j'espère que j'utilise le bon vocalaire). Cnx est mon abréviation de connexion en fait.

    Si tu le souhaite, je peux te filer les sources de cette dll mais je doute que ce soit une bonne idée. C'est vraiment un truc mal foutu que je vais m'atteler à rendre plus propre dans pas longtemps (j'ai une formation prévue en décembre, ça va aider^^). Par exemple, je n'utilise aucune requête paramétrée. Bref, c'est casse gueule. Mais bon, dans mon environnement, je n'ai pas besoin de qqch de plus perfectionné. Par contre, je ne la recommanderais pas pour qqn d'autre.

  20. #40
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2011
    Messages : 63
    Par défaut
    Citation Envoyé par griftou Voir le message
    Si tu le souhaite, je peux te filer les sources de cette dll mais je doute que ce soit une bonne idée.
    Non t'en fais pas je vais me débrouiller. C'est juste que je trouvais ton code interessant car je n'arrive pas à saisir comment faire un select d'une table, afin d'entrer les valeurs des colonnes de ma table dans un objet métier.

    Bref je n'arrive pas à faire de SELECT, c'est super .

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 3 PremièrePremière 123 DernièreDernière

Discussions similaires

  1. Réponses: 1
    Dernier message: 11/06/2007, 16h33
  2. Debuter en programmation VB.net pour Win mobile
    Par oldman dans le forum VB.NET
    Réponses: 4
    Dernier message: 09/05/2007, 10h45
  3. inclure une BD oracle dans un programme VB.net
    Par noussaENSI dans le forum Windows Forms
    Réponses: 1
    Dernier message: 26/07/2006, 15h29
  4. Réponses: 4
    Dernier message: 28/04/2006, 23h21
  5. [VB.NET] Activation d'un programme VB.NET
    Par cyrcroix dans le forum Windows Forms
    Réponses: 7
    Dernier message: 03/06/2005, 12h21

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