2 votes

Solution proposée pour la vérification des nuls dans une hiérarchie d'objets

Revenant sur le sujet d'un précédent message, j'aimerais avoir un retour sur une solution proposée.

Dans mon code (C# 3.0), je dois gérer des formulaires d'application qui me sont fournis par un service dans une structure objet à partir d'un gros document XML désérialisé. Le formulaire peut contenir de nombreux types de données différents. Je dois donc effectuer de nombreux contrôles de nullité pour vérifier la présence de données.

Par exemple, il pourrait y avoir une valeur pour :

ApplicationForm.EmployeeInfo.PersonalInfo.Name

Et pour vérifier une valeur non nulle, je dois vérifier chaque étape de la descente.

Je veux éviter les longues instructions if et les blocs try-catch. Ma solution est donc la méthode d'extension.

public static T NN<T>(this T obj) where T : class, new()
{
    return obj ?? new T();
}

qui peut être utilisé comme

if (ApplicationForm.NN().EmployeeInfo.NN().PersonalInfo.NN().Name != null)

De cette façon, si l'étape suivante de la hiérarchie n'est pas initialisée, elle est temporairement réinitialisée et retournée. La méthode NN (Not Null) renvoie l'objet par défaut au lieu de null, ce qui dans mon cas convient parfaitement. Et lorsque je travaille avec des structures d'objets générées par xsd-tool où je dois vérifier la propriété "~Specified" de tous les éléments optionnels, cette méthode est très utile.

Je me demande maintenant si je ne manque pas quelque chose qui fait de cette solution, par ailleurs bonne, un mauvais choix. La création d'un si grand nombre d'objets vides par défaut est-elle trop lourde pour la mémoire ou les performances ou y a-t-il d'autres problèmes ?

Un test rapide, mais bien sûr non concluant, que j'ai effectué n'a révélé aucune baisse significative des performances.

4voto

Kobi Points 65357

Demandez à un programmeur ce qu'il fait, votre réponse habituelle est "hmm, de la programmation ?".
Faux.
J'ai eu un professeur de sciences naturelles comme patron pendant un moment. Il affirmait que les programmeurs écrivaient du code moins de 10% de leur temps. La plupart du temps, ils passent lecture y Débogage code. Il a donc insisté sur le fait que nous devions éviter les "chaînes" de propriétés ou d'appels de fonctions qui se tordent. Ceci est très pertinent dans votre cas - le NN Le piratage peut sembler agréable et vous faire gagner quelques minutes aujourd'hui, mais il vous en coûtera plus que quelques minutes à l'avenir.

2voto

Paolo Tedesco Points 22442

Je suis d'accord pour dire que c'est plus long :

if (ApplicationForm != null && 
    ApplicationForm.EemployeeInfo != null && 
    ApplicationForm.EemployeeInfo.PersonalInfo != null &&
    ApplicationForm.EemployeeInfo.PersonalInfo.Name != null) {
    // ...
} 

mais aussi plus lisible ; si je devais maintenir votre application, je vous serais reconnaissant de faire les vérifications d'une manière standard.
Je privilégierais la lisibilité, même au prix d'un code plus long et même si votre solution n'a pas d'incidence sur les performances.

0voto

Thomas Levesque Points 141081

Il y a quelques jours, j'ai écrit un article de blog sur une façon d'automatiser les contrôles de nullité à l'aide d'expressions Linq :

http://www.thomaslevesque.com/2010/02/21/automating-null-checks-with-linq-expressions/

J'ai trouvé une solution qui vous permet d'écrire quelque chose comme ça :

string name = ApplicationForm.NullSafeEval(a => a.EmployeeInfo.PersonalInfo.Name);

L'arbre d'expression est analysé et réécrit pour ajouter des contrôles de nullité à chaque niveau du chemin de propriété.

Cependant, bien que cette solution fonctionne, je ne recommanderais pas de l'utiliser si les performances sont critiques...

0voto

Dax Fohl Points 3616

Utilisez la monade Null. Il peut se trouver dans le même fichier ou dans un fichier différent, à condition que vous using il.

public static class NullMonad {
    public static TResult SelectMany<TIn, TOut, TResult>(this TIn @in, Func<TIn, TOut> remainder, Func<TIn, TOut, TResult> resultSelector)
        where TIn : class
        where TOut : class
        where TResult : class {
        var @out = @in != null ? remainder(@in) : null;
        return @out != null ? resultSelector(@in, @out) : null;
    }
}

Vous pouvez alors utiliser LINQ :

var salary = from form in applicationForm
             from info in form.employeeInfo
             from cond in info.workingConditions
             select cond.salary

Cela renverra le salaire s'il existe, ou null si l'une des déclarations précédentes aboutit à null, sans lever une exception. Cela réduit la répétition de la vérification manuelle de chaque variable. Elle évite également les frais généraux liés à la création de tous les objets "NN" inutilisés.

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