2009-10-06 7 views
2

J'écris un plug-in pour un programme de modélisation géométrique, et j'ai une classe abstraite basée sur un objet Curve. La courbe n'est considérée valide que si elle est plane, fermée et ne s'intersecte pas. J'ai alors une chaîne d'autres méthodes qui font référence à cette courbe pour faire une surface, ou l'extruder dans un volume. Ces méthodes lèveront une exception si elles sont appelées lorsque BaseCurve n'est pas valide. À l'heure actuelle, mon programme se bloque simplement si l'utilisateur invalide l'une des courbes, et j'essaie de trouver la meilleure façon d'avoir mon programme gérer cette entrée invalide.Comment gérer les entrées utilisateur invalides dans ce cas?

Voici ce que ma classe ressemble à:

public abstract class AbsCurveBasedObject 
{ 
    public abstract Curve BaseCurve 
    { 
     get; 
    } 

    public bool BaseCurveIsValid 
    { 
     get 
     { 
      Curve c = this.BaseCurve; 
      ... 
      //checks that curve is valid 
      ... 
      return true/false; 
     } 
    } 

    public Surface GetSurface() 
    { 
     Curve c = this.BaseCurve(); 
     ... 
     //magic that converts c to a surface 
     //exception is thrown if c is invalid 
     ... 
     return surface; 
    } 

    public Surface GetVolume() 
    { 
     Surface s = this.GetSurface(); 
     ... 
     //magic that converts s into a volume 
     ... 
     return volume; 
    } 
} 

Je ne sais pas si GetSurface() doit revenir NULL si la courbe est invalide ou si je devrais jeter une exception.

Il n'est pas inattendu que la courbe de base soit invalide car je sais que l'utilisateur finira par créer une courbe invalide lors de l'utilisation de mon programme. Je crois comprendre que les exceptions ne devraient normalement être levées que lorsque le programme atteint un point où il se produit quelque chose d'inattendu et ne sait pas comment continuer. Dois-je simplement retourner NULL de GetSurface() si la courbe n'est pas valide et que toutes les méthodes basées sur GetSurface() retournent aussi null si GetSurface() le fait? Cela semble être plus difficile à déboguer. Je sais que je vais finir par oublier de vérifier si une valeur de retour quelque part est NULL et se retrouver avec quelques ArgumentNullException qui pistes tout le chemin du retour à AbsCurveBasedObject.GetSurface()

Alors serait-il préférable d'avoir si/else ou d'essayer/catch bloque tout le suivi de la place à gérer lorsque l'utilisateur invalide quelque peu la propriété de la courbe de base?

Répondre

1

Le C# officiel Design guidelines dit de lancer une exception et laisser la couche d'interface utilisateur gérer l'exception.

+0

Il y a une très bonne discussion à ce sujet dans l'excellent ouvrage Framework Design Guidelines 2nd Ed. Il passe en revue les avantages et les inconvénients du modèle Tester-Doer (voir la réponse d'Eric Lippert - les problèmes d'enfilement sont liés au filetage) et le modèle Try-Parse, ainsi que de nombreuses directives d'exception. Le retour de null n'est généralement pas recommandé. – TrueWill

2

Idéalement, vous ne voulez jamais jeter une exception si vous pouvez éventuellement l'éviter. Cependant, cela ne signifie pas nécessairement que le retour de null est la bonne chose à faire! C'est probablement la mauvaise chose à faire.

Regardez comme ça. Votre code ressemble probablement ceci:

Blah MakeMeABlah(Foo foo) 
{ 
    if (!IsValid(foo)) throw new InvalidArgumentException("foo"); 
    // [make a blah from a foo] 
} 

Vous pourriez faire l'appelant ressemble à ceci:

Foo foo = GetFooFromUser(); 
try 
{ 
    blah = MakeMeABlah(foo); 
} 
catch(...) 
{ 
    // Tell user that input foo was invalid 
} 

Ce n'est pas si bon. La solution à votre problème est de faire IsValid dans une méthode publique:

Foo foo = GetFooFromUser(); 
if (!IsValid(foo)) 
    // Tell user that input foo was invalid 
else 
    blah = MakeMeABlah(foo); 

Et hey, pas la gestion des exceptions, au prix d'avoir à appeler IsValid deux fois. Si la validation est bon marché, qui s'en soucie? Si la validation est coûteuse, vous pouvez refactoriser cela pour avoir une version interne de MakeMeABlah qui ne refait pas la vérification dans la version finale.

0

Pourquoi voudrait que la courbe soit construite si elle n'est pas valide. À l'aide du modèle de générateur, vous pouvez exposer la possibilité de créer uniquement des objets Courbe valides et autoriser l'interface utilisateur à gérer l'état non valide.Ceci est (je pense) l'essence de la suggestion d'Eric, exposer une manière externe de valider l'état avant de construire un objet invalide.

Remarque: Une fois que vous avez créé uniquement des objets Courbe valides, vous pouvez supprimer le redouté if-creating boolean "bool BaseCurveIsValid". :)

Questions connexes