[python] Tipy na n�vrh t��dy

Filip Štědronský regnarg na seznam.cz
Pátek Srpen 1 18:57:15 CEST 2008


On Čt, čec 31, 2008 at 11:55:59 +0200, Tomas Fulajtar wrote:
> V teto souvislosti se nabizi pouzit modifikaci navrhoveho vzoru Command viz napr: http://en.wikipedia.org/wiki/Command_pattern, pripadne ho zkombinovat se vzorem Strategy. Doporucuji prostudovat, je zde spousta napadu, jak navrhovat. 
> 
> Pokud vim ,tak ceska prace na tohle tema vytvorena Iljou Kravalem je nabizena zdarma na http://www.objects.cz/produkty/produkty.html viz "Design Patterns v OOP". Mne se velice libila, i kdyz je psana pomerne narocnym stylem. Presto obsahuje dobre priklady a analogie.  

Zdravím...
...a zcela nesouhlasím. Návrhové vzory jsem nikdy neměl 
rád protože jsem zastáncem toho, že je vždy třeba 
posoudit konrétní situaci a najít chytré řešení, ne 
napasovat nějakou "oficiální" metodu jen pro vytvoření 
dojmu něčeho lepšího. Navíc, s OOP se to nikdy nesmí
přehánět, a co-příkaz-to-třída může spíš uškodit než na 
opak.

Měli bychom se ptát: co je příkaz ? Je to reakce na 
událost, reakce jako kód, posloupnost odpovědí vyvolaných
určitou podmínkou. Kód, tedy funkce. Necpějeme OOP, kam
nepatří, jen protože je to OO. Odhoďme předsudky, odhoďme
iluze. Ne vždy je dokonalé zapozdření či úplná 
objektovost ideálním východiskem. Proto se také Python 
nevydal cestou Javy. Protože tam je vynucené používání
tříd na příliš mnoho věcí, kde je to jinak absurdní. 

Je třeba přemýšlet. Každý problém si vyžaduje řešení. 
Důmyslné, originální a chytré řešení, které zároveň je
pohodlné pro okolí. V tomto případě navrhuji rozšířit
původní, dle mého názoru dobrý, nápad, jen bez 
"zneužívání" dokumentačních řetězců, které se můžou třeba
později zneužít pro nápovědu k příkazům.

Dekorátor. Opět to samozřejmě vyžaduje prohledání 
namespace, ale od čeho máme metatřídy ? Je nesmysl to 
dělat při každé inicializaci instance. Při vytváření 
třídy se stejně ns prochází a mění, takže na efektivitě
netratíme. Ba naopak.

import inspect

class CmdMeta(type):
    def __init__(self, *a):
        type.__init__(*a)
        self.commands={}
        for k,v in inspect.getmembers(self):
            if hasattr(v, '__command__'):
                self.commands[v.__command__]=v

class command(object):
    def __init__(self, cmd):
        self.cmd=cmd
    def __call__(self, fx): #when decorating
        fx.__command__=self.cmd
        return fx

class Commands(object):
    __metaclass__=CmdMeta

    ### vlastní definice příkazů ###
    @command("echo")
    def echo(self, rest):
        self.connection.send(rest)
    ################################

    def execute_command(self, line):
        cmd,rest=line.split(None, 1)
        self.__class__.commands[cmd](self, rest) #unbound

Ukázka je velmi jednoduchá ve stylu "příkazového řádku",
tedy že bere jen formát "příkaz parametr", ale to již lze
jakkoliv upravit. A troufám si toto řešení označit za
elegantní...


-- 
regnarg --- http://rg.pretel.cz -- JID: regnarg na jabber.cz
V péči o štěstí druhých nacházíme své vlastní.   --Platón
Přátelství může trvat jedině mezi dobrými lidmi. --Cicero



Další informace o konferenci Python