Comments on: Le pattern strategy version gastronomique http://sametmax.com/le-pattern-strategy-version-gastronomique/ Du code, du cul Mon, 28 Oct 2019 11:54:55 +0000 hourly 1 https://wordpress.org/?v=4.9.7 By: Sam http://sametmax.com/le-pattern-strategy-version-gastronomique/#comment-188322 Wed, 19 Jul 2017 19:20:19 +0000 http://sametmax.com/?p=23520#comment-188322 @Stéphane : oui

@Lenma : c’est en effet assez courant d’utiliser des classes abstraites avec strategy

@Brice: la strategy peut être un objet complet avec plusieurs methodes.

]]>
By: Brice http://sametmax.com/le-pattern-strategy-version-gastronomique/#comment-188307 Wed, 19 Jul 2017 10:10:29 +0000 http://sametmax.com/?p=23520#comment-188307 Je viens de tomber sur https://github.com/faif/python-patterns/blob/master/behavioral/strategy.py qui met en place ce pattern d’une manière intéressante, en utilisant types.MethodType pour injecter la nouvelle méthode directement dans l’objet (ou la remplacer si elle existait).

Quelqu’un voit des avantages ou inconvénients de cette manière de mettre en place cette stratégie? Ça me semble assez élégant en tout cas…

]]>
By: Lenma http://sametmax.com/le-pattern-strategy-version-gastronomique/#comment-188291 Tue, 18 Jul 2017 13:26:42 +0000 http://sametmax.com/?p=23520#comment-188291 Merci pour ce bonne article ;-)

Petit question pour pousser ce design pattern un peu plus loin : je sais que les exemples doivent êtres courts pour aller à l’essentiel mais dans ce genre de stratégie ne serait il pas approprié de créer une classe abstraite pour MaStrategie avec toutes les méthodes requise par la classe MonObjet et tester que MaStrategie ou MonAutreStrategie (ou n’importe quoi d’autre) hérite bien de cette classe abstraite.

Cela permettrai de fournir une API plus sûr pour quiconque voudrait écrire sa propre classe stratégie.

J’ai écris un exemple pour illustrer mon propos mais je suis dans l’embarra car je ne trouve pas la balise approprier pour afficher le code python proprement dans les commentaires, du coup c’est pas terriblement fonctionnel vu que des indentations disparaissent…

from abc import ABCMeta, abstractmethod


# Classe abstraite qui ne peut être instanciée
class MaStrategieAbstraite(object):

    # Metaclass associé au décorateur abstractmethod
    __metaclass__ = ABCMeta

    def __init__(self, parent):
        super(MaStrategieAbstraite, self).__init__()
        # ...

    # Décorateur qui oblige a réécrire la méthode dans les classes filles.
    # Il ne faut pas oublier de définir la méta-classe ABCMeta pour que ça
    # fonctionne.
    @abstractmethod
    def foo(self, arg1, arg2):
        """ Cette méthode prend deux entiers et revois la somme des deux. """
        pass


class MaStrategie(MaStrategieAbstraite):

    # Si cette méthode n'est pas défini il sera impossible de créer des
    # instances de cette classe.
    def foo(self, arg1, arg2):
        return arg1 + arg2


class MonObjet:
    # On appelle souvent cet attribut "strategy_class" ou "strategy_factory"
    strategie_par_default = MaStrategie

    def __init__(self, strategie=None):
        strategie = strategie if strategie else self.strategie_par_default

        # On test le lien de parenté pour être sûr qu'il n'y aura pas de
        # problème de méthodes manquantes par la suite
        if not issubclass(strategie, MaStrategieAbstraite):
            raise TypeError("C'est pour ton bien mon enfant !")

        self.strategie = strategie(self)

    def addition(self, a, b):
        return self.strategie.foo(a, b)


