2012-11-16 7 views
2

J'ai pensé en général au sujet de la gestion des exceptions.Exceptions - Les meilleures pratiques

Quelle serait la meilleure pratique pour la mise en œuvre d'une méthode qui obtient un objet User en fonction du paramètre de nom d'utilisateur fourni. Voir ci-dessous.

/// <summary> 
    /// Gets a user. 
    /// </summary> 
    /// <param name="username">Username</param> 
    /// <returns>User instance</returns> 
    public Model.User GetUser(string username) 
    { 
     return Context.Users.SingleOrDefault(u => u.Username.ToLower() == username.ToLower()); 
    } 

si aucun utilisateur existe avec ce paramètre username, serait-il préférable de retourner un objet nul User ou plutôt lancer une exception personnalisée précisant que l'utilisateur n'existe pas.

+0

Qu'attendez-vous d'appeler la méthode? Est-ce important si un utilisateur est retourné ou est-ce obligatoire? –

+0

Voir http://stackoverflow.com/questions/tagged/exception-handling?sort=votes –

+0

Des exceptions à mon humble avis existent pour des cas exceptionnels, si un utilisateur n'existe pas, vous devez le gérer en retournant null. Par contre, si vous avez un problème de connexion db, vous devez gérer l'exception, la relancer, etc ... –

Répondre

2

Throw une exception . Dans le cas contraire, votre interlocuteur et d'autre de l'appelant de votre correspondant, et tout le monde devra vérifier null, ou devront gérer une collection vide.

S'il s'agit d'une méthode à usage général, destinée à être utilisée dans un contexte où l'appelant sait il doit vérifier null, alors je le ferais un peu différemment. J'aurais une méthode private qui renvoie null si aucun utilisateur ne correspond. Je voudrais ajouter un appelant qui utilise le modèle « essayer »:

public bool TryGetUser(string username, out Model.User user) 

et aussi celui qui retourne simplement à l'utilisateur, mais lève une exception si elle est introuvable

public Model.User GetUser(string username) 
+0

Ce poste répond le mieux à mes préoccupations, et en plus, j'ai lu quelque part que si un module ne peut pas faire ce qu'il dit, il peut dans ce cas retourner un objet 'User' puis lancer une exception. – kooldave98

+0

Ils n'auront pas à vérifier null si vous implémentez le modèle d'objet nul. – weston

+0

Je ne suis pas d'accord avec cette réponse. Les exceptions sont pour des situations exceptionnelles. Ne pas trouver une entrée correspondante n'est * pas * une situation exceptionnelle. Renvoyer 'null' fait à la fois un sens logique parfait et une programmation parfaite - vous n'avez rien trouvé, donc ne retournez rien.En fait, le code comme la réponse ci-dessus suggère des résultats dans les développeurs utilisant try/catch dans le cadre du flux de contrôle de leur code, ce qui est une pratique terrible. – MgSam

2

Mon conseil serait si le programme ne peut pas continuer sans utilisateur, puis lancer une exception. Si c'est ok que vous ne pouvez pas trouver un utilisateur ou que ce serait une erreur de connexion alors je retournerais null. Je ne lancerais une exception que si le programme ne pouvait pas continuer sans obtenir l'utilisateur et qu'il ne pouvait pas dire redirect pour se reconnecter.

Rappelez-vous lancer une exception est plus d'une opération coûteuse que le retour nul trop (je veux dire rien remarquer et ne pense comme ça (micro-optimisation) mais des exceptions devrait être utilisé pour la logique métier normal)

+1

oublier d'être cher, assurez-vous que le programme fait ce qu'il faut faire correctement., – DarthVader

+0

droit la chose est cette méthode est destinée à être utilisée dans divers scénarios, 'login' et d'obtenir' User' de simplement connaître le nom d'utilisateur. Ou serait-il préférable d'avoir des méthodes séparées pour se connecter et obtenir un utilisateur? – kooldave98

+0

@DarthVader Oui d'accord, je voulais juste ajouter qu'il y a un coût pour les exceptions –

0

