C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Définition d'une hiérarchie d'exceptions
Goto page 1, 2, 3, 4, 5, 6  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French)
View previous topic :: View next topic  
Author Message
Michael
Guest





PostPosted: Wed Aug 16, 2006 12:15 am    Post subject: Définition d'une hiérarchie d'exceptions Reply with quote



Bonsoir à tous,

achevant l'écriture de ma bibliothèque servant à utiliser l'API DirectShow,
j'en arrive au sujet un peu brulant pour moi que sont les exceptions...

Je ne sais pas comment les implémenter correctement.

J'ai distingué trois types d'exception qui peuvent être levées:

1) Les exceptions qui surgissent pendant l'initialisation des modules et
qui interdisent l'utilisation du module (initialisation d'un filtre qui
échoue par exemple, ou bien tentative de connecter deux filtres qui ne
peuvent pas être mis en relation ensemble)

2) Les exceptions qui surgissent lors de l'utilisation d'un module, mais
qui n'entravent pas son fonctionnement (impossibilité de se déplacer dans
une vidéo manuellement par exemple, impossibilité d'extraire une image
d'une vidéo)

3) Les exceptions qui sont levées suite à une action de l'utilisateur du
programme final (Problème dans le choix d'un fichier par exemple (un ZIP au
lieu d'un AVI))


Les exceptions de la première catégorie sont plutôt destinés au programmeur
qui utilise la bibliothèque et n'aident en rien l'utilisateur du programme
final, puisqu'il ne pourra rien modifier.


Les exceptions de la deuxième catégorie peuvent être utiles à l'utilisateur
de la librairie et à l'utilisateur du programme


Enfin les exceptions de la dernière catégorie sont exclusivement destinées
à l'utilisateur du programme, afin qu'il change de fichier qui doit être lu
par exemple.



Bref toujours est-il que je ne sais pas comment m'y prendre...

Est-ce que je dois encadrer les fonctions susceptibles de lever une
exception par un try catch()? Lesquelles?

Est-ce à l'utilisateur de la bibiliothèque de le faire?
L'utilisateur du programme?

Ou bien je laisse les exceptions se déclencher et c'est au programmeur de
se débrouiller comme il veut?

Un peu d'aide serait la bienvenue :)

Merci d'avance

Michael
Back to top
Michael
Guest





PostPosted: Wed Aug 16, 2006 4:25 am    Post subject: Re: Définition d'une hiérarchie d'exceptions Reply with quote



La question que je me pose en fait est la suivante:
* A qui sont destinées les exceptions? Au concepteur de bibliothèque, à
l'utilisateur de la bibliothèque, ou au client final?

Par exemple, voici une fonction tirée de la bibliothèque (c'est une
fonction utilisée à l'intérieur de la bibilothèque, qui n'est pas
accessible à l'utilisateur)

//-------------------------------------------------------------------------
void OutputFileDVType2::ConnectToVideoDevice(CComPtr<IBaseFilter> &
pDevice)
{
assert(CheckInputDeviceIsDVCam() == true);

/* Check if the device is the smart tee filter or the real capture device
The process is different in case of the smart tee filter, because we must
use
Dshow::Func::GetPinCategory with NULL parameters on its pin, because the
output pins of the Smart Tee
don't support IEnumMediaTypes and IKsPropertySet. */

CComPtr<IPin> pPinDeviceOutput;

GUID deviceCateg;
if (FAILED(pDevice->GetClassID(&deviceCateg)))
{
//Exception
}

if (deviceCateg == CLSID_SmartTee)
DShow::Func::GetPin(pDevice,NULL,PINDIR_OUTPUT,NULL,pPinDeviceOutput);
else
DShow::Func::GetPin(pDevice,&MEDIATYPE_Interleaved,PINDIR_OUTPUT,
&PIN_CATEGORY_CAPTURE,pPinDeviceOutput);

if (pPinDeviceOutput == NULL)
{
//Exception
}

if (FAILED(Func::ConnectFilters(pGraph,pPinDeviceOutput,pDVSplit)))
{
//Exception
}

//Connect the DV Splitter to the AVI Mux (twice)
if (FAILED(Func::ConnectFilters(pGraph,pDVSplit,pFilter)))
{
//Exception
}

if (FAILED(Func::ConnectFilters(pGraph,pDVSplit,pFilter)))
{
//Exception
}
}

Je me rends compte en fait que les exceptions que je pourrais lancer ici
n'intéressent qu'une seule personne : Moi !! En effet elles me
permettraient de savoir où se trouve une erreur dans le code (Par exemple
quels sont les filtres que je tente de mettre en relation alors qu'ils ne
le devraient pas...)

Mais je me dis que ce pourrait être intéressant de les laisser, ce qui
permettrait à l'utilisateur de la bibliothèque ou à l'utilisateur final de
faire remonter des "codes d'erreur" lancés par les exceptions...




Pour moi écrire la bibliothèque et vérifier que ce que je fais est bon,
est-ce que des simples assert sont suffisants? Auquel cas le code précédent
deviendrait

//-------------------------------------------------------------------------
void OutputFileDVType2::ConnectToVideoDevice(CComPtr<IBaseFilter> &
pDevice)
{
assert(CheckInputDeviceIsDVCam() == true);

/* Check if the device is the smart tee filter or the real capture device
The process is different in case of the smart tee filter, because we must
use
Dshow::Func::GetPinCategory with NULL parameters on its pin, because the
output pins of the Smart Tee
don't support IEnumMediaTypes and IKsPropertySet. */

CComPtr<IPin> pPinDeviceOutput;

GUID deviceCateg;
assert(pDevice->GetClassID(&deviceCateg));

if (deviceCateg == CLSID_SmartTee)
DShow::Func::GetPin(pDevice,NULL,PINDIR_OUTPUT,NULL,pPinDeviceOutput);
else
DShow::Func::GetPin(pDevice,&MEDIATYPE_Interleaved,PINDIR_OUTPUT,
&PIN_CATEGORY_CAPTURE,pPinDeviceOutput);

assert(pPinDeviceOutput != NULL);

assert(Func::ConnectFilters(pGraph,pPinDeviceOutput,pDVSplit));

//Connect the DV Splitter to the AVI Mux (twice)
assert(Func::ConnectFilters(pGraph,pDVSplit,pFilter));

assert(Func::ConnectFilters(pGraph,pDVSplit,pFilter));
}


Et ne lancer des exceptions que lors des fonctions utilisées par
l'utilisateur de la bibliothèque?
Back to top
Pierre Barbier de Reuille
Guest





PostPosted: Wed Aug 16, 2006 4:30 am    Post subject: Re: Définition d'une hiérarchie d'e xceptions Reply with quote



Michael wrote:
Quote:
Bonsoir à tous,

achevant l'écriture de ma bibliothèque servant à utiliser l'API DirectShow,
j'en arrive au sujet un peu brulant pour moi que sont les exceptions...

Arf ... c'est pas le bon moment pour penser à ça ... les exceptions,
c'est comme les const, c'est plus facile si tu le fais dès le début
(sinon tu risques de trouver ça inutilement pénible et de ne plus le
faire par la suite, ce qui serait dommage ...).

Quote:

Je ne sais pas comment les implémenter correctement.

J'ai distingué trois types d'exception qui peuvent être levées:

1) Les exceptions qui surgissent pendant l'initialisation des modules et
qui interdisent l'utilisation du module (initialisation d'un filtre qui
échoue par exemple, ou bien tentative de connecter deux filtres qui ne
peuvent pas être mis en relation ensemble)