# On pourrais aussi hériter de `MaStrategie` si il y a plusieurs
# methodes abstraites et qu'on veut n'en redéfinir qu'une seule.
class MonAutreStrategie(MaStrategieAbstraite):

    def foo(self, arg1, arg2):
        print('%i + %i = %i' % (arg1, arg2, arg1+arg2))
        return arg1 + arg2


class MonSousObjet(MonObjet):
    # Et boom, overriding de la stratégie par la classe enfant en une ligne.
    # Django fait ça par exemple avec les classes based views et l'attribut
    # model

    strategie_par_default = MonAutreStrategie


# Exemples en action
# ------------------

mon_objet = MonObjet()
mon_objet.addition(1, 2)  # Revois 3

mon_sous_objet = MonSousObjet()
mon_sous_objet.addition(1, 2)  # affiche '1 + 2 = 3' et revois 3


class MauvaiseExampleDeStrategie(MaStrategieAbstraite):
    pass


class AutreMauvaiseExampleDeStrategie(object):
    pass

# Lève une exception (TypeError) puique la méthode foo n'a pas été redéfinie
mon_objet2 = MonObjet(strategie=MauvaiseExampleDeStrategie)

# Lève une exception (TypeError) puique la strategie n'hérite pas de `MaStrategieAbstraite`
mon_objet3 = MonObjet(strategie=MauvaiseExampleDeStrategie)

]]>
By: Stéphane http://sametmax.com/le-pattern-strategy-version-gastronomique/#comment-188288 Mon, 17 Jul 2017 20:17:52 +0000 http://sametmax.com/?p=23520#comment-188288 strategie_par_default étant une constante, il faudrait que ce soit plutôt en majuscule (STRATEGIE_PAR_DEFAULT), non?

]]>
By: Sam http://sametmax.com/le-pattern-strategy-version-gastronomique/#comment-188244 Sat, 15 Jul 2017 05:00:45 +0000 http://sametmax.com/?p=23520#comment-188244 @Cym13 : comme le dit LandReagan, dans l’exemple 4 et 5, c’est pour permettre aux classes filles d’overrider l’attribut de classe et donc la valeur par défaut. Dans l’exemple 3, c’était juste pour être consistant avec le reste et faciliter la compréhension mais je vois que ça n’aide pas donc je vais changer.

]]>
By: LandReagan http://sametmax.com/le-pattern-strategy-version-gastronomique/#comment-188241 Fri, 14 Jul 2017 22:36:15 +0000 http://sametmax.com/?p=23520#comment-188241 Pour que la stratégie par défaut soit un attribut de la classe mère, non ? Comme ça, au choix, tu la gardes telle que dans la classe fille ou tu l’overrides par un attribut de classe de la fille. Tu appelles super().init() sans rien changer. Et ça marche dans toute la descendance.

Ou je dis une connerie ?

]]>
By: abcd http://sametmax.com/le-pattern-strategy-version-gastronomique/#comment-188239 Fri, 14 Jul 2017 21:21:27 +0000 http://sametmax.com/?p=23520#comment-188239 Intéressant !

Par contre, dans l’avant dernier exemple, ce ne serait pas par hasard

        self.strategie = strategie(self) if strategie else self.strategie_par_default(self)
]]>
By: Cym13 http://sametmax.com/le-pattern-strategy-version-gastronomique/#comment-188238 Fri, 14 Jul 2017 21:10:19 +0000 http://sametmax.com/?p=23520#comment-188238 Pourquoi utiliser un ternaire plutôt que la valeur par défaut du paramètre dans le constructeur de l’objet pour exprimer une valeur par défaut ? On perd en auto-documentation et en concision.

]]>
By: azzra http://sametmax.com/le-pattern-strategy-version-gastronomique/#comment-188236 Fri, 14 Jul 2017 20:16:19 +0000 http://sametmax.com/?p=23520#comment-188236 Merci pour l’article! Quelques coquilles à mon avis:

POO un peu avancé -> avancée

et créer des stratégies à la volées -> volée

C’est rare que ça arrive, est c’est vraiment -> et

]]>