IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

eviter les pointeurs NULL


Sujet :

C++

  1. #21
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Salut,

    Des fois c'est pratique mais souvent, quand on n'a que des classes avec 3 données membres et 5 méthodes, faut pas exagérer quand même, 'oublier' de tester un pointeur a peu de chance d'arriver...
    Compliquer le code (un visiteur sur un Boost.Variant ça complique un poil) pour une garantie de cet ordre bien souvent je ne considère pas vraiment que ça vaut le coup.

    Citation Envoyé par Emmanuel Deloget Voir le message
    Je sais que c'est un peu hors sujet, mais je n'ai pas encore trouvé d'explication suffisament convaincante de cette affaire liée aux pointeurs NULL (comme quoi, avoir à en gérer serait un code smell...). Est-ce que quelqu'un maitrise bien le sujet ?
    Peut-être parce qu'on peut sans doute toujours remanier pour soit séparer en deux classes (une avec une référence et l'autre sans rien du tout), soit utiliser un Null Object, soit un Composite, etc.. ?

    MAT.

  2. #22
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par Mat007 Voir le message
    Peut-être parce qu'on peut sans doute toujours remanier pour soit séparer en deux classes (une avec une référence et l'autre sans rien du tout), soit utiliser un Null Object, soit un Composite, etc.. ?

    MAT.
    Je ne vois pas de problème pour imaginer des solutions (y compris l'utilisation du pattern Null Object) mais pour être franc, je ne vois pas ce que ça apporte à une implémentation.

    J'ai regardé depuis hier si je trouvais quelque chose sur le sujet caché au coeur de l'intraweb, et je n'ai trouvé que des discussions confuses. Je vais regarder dans les bouquins qu'on a u boulot si j'y vois quelque chose.

    En gros, la seule chose que j'ai retenu de ce que j'ai lu jusqu'à présent, c'est que l'utilisation d'un pointeur qui peut être NULL entraîne
    1) l'implémentation de cas particuliers.
    2) de fortes duplications de code.
    Le Refactoring de Fowler introduit une courte discussion à propos de ces deux problèmes, dans la partie consacrée au refactoring "introduce null object". Il cite Ron Jeffries:
    We first started using the null object pattern when Rich Garzaniti found that lots of code in the system would check objects for presence before sending a message to the object. We might ask an object for its person, then ask the result whether it was null. If the object was present, we would ask it for its rate. We were doing this in several places, and the resulting duplicate code was getting annoying.

    So we implemented a missing-person object that answered a zero rate
    (we call our null objects missing objects). Soon missing person knew a
    lot of methods, such as rate. Now we have more than 80 null-object
    classes.
    Personnellement, j'ai déjà travaillé sur des projets ou le nombre d'objets pouvant être null était énorme, et même si je conçois que le pattern null object aurait pu être un pattern relativement interessant dans ce cadre, je ne vois toujours pas en quoi le problème est sévère (peut être qu'il ne l'est pas en fait; Fowler et Beck (Refactoring...) ne cite pas de bad smell concernant ce point. Je ne pense pas que ça soit une ommission, car ils introduisent quand même ce refactoring particulier.
    Pour continuer avec la description de Jeffries:
    Our most common use of null objects is in the display of information. When we display, for example, a person, the object may or may not have any of perhaps 20 instance variables. If these were allowed to be null, the printing of a person would be very complex. Instead we plug in various null objects, all of which know how to display themselves in an orderly way. This got rid of huge amounts of procedural code.
    Soit. Je pense que d'autres approches étaient disponibles (comme par exemple encapsuler le code d'affichage de l'information dans plusieurs objets, capable de traiter des pointeurs NULL).

    J'ai vaguement regardé dans le Meyer, mais je n'ai pas trouvé grand chose sur le sujet. Il y a encore quelques livres ici que je dois regarder avant d'avoir une vision plus claire du problème, donc si entre temps vous avez des idées sur la question, n'hésitez pas !
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  3. #23
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    (...) je ne vois toujours pas en quoi le problème est sévère (...)
    Si en effet un accesseur renvoie un pointeur, qui donc peut être nul, ça veut dire que tous les utilisateurs vont devoir tester le pointeur avant de l'utiliser, d'où duplication de code et risque tout de suite beaucoup plus élevé d'oublier de tester (c'est exactement ce que décrit Jeffries).

    En fait je viens de réaliser (je n'utilise jamais d'accesseurs) que le problème ne se pose pas tellement lorsqu'un pointeur est encapsulé et reste un détail d'implémentation, mais plus à partir du moment où il est se promène à l'extérieur.
    Du coup le fait de devoir beaucoup tester des pointeurs révélerait des problèmes d'encapsulation, ou de sur-utilisation d'accesseurs ?

    MAT.

  4. #24
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Dans "Refactoring to Patterns" le problème est listé dans les différentes formes que peut prendre le code smell "Conditional Complexity" :
    Citation Envoyé par Refactoring to Patterns
    Dealing with null cases often leads to the creation of conditional logic. If the same null conditional logic is duplicated throughout your system, you can clean it up by using Introduce Null Object.
    Et globalement "Conditional Complexity" est introduit par :
    Citation Envoyé par Refactoring to Patterns
    Conditional logic is innocent in its infancy, when it is simple to understand and contained within a few lines of code. Unfortunately, it rarely ages well. For example, you implement several new features ans suddenly you conditional logic becomes complicated and expansive.
    Il y a un peu plus de contenu dans la description du remaniement "Introduce Null Object" mais globalement ça tourne toujours autour de la même chose...

    MAT.

  5. #25
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 754
    Par défaut
    Citation Envoyé par Mat007 Voir le message
    Si en effet un accesseur renvoie un pointeur, qui donc peut être nul, ça veut dire que tous les utilisateurs vont devoir tester le pointeur avant de l'utiliser, d'où duplication de code et risque tout de suite beaucoup plus élevé d'oublier de tester (c'est exactement ce que décrit Jeffries).
    Grosso modo si on a un objet qui implémente null object, on peut remplacer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    objet <- assignation
    si (objet != NULL)
       // faire qqc.
    par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    objet <- assignation
    // faire qqc.
    Une des implications est, qu'à chaque fois, il faudra tester le comportement du code dans le cas "null" et le cas "non null". (Bien sûr, on peut aussi "oublier" de faire le test dans le code et de tester l'oubli...)

    Implémenter un nul object dans ce cas, permet de réduire les "cas" possibles... et donc la complexité à un coût plus que raisonnable.

    En fait je viens de réaliser (je n'utilise jamais d'accesseurs) que le problème ne se pose pas tellement lorsqu'un pointeur est encapsulé et reste un détail d'implémentation, mais plus à partir du moment où il est se promène à l'extérieur.
    Du coup le fait de devoir beaucoup tester des pointeurs révélerait des problèmes d'encapsulation, ou de sur-utilisation d'accesseurs ?
    MAT.
    Je pencherais plutôt pour une question d'interface.
    La classe X définit l'accesseur A qui retourne
    • un objet ou nul
    • un objet (qui pourra être un null object).

    Le client ne pourra peut être pas utiliser le null object comme un object normal dans tous les cas (quoique) mais on essaie bien de limiter les variations dans le code client pour traiter les différents cas.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  6. #26
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Mais plus le fait de devoir appliquer un visiteur, devoir écrire une classe et la faire hériter de boost::static_visitor<>, et tout le tralala qui va avec quoi.
    Hériter de static_visitor ça sert juste à définir le typedef result_type.
    En fait, le problème c'est qu'il faut faire des fonctions. Avec un DSEL pour expression lambda, ça s'écrit plus concisement.

    Et les histoires de faux objet vide, ça c'est vraiment un hack.

  7. #27
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par HanLee Voir le message
    boost::optional<T>, j'aime pas trop, la valeur est ajoutée est pas énorme, dans le sens où le typage ne te force pas à vérifier si l'objet est nul ou non.

    Alors qu'à l'inverse boost::variant<T, null_type> ou le type Option de ML t'oblige à vérifier si l'objet est valide.

    si je comprend bien,boost::optional<T> c'est grosso modo comme tester un pointeur.
    boost::variant<T, null_type>, faut tester. ou est la différence??

    En tout cas, je pense comprendre mieux le problème que vous pose d'avoir un pointeur NULL, si j'ai bien compris, il faut mieux avoir un objet qui ne fait rien et correspond au null, que d'avoir ce pointeur où l'on peut oublier un teste. C'est bien cela?

  8. #28
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 754
    Par défaut
    En tout cas, je pense comprendre mieux le problème que vous pose d'avoir un pointeur NULL, on si j'ai bien compris, il faut mieux avoir un objet qui ne fait rien et correspond au null, que d'avoir ce pointeur où l'on peut oublier un teste. C'est bien cela?
    Oui! Plus de tests if ( x!=0 ) dans le code et plus besoin de tester que le code n'a pas oublié de faire le test.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  9. #29
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Citation Envoyé par Mongaulois Voir le message
    boost::variant<T, null_type>, faut tester. ou est la différence??
    Avec boost::variant, la différence c'est que tu ne peux pas oublier de tester, dans les conditions normales d'utilisation.

    Si t'oublies de traiter le cas null_type, le compilateur t'envoie chier tout simplement.

    ------

    Evidemment, ça ne marche que si tu ne contournes pas le typage, avec les pointeurs par exemple.

    Supposons que ça te fasse chier de faire un visiteur, parce que tu sais que l'objet n'est pas nul. Tu vas te faire une fonction get() qui te retourne une référence vers l'objet variant.

    Tu dois faire 2 fonctions membres, un qui prend en paramètre le type null_type, et l'autre de type T.
    Pourquoi ? Sinon ça compile pas.

    Pour traiter le type T, c'est évident, tu retournes le paramètre d'entrée.
    Et quand tu traites le type null ?
    Bah t'as pas d'autre choix que lancer une exception, si tu veux pas contourner le typage.

    Et au final, on a rien gagné, autant écrire la fonction intéressante dans le visiteur, non ?

  10. #30
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Si dans le cas nul tu lances une exception ou que tu génères une erreur, c'est que ton état nul n'a pas de raison d'être...

  11. #31
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Citation Envoyé par loufoque Voir le message
    Si dans le cas nul tu lances une exception ou que tu génères une erreur, c'est que ton l'état nul n'a pas de raison d'être...
    Et c'est ce qui rend la situation encore plus absurde avec ce get().

Discussions similaires

  1. Mesure qui n'est pas lié à toutes les dimension => eviter les NULL
    Par khadhraoui1 dans le forum Décisions SGBD
    Réponses: 1
    Dernier message: 14/08/2014, 12h04
  2. Tester les Pointeurs Null
    Par hibou107 dans le forum Débuter
    Réponses: 13
    Dernier message: 27/05/2011, 14h11
  3. Réponses: 11
    Dernier message: 03/11/2007, 18h33
  4. Réponses: 4
    Dernier message: 13/08/2004, 18h39
  5. Pb de débutant sur les pointeurs!!!
    Par benji17c dans le forum C
    Réponses: 6
    Dernier message: 30/09/2003, 17h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo