Bien programmé

Résolu
thomasaurelien Messages postés 71 Date d'inscription jeudi 7 juillet 2011 Statut Membre Dernière intervention 27 novembre 2017 - 21 déc. 2011 à 00:30
thomasaurelien Messages postés 71 Date d'inscription jeudi 7 juillet 2011 Statut Membre Dernière intervention 27 novembre 2017 - 22 déc. 2011 à 15:07
Bonjour voila toute mes fonctions marchent mais je voulais savoir si c'était bien programmé, si je pourrais simplifié des fonctions pour avoir un code propre ? merci

Module base

    'CREE le chemin d'accès à la base
    Public Function createChemin() As String
        Dim chemin As String
        Dim dbname As String = "Base"
        Dim cheminApp As String = Application.StartupPath
        cheminApp &= ""
        chemin = cheminApp & dbname & ".mdb"
        'MessageBox.Show(chemin)
        Return chemin
    End Function

    ' TEST si la base existe
    'renvoie ok si base existe
    Public Function test() As Boolean
        If System.IO.File.Exists(createChemin()) Then
            Return True
        Else
            Return False
        End If
    End Function

    'Declarer la connexion
    Private Cnx As OleDbConnection
    'Objet commande
    Private Cmd As OleDbCommand
    'Paramètre de connexion
    Private dta As OleDbDataAdapter
    Private CnxStr As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & createChemin() & ";"
    Private dts As New DataSet
    Private dt As DataTable
    Private dtc As DataColumn
    Private dtr As DataRow

    Public Sub connection()
        Try
            Cnx = New OleDbConnection
            'Donner à la propriété ConnectionString les paramètres de connexion
            Cnx.ConnectionString = CnxStr
            'Ouvrir la connexion
            Cnx.Open()
            'Instancier un objet Commande
            Cmd = New OleDbCommand
            'Lier Commande et Connexion
            Cmd.Connection = Cnx
        Catch ex As Exception
            MsgBox("Erreur de création de la table" & vbCrLf & ex.Message, , "Erreur")
        End Try
    End Sub
    Public Sub create_base()

        Try
            Dim dbe As New DBEngine
            Dim db As Database

            db = dbe.CreateDatabase("base", dbLangGeneral)

            If Not (db Is Nothing) Then db.Close()
        Catch ex As Exception
            MsgBox("Erreur de création de la base de donnée" & vbCrLf & ex.Message, , "Erreur")
        End Try

        connection()
        Try
            'Indiquer le type de commande
            Cmd.CommandType = CommandType.Text
            Cmd.CommandText = "CREATE TABLE USERS (LOGIN CHAR(8) NOT NULL PRIMARY KEY,MDP CHAR(8) NOT NULL,QUESTION VARCHAR(32) NOT NULL,REPONSE CHAR(8) NOT NULL)"
            'on exécute la commande
            Cmd.ExecuteNonQuery()
            'Fermer la connexion
            Cnx.Close()

        Catch ex As Exception
            MsgBox("Erreur de création de la table USERS" & vbCrLf & ex.Message, , "Erreur")
        End Try

    End Sub

    Public Function insert_user(ByVal login As String, ByVal mdp As String, ByVal question As String, ByVal rep As String) As Boolean

        connection()
        Try
            'Indiquer le type de commande
            Cmd.CommandType = CommandType.Text
            Cmd.CommandText = "INSERT INTO USERS (LOGIN, MDP, QUESTION, REPONSE) VALUES ('" & login & "','" & mdp & "','" & question & "','" & rep & "')"
            'on exécute la commande
            Cmd.ExecuteNonQuery()
            'Fermer la connexion
            Cnx.Close()
            Return True
        Catch ex As Exception
            MsgBox("Erreur dans l'insertion de d'un USERS" & vbCrLf & ex.Message, , "Erreur")
            Return False
        End Try

    End Function

    'Charge la table USERS en connectant
    Public Sub TableUSERS(ByVal log As String)
        Dim sql As String
        dts.Clear()
        connection()
        Try
            'Indiquer le type de commande
            Cmd.CommandType = CommandType.Text
            sql "select * from USERS where login'" & log & "'"
            'on exécute la commande
            Cmd = New OleDbCommand(sql)
            dta = New OleDbDataAdapter(Cmd)
            Cmd.Connection() = Cnx
            dta.Fill(dts, "USERS")
            dt = dts.Tables("USERS")
        Catch ex As Exception
            MsgBox("Erreur de recherche dans la table USERS" & vbCrLf & ex.Message, , "Erreur")
        End Try
    End Sub

    'Vérifie si le login existe ou pas
    Public Function rech_user(ByVal login As String) As Boolean
        TableUSERS(login)
        If dt.Rows.Count() = 0 Then
            'MessageBox.Show(dt.Rows.Count())
            Return False
        Else
            'MessageBox.Show(dt.Rows.Count())
            Return True
        End If
        'Fermer la connexion
        Cnx.Close()
    End Function

    'Rempli le combobox de la question et retourne la reponse
    Public Function info_user(ByVal login As String) As String
        TableUSERS(login)
        mdpoubli.TBquest.Text = dt.Rows(0).Item(2)
        Return dt.Rows(0).Item(3)
    End Function
    'renvoie le mot de passe
    Public Function mdp_user(ByVal login As String) As String
        TableUSERS(login)
        Return dt.Rows(0).Item(1)
    End Function
