129 votes

Meilleure façon de définir des chaînes/codes d’erreur dans Java ?

Je suis en train d'écrire un web service en Java, et je suis à essayer de comprendre la meilleure façon de définir des codes d'erreur associés à leurs chaînes d'erreur. J'ai besoin d'avoir un code d'erreur numérique et une chaîne d'erreur regroupés. À la fois le code d'erreur et la chaîne d'erreur sera envoyé au client d'accéder au service web. Par exemple, quand une SQLException se produit, j'aimerais faire le suivant:

// Example: errorCode = 1, 
//          errorString = "There was a problem accessing the database."
throw new SomeWebServiceException(errorCode, errorString);

Le programme client peut être affiché le message:

"Erreur #1 a eu lieu: Il y avait un problème d'accès à la base de données."

Ma première idée était d'utiliser un Enum des codes d'erreur et les remplacer le toString méthodes pour renvoyer les chaînes d'erreur. Voici ce que j'ai trouvé:

public enum Errors {
  DATABASE {
    @Override
    public String toString() {
      return "A database error has occured.";
    }
  },

  DUPLICATE_USER {
    @Override
    public String toString() {
      return "This user already exists.";
    }
  },

  // more errors follow
}

Ma question est: Est-il une meilleure façon de le faire? Je préfère une solution dans le code, plutôt que de lire à partir d'un fichier externe. Je suis à l'aide de Javadoc pour ce projet, et d'être en mesure de documenter les codes d'erreur en ligne et de les faire automatiquement mise à jour dans la documentation serait utile.

178voto

Jon Skeet Points 692016

Eh bien, il est certainement une meilleure mise en œuvre d'enum solution (qui est généralement très agréable):

public enum Error {
  DATABASE(0, "A database error has occured."),
  DUPLICATE_USER(1, "This user already exists.");

  private final int code;
  private final String description;

  private Error(int code, String description) {
    this.code = code;
    this.description = description;
  }

  public String getDescription() {
     return description;
  }

  public int getCode() {
     return code;
  }

  @Override
  public String toString() {
    return code + ": " + description;
  }
}

Vous souhaiterez peut-être modifier toString() pour juste retour de la description au lieu - pas sûr. De toute façon, le point principal est que vous n'avez pas besoin de remplacer séparément pour chaque code d'erreur. Notez également que j'ai spécifié explicitement le code au lieu d'utiliser la valeur ordinale - de ce fait, il est plus facile de modifier l'ordre et à ajouter/supprimer des erreurs par la suite.

N'oubliez pas que ce n'est pas internationalisé à tous - mais à moins que votre service web client vous envoie un jeu de paramètres régionaux description, vous ne pouvez pas facilement à s'internationaliser vous-même de toute façon. Au moins ils ont le code d'erreur à utiliser pour l'i18n du côté client...

35voto

romaintaz Points 32120

Pour autant que je suis concerné, je préfère externaliser les messages d'erreur dans un des fichiers de propriétés. Ce sera vraiment utile dans le cas de l'internationalisation de votre application (un fichier de propriétés par langue). Il est également plus facile de modifier un message d'erreur, et il n'aura pas besoin de re-compilation des sources Java.

Sur mes projets, généralement j'ai une interface qui contient les codes d'erreurs (Chaîne ou un entier, il ne se soucie pas beaucoup), qui contient la clé dans les fichiers de propriétés pour cette erreur:

public interface ErrorCodes {
    String DATABASE_ERROR = "DATABASE_ERROR";
    String DUPLICATE_USER = "DUPLICATE_USER";
    ...
}

dans le fichier de propriétés:

DATABASE_ERROR=An error occurred in the database.
DUPLICATE_USER=The user already exists.
...

Un autre problème avec votre solution est la mise à jour: Vous n'avez que 2 erreurs, et déjà 12 lignes de code. Alors, imaginez votre Énumération de fichier lorsque vous avez des centaines d'erreurs à gérer!

22voto

Cowan Points 17235

Une surcharge de ToString semble un peu dégueu--qui semble un peu exagéré d’une utilisation normale de toString ().

Qu'en est-il de :

semble beaucoup plus propre to me... et moins verbeux.

19voto

Scott Stanchfield Points 15863

Lors de mon dernier emploi, je suis allé un peu plus loin dans l'enum version:

public enum Messages {
    @Error
    @Text("You can''t put a {0} in a {1}")
    XYZ00001_CONTAINMENT_NOT_ALLOWED,
    ...
}

@Erreur, @Info, @Avertissement sont conservés dans le fichier de classe et sont disponibles au moment de l'exécution. (Nous avons eu un couple de d'autres annotations pour aider à décrire la livraison d'un message)

@Texte est une compilation d'annotation.

J'ai écrit un processeur d'annotation pour ce qui ne le suivant:

  • Vérifiez qu'il n'existe pas de dupliquer les numéros de message (la partie avant le premier trait de soulignement)
  • La syntaxe de vérifier le texte du message
  • Générer un messages.fichier de propriétés qui contient le texte, identifié par la valeur d'enum.

J'ai écrit quelques routines utilitaires qui ont aidé les erreurs du journal, enveloppez-les comme des exceptions (si désiré) et ainsi de suite.

J'essaie de me laisser m'open-source... -- Scott

5voto

duffymo Points 188155

Je vous recommande de prendre un coup d'oeil à java.util.ResourceBundle. Faut-il se préoccuper de l'I18N, mais ça en vaut la peine, même si vous ne le faites pas. Externalisation des messages est une très bonne idée. J'ai trouvé qu'il était utile d'être en mesure de donner une feuille de calcul pour gens d'affaires qui leur a permis de mettre exactement dans la langue qu'ils voulaient voir. Nous avons écrit une tâche Ant pour générer le .les propriétés des fichiers au moment de la compilation. Il fait I18N trivial.

Si vous êtes également à l'aide de Printemps, tant mieux. Leur MessageSource classe est utile pour ces sortes de choses.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X