Je pense que @JackAidley en a déjà dit l'essentiel , mais laissez-moi le formuler comme suit :
sans exceptions (par exemple C)
Dans le flux de code normal, vous avez:
if (condition) {
statement;
} else if (less_likely_condition) {
less_likely_statement;
} else {
least_likely_statement;
}
more_statements;
Dans le cas «erreur sur tôt», votre code lit tout à coup:
/* demonstration example, do NOT code like this */
if (condition) {
statement;
} else {
error_handling;
return;
}
Si vous voyez ce modèle - un return
dans un else
(ou même if
bloc), retravailler immédiatement si le code en question ne pas avoir un else
bloc:
/* only code like this at University, to please structured programming professors */
function foo {
if (condition) {
lots_of_statements;
}
return;
}
Dans le monde réel…
/* code like this instead */
if (!condition) {
error_handling;
return;
}
lots_of_statements;
Cela évite les imbrications trop profondes et remplit le cas de «rupture précoce» (aide à garder l'esprit et le flux de code propres) et ne viole pas la «mise de la chose la plus probable dans la if
pièce», car il n'y a tout simplement aucune else
partie .
C
et nettoyage
Inspiré par une réponse à une question similaire (qui s’est mal compris), voici comment vous effectuez le nettoyage avec C. Vous pouvez utiliser un ou deux points de sortie, voici un pour deux points de sortie:
struct foo *
alloc_and_init(size_t arg1, int arg2)
{
struct foo *res;
if (!(res = calloc(sizeof(struct foo), 1)))
return (NULL);
if (foo_init1(res, arg1))
goto err;
res.arg1_inited = true;
if (foo_init2(&(res->blah), arg2))
goto err;
foo_init_complete(res);
return (res);
err:
/* safe because we use calloc and false == 0 */
if (res.arg1_inited)
foo_dispose1(res);
free(res);
return (NULL);
}
Vous pouvez les réduire en un point de sortie s'il y a moins de nettoyage à faire:
char *
NULL_safe_strdup(const char *arg)
{
char *res = NULL;
if (arg == NULL)
goto out;
/* imagine more lines here */
res = strdup(arg);
out:
return (res);
}
Cette utilisation de goto
est parfaitement bien, si vous pouvez vous en occuper; Le conseil de ne pas utiliser goto
est destiné aux personnes qui ne peuvent pas encore décider par elles-mêmes si une utilisation est bonne, acceptable, mauvaise, code spaghetti ou autre chose.
Exceptions
Ce qui précède parle de langues sans exceptions, ce que je préfère vraiment (je peux utiliser la gestion explicite des erreurs beaucoup mieux et avec beaucoup moins de surprise). Pour citer igli:
<igli> exceptions: a truly awful implementation of quite a nice idea.
<igli> just about the worst way you could do something like that, afaic.
<igli> it's like anti-design.
<mirabilos> that too… may I quote you on that?
<igli> sure, tho i doubt anyone will listen ;)
Mais voici une suggestion pour savoir comment le faire dans une langue avec des exceptions et quand vous voulez bien l'utiliser:
erreur de retour face aux exceptions
Vous pouvez remplacer la plupart des premiers temps return
par une exception. Cependant , votre flux de programme normal , c’est-à-dire tout flux de code dans lequel le programme n’a pas rencontré, eh bien, une exception… une condition d’erreur ou une telle erreur ne doit pas déclencher d’exception.
Cela signifie que…
# this page is only available to logged-in users
if not isLoggedIn():
# this is Python 2.5 style; insert your favourite raise/throw here
raise "eh?"
… Ça va, mais…
/* do not code like this! */
try {
openFile(xyz, "rw");
} catch (LockedException e) {
return "file is locked";
}
closeFile(xyz);
return "file is not locked";
… n'est pas. Fondamentalement, une exception n'est pas un élément de flux de contrôle . Cela rend également les opérations étranges («ces programmeurs Java ™ nous disent toujours que ces exceptions sont normales») et peuvent entraver le débogage (par exemple, demander à l'EDI d'interrompre toute exception). Les exceptions nécessitent souvent que l'environnement d'exécution décompresse la pile pour produire une trace, etc. Il existe probablement d'autres raisons.
Cela revient à: dans un langage prenant en charge les exceptions, utilisez ce qui correspond à la logique et au style existants et vous semble naturel. Si vous écrivez quelque chose à partir de zéro, faites-le d’accord tôt. Si vous écrivez une bibliothèque à partir de zéro, pensez à vos consommateurs. (N'utilisez jamais non plus abort()
dans une bibliothèque…). Mais quoi que vous fassiez, en règle générale, aucune exception n'est levée si l'opération se poursuit (plus ou moins) normalement après.
conseils généraux Exceptions
Essayez d’obtenir l’utilisation en premier lieu des exceptions approuvées par toute l’équipe de développement. Fondamentalement, planifiez-les. Ne les utilisez pas en abondance. Parfois, même en C ++, Java ™, Python, un retour d'erreur est préférable. Parfois ce n'est pas; utilisez-les avec pensée.