End Module


Oui je sais sa fait beaucoup de code d'un seul coup mais je demande votre aide pour apprendre à bien programmé car programmé c'est facile mais bien programmé c'est un peu plus dur.

11 réponses

Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
21 déc. 2011 à 08:12
mal strucuturé en général:
le code est découpé en taches, mais la liaison entre celles-ci est maladroite

tes procs devraient utiliser des parametres, elles ne sont pas réutilisables en l'état.

createChemin:

Dim cheminApp As String = Application.StartupPath
cheminApp &= ""
chemin = cheminApp & dbname & ".mdb"
pas propre, utilise ath.Combine

test:
If [...] Then
Return True
Else
Return False
End If

renvient a écrire :
Return [...]


connection :
en cas d'echec, pense a fermer la connection, détruire les objets, etc.


create_base:
If Not (db Is Nothing) Then db.Close()
code a placer dans un finally
idem pour Cnx.Close()


Private dts As New DataSet
Private dt As DataTable
Private dtc As DataColumn
Private dtr As DataRow

il n'y a pas lieu de partager ces variables

mdp_user:
que ce passe t'il en cas d'echec ?


Renfield - Admin CodeS-SourceS - MVP Visual Basic & Spécialiste des RegExp
3
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
21 déc. 2011 à 10:06
Code nettoyé (a noter que je ne suis pas 100% a l'aise en VB.Net)

Form1:
Partial Class Form1
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Try
            base.AjouterUser("toto", "password2toto", "Quel age avait Rimbaud ?", "28 ans")
            base.AjouterUser("fred", "password2fred", "Quel est le double du quart de quatre ?", "deux")
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Try
            If base.TesterUserExistence("renfield") Then
                MessageBox.Show("L'utilisateur 'renfield' existe bel et bien.")
            Else
                MessageBox.Show("L'utilisateur 'renfield' n'existe pas.")
            End If
            If base.TesterUserExistence("fred") Then
                MessageBox.Show("L'utilisateur 'fred' existe bel et bien.")
            Else
                MessageBox.Show("L'utilisateur 'fred' n'existe pas.")
            End If
            MessageBox.Show("Le mot de passe de toto est : " & base.LirePassword("toto"))
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    End Sub

    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        Dim Question As String
        Dim Reponse As String
        Try
            If base.LireQuestionReponse("fred", Question, Reponse) Then
                MessageBox.Show("La question de fred est '" & Question & "'" & Environment.NewLine & _
                                "La réponse donnée est '" & Reponse & "'.")
            End If
            If base.LireQuestionReponse("renfield", Question, Reponse) Then
                MessageBox.Show("La question de fred est '" & Question & "'" & Environment.NewLine & _
                                "La réponse donnée est '" & Reponse & "'.")
            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    End Sub
End Class


Module1:
Imports System.IO
Imports System.Data
Imports System.Data.OleDb
Imports ADOX

Module base
    Public ReadOnly Property Chemin() As String
        Get
            Return Path.Combine(Application.StartupPath, "Base.mdb")
        End Get
    End Property

    Private Function EtablirConnection() As OleDbConnection
        Dim Cnx As OleDbConnection
        Dim Cat As Catalog
        Dim Cmd As OleDbCommand
        Dim baseACreer As Boolean = False
        Dim echec As Boolean = False
        Dim ConnectionString As String = "Provider=Microsoft.Jet.OLEDB.4.0;Jet OLEDB:Engine Type=5;Data Source=" & Chemin & ";"
        '# Creation du fichier de base de données
        Try
            If Not File.Exists(Chemin) Then
                baseACreer = True
                Cat = New Catalog '# Ajouter une reference COM à : Microsoft ADO Ext
                Cat.Create(ConnectionString)
            End If
        Catch ex As Exception
            '# On ne doit pas afficher de MessageBox, elle doit remonter l'info
            Throw New Exception("Erreur de création de la base de donnée" & Environment.NewLine & ex.Message)
        End Try

        '# Ouverture de la connection proprement dite
        Try
            Cnx = New OleDbConnection
            Cnx.ConnectionString = ConnectionString
            Cnx.Open()
            '# On a créé le fichier mdb, rest a ajouter la table USERS
            If baseACreer Then
                Cmd = New OleDbCommand()
                Cmd.Connection = Cnx
                Cmd.CommandType = CommandType.Text
                Cmd.CommandText = "CREATE TABLE USERS (LOGIN CHAR(8) NOT NULL PRIMARY KEY," & _
                                                      "MDP CHAR(16) NOT NULL," & _
                                                      "QUESTION VARCHAR(64) NOT NULL," & _
                                                      "REPONSE CHAR(8) NOT NULL)"
                Cmd.ExecuteNonQuery()
            End If
        Catch ex As Exception
            echec = True
            Throw New Exception("Erreur de création de la table" & Environment.NewLine & ex.Message)
        Finally
            If echec Then
                If Not Nothing Is Cnx Then
                    If Cnx.State = ConnectionState.Open Then
                        Cnx.Close()
                    End If
                    Cnx.Dispose()
                End If
            End If
        End Try

        Return Cnx
    End Function

    Public Function AjouterUser(ByVal login As String, ByVal mdp As String, ByVal question As String, ByVal rep As String) As Boolean
        Dim Cnx As OleDbConnection = Nothing
        Dim Cmd As OleDbCommand
        Try
            If TesterUserExistence(login) Then
                Throw New Exception("L'utilisateur " & login & " existe déjà")
            End If
            Cnx = EtablirConnection()
            'Indiquer le type de commande
            Cmd = New OleDbCommand
            Cmd.CommandType = CommandType.Text
            '# On utilise des requètes parametrées, pas de concaténation aléatoires (risque d'injection SQL)
            Cmd.CommandText = "INSERT INTO USERS (LOGIN, MDP, QUESTION, REPONSE) VALUES (@login, @mdp, @question, @rep)"
            Cmd.Parameters.AddWithValue("@login", login)
            Cmd.Parameters.AddWithValue("@mdp", mdp)
            Cmd.Parameters.AddWithValue("@question", question)
            Cmd.Parameters.AddWithValue("@rep", rep)
            Cmd.Connection = Cnx
            Cmd.ExecuteNonQuery()
            Return True
        Catch ex As Exception
            Throw New Exception("Erreur dans l'ajout d'un USERS" & Environment.NewLine & ex.Message)
        Finally
            If Not Nothing Is Cnx Then
                Cnx.Close()
            End If
        End Try
        Return True
    End Function

    Private Function LireDataRow(ByVal Cmd As OleDbCommand) As DataRow
        Dim Cnx As OleDbConnection = Nothing
        Dim dta As OleDbDataAdapter
        Dim dts As DataSet
        If Nothing Is Cmd Then
            Throw New NullReferenceException("Cmd doit être renseigné.")
        End If
        Try
            Cnx = EtablirConnection()
            Cmd.CommandType = CommandType.Text
            Cmd.Connection = Cnx
            dta = New OleDbDataAdapter(Cmd)
            dts = New DataSet
            dta.Fill(dts)
            If dts.Tables(0).Rows.Count = 1 Then
                Return dts.Tables(0).Rows(0)
            Else
                Return Nothing
            End If
        Catch ex As Exception
            Throw New Exception("Erreur lors de la lecture de la table USERS" & Environment.NewLine & ex.Message)
        Finally
            '# Un peu de nettoyage...
            If Not Nothing Is Cnx Then
                Cnx.Close()
            End If
        End Try
    End Function

    'Vérifie si le login existe ou pas
    Public Function TesterUserExistence(ByVal login As String) As Boolean
        Dim Cmd As OleDbCommand
        Dim dtr As DataRow
        Try
            Cmd = New OleDbCommand("SELECT COUNT(0) FROM USERS WHERE LOGIN=@login")
            Cmd.Parameters.AddWithValue("@login", login)
            dtr = LireDataRow(Cmd)
            '# Si le Count renvoie 1, on quitte
            Return CType(dtr.Item(0), Integer) = 1
        Catch ex As Exception
            Throw New Exception("Erreur dans l'ajout d'un USERS" & Environment.NewLine & ex.Message)
        End Try
    End Function

    'Rempli le combobox de la question et retourne la reponse
    Public Function LireQuestionReponse(ByVal login As String, ByRef question As String, ByRef reponse As String) As Boolean
        Dim Cmd As OleDbCommand
        Dim dtr As DataRow
        Try
            question = String.Empty
            reponse = String.Empty
            If TesterUserExistence(login) Then
                Cmd = New OleDbCommand("SELECT QUESTION, REPONSE FROM USERS WHERE LOGIN=@login")
                Cmd.Parameters.AddWithValue("@login", login)
                dtr = LireDataRow(Cmd)
                question = dtr.Item("QUESTION").ToString()
                reponse = dtr.Item("REPONSE").ToString()
                Return True
            End If
        Catch ex As Exception
            Throw New Exception("Erreur dans la lecture du mot de passe" & Environment.NewLine & ex.Message)
        End Try
    End Function

    '# Renvoie le mot de passe
    '#=> Pas courant, on compare en général le hash du mot de passe avec le hash stocké dans la base
    '#   La base ne devrait pas stocker le mot de passe en clair.
    Public Function LirePassword(ByVal login As String) As String
        Dim Cmd As OleDbCommand
        Dim dtr As DataRow
        Try
            If TesterUserExistence(login) Then
                Cmd = New OleDbCommand("SELECT MDP FROM USERS WHERE LOGIN=@login")
                Cmd.Parameters.AddWithValue("@login", login)
                dtr = LireDataRow(Cmd)
                '# Si le Count renvoie 1, on quitte
                Return dtr.Item(0).ToString()
            End If
        Catch ex As Exception
            Throw New Exception("Erreur dans la lecture du mot de passe" & Environment.NewLine & ex.Message)
        End Try
        Return Nothing
    End Function