2) Les exceptions qui surgissent lors de l'utilisation d'un module, mais
qui n'entravent pas son fonctionnement (impossibilité de se déplacer dans
une vidéo manuellement par exemple, impossibilité d'extraire une image
d'une vidéo)

3) Les exceptions qui sont levées suite à une action de l'utilisateur du
programme final (Problème dans le choix d'un fichier par exemple (un ZIP au
lieu d'un AVI))


Les exceptions de la première catégorie sont plutôt destinés au programmeur
qui utilise la bibliothèque et n'aident en rien l'utilisateur du programme
final, puisqu'il ne pourra rien modifier.


Les exceptions de la deuxième catégorie peuvent être utiles à l'utilisateur
de la librairie et à l'utilisateur du programme


Enfin les exceptions de la dernière catégorie sont exclusivement destinées
à l'utilisateur du programme, afin qu'il change de fichier qui doit être lu
par exemple.



Bref toujours est-il que je ne sais pas comment m'y prendre...

Est-ce que je dois encadrer les fonctions susceptibles de lever une
exception par un try catch()? Lesquelles?

Pour ça y a de très bons remarques dans "Guru of the Week" :
http://www.gotw.ca/gotw/065.htm

En gros, gérer les exceptions, ce n'est que *peu* utiliser try/catch.
Pour les exceptions qui mettent ta bibliothèque dans un état pas
possible, en gros ton seul soucis sera de ne pas avoir de fuites de
mémoire et que tu libères bien les ressources, ce qui ne posera aucun
problème si tu n'utilises que des smart pointer et, plus généralement,
l'idiome de l'initialisation à la création (i.e. c'est toujours le
constructeur de l'objet dans la pile qui s'occupe de l'allocation des
ressources, mémoire ou non, et ce sera donc le destructeur de cet objet
qui désallouera les ressources). Après, comme de toute façon faudra
réinitialiser la lib, autant ne pas s'embetter avec (enfin, c'est mon
opinion Razz ).

