6
votes

Java: Quelle est la bonne façon de déclarer une méthode d'interface qui peut lancer une exception?

Disons que j'ai cette interface A qui est implémentée par plusieurs vendeurs: xxx

Cependant, je veux que les fournisseurs puissent lancer des exceptions pour signaler quelque chose a échoué et que la méthode pourrait potentiellement jeté. un runtimédiaxception . Dans chaque cas, le code qui appelle ces méthodes doit gérer l'échec et continuer. Juste parce que 1 fournisseur jette une NPE, je ne veux pas que le système vienne tomber en panne. Au lieu de le laisser à la personne qui appelle la méthode (ou en bas de la maintenance de la ligne), je voudrais assurer que chaque appel attrape toutes les exceptions en déclarant chaque méthode de: xxx

Mais c'est généralement une mauvaise pratique (PMD ne l'aime pas et généralement je suis d'accord avec la règle des méthodes concrètes), donc je me demande est une exception à la règle ou y a-t-il une meilleure façon?

Laissez-moi être clair, je cherche une solution dans laquelle l'appelant de l'interface est obligé de gérer toutes les exceptions (y compris RunTimeException s).

Pour détailler davantage mon environnement , tout cela fonctionne dans un cadre OSGI. Donc, chaque fournisseur packages que leur code dans un paquet et OSGI gérera toutes les exceptions pour empêcher tout le système. Ce que je regarde vraiment sont les interfaces de service OSGI qui seront appelées par un ensemble de nœuds. Ce que je veux faire, c'est que lorsque je ise itérale à tous les services, un service ne jette pas une NPE et arrête le processus qui exécute. Je veux le gérer plus gracieusement en attrapant toutes les exceptions projetées du service afin que les autres services fournis soient toujours gérés.


3 commentaires

Cette question n'est pas spécifique aux interfaces, n'est-ce pas? Je veux dire, les mêmes problèmes s'appliquent aux méthodes abstraits et même à des mises en œuvre de la méthode pouvant être (ou même être censées être) remplacées.


Si cette méthode fait «quelque chose», c'est que quelque chose de si large qu'elle pourrait éventuellement jeter une exception?


Il serait difficile de contraindre l'ensemble des exceptions, alors oui.


7 Réponses :


9
votes

Créez votre propre classe d'exception IE. myseviceException et jetez-le de l'interface. L'idée ici est de lancer des exceptions significatives alors n'ayez pas peur de créer de nombreuses classes d'exception personnalisées si cela fournit la plus grande lisibilité et la maintenabilité à vos besoins. Vous pouvez attraper les exceptions détaillées du fournisseur en aval et les envelopper comme votre exception personnalisée afin que le flux amont ne soit pas obligé de traiter des exceptions spécifiques au fournisseur. XXX

En règle générale Erreurs , attrapez toujours exceptions et gérer-le!


2 commentaires

J'aime cette idée, mais cela ne forte pas les appelants à vérifier les runtimédies. Peut-être que j'ai juste besoin de le faire déclarer de jeter les deux.