End Module


Pour résumer :
- structure mieux ton code
- vire la reference a VB6 (Microsoft.VisualBasic)
- pas de MessageBox dans les classes de travail, uniquement dans la partie GUI (Form). La remontée des erreurs se fait par le biais des exception
- pas de concaténation SQL, utiliser des requetes parametrées
- penses au Finally
- ne pas manipuler les controles de ta form depuis un procédure d'un module
- inutile de mettre toutes les variables en Private, ca t'aidera d'autre part a bien structurer ton code

c'est pas exhaustif au niveau des remarques, et perfectible au niveau du code, mais c'est un début

Renfield - Admin CodeS-SourceS - MVP Visual Basic & Spécialiste des RegExp
3
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
22 déc. 2011 à 11:10
l'exemple me paraissait clair...

Question et Reponse sont marqué en tant que ByRef

leur contenu est donc modifiable dans la fonction du Module.

Dim Question As String
        Dim Reponse As String
        Try
            If base.LireQuestionReponse("fred", Question, Reponse) Then
                MessageBox.Show("La question de fred est '" & Question & "'" & Environment.NewLine & _
                                "La réponse donnée est '" & Reponse & "'.")
            End If


La fonction renvoie False si l'user n'existe pas.

Renfield - Admin CodeS-SourceS - MVP Visual Basic & Spécialiste des RegExp
3
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
21 déc. 2011 à 08:52
Pense également a décocher la référence Microsoft Visual Basic des propriétés de ton projet.