Pour les autres exceptions, ça peut devenir un peu plus difficile
(paradoxalement) car il serait vraiment bien que la levée de ces
exceptions laisse ta lib dans l'état où elle était avant l'appel de la
fonction qui lève l'exception. Dans tous les cas, je te recommande la
lecture des sujets de Guru of the Week concernant les exceptions, tu les
trouveras là :

http://www.gotw.ca/gotw/

Pour les exceptions utilisateurs, c'est le même problème que pour les
précédentes.

Pour la hiérarchie, je ferais trois classes abstraites dérivant
directement de std::exception, une par type d'exception, de façon à
permettre à l'utilisateur de ta lib (i.e. le programmeur) d'intercepter
l'exceptions pertinente où il le veut (par exemple gérer les exceptions
utilisateur de manière centralisée pour avoir un affichage, les
exceptions qui lui sont destinées aux endroits où il pourra y faire
qqch, et les exceptions graves pourront éventuellement donner lieu à un
traitement entrainant la fermeture du programme ...).

Quote:

Est-ce à l'utilisateur de la bibiliothèque de le faire?
L'utilisateur du programme?

L'utilisateur du programme finale n'a aucune idée de la notion
d'exception et ne devrait jamais l'avoir ! En gros, du moment qu'il a un
bon rapport d'erreur, il se fout de la méthode utilisée (et il a
raison). C'est l'utilisateur de la lib qui sera content d'avoir un
système d'exception bien fait !

Quote:

Ou bien je laisse les exceptions se déclencher et c'est au programmeur de
se débrouiller comme il veut?

Dans tout les cas, pour ta lib, tu ne spécifies que les exceptions qui
peuvent "sortir" de la lib (i.e. des fonctions de ton utilisateurs
peuvent les voir passer).

Quote:

Un peu d'aide serait la bienvenue :)


Bah j'espère que ça aide ... en lisant un peu avant, les exceptions
réduisent vraiment de beaucoup les problèmes liés à la gestion des
erreurs. Par contre, ça demande de structure le programme en conséquence
(mais souvent la structuration pour les exceptions à d'autres avantages,
comme ne plus s'occuper *du tout* de la libération des ressources, vu
que c'est fait automatiquement à la destruction des objets ...).

Quote:
Merci d'avance

Michael

Pierre
Back to top
Pierre Barbier de Reuille
Guest





PostPosted: Wed Aug 16, 2006 4:34 am    Post subject: Re: Définition d'une hiérarchie d'e xceptions Reply with quote

Michael wrote:
Quote:
La question que je me pose en fait est la suivante:
* A qui sont destinées les exceptions? Au concepteur de bibliothèque, à
l'utilisateur de la bibliothèque, ou au client final?

AMA, les exceptions sont utiles pour deux cas (quand tu fais un lib):
1 - pour les erreurs que tu peux récupérer (exceptions "internes", qui
ne sont pas spécifiées car elles ne sortent pas de la lib)
2 - pour les erreurs qui sortiront de la lib car c'est soit la faute de
l'utilisateur, soit une erreur "matérielle" (ou système ou ... un truc
qu'il faut remonter quoi)

Pour les erreurs de programmation, le mieux c'est les assert. Après, tu
peux fournir une version de debug de ta lib si un utilisateur à un doute
.... avec la version de debug il pourra te dire si un assert foire !

Ouala mon avis,

Pierre

Quote:

Par exemple, voici une fonction tirée de la bibliothèque (c'est une
fonction utilisée à l'intérieur de la bibilothèque, qui n'est pas
accessible à l'utilisateur)

//-------------------------------------------------------------------------
void OutputFileDVType2::ConnectToVideoDevice(CComPtr<IBaseFilter> &
pDevice)
{
assert(CheckInputDeviceIsDVCam() == true);

/* Check if the device is the smart tee filter or the real capture device
The process is different in case of the smart tee filter, because we must
use
Dshow::Func::GetPinCategory with NULL parameters on its pin, because the
output pins of the Smart Tee
don't support IEnumMediaTypes and IKsPropertySet. */

CComPtr<IPin> pPinDeviceOutput;

GUID deviceCateg;
if (FAILED(pDevice->GetClassID(&deviceCateg)))
{
//Exception
}

if (deviceCateg == CLSID_SmartTee)
DShow::Func::GetPin(pDevice,NULL,PINDIR_OUTPUT,NULL,pPinDeviceOutput);
else
DShow::Func::GetPin(pDevice,&MEDIATYPE_Interleaved,PINDIR_OUTPUT,
&PIN_CATEGORY_CAPTURE,pPinDeviceOutput);

if (pPinDeviceOutput == NULL)
{
//Exception
}

if (FAILED(Func::ConnectFilters(pGraph,pPinDeviceOutput,pDVSplit)))
{
//Exception
}

//Connect the DV Splitter to the AVI Mux (twice)
if (FAILED(Func::ConnectFilters(pGraph,pDVSplit,pFilter)))
{
//Exception
}

if (FAILED(Func::ConnectFilters(pGraph,pDVSplit,pFilter)))
{
//Exception
}
}

Je me rends compte en fait que les exceptions que je pourrais lancer ici
n'intéressent qu'une seule personne : Moi !! En effet elles me
permettraient de savoir où se trouve une erreur dans le code (Par exemple
quels sont les filtres que je tente de mettre en relation alors qu'ils ne
le devraient pas...)

Mais je me dis que ce pourrait être intéressant de les laisser, ce qui
permettrait à l'utilisateur de la bibliothèque ou à l'utilisateur final de
faire remonter des "codes d'erreur" lancés par les exceptions...




Pour moi écrire la bibliothèque et vérifier que ce que je fais est bon,
est-ce que des simples assert sont suffisants? Auquel cas le code précédent
deviendrait

//-------------------------------------------------------------------------
void OutputFileDVType2::ConnectToVideoDevice(CComPtr<IBaseFilter> &
pDevice)
{
assert(CheckInputDeviceIsDVCam() == true);

/* Check if the device is the smart tee filter or the real capture device
The process is different in case of the smart tee filter, because we must
use
Dshow::Func::GetPinCategory with NULL parameters on its pin, because the
output pins of the Smart Tee
don't support IEnumMediaTypes and IKsPropertySet. */

CComPtr<IPin> pPinDeviceOutput;

GUID deviceCateg;
assert(pDevice->GetClassID(&deviceCateg));

if (deviceCateg == CLSID_SmartTee)
DShow::Func::GetPin(pDevice,NULL,PINDIR_OUTPUT,NULL,pPinDeviceOutput);
else
DShow::Func::GetPin(pDevice,&MEDIATYPE_Interleaved,PINDIR_OUTPUT,
&PIN_CATEGORY_CAPTURE,pPinDeviceOutput);

assert(pPinDeviceOutput != NULL);

assert(Func::ConnectFilters(pGraph,pPinDeviceOutput,pDVSplit));

//Connect the DV Splitter to the AVI Mux (twice)
assert(Func::ConnectFilters(pGraph,pDVSplit,pFilter));

assert(Func::ConnectFilters(pGraph,pDVSplit,pFilter));
}


Et ne lancer des exceptions que lors des fonctions utilisées par
l'utilisateur de la bibliothèque?
Back to top
kanze
Guest





PostPosted: Wed Aug 16, 2006 6:14 pm    Post subject: Re: Définition d'une hiérarchie d'e xceptions Reply with quote

Pierre Barbier de Reuille wrote:
Quote:
Michael wrote:
Pierre Barbier de Reuille <p.barbierdereuille (AT) free (DOT) fr> wrote
in news:44e2590c $0$18265$636a55ce (AT) news (DOT) free.fr:

Pour la hi?rarchie, je ferais trois classes abstraites
d?rivant directement de std::exception, une par type
d'exception, de fa?on ? permettre ? l'utilisateur de ta
lib (i.e. le programmeur) d'intercepter l'exceptions
pertinente o? il le veut (par exemple g?rer les exceptions
utilisateur de mani?re centralis?e pour avoir un affichage,
les exceptions qui lui sont destin?es aux endroits o? il
pourra y faire qqch, et les exceptions graves pourront
?ventuellement donner lieu ? un traitement entrainant la
fermeture du programme ...).

Donc le mieux c'est que tout type d'erreur passe par une
exception, puisque par exemple si dans la lib il est
impossible de créer un objet qui doit être utilisé, il est
inutile d'aller plus loin. Et autant avertir tout le monde
de ce qui a foiré.

Quant aux assert, je les utiliserai pour vérifier que les
paramètres entrés par l'utilisateur de la lib sont
corrects...

Voilà, pour moi la distinction est:

- Exception : erreur d'utilisation ou matérielle
- Assert : pour vérifier que *je* ne me suis pas trompé quelque part,
de toute façon ce sera supprimé dans la version finale (sans avoir rien
à faire, l'entête <cassert> définit la macro assert comme une fonction
vide si la compilation n'est pas en debug ...)

Je vois trois catégories :

-- Code de rétour : erreur « attendue », donc, non
exceptionnelle. L'exemple type, c'est toute erreur dans les
entrées d'une utilisateur. (Utilisateur, ici, c'est le
bonhomme devant le clavier ; pour le code qui t'appelle, je
parlerais de client.) Pour la reste, c'est souvent une
question de jugement : d'une part, une connexion TCP qui
tombe, il faut s'y attendre de temps en temps, mais de
l'autre, si tu es sur un reseau local, et même en général
sur l'internet, c'est quand même assez exceptionnel.

En gros, je dirais que s'il y a des chances de pouvoir
continuer l'opération en cours, c'est le code de rétour qui
s'impose. (Donc, par exemple, on peut toujours démander que
l'utilisateur rentrer les informations erronées de nouveau,
sans avorter la session.)

-- Exception : ce sont les erreurs auxquelles on ne s'attend
pas dans un fonctionnement normal, mais qui peuvent se
produire dans des cas limites, où dans les cas où quelque
chose est cloche dans l'environement (std::bad_alloc, parce
qu'une requête utilisateur est trop compliquée, ou parce
qu'un autre processus sur la machine bouffe toute la
mémoire). En général, on ne lève une exception que quand on
est sûr qu'il va falloir avorter le traitement en cours,
mais qu'on n'a aucune raison particulière à penser que le
problème devient d'une défaut dans le programme (ou
matériel, mais c'est rare de pouvoir detecter des problèmes
réelement matériel).

