RSS Feed

Articles associés au tag ‘exception’

Java – impossible de supprimer des éléments dans une liste

2 September 2010 par SeB 3 commentaires »

Parfois, le Java peut nous rendre quelque peu perplexe. Prenons par exemple le code suivant :

String s[] = {"1","2","3","4"};
List<String> l = Arrays.asList(s);
l.remove("1");

Ces lignes de code Java semblent correctes. Pourtant, à l’exécution, elles vont lever l’exception suivante :

java.lang.UnsupportedOperationException
java.util.AbstractList.remove(Unknown Source)
java.util.AbstractList$Itr.remove(Unknown Source)
java.util.AbstractCollection.remove(Unknown Source)

Mais pourquoi la classe List propose une méthode remove() qui n’est pas supportée ? Rappelons que List est une interface. En fait, la faute revient à la méthode Arrays.asList() qui retourne une liste liée à un tableau et donc non modifiable. Si vous voulez modifier une liste créée à partir de cette méthode, il faut utiliser le code suivant :

List<String> l = new ArrayList<String>(Arrays.asList(s));

La liste obtenue est modifiable. Vous pouvez y ajouter ou y enlever des éléments sans risquer une exception. ;-)

 

Stratégie de gestion des exceptions

6 September 2006 par SeB Pas de commentaire »

La gestion des exceptions n’est pas souvent prise au sérieux. La plupart des développeurs ajoute un bloc que try/catch seulement pour contenter le compilateur et laisse souvent le bloc catch vide.

Pourtant, l’utilisation des exceptions pour la gestion des erreurs se révèle être un outil très puissant lorsqu’il est bien utilisé. Julien Carnelos propose justement un guide sur la gestion des exceptions.

Selon lui, il existe quatre modes d’utilisation des exceptions :

  • Algorithme de décision : l’exception levée nécessite l’exécution de code traitant l’erreur spécifique à l’exception.
  • Rethrow : lever une exception encapuslant celle qui vient d’être levée. Souvent ce traitement est inutile. Sauf si l’on souhaite masquer l’implémentation sous jacente[1] ou que la nouvelle exception possède une réelle valeur ajoutée.
  • Fail fast : laisser remonter l’exception jusqu’à l’utilisateur. Celà permet d’identifier au plus tôt les exceptions incontrôlées.
  • Legacy : beaucoup de programme utilisent ce mode de fonctionnement où les exceptions sont attrapées mais rien n’est traité. Ce type de gestion est à proscrire ! Car il ne permet pas d’identifier les causes d’erreur facilement. Sans modifier ces applications pour les passer en Fail Fast, il est possible de tracer les piles d’exception[2].

Le Fail Fast représente vraiment un cas de bonne utilisation de la gestion des exceptions. Comme évoqué dans mon billet sur les modèles d’anti-conception pour la gestion de exceptions, il faut lever une exception le plus tôt possible et l’attraper le plus tard possible[3].

Vous êtes maintenant armé pour utiliser toutes les capacités de la gestion des exceptions.

Notes

[1] Pour rendre les couches logicielles imperméables.

[2] Celà permet d’analyser le comportement de l’application sans tout réecrire et sans provoquer d’effet de bord.

[3] L’idéal étant de l’attraper dans la couche de présentation pour l’afficher.

 

Modèle d’anti-conception pour la gestion des exceptions

24 April 2006 par SeB Pas de commentaire »

Les exceptions sont très utilisées. Pourtant, il n’est pas toujours évident de savoir comment les gérer correctement.

Tim McCune a écrit un article intitulé Exception-Handling Antipatterns où il présente les modèles d’anti-conception sur le traitement des exceptions.

Cet article donne les réponses aux questions :

  • Faut-il créer ses propres exceptions ?
  • Quand faut-il lever une exception ?
  • Quand capturer une exception ?

De son étude, on peut retenir qu’il existe deux types d’exception à créer soi-même :

  • Quand un problème survient : elle est propre à la couche applicative.
  • Pour encapsuler et lever une exception rencontrée : elle est utilisé pour masquer l’implémentation sous-jacente.

Quelques cas d’anti-conception

De plus, il nous conseille de ne pas tracer puis lever une exception. En effet lors de la capture d’une exception, il faut soit la tracer soit la lever. Mais il ne faut pas faire ces deux actions en même temps, sous peine de rencontrer les piles d’exception en double (voir plus) dans les traces.

Il est très dangereux de capturer directement l’exception générique : Exception. En effet, si le code appelé est modifié et peut lever de nouvelles exceptions, il est possible de passer à côté de nouveaux cas d’erreur non gérés.

Il faut faire attention à l’utilisation de l’encapsulation d’exception pour ne pas perdre les informations transmises par l’exception source.

De même, il n’est pas conseillé de retourner null lors qu’une exception est rencontrée. Comme son nom l’indique, une exception est un cas exceptionnel. Il faut réserver l’utilisation de la valeur null pour les cas fonctionnels.

Le traitement d’une exception peut passer par l’exécution de code de finalisation. Ce code ne doit en aucun cas pouvoir lever une exception sous peine de perdre la cause réelle la première exception.

Parfois l’implémentation de certaines méthodes ne sont pas toujours disponible. Cela se traduit souvent par l’écriture d’une méthode qui retourne la valeur null. Il est préférable de retourner une exception expliquant que la méthode n’est pas implémentée.

La gestion des exceptions, par le traitement de la cause de l’exception, fragilise le code. En effet, lorsque l’on est pas maitre du code levant l’exception, la cause de l’exception peut changer si l’implémentation change. Le code appelant compilera toujours, pourtant le résultat à l’exécution n’est pas garanti !

Quelques conseils supplémentaires

Sur le même thème, Gunjan Doshi et Jim Cushing ont écrit respectivement les meilleures utilisations de la gestion des exceptions et trois règles pour la gestion des exceptions. Les auteurs insistent sur la différence entre les classes Throwable, Error, Exception et RuntimeException en Java.

J. Cushing explique également qu’il faut lever le plus tôt possible une exception. Et de la même manière, il faut capturer le plus tard possible une exception levée. Le fait de lever le plus tôt possible une exception la rend plus spécifique et donc plus explicite. Et en capturant le plus tard possible une exception, cela permet de bénéficier d’une pile d’exception plus complète et donc plus facile à analyser.

Conclusion

La prochaine fois que vous vous posez des questions sur la façon dont il faut concevoir la gestion des exceptions dans votre application, repensez à ces modèles d’anti-conception. Celà vous permettra d’éviter quelques pièges.