Renfield - Admin CodeS-SourceS - MVP Visual Basic & Spécialiste des RegExp
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
thomasaurelien Messages postés 71 Date d'inscription jeudi 7 juillet 2011 Statut Membre Dernière intervention 27 novembre 2017
21 déc. 2011 à 13:50
Ah oui quand même sa ne ressemble pu trop à se que j'avais codé, il va me falloir un p'tit moment pour comprendre tous cela. Mais merci pour d'avoir tous regardé et d'avoir réfléchi à mon code.
0
thomasaurelien Messages postés 71 Date d'inscription jeudi 7 juillet 2011 Statut Membre Dernière intervention 27 novembre 2017
21 déc. 2011 à 22:20
j'étudie ton code petit à petit mais j'ai un petit dans la compréhension dans la fonction AjouterUSERS car au début on test si le user existe mais quand je lance le programme cela me met un messaage d'erreur dans le code si l'utilisateur existe deja alors que l'on devrait afficher un message à l'utilisateur.

Try
            If TesterUserExistence(login) Then
                Throw New Exception("L'utilisateur " & login & " existe déjà")
            endif
                Cnx = EtablirConnection()
                'Indiquer le type de commande
                Cmd = New OleDbCommand
                Cmd.CommandType = CommandType.Text
                '# On utilise des requètes parametrées, pas de concaténation aléatoires (risque d'injection SQL)
                Cmd.CommandText = "INSERT INTO USERS (LOGIN, MDP, QUESTION, REPONSE) VALUES (@login, @mdp, @question, @rep)"
                Cmd.Parameters.AddWithValue("@login", login)
                Cmd.Parameters.AddWithValue("@mdp", mdp)
                Cmd.Parameters.AddWithValue("@question", question)
                Cmd.Parameters.AddWithValue("@rep", rep)
                MessageBox.Show(Cmd.CommandText)
                Cmd.Connection = Cnx
                Cmd.ExecuteNonQuery()
                Return True

        Catch ex As Exception
            Throw New Exception("Erreur dans l'ajout d'un USERS" & Environment.NewLine & ex.Message)
        Finally
            If Not Nothing Is Cnx Then
                Cnx.Close()
            End If
        End Try