Ici aussi, il y a des questions de jugements. Mes serveurs,
par exemple, tournent sur des systèmes dédiés, avec
suffisament de mémoire -- la seule cause possible d'un
std::bad_alloc, c'est une fuite de mémoire, et la seule
solution, c'est de terminer le processus et le rédémarrer.
Du coup, je remplace le new_handler par un qui avorte. Mais
il y a bien d'applications qui peuvent récupérer simplement
en abandonnant la requête en cours (avec par exemple un
message d'erreur indiquant une manque de ressources).

-- Assert (avec avortement en cas d'erreur) : tout ce qui
relève de l'erreur logiciel (y compris dans le code client)
ou d'une panne matérielle qui empêcherait au programme de
fonctionner.

Chacune a sa place.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Back to top
kanze
Guest





PostPosted: Wed Aug 16, 2006 6:17 pm    Post subject: Re: Définition d'une hiérarchie d' e xceptions Reply with quote

Fabien LE LEZ wrote:
Quote:
On Wed, 16 Aug 2006 12:59:08 +0200, Fabien LE LEZ
gramster (AT) gramster (DOT) com>:

De toutes façons, quelle que soit la tronche de la liste
d'initialisation, les classes de base sont initialisées
d'abord, puis vient le tour des variables membres, dans
l'ordre de déclaration dans la classe.

Mais bien sûr, respecter cet ordre dans la liste
d'initialisation, même si ça ne change rien au fonctionnement
du programme, améliore sa lisibilité.

Et empêche des avertissements de certains compilateurs.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Back to top
Michael
Guest





PostPosted: Wed Aug 16, 2006 7:04 pm    Post subject: Re: Définition d'une hiérarchie d'e xceptions Reply with quote

Quote:
Je vois trois catégories :

-- Code de rétour : erreur « attendue », donc, non
exceptionnelle. L'exemple type, c'est toute erreur dans les
entrées d'une utilisateur. (Utilisateur, ici, c'est le
bonhomme devant le clavier ; pour le code qui t'appelle, je
parlerais de client.) Pour la reste, c'est souvent une
question de jugement : d'une part, une connexion TCP qui
tombe, il faut s'y attendre de temps en temps, mais de
l'autre, si tu es sur un reseau local, et même en général
sur l'internet, c'est quand même assez exceptionnel.

En gros, je dirais que s'il y a des chances de pouvoir
continuer l'opération en cours, c'est le code de rétour qui
s'impose. (Donc, par exemple, on peut toujours démander que
l'utilisateur rentrer les informations erronées de nouveau,
sans avorter la session.)

Au sein de ma lib, quand un paramètre de fonction est le chemin d'un
fichier vidéo à lire par exemple, et que ce chemin est invalide, je fais
comment?

Je balance une exception, ou bien c'est au client de s'en charger?

Parce que de mon côté, la construction des élèments permettant de lire un
fichier vidéo se font dans le constructeur d'une classe, donc pas de retour
possible ici...

Quote:
-- Exception : ce sont les erreurs auxquelles on ne s'attend
pas dans un fonctionnement normal, mais qui peuvent se
produire dans des cas limites, où dans les cas où quelque
chose est cloche dans l'environement (std::bad_alloc, parce
qu'une requête utilisateur est trop compliquée, ou parce
qu'un autre processus sur la machine bouffe toute la
mémoire). En général, on ne lève une exception que quand on
est sûr qu'il va falloir avorter le traitement en cours,
mais qu'on n'a aucune raison particulière à penser que le
problème devient d'une défaut dans le programme (ou
matériel, mais c'est rare de pouvoir detecter des problèmes
réelement matériel).