@Dave H - Vous ne pouvez pas (et n'essayez pas de tenter de) obliger les appelants à vérifier les runtimédiesxceptions, c'est la nature d'une exception décochée.



2
votes

Les fournisseurs peuvent certainement lancer des exceptions de runtimédies au contenu de leur cœur, car ils sont décochés. Cela signifie que vous n'avez pas besoin d'ajouter la clause à l'interface.

Cela signifie également que les clients n'auront aucun avertissement de la définition de l'interface, et le compilateur n'appliquera pas l'essai / capture requis. La seule façon dont ils sauront est de lire vos javadocss.

Vous pouvez créer une exception personnalisée qui étend java.lang.exception ; C'est une exception vérifiée. Vous devrez l'ajouter à la clause de lancers; Le compilateur appliquera un essai / attrapera autour de ces méthodes; Vos clients devront gérer le problème.


3 commentaires

Je cherche quelque chose de plus compilateur exécutoire au lieu de s'appuyer sur Javadocs.


Il dit que ça n'a pas d'importance. Encore une fois, ils peuvent simplement lancer des exceptions d'exécution à tout moment et le compilateur ne force pas d'essayer / attraper. Même dans la solution de Coolbeans, ce qui est le meilleur cas ne forte pas le fournisseur à envelopper leur exception dans MyServiceException. C'est une limitation de Java. Si vous autorisez les fournisseurs à construire des modules pluggal, vous devez négocier une compréhension que leur code ne peut pas jeter des exceptions fatales et que cela devrait faire partie de votre processus d'assurance qualité pour assurer leur conformité.


Autre que tout ce que vous pouvez faire, c'est d'envelopper tous les appels de service dans une prise de vue {} (exception e)



1
votes

Je voudrais éviter de placer l'exception dans l'interface en raison de limitations que vous forcez sur les implémentations. Si je dois jeter une exception en implémentant votre interface, il permettra de tester des maquettes plus difficiles.

Si quelque chose ne va pas dans le code qui implémente votre interface, cela devrait être la préoccupation du programmeur de la classe d'implémentation.


1 commentaires

Juste parce que l'interface déclare une exception étant lancée, ne forcent pas la mise en œuvre de jeter la même chose. Cela peut toujours jeter moins. En outre, le vendeur ne peut pas toujours gérer si quelque chose ne va pas, peut être nécessaire pour informer l'appelant Quelque chose ne va pas.



1
votes

Création d'une clause de lancers, même avec un type d'exception personnalisé, n'est pas vraiment une réponse ici. Vous allez toujours avoir des choses comme NPES. Même si vous spécifiez aux fournisseurs que toutes les exceptions doivent être enveloppées dans votre type d'exception personnalisée, il y aura des cas où quelqu'un fait une erreur et une NPE traverse. Si ce n'était pas pour des erreurs, vous n'auriez pas de NPES.

Ajout de "exception" est une mauvaise idée dans beaucoup de cas, mais dans certains cas, cela fonctionne. Dans les cadres tels que des jambes de force et Junit, vous pouvez ajouter des "exceptions de lancers" sans problème car le cadre le permet. (Junit ne serait pas très utile si la première exception projetée a fait l'arrêt de la suite de tests.)

Vous pouvez concevoir le système afin que les appels au code du fournisseur se produisent dans des modules spécifiques qui se branchent sur le système et qui ont pris des mesures prises en charge par le système, semblables à la manière dont les actions fonctionnent dans des punitions. Chaque action peut joindre n'importe quoi, il y a un gestionnaire d'exception qui enregistre ce qui s'est mal passé. De cette façon, la logique commerciale qui appelle les API de Vendor n'aurait pas besoin d'être dérangée par une chaudière inutile attrapant à l'exception, mais si quelque chose ne va pas, le programme ne quitte pas.


1 commentaires

J'ai édité la question initiale. J'utilise OSGI afin que l'application ne sort pas vraiment, c'est plus que l'opération actuelle est interrompue à cause de 1 mauvaise pomme.



1
votes

Je suis d'accord avec PMD - déclarant que vous lancez générique exception s est laid. Je pense qu'il vaut mieux

  • Définissez des classes d'exception non spécifiques à des domaines spécifiques à un domaine (si les bâtiments intégrés ne le feront pas; tenez toujours à des classes prédéfinies si vous faites correspondre leur sémantique) et les déclarer dans les méthodes qui peuvent les jeter < / li>
  • garder des exceptions d'exécution à un minimum nu. Ils n'ont de sens que lorsque vous n'avez aucun contrôle sur la façon dont vous êtes appelé, et rien d'autre ne fera. Si vous avez une raison de s'attendre à ce qu'ils soient lancés dans un morceau de code, vous appelez, puis attrapez-les dès que cela a du sens et de les rejeter comme des exceptions standard (voir point ci-dessus).

    Les versions récentes de Java vous permettent de chaîner des exceptions. Par exemple, si vous obtenez un nullpointException ex lors de l'analyse d'un fichier F avec une bibliothèque externe, vous voudrez l'attraper et retirez-le comme, dites, un NOUVELLE SILEPARSINGEXCEPTION ("Erreur d'analyse" + F + ":" + ex.getMessage (), ex);


2 commentaires

désolé mais c'est terrible, vous augmentez la quantité d'exceptions et enfin que cette exception personnalisée ne vous dit rien de ce qui s'est mal tourné, vous devez donc faire de l'archéologie de creuser dans des exceptions internes et des objets pour trouver une cause réelle tout en jetant une exception qui vous dirait immédiatement ce qui a disparu tort...


Je suis fortement en désaccord. Emballage des exceptions est la manière recommandée de gérer ce cas (comme préconisé par la réponse acceptée, ce qui est mieux écrit mais très très similaire à cette réponse); Parce que l'enveloppement ajoute un contexte indisponible autrement. Dans l'exemple de cette réponse, comment une NPE non emballée vous aiderait-elle à diagnostiquer un fichier mal formé qui enfreint l'analyseur?



1
votes

Selon vos paramètres JVM, toute méthode a la capacité de lancer une exception à la fois si vous le déclarez comme une exception ou non. Catching / Manipulation RunTimeExceptions est généralement une mauvaise pratique. Bien qu'il existe des cas limités dans lesquels ce comportement pourrait être requis, les runtimédies sont principalement un indicateur qu'il y a quelque chose qui ne va pas avec le code, plutôt que l'utilisation du produit. Bien sûr, un inconvénient majeur pour attraper des punitions (surtout si vous les ignorez), c'est que les choses pourraient souffler dans votre système et que vous ne savez pas que cela se produise ... alors tout d'un coup, votre système crache complètement Des données non valides ou des accidents de toute façon à partir d'une autre raison, rendant plus difficile la trajectoire de la cause fondamentale.

Voir le tutoriel du soleil / Oracle sur les exceptions

http://download.oracle.com/javase/tatuuteur/ Essential / Exceptions / Runtime.html

Pour répondre à la question, sauf si vous savez exactement la dérivée d'exception, vous pouvez vous attendre à lancer, vous êtes à peu près bloqué une exception, même si j'ai des doutes majeurs quant à l'utilité de la classe d'exception générique, à moins que vous ne comprenez que Soin de la déconnexion de la trace de la pile et de telle sorte que vous sachiez que c'est arrivé? Si vous essayez de gérer de manière robuste l'exception sans savoir quel genre d'exception, vous ne réussirez probablement pas à la manipuler correctement ou même assez bien.


1 commentaires

Il s'agit davantage de veiller à ce que le fournisseur ne conserve pas le système de fonctionner. Il s'agit d'un cadre plug-in dans lequel les plug-ins de plusieurs fournisseurs peuvent être ajoutés au besoin.



1
votes

Vous pouvez implémenter votre interface dans une classe abstraite qui utilise le motif de la méthode de modèle pour attraper et envelopper les runtimédies avec une exception personnalisée. Cependant, il n'existe aucun moyen de faire respecter que les fournisseurs utilisent la classe abstraite (autre que la documentation).

class MySeviceException extends Exception{
    public MySeviceException() {}  
    public MySeviceException(String msg) { super(msg); }  
    public MySeviceException(Throwable cause) { super(cause); }  
    public MySeviceException(String msg, Throwable cause) { super(msg, cause); } 
}

interface A
{
    void x() throws MySeviceExceptionException;
    void y() throws MySeviceExceptionException;
}

class ABase implements A
{
    public final void x() throws MySeviceExceptionException {
        try {
            doX();
        } catch(RuntimeException ex) {
            throw new MySeviceExceptionException(ex);
        }
    }
    public final void y() throws MySeviceExceptionException {
        try {
            doY();
        } catch(RuntimeException ex) {
            throw new MySeviceExceptionException(ex);
        }
    }

    public abstract void doX() throws MySeviceExceptionException;
    public abstract void doY() throws MySeviceExceptionException;
}


0 commentaires