0
thomasaurelien Messages postés 71 Date d'inscription jeudi 7 juillet 2011 Statut Membre Dernière intervention 27 novembre 2017
21 déc. 2011 à 22:34
Ah autant pour moi j'avais pas fais attention au try catch pour le clic du bouton !
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
22 déc. 2011 à 06:52
Oui:
on remonte les informations au niveau du click sur le bouton...
des actions utilisateur en général.

ainsi, si plus tard tu veux en ajouter a la chaine, tu peux afficher un rapport indiquant les user ajoutés ou non, sans avoir de multiples msgBox

Renfield - Admin CodeS-SourceS - MVP Visual Basic & Spécialiste des RegExp
0
thomasaurelien Messages postés 71 Date d'inscription jeudi 7 juillet 2011 Statut Membre Dernière intervention 27 novembre 2017
22 déc. 2011 à 10:49
Pourrais tu m'expliquer la fonction LireQuestionReponse ? car j'ai un peu de mal à l'appliquer car en faite j'ai un formulaire qui permet de demandé son mot de passe si celui si est oublié.
Dans un premier temps, j'ai un textBox avec un bouton afficher qui teste si le user existe ou pas, si celui-ci existe alors 2 apparaissent dont 1 qui se rempli de la question et l'autre est vide qui permet à l'utilisateur de saisir sa reponse.

La fonction LireQuestionReponse demande 3 paramètre et renvoie un booleén mais j'ai pas la question et reponse au départ.
0
thomasaurelien Messages postés 71 Date d'inscription jeudi 7 juillet 2011 Statut Membre Dernière intervention 27 novembre 2017
22 déc. 2011 à 11:25
Ok merci c'est la première fois que j'utilise ByRef c'est drolement utile moi qui fesait à chaque fois une fonction pour renvoyé chaque élément sa s'implifie la tâche.

Merci pour ton aide
0
thomasaurelien Messages postés 71 Date d'inscription jeudi 7 juillet 2011 Statut Membre Dernière intervention 27 novembre 2017
22 déc. 2011 à 15:07
Merci Renfiels pour tous. Tous fonctionne bien ! Maintenant j'ai juste à mettre les contrôles sur le formulaire.
0
Rejoignez-nous