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

Langage C++ Discussion :

Conception policy class


Sujet :

Langage C++

Vue hybride

Message pr�c�dent Message pr�c�dent   Message suivant Message suivant
  1. #1
    Membre Expert Avatar de Trademark
    Profil pro
    Inscrit en
    F�vrier 2009
    Messages
    762
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2009
    Messages : 762
    Par d�faut Conception policy class
    Bonjour � tous,

    J'aimerais savoir si j'utilise correctement les policy class ou s'il y a un autre pattern qui correspondrait plus � mon cas.

    J'ai isol� plusieurs caract�ristiques d'un algorithme dans des policy class, ainsi l'algorithme se comporte diff�remment suivant les policy class pass�es en param�tre template.

    Le probl�me c'est que pour quelques policy class, son comportement est de soit, ne rien faire ou faire quelque chose. Je me demande alors si c'est toujours la bonne strat�gie de passer par ce pattern.

    Merci et bonne journ�e

  2. #2
    Membre confirm�
    Inscrit en
    D�cembre 2003
    Messages
    87
    D�tails du profil
    Informations forums :
    Inscription : D�cembre 2003
    Messages : 87
    Par d�faut
    Je ne pense pas qu'il soit n�cessaire dans ton cas d'utiliser le pattern policy, tu peux plut�t utiliser le pattern strategy pour configurer le comportement de ton algorithme. Le pattern policy est utile seulement dans le cas ou tu dois ajouter des m�thodes � ta classe en fonction de la policy (par l'interm�diaire de l'h�ritage).

    A part �a les deux patterns sont tr�s proches et c'est une bonne id�e de les utiliser pour param�trer un algorithme. Par contre je pense que si ton algo appel souvent des m�thodes qui ne font rien c'est surement que la repartition du travail entre algo et policy/strategy est mal pens�e. Peux tu revoir ton algo pour que les appels des m�thodes qui ne font rien se passent au niveau de la strategy/policy plut�t que dans l'algo principal?

  3. #3
    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
    En supposant qu'on soit d'accord sur les termes, c'est � dire qu'on parle bien du pattern strategy d�fini par le GoF dans "Design Patterns : elements of reusable software" et du pattern policy montr� dans le "Modern C++ Design" d'Andrei Alexandrescu.

    Citation Envoy� par piemur2000 Voir le message
    Je ne pense pas qu'il soit n�cessaire dans ton cas d'utiliser le pattern policy, tu peux plut�t utiliser le pattern strategy pour configurer le comportement de ton algorithme. Le pattern policy est utile seulement dans le cas ou tu dois ajouter des m�thodes � ta classe en fonction de la policy (par l'interm�diaire de l'h�ritage).
    L'int�r�t des classes de policy est justement de ne pas passer par l'h�ritage, mais de composer l'agorithme, qui sera alors d�fini compl�tement lors de la compilation et du lien, sans avoir besoin de traitement suppl�mentaires au runtime. Cf. le classique singleton d'Alexandrescu dans Modern C++ Design.

    Citation Envoy� par piemur2000 Voir le message
    A part �a les deux patterns sont tr�s proches et c'est une bonne id�e de les utiliser pour param�trer un algorithme.
    Tou a fait d'accord avec �a (modulo le fait que le pattern strategy a un impact sur l'architecture car il cr�e des liens entre les classes d'algorithmes, tandis que le pattern policy n'en cr�e pas, ce qui a aussi des avantages importants) mais...

    Citation Envoy� par piemur2000 Voir le message
    Par contre je pense que si ton algo appel souvent des m�thodes qui ne font rien c'est surement que la r�partition du travail entre algo et policy/strategy est mal pens�e.
    ... l�, je suis moins d'accord ; l'avantage du pattern policy par rapport au pattern strategy dans ce cas est que l'algorithme est optimis� par le compilateur, qui �limine le code mort ; le pattern strategy va au contraire forcer l'appel des m�thodes virtuelles permettant d'affiner le comportement de l'algorithme, ce qui va entra�ner une perte de temps (qui peut �tre n�gligeable dans certains cas, ou au contraire prohibitive).

    Je peux ainsi �crire :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    template <class _Ret, class _Arg1, class _Policy>
    class algo
    {
    private:
      void do_something_on_arg1(_Arg1& arg1)
      {  _Policy().exec(arg1); }
    public:
      _Ret operator()(_Arg1 arg1)
      {
        do_something_on_arg1(arg1);
        return blablablah(arg1);
      }
    };
     
    template <class _Ret, class _Arg1>
    struct nullop
    {
       void exec(_Arg1& arg1) { }
    }
    Un appel � algo<X,Y,nullop<X,Y> >.operator() va �tre optimis� par le compilateur sans que j'ai besoin de faire quoi que ce soit : l'appel de exec() sera supprim�. En passant par le pattern strategy, on va appeler une m�thode virtuelle, ce qui suppose deux op�rations suppl�mentaires :

    1) initialisation du pointeur de l'objet.
    2) appel de la m�thode.

    Il n'y a gu�re de moyen d'�chaper � ce surco�t.

    En dehors de cet �tat de fait, il reste tout � fait possible que le pattern policy ne soit pas le bon dans ce cas pr�cis. Si un algorithme est enti�rement d�fini par une policy particuli�re, ou si la policy en question stocke un �tat, il sera plus judicieux d'utiliser le pattern strategy.

    Citation Envoy� par piemur2000 Voir le message
    Peux tu revoir ton algo pour que les appels des m�thodes qui ne font rien se passent au niveau de la strategy/policy plut�t que dans l'algo principal?
    En cas d'application du pattern strategy, c'est une chose � faire. Dans le cas du pattern policy, �a se dispute.
    [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.

  4. #4
    Membre confirm�
    Inscrit en
    D�cembre 2003
    Messages
    87
    D�tails du profil
    Informations forums :
    Inscription : D�cembre 2003
    Messages : 87
    Par d�faut
    Citation Envoy� par Emmanuel Deloget Voir le message
    L'int�r�t des classes de policy est justement de ne pas passer par l'h�ritage...
    Je ne suis pas tout � fait d'accord. J'ai en effet trop simplifi� en limitant l�int�r�t du pattern Policy � l'utilisation de l'h�ritage. Je pense cependant que l'utilisation de Policy dans la forme suivante peut �tre int�ressant:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    template <class _Ret, class _Arg1, class _Policy>
    class algo : public _Policy
    {
    private:
      void do_something_on_arg1(_Arg1& arg1)
      {  _Policy::exec(arg1); }
    public:
      _Ret operator()(_Arg1 arg1)
      {
        do_something_on_arg1(arg1);
        return blablablah(arg1);
      }
    };
    Cela permet dans des cas particuliers d'appeler des m�thodes sp�cifiques � la Policy sur la classe Algo.

    Citation Envoy� par Emmanuel Deloget Voir le message
    l'agorithme, qui sera alors d�fini compl�tement lors de la compilation et du lien, sans avoir besoin de traitement suppl�mentaires au runtime...
    Encore une fois je suis d'accord sur ce point et tout ceux qui suivent . L'un des avantage du pattern policy sur le pattern strategy est l'optimisation apport� par le fait qu'on ne passe pas par des m�thodes virtuelles. Ceci ne rel�ve cependant pas du design mais seulement de l'optimisation (ce qui ne veut pas dire que �a doit �tre n�glig�).

    Citation Envoy� par Emmanuel Deloget Voir le message
    En cas d'application du pattern strategy, c'est une chose � faire. Dans le cas du pattern policy, �a se dispute.
    Loin de moi l'id�e de me disputer la dessus . Je pense tout de m�me que l'utilisation de beaucoup de fonction vide peut r�v�ler une mauvaise r�partition de l'algorithme entre les policies/strategies et l'algo de base. Les m�thodes en fonction peuvent peut-�tre �tre appel�es depuis les policies/strategies. Mais bien sur c'est juste une supposition et �a d�pends grandement du contexte.

    Un autre avantage des strat�gies qui doit �tre soulign� est le fait de pouvoir changer de strat�gie en "live". Cela peut-�tre tr�s utile si une partie de l'algo est d�termin�e par des choix de l'utilisateur.

  5. #5
    R�dacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par d�faut
    Bonjour,

    Citation Envoy� par piemur2000 Voir le message
    Ceci ne rel�ve cependant pas du design mais seulement de l'optimisation (ce qui ne veut pas dire que �a doit �tre n�glig�).
    Je ne partage pas cet avis. Le pattern strat�gie impose de par l'utilisation de l'h�ritage un couplage plus fort entre le client, la strat�gie abstraite et la strat�gie concr�te.

    Avec les politiques, le client n'impose qu'une signature � la politique. Et c'est tout. Pas d'impact sur la structure des types. Le couplage est tr�s relach� (moins fort, au moins �quivalent, ce serait l'OAP peut �tre).

    Donc, c'est aussi (surtout) un choix de design.

    Citation Envoy� par piemur2000 Voir le message
    Je pense tout de m�me que l'utilisation de beaucoup de fonction vide peut r�v�ler une mauvaise r�partition de l'algorithme entre les policies/strategies et l'algo de base.
    Avec les politiques, c'est un moyen pratique d'ins�rer beaucoup de point de variation � co�t nul. J'ai compris la remarque d'Emmanuel en ce sens.

    Citation Envoy� par piemur2000 Voir le message
    Un autre avantage des strat�gies qui doit �tre soulign� est le fait de pouvoir changer de strat�gie en "live". Cela peut-�tre tr�s utile si une partie de l'algo est d�termin�e par des choix de l'utilisateur.
    Je pense que la force de la strat�gie est bien ici : arbitrer l'algo � l'ex�cution.

  6. #6
    Membre Expert Avatar de Trademark
    Profil pro
    Inscrit en
    F�vrier 2009
    Messages
    762
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2009
    Messages : 762
    Par d�faut
    Ce d�bat est tr�s int�ressant, n�anmoins sans vouloir vous relancez dans votre lutte de diff�renciation entre le policy et strategy pattern, j'aimerais vous proposez un cas plus concret.

    La situation est simple, il s'agit de r�aliser un algorithme qui agit diff�remment si une taille est pr�cis�e ou non. Exemple :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    template <typename size, typename error_policy, typename seq_iter>
    int somme(seq_iter begin, seq_iter end)
    {
      int sum = 0, i ;
      for( i=0; begin != end && size::reach_the_end(i) ; ++i, ++begin)
        sum += *begin ;
     
      if( i == 0)
        error_policy::empty_sequence() ;
     
      if( ! size::is_correct(i) || begin != end)
        error_policy::error_on_length() ;
     
      return sum ;
    }
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
    template <size_t size_expected>
    struct with_expected_size
    {
      static bool reach_the_end ( unsigned int current_pos )
      {
         return size_expected != current_pos ;
      }
     
      static bool is_correct( unsigned int number_of_digits_hit )
      {
        return number_of_digits_hit == size_expected ;
      }
    };
     
    struct no_expected_size
    {
      static bool reach_the_end ( unsigned int current_pos )
      {
         return false ;
      }
     
      static bool is_correct( unsigned int number_of_digits_hit )
      {
        return true ;
      }
    };
    Premi�rement pour diff�rencier un nombre sans et avec taille attendue j'ai utilis� deux structures diff�rentes. Dans ce cas, est-ce l'id�al ? J'aurais �galement pu faire une sp�cialisation true/false mais ce n'est peut-�tre pas aussi propre. Qu'en pensez-vous ?

    Ensuite, trouvez-vous judicieux l'utilisation de "error_policy" ? Auriez-vous utilis� une autre technique ?

    Merci beaucoup de vos r�ponses.

  7. #7
    R�dacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par d�faut
    Citation Envoy� par Trademark Voir le message
    Qu'en pensez-vous ?
    En lisant le code, je comprends qu'il ne s'agit pas d'une fonction avec 2 stat�gies/politiques diff�rentes mais d'une fonction qui pourrait avoir deux contrats diff�rents :
    On peut alors l'�crire dans ce sens :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include <numeric>
     
    template <typename contract_type, typename seq_iter>
    int somme(seq_iter begin, seq_iter end, contract_type c = contract_type())
    {
        c.check_precondition(begin,end);
     
        return std::accumulate(begin,end,0);
    }
    Le deux contrats que je comprends sont :
    => un premier assez souple : std::distance(begin,end)>=0 et

    => un second plus contraint : std::distance(begin,end)==TAILLE_DONNEE.

    �crivons les en s�parant la gestion de la rupture du contrat de sa d�finition :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #include <iterator>
    template<class failure_policy_t_>
    struct simple_contract
    {
        template<class it_>
        void check_precondition(it_ begin, it_ end)
        {
            if(std::distance(begin,end)<0)
            {
                failure.precondition_failed();
            }
        }
     
        explicit simple_contract(failure_policy_t_ failure_)
            :failure(failure_)
        {}
     
        failure_policy_t_ failure;
    };
    template<class failure_policy_t_>
    simple_contract<failure_policy_t_> make_simple_contrat(failure_policy_t_ failure_)
    {
        return simple_contract<failure_policy_t_>(failure_);
    }
    et
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    template<typename failure_policy_t_>
    struct strict_contrat
    {
        template<class it_>
        void check_precondition(it_ begin, it_ end)
        {
            if(std::distance(begin,end)!=size_expected)
            {
                failure.precondition_failed();
            }
        }
        explicit strict_contrat(int size_expected_,failure_policy_t_ failure_ = failure_policy_t_())
            :size_expected(size_expected_)
            ,failure(failure_)
        {}
     
        const int size_expected;
        failure_policy_t_ failure;
    };
     
    template<typename failure_policy_t_>
    strict_contrat<failure_policy_t_> make_strict_contrat(const int size_expected_,failure_policy_t_ failure_)
    {
        return strict_contrat<failure_policy_t_>(size_expected_,failure_);
    }
    Ensuite tu peux te construire diff�rentes politiques pour g�rer cette rupture :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #include <iostream>
     
    struct trace_policy
    {
        void precondition_failed()
        {
            std::cout<<"TRACE : precondition failed\n";
        }
    };
     
    template<typename exception_t_>
    struct exception_policy
    {
        void precondition_failed()
        {
            throw exception_t_("precondition failed");
        }
    };
    reste plus qu'� assembler :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    #include <vector>
    #include <stdexcept>
     
    int main()
    {
        std::vector<int> v(10);
        somme(v.begin(),v.end(),make_simple_contrat(trace_policy()));
        somme(v.begin(),v.end(),make_strict_contrat(3,trace_policy()));
        try
        {
            somme(v.begin(),v.end(),make_strict_contrat(15,exception_policy<std::invalid_argument>()));
        }
        catch(std::exception const&e_)
        {
            std::cout<<"EXCEPTION : "<<e_.what()<<"\n";
        }
     
        try
        {
            somme(v.end(),v.begin(),make_simple_contrat(exception_policy<std::invalid_argument>()));
        }
        catch(std::exception const&e_)
        {
            std::cout<<"EXCEPTION : "<<e_.what()<<"\n";
        }
     
        return 0;
    }
    On peut enrichir pour rajouter la v�rification de post-condition
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <numeric>
     
    template <typename contract_type, typename seq_iter>
    int somme(seq_iter begin, seq_iter end, contract_type c = contract_type())
    {
        c.check_precondition(begin,end);
     
        int retour = std::accumulate(begin,end,0);
        c.check_postcondition(retour);
        return retour;
    }
    etc...

    J'allais oublier, tu voulais aussi ne rien v�rifier : contrat sans v�rification :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    struct no_check_contrat
    {
        template<class it_>
        void check_precondition(it_ , it_ )
        {
        }
     
    };
    et hop :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    somme(v.begin(),v.end(),no_check_contrat());

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. Conception de classes
    Par Seth77 dans le forum G�n�ral Dotnet
    R�ponses: 8
    Dernier message: 15/01/2007, 15h57
  2. [POO] conception des classes
    Par poukill dans le forum C++
    R�ponses: 229
    Dernier message: 19/07/2006, 08h28
  3. [conception] reprise classes mal pens�es
    Par in dans le forum G�n�ral Java
    R�ponses: 8
    Dernier message: 05/06/2006, 13h45
  4. Conception de classe
    Par Azharis dans le forum C++
    R�ponses: 9
    Dernier message: 17/12/2005, 10h15
  5. probleme de conception de classe
    Par NhyMbuS dans le forum C++
    R�ponses: 2
    Dernier message: 08/05/2005, 17h10

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