Je dirais que la méthode d'appel peut décider si le résultat de l'absence d'un utilisateur nécessite ou non le lancement d'une exception. Si un nom d'utilisateur est fourni, mais pas trouvé, retourner null a un sens pour moi et laisser le code appelant décider comment il doit procéder.

Étant donné la façon dont la méthode est générique, pourquoi voudriez-vous jeter une exception si un nom d'utilisateur fourni ne se trouve pas? C'est une chose si une erreur de base de données se produit, etc, mais si le SELECT ne donne pas de lignes, je pense que ce n'est pas exceptionnel.

1

D'abord, je veux simplement suggérer une amélioration de votre mode de comparaison de chaînes sans sensibilité à la casse.

/// <summary> 
/// Gets a user. 
/// </summary> 
/// <param name="username">Username</param> 
/// <returns>User instance</returns> 
public Model.User GetUser(string username) 
{ 
    return Context.Users.SingleOrDefault(u => 
     string.Compare(u.Username, username, true)); 
} 

String.Compare on MSDN

Maintenant, ma suggestion sur cette question

Plutôt que nulle de retour. Vous souhaiterez peut-être retourner un objet nul, en utilisant le null object pattern.

public class User 
{ 

    public static readonly User Null = new Null{Username = "Anonymous"}; 

    ... 

} 

Ensuite, votre méthode devient:

public Model.User GetUser(string username) 
{ 
    return Context.Users.SingleOrDefault(u => 
     string.Compare(u.Username, username, true)) ?? Model.User.Null; 
} 

Ceci est utile dans les situations où null est indésirable. Il supprime le besoin de vérifier null plus tard. Si cet objet utilisateur a des droits associés par exemple, vous pouvez simplement vous assurer que l'utilisateur "null" n'a aucun droit.

+0

Bien sûr, cela n'a aucun sens si l'objet 'User' est censé être quelque chose de réel dans le système. Maintenant, vous devez vous assurer, non seulement que l'utilisateur null n'a pas de droits, mais qu'ils ne peuvent pas être listés dans une liste d'utilisateurs, ou en fait, que l'utilisateur null agit réellement comme s'il n'existait pas. Tu ferais mieux avec une exception. –

+0

@JohnSaunders Dans ce cas, je suis d'accord. La méthode s'appelle 'GetUser'. il ne serait pas judicieux de retourner un utilisateur qui n'était pas l'utilisateur demandé. Mais si le nom que j'ai choisi était meilleur, cela ne vous dérangerait pas d'apparaître dans une liste d'utilisateurs. par exemple. "Anonymous" – weston

+0

Peut-être un "utilisateur" est un mauvais exemple pour le modèle d'objet nul, mais je ne peux pas penser à des cas où je préfère retourner une entité fausse que d'admettre que l'entité demandée n'existe pas. Les fausses entités n'existent généralement pas dans le domaine du problème, d'après mon expérience. –

0

Je ne suis pas d'accord avec les réponses précédemment affichées.

Les exceptions ne doivent être utilisées que dans circonstances exceptionnelles. Ne pas trouver une valeur correspondante n'est pas exceptionnel. IMO, retourner null est beaucoup plus élégant - il laisse la décision de lancer une exception à l'appelant, pas l'appelé, et cela a du sens; vous demandez la méthode pour un utilisateur et s'il n'y en a pas, il ne retourne rien. De plus, votre code et l'autre répondent à travers l'ensemble de la collection à chaque fois, ce qui sera inutilement lent. Vous devriez utiliser un dictionnaire pour les recherches rapides (à moins, bien sûr, de fréquentes modifications de la collection Users qui rendent la mise en cache impossible).

Exemple:

class MyClass 
{ 
    private Dictionary<String,User> _userLookup; 

    public MyClass() 
    { 
     _userLookup = Context.Users.ToDictionary(u => u.UserName.ToLower()); 
    } 

    private User getUserByName(String name) 
    { 
     var lowerName = name.ToLower(); 
     return _userLookup.ContainsKey(lowerName) ? _userLookup[lowerName] : null; 
    }  
}