Ici aussi, il y a des questions de jugements. Mes serveurs,
par exemple, tournent sur des systèmes dédiés, avec
suffisament de mémoire -- la seule cause possible d'un
std::bad_alloc, c'est une fuite de mémoire, et la seule
solution, c'est de terminer le processus et le rédémarrer.
Du coup, je remplace le new_handler par un qui avorte. Mais
il y a bien d'applications qui peuvent récupérer simplement
en abandonnant la requête en cours (avec par exemple un
message d'erreur indiquant une manque de ressources).

Ce qui me confirme dans l'idée que dès qu'une erreur apparaît dans
l'enchainement des constructions, connexions, etc... des filtres DirectShow
au sein de la lib, il faut balancer une exception car dès lors la lib ne
peut plus fonctionner...

Quote:
-- Assert (avec avortement en cas d'erreur) : tout ce qui
relève de l'erreur logiciel (y compris dans le code client)
ou d'une panne matérielle qui empêcherait au programme de
fonctionner.

Je ne m'en sers que comme vérification que les bons paramètres ont été
transmis...
Back to top
Pierre Barbier de Reuille
Guest





PostPosted: Wed Aug 16, 2006 7:21 pm    Post subject: Re: Définition d'une hiérarchie d'e xceptions Reply with quote

kanze wrote:
Quote:
Pierre Barbier de Reuille wrote:
Michael wrote:
Pierre Barbier de Reuille <p.barbierdereuille (AT) free (DOT) fr> wrote
in news:44e2590c $0$18265$636a55ce (AT) news (DOT) free.fr:

Pour la hi?rarchie, je ferais trois classes abstraites
d?rivant directement de std::exception, une par type
d'exception, de fa?on ? permettre ? l'utilisateur de ta
lib (i.e. le programmeur) d'intercepter l'exceptions
pertinente o? il le veut (par exemple g?rer les exceptions
utilisateur de mani?re centralis?e pour avoir un affichage,
les exceptions qui lui sont destin?es aux endroits o? il
pourra y faire qqch, et les exceptions graves pourront
?ventuellement donner lieu ? un traitement entrainant la
fermeture du programme ...).

Donc le mieux c'est que tout type d'erreur passe par une
exception, puisque par exemple si dans la lib il est
impossible de créer un objet qui doit être utilisé, il est
inutile d'aller plus loin. Et autant avertir tout le monde
de ce qui a foiré.

Quant aux assert, je les utiliserai pour vérifier que les
paramètres entrés par l'utilisateur de la lib sont
corrects...

Voilà, pour moi la distinction est:

- Exception : erreur d'utilisation ou matérielle
- Assert : pour vérifier que *je* ne me suis pas trompé quelque part,
de toute façon ce sera supprimé dans la version finale (sans avoir rien
à faire, l'entête <cassert> définit la macro assert comme une fonction
vide si la compilation n'est pas en debug ...)

Je vois trois catégories :

-- Code de rétour : erreur « attendue », donc, non
exceptionnelle. L'exemple type, c'est toute erreur dans les
entrées d'une utilisateur. (Utilisateur, ici, c'est le
bonhomme devant le clavier ; pour le code qui t'appelle, je
parlerais de client.) Pour la reste, c'est souvent une
question de jugement : d'une part, une connexion TCP qui
tombe, il faut s'y attendre de temps en temps, mais de
l'autre, si tu es sur un reseau local, et même en général
sur l'internet, c'est quand même assez exceptionnel.

En gros, je dirais que s'il y a des chances de pouvoir
continuer l'opération en cours, c'est le code de rétour qui
s'impose. (Donc, par exemple, on peut toujours démander que
l'utilisateur rentrer les informations erronées de nouveau,
sans avorter la session.)

Je dois dire que je ne suis pas d'accord (même si, comme tu le dis plus
loin, c'est une affaire de jugement). Mais je ne pense pas qu'il soit
bon de mélanger code de retour et exceptions. Un des objectif des
exceptions est de ne gérer les erreurs qu'à l'endroit où tu peux y faire
quelque chose ... alors qu'avec les codes de retour, il faut propager
les erreurs à la main jusqu'à l'endroit qui peut gérer les erreurs. Et,
typiquement, les erreurs de saisies nécessiteront une re-saisie des
données et l'erreur sera donc gérées au mieux au niveau de l'interface
graphique (pour pouvoir redemander la saisie). Si tu utilises un code de
retour pour ça, ce sera très lourd à gérer. Pour moi, le seul cas où un
code de retour est utilisable dans un système utilisant les exceptions,
est s'il est acceptable d'avoir une erreur "silencieuse". Par exemple,
dans le cas d'un overflow numérique, le fait d'avoir NaN ou inf à la
place d'un nombre valide peut se justifier, car il est probable que le
client remplace ces valeurs par autre chose par la suite ... mais c'est
un des rares exemples que je vois comme ça.

De plus, je ne vois vraiment pas en quoi le code de retour permet, plus
que les exceptions, de récupérer l'exécution (ni plus ni moins
d'ailleurs ...). Il faut aussi savoir que la gestion de code de retour
est coûteuse en temps de calcul tout le temps alors que la gestion des
exceptions ne coûte que quand une exception est levée ...

Quote:

-- Exception : ce sont les erreurs auxquelles on ne s'attend
pas dans un fonctionnement normal, mais qui peuvent se
produire dans des cas limites, où dans les cas où quelque
chose est cloche dans l'environement (std::bad_alloc, parce
qu'une requête utilisateur est trop compliquée, ou parce
qu'un autre processus sur la machine bouffe toute la
mémoire). En général, on ne lève une exception que quand on
est sûr qu'il va falloir avorter le traitement en cours,
mais qu'on n'a aucune raison particulière à penser que le
problème devient d'une défaut dans le programme (ou
matériel, mais c'est rare de pouvoir detecter des problèmes
réelement matériel).

