Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

ERREUR SANS DOULEURS...


Information sur le tutorial

Catégorie :Optimisation du code Date de création : 08/09/2006 22:24:10 Vu : 7 748 fois

Note :
8 / 10 - par 4 personnes
8,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (2)
Ajouter un commentaire et/ou une note

Description

Ce tutoriel va vous montrer comment structurer votre manipulation d'erreur jusqu'à rendre votre application vraiment fiable.

Tutorial

ERREURS SANS DOULEURS...

La manipulation d'erreur de VB est déficiente (mais elle existe) parce que trop simpliste et sans structure.

Ce tutoriel va vous montrer comment structurer votre manipulation d'erreur jusqu'à rendre votre application
vraiment fiable.

MODELE

La manipulation d'erreur de Java (et de C#, VB.Fred et autres) est la suivante:

try{
    code risqué}
catch (typeErreur = spécifique){
    récupération de cette erreur}
catch (typeErreur = générale){
    récupération de l'erreur plus lourde}
finally{
    allez, on essuie tout ou s'il n'y a pas eu d'erreur, on nettoie quand même}


Je vais essayer de structurer une manipulation d'erreur approchant ce modèle.

EXAMPLE A NE PAS SUIVRE

Ce code fictif ne montre que la manipulation, déficiente parce que suivre ce code est difficile et cette difficulté n'est pas nécessaire. Ce code oblige le programmeur à tricoter dans le code et souvent il doit deviner le pourquoi du Resume Next

On Error GoTo label_1
Open DocAbsent for Binary as #number
Open DocAbsent2 for Binary as #number2
...
label_1:
MsgBox "Document n'existe pas...", vbOkOnly,"Crétin"
Resume next
End Function


AUTRE MAUVAIS EXAMPLE

On Error Resume Next
... 'ignorons ici toutes les préventions possible qu'on peut y mettre. Ce n'est pas encore le but.
CommonDialog1.CancelError = True
CommonDialog1.ShowOpen
FaireManip CommonDialog1.Filename


...que se passe-t-il si l'usager cancelle ? Est-ce que "FaireManip" maniera l'erreur ?

COMMENT SELECTIONNER UNE METHODE SIMPLE

LABEL

L'utilisation d'un label de renvoi d'erreur est à prévoir s'il y a un gros bloc de code entre le début de
l'opération risquée et sa fin et s'il n'y as pas d'autre opération risquée après le label.
Si c'est le cas, la fonction est tros longue et doit être normalisée (répartie) en plusieurs fonctions distinctes.
Dans tous les cas, si la fonction appelante doit tenir compte des erreurs, faire suivre la valeur.

Ex.:
Public Function Appelée() as Long
On Error GoTo label2
Call FonctionQuiPlante
....
Exit function
label2:

' Si nécessaire quelque code de nettoyage
Call RamasseToi
Appelée = Err.Number
End Function


Pourquoi faire suivre le numéro d'erreur ? Parce qu'en VB, toute erreur déclarée et maniée localement reste locale tout comme une variable locale. S'il y a erreur, la fonction appelante n'en saura rien à moins qu'on lui dise.
Je sais que la commande Err.Raise Err.Number pourrait être utilisée mais je répugne à l'utiliser, étant super
habitué à l'autre méthode.

ON ERROR RESUME NEXT

De nombreux programmeurs décrient cette méthode et avec raison car trop souvent, un paresseux s'en sert pour
ignorer l'erreur en espérant que ses effets peuvent être ignorés plus tard.
Mais bien planifiée, elle permet un réel controle du cheminement des opérations.

Ex.: CommonDialog sécurisé: méthode simple

Public Function GetFile(byval strDefaultFile as string) as string

    On Error Resume Next  'ligne nécessaire à cause de CancelError = True
    With CommonDialog1
        .Flags  = cdlOFNFileMustExist 
       ' l'usager est forcé de sélectionner un document existant
        .Filter ="Text (*.txt)|*.txt"        ' l'usager est forcé de sélectionner un doc 'txt'
        .FilterIndex = 1                '  ...et rien d'autre. noter l'extension est montrée à l'usager
        .Filename = strDefaultFile         ' Facultatif mais bon enfin...
        .DialogTitle = "Choisi, mec !"
        .CancelError = True            ' le coeur de l'affaire: en cas de cancel, une erreur est générée.
        .ShowOpen
    End With
    If Err.Number = 0 then 
               ' il n'y a qu'une erreur possible ici
        GetFile = CommonDialog1.FileName    ' passer le nom. Sinon, GetFile = ""
    End If    
End Function


Ex.: Manipulation plus complexe

....
On Error Resume Next
...
Set ExcelObject = GetObject(paramètres) ' Si Excel est déjà ouvert cette méthode le trouvera
' Sinon, deux facon de déceler l'erreur:
If ExcelObject Is Nothing then        ' mais cette méthode n'illustre pas l'example

If Err.Number <>0 then
    Err.Clear                    ' sinon la seconde partie sera déjà dans l'erreur
    Set ExcelObject = CreateObject(paramètres)
    If Err.Number <>0 then            ' capturer cette erreur nouvelle
        FunctionName = Err.Number    ' avertir la fonction appelante
        Exit Function            ' Err est locale ici donc nul besoin de faire un reset
    End If
    Err.Clear                    ' ici on continue

Ex.: Style Java

Dans ce dernier example, le code de la fonction doit ouvrir/créer un document binaire sans détruire un doc du même
nom préexistant. Certaines conditions (qui peuvent sembler factices (mais qui nous sont arrivées avec des clients
qui regardaient)) sont établies pour démontrer comment faire une cascade de manipulation.

Les codes d'erreur sont factices. Voir plus NOTE SUR CONSTANTES D'ERREUR plus bas.
Les erreurs ne sont pas maniées par les fonctions appelées, seulement capturées et renvoyées, comme ceci:

On Error Resume Next
If Err.Number <>0 then
    FunctionCalled = err.Number
    Exit Function
End If



If IsMediumPresent(Path) = err_NOMEDIUM then
    FunctionName = err_NOMEDIUM
    Exit Function

Else
    If IsMediumUnLocked(Path) = err_MEDIUMLOCKED then
        FunctionName = err_MEDIUMLOCKED
        Exit Function

    
    Else
        If IsMediumHasSpace(DocSize) = err_INSUFFICIENTSPACE then
            FunctionName = err_INSUFFICIENTSPACE
            Exit Function

        ' Si ces trois conditions sont satisfaites, le code continue après le block
        Endif
    End If
Endif


Maintenant continuons avec une autre approche

Err.Clear
On Error Resume Next
Select Case CreateDoc(strFilename)
    Case err_DOCEXIST

        ' demander un autre nom ou changer le nom du doc et informer l'usager
    Case err_DOCACCESSERROR
        ' le doc est ReadOnly: unlock ou informer l'usager
    Case err_DOCWRITEERROR
        ' Faut voir la cause exacte de l'erreur
    Case err_GENERICERROR
        ' alors la c'était vraiment pas prévu comme type d'erreur mais on reste dans le possible
    Case er_NOERROR
        ' mettre une continuation pour la function
        If WriteAllToDoc(strFilename) <> err_NOERROR Then GoTo label 'ici GoTo vaux la peine!

    Case Else
         ' ici c'est le délire...mais écrire dans un log d'erreur pourrait être une bonne idée.
          ' Charactères inconnus, valeurs invalide, ça peut être vraiment n'importe quoi.
End Select

......
label:

' réparation et controle des dommages

NOTE SUR CONSTANTES D'ERREUR

Par expérience, dès qu'une application dépasse une certaine masse de code, déboguer les erreurs devient très
difficile à suivre si les valeurs ne sont pas nommées d'une façon descriptive.
Pour faciliter le travail, regrouper toutes les erreurs possible à mesure que vous écrivez le code, en commencant
par la valeur de "pas d'erreur".
Ca donne quelque chose comme ceci.

Public Const err_NOERROR as Long = 0
Public Const err_DOCEXIST as Long = 64  
 ' rien n'interdit d'utiliser les codes d'erreur de VB
Public Const err_DOCACCESSERROR as Long = 98

Rien n'interdit d'avoir des valeurs doublées. L'mportant est d'avoir un nom pour la valeur.

Pour certaines fonction pouvant retourner des combinaisons de valeurs, utiliser des valeurs Hex comme ceci:

Public Const err_FlAGNONAME as Long= &H1
Public Const err_FlAGNOPASSWORD as Long= &H2
Public Const err_FlAGNOGROUP as Long= &H4
Public Const err_FlAGNOPERMISSION as Long= &H8

...et de suite
et les combiner en untilisant l'opérateur 'Or'

Un Long peut avoir 32 valeurs distinctes.

NOTRES EPARSES

La capture d'une erreur dans une structure If...ElseIf...Else...End If doit être regardée non seulement de façon à arrêter rapidement les opérations mais aussi à montrer qu'elles sont arrètées rapidement.

Une condition d'arrêt devrait être au début de la structure si des conditions complexes viennent après.
Ces conditions (il peut y en avoir plusieurs imbriquées) devraient être en tête de la structure.

Ex.:

If IsMediumUnLocked(docName)= False then
    ' erreur qui bloque tout
Else

    ' on continue
    ...
    ' D'autres conditions complexes suivent
End If

Cepandant si les conditions d'arrêts (même imbriquées) qui arrêtent tout ne sont pas suivies pas quoi que ce soitr d'autre, il est plus simple de sauter par dessus.

Ex.:

If DocExist(docName) = true then
    If DocNotLocked(docName) then

        ' faire la chose....
    End If
End If
' rien d'autre à faire

Bonne chance et ne succombez pas à l'erreur.  :-)
signaler à un administrateur
Commentaire de tof008 le 31/01/2007 16:00:04

trés beau tuto qui se peut se réveler trés utile, surtout qu'en général j'utilise les on error resume next et pas de la meilleure des manieres!
Bravo et merci

signaler à un administrateur
Commentaire de salim0shark le 20/04/2008 10:27:21

Bon tuto, pour gérer les erreurs en plus on sait tous que la force d'un programme qui tourne est la capacité de son créateur à gérer touts ses beugs
merci
salim0shark

Ajouter un commentaire



Nos sponsors

Sondage...

CalendriCode

Décembre 2008
LMMJVSD
1234567
891011121314
15161718192021
22232425262728
293031    

Consulter la suite du CalendriCode



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel BAÏSE, Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,000 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.