Ici aussi, il y a des questions de jugements. Mes serveurs,
par exemple, tournent sur des systèmes dédiés, avec
suffisament de mémoire -- la seule cause possible d'un
std::bad_alloc, c'est une fuite de mémoire, et la seule
solution, c'est de terminer le processus et le rédémarrer.
Du coup, je remplace le new_handler par un qui avorte. Mais
il y a bien d'applications qui peuvent récupérer simplement
en abandonnant la requête en cours (avec par exemple un
message d'erreur indiquant une manque de ressources).

-- Assert (avec avortement en cas d'erreur) : tout ce qui
relève de l'erreur logiciel (y compris dans le code client)
ou d'une panne matérielle qui empêcherait au programme de
fonctionner.

Je suis d'accord pour l'erreur logiciel mais pas pour l'erreur
matérielle ! Lors d'une erreur matériel, une exception est appropriée,
quitte à simplement avertir l'utilisateur et quitter ... Le problème de
la gestion d'une panne matérielle avec un assert et qu'il n'y aura plus
aucune erreur de gérées dès que le code est mis en production (i.e. donc
plus en debug).


Pierre

Quote:

Chacune a sa place.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Back to top
Michel Decima
Guest





PostPosted: Wed Aug 16, 2006 8:55 pm    Post subject: Re: Définition d'une hiérarchie d'e xceptions Reply with quote

Pierre Barbier de Reuille a écrit :

Quote:
Je suis d'accord pour l'erreur logiciel mais pas pour l'erreur
matérielle ! Lors d'une erreur matériel, une exception est appropriée,
quitte à simplement avertir l'utilisateur et quitter ... Le problème de
la gestion d'une panne matérielle avec un assert et qu'il n'y aura plus
aucune erreur de gérées dès que le code est mis en production (i.e. donc
plus en debug).

Qu'est ce qui empeche de garder les assert en production ?
Back to top
Pierre Barbier de Reuille
Guest





PostPosted: Wed Aug 16, 2006 9:07 pm    Post subject: Re: Définition d'une hiérarchie d'e xceptions Reply with quote

Michel Decima wrote:
Quote:
Pierre Barbier de Reuille a écrit :

Je suis d'accord pour l'erreur logiciel mais pas pour l'erreur
matérielle ! Lors d'une erreur matériel, une exception est appropriée,
quitte à simplement avertir l'utilisateur et quitter ... Le problème de
la gestion d'une panne matérielle avec un assert et qu'il n'y aura plus
aucune erreur de gérées dès que le code est mis en production (i.e. donc
plus en debug).

Qu'est ce qui empeche de garder les assert en production ?

Le fait que la fonction assert est redéfinit en fonction vide dès que le
programme n'est plus compilé en debug ... (ce qui en dit long sur
l'usage prévu pour les assert)

Pierre
Back to top
Michael
Guest





PostPosted: Wed Aug 16, 2006 9:10 pm    Post subject: Re: Définition d'une hiérarchie d' e xceptions Reply with quote

Quote:
Sinon ça se fait tout à fait d'avoir un message lisible dans
l'exception. Ça se fait aussi de faire des accesseurs pour que
l'utilisateur de la lib ait un accès facile à l'erreur. Dans ton cas, je
rajouterais, dans DSException, une méthode error_number() qui renvoie
hr. Juste au cas où pour certains erreurs, l'utilisateur de la lib
puisse réinitialiser qqch et relancer le processus ...

C'est donc une chose courament admise qu'une lib formatte elle-même ses
messages d'erreur?

Moi par exemple je peux créer un message du type:

DirectShow Error
Error Code : 0x80040200

CoCreateInstance Error : CLSID_VideoRenderer
GUID : xxxxxxx

Si on veut internationaliser les messages d'erreur, ça devient un problème
non?

Bien que je conçoive que pour des exceptions, dont le message est amené à
apparaître très peu souvent, l'anglais ne soit pas non plus une fatalité...
Back to top
Pierre Barbier de Reuille
Guest





PostPosted: Wed Aug 16, 2006 9:27 pm    Post subject: Re: Définition d'une hiérarchie d' e xceptions Reply with quote

Michael wrote:
Quote:
Sinon ça se fait tout à fait d'avoir un message lisible dans
l'exception. Ça se fait aussi de faire des accesseurs pour que
l'utilisateur de la lib ait un accès facile à l'erreur. Dans ton cas, je
rajouterais, dans DSException, une méthode error_number() qui renvoie
hr. Juste au cas où pour certains erreurs, l'utilisateur de la lib
puisse réinitialiser qqch et relancer le processus ...

C'est donc une chose courament admise qu'une lib formatte elle-même ses
messages d'erreur?

Moi par exemple je peux créer un message du type:

DirectShow Error
Error Code : 0x80040200

CoCreateInstance Error : CLSID_VideoRenderer
GUID : xxxxxxx

Si on veut internationaliser les messages d'erreur, ça devient un problème
non?

Bien que je conçoive que pour des exceptions, dont le message est amené à
apparaître très peu souvent, l'anglais ne soit pas non plus une fatalité...

Je pense que c'est en effet un chose bien admise, d'autant que la classe
standard de base std::exception définie dans la norme C++ inclue une
méthode virtuelle "what" qui renvoie une chaîne ...
à toi de renvoyer une chaîne en fonction des locales ...

Pierre
Back to top
Fabien LE LEZ
Guest





PostPosted: Wed Aug 16, 2006 11:58 pm    Post subject: Re: Définition d'une hiérarchie d'e xceptions Reply with quote

On Wed, 16 Aug 2006 17:07:00 +0100, Pierre Barbier de Reuille
<p.barbierdereuille (AT) free (DOT) fr>:

Quote:
Le fait que la fonction assert est redéfinit en fonction vide dès que le
programme n'est plus compilé en debug ...

Ça, c'est une spécificité de ton compilo.
Back to top
Fabien LE LEZ
Guest





PostPosted: Thu Aug 17, 2006 12:13 am    Post subject: Re: Définition d'une hiérarchie d'e xceptions Reply with quote

On 16 Aug 2006 06:14:33 -0700, "kanze" <kanze@gabi-soft.fr>:

Quote:
-- Exception : ce sont les erreurs auxquelles on ne s'attend
pas dans un fonctionnement normal, mais qui peuvent se
produire dans des cas limites,

Je serais moins manichéen que toi sur la distinction
code de retour / exception. J'ai plutôt tendance à choisir suivant la
lisibilité de code plutôt que d'après une règle fixe.

En particulier, si réparer le problème (par exemple, demander à
l'utilisateur de saisir une nouvelle valeur) demande de remonter
plusieurs appels de fonctions, les exceptions sont parfaitement
adaptées.
Si, en plein milieu d'un calcul, on s'aperçoit que la valeur saisie
entraîne des résultats incorrects, j'aime pouvoir dire "On arrête tout
et on recommence avec une autre valeur", sans avoir à mettre des
dizaines de vérifications de valeurs de retour qui alourdissent le
code.
Back to top
Gabriel Dos Reis
Guest





PostPosted: Thu Aug 17, 2006 2:11 am    Post subject: Re: Définition d'une hiérarchie d'e xceptions Reply with quote

Fabien LE LEZ <gramster (AT) gramster (DOT) com> writes:

| On 16 Aug 2006 06:14:33 -0700, "kanze" <kanze@gabi-soft.fr>:
|
| > -- Exception : ce sont les erreurs auxquelles on ne s'attend
| > pas dans un fonctionnement normal, mais qui peuvent se
| > produire dans des cas limites,
|
| Je serais moins manichéen que toi sur la distinction
| code de retour / exception. J'ai plutôt tendance à choisir suivant la
| lisibilité de code plutôt que d'après une règle fixe.

la correction d'un programme est-elle un corollaire de « lisibilité » ?


-- Gaby
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French) All times are GMT
Goto page 1, 2, 3, 4, 5, 6  Next
Page 1 of 6

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.