SlideShare uma empresa Scribd logo
1 de 88
Alex Martelli’s
            Design Patterns
              in Python
 Apresentada originalmente no Google Developer’s Day 2007
           Vídeo no YouTube: http://bit.ly/okP7hh

  Traduzida para a PythonBrasil 7 por Luciano Ramalho com
autorização de Alex Martelli gentilmente cedida em 23/08/2011
Alex Martelli and Anna Martelli Ravenscroft
             EuroPython, Firenze, June 2011
                   photo by Josette Garcia
O melhor livro sobre Python já escrito
      (mesmo sendo de 2006)
Saímos cantando os pneus...
• Forças: um sub-sistema
  rico e complexo oferece
  muita funcionalidade útil;
  componentes clientes
  interagem com várias
  partes dessa funcionali-
  dade, de um jeito que
  está “fora de controle”

• isto causa muitos problemas para programadores do
  código cliente e também do sub-sistema
  (complexidade + rigidez)
Solução: o padrão “Façade”
• interpor um objeto/classe
                                                  Django: classe do domínio
                                                  versus um monte de classes
                                                  de modelo, para facilitar a
                                                  api exposta às views
  de “fachada”, expondo um
  sub-conjunto controlado
  da funcionalidade
  • clientes acessam
    somente a fachada
  • a fachada implementa a
    funcionalidade simples
    invocando o sub-sistema complexo
• a implementação do sub-sistema ganha
  flexibilidade, os clientes ganham simplicidade
Façade é um padrão de projeto
• resumo de um problema comum de projeto +
    estrutura de uma solução (+ vantagens e desvantagens,
    alternativas, ...) e:
    •  um nome (mais fácil de lembrar/discutir)
•   “descrições de objetos e classes que se comunicam,
    customizados para resolver um problema geral de
    projeto em um contexto específico” (GOF)
•   não é: estrutura de dados, algoritmo, arquitetura
    específica de domínio, recurso de uma linguagem ou
    de uma biblioteca                              Façade é uma exceção



•   tem que ser estudado no contexto de uma linguagem!
•   tem que fornecer Usos Conhecidos (UC / KU) PP não são inventados, são
                                               descobertos por arqueólogos
Alguns UC de Façade
• ...na biblioteca padrão de Python...
 • dbhash é uma fachada para o bsddb
     • acesso muito simplificado a uma parte da API
     • também atende à interface dbm (portanto, é
       também um exemplo do PP Adapter)
• os.path: basename, dirname são fachada para
    split + acesso a item; isdir (etc.) fachada para
    os.stat + stat.S_ISDIR (etc.)
•   Façade é um PP estrutural (veremos outro, Adapter,
    depois; no exemplo do dbhash eles se fundem)
O que é um padrão de projeto
• resumo de um problema comum de projeto +
    estrutura de uma solução (+ vantagens e desvantagens,
    alternativas, ...) e:
    •  um nome (mais fácil de lembrar/discutir)
•   “descrições de objetos e classes que se comunicam
    customizadas para resolver um problema geral de
    projeto em um contexto específico” (GOF)
•   um PP não é: estrutura de dados, algoritmo,
    arquitetura específica de domínio, recurso de uma
    linguagem ou de uma biblioteca
•   tem que ser estudado no contexto de uma linguagem!
•   tem que fornecer Usos Conhecidos (UC / KU)
Nenhum livro bom
de PP em Python
Preferível
Categorias clássicas de PP
• Criacionais: formas e modos de instanciar
  objetos
• Estruturais: composição mútua de classes
  ou objetos (o Façade é um PP estrutural)
• Comportamental: como classes e
  objetos interagem e dividem
  responsabilidades entre si
• Cada um pode ser a nível de classe ou a
  nível de objeto
Princípios básicos de PP
• “programe para uma interface, não
  para uma implementação” (GOF)
 • isto é feito principalmente através
   de “tipagem pato” em Python –
   raramente com interfaces “formais”
 • semelhante a “polimorfismo
   baseado em assinatura” nas
   templates de C++
Princípios básicos de PP
• “prefira composição de objetos do que herança
  de classes” (GOF)
 • em Python, segurar ou embrulhar
 • herdar apenas quando é realmente
    conveniente
   • expor todos os métodos da super classe
      (reusar + normalmente sobrescrever +
      talvez estender)
   • mas é um acoplamento muito forte!
Python: segurar ou embrulhar?
 • “Segurar”: objeto O tem um sub-objeto
   S como um atributo (talvez uma
   propriedade) – só isso
  • usa-se self.S.method ou O.S.method
  • simples, direto, imediato,
    porém...
    acoplamento bem forte,
    frequentemente no eixo
    errado
Python: segurar ou embrulhar?
• “Embrulhar”: segurar (frequentemente com
  um nome privado) e delegar (de modo que se
  possa acessar diretamente O.metodo)
 • delegação explícita
   (def metodo(self...): self.S.metodo)
 • automática (via __getattr__)
 • acoplamento correto
   (Lei de Deméter)      Evitar expressões do tipo
                         a.b.c. porque isso limita a
                         a expor um b que tem um
Ex.: embrulhar para “restringir”
class EmbrulhoRestritor(object):
   def __init__(self, embrulhado, bloqueios):
         self._embrulhado = embrulhado
         self._bloqueios = bloqueios
   def __getattr__(self, nome):
         if nome in self._bloqueios:
            raise AttributeError, nome
         return getattr(self._embrulhado, nome)
   ...

     Herança não tem o poder de restringir!
Padrões criacionais
• não muito comuns em Python...
• ... porque basicamente Factory já vem pronto
“Factory já
vem pronto”
•   Em linguagens que tem o
    operador new, a chamada
    new Foo() implica que
    Foo é uma classe concreta
    específica. Isso aumenta o
    acoplamento.

•   Python é mais flexível,
    porque Foo() pode ser a
    invocação de uma classe
    ou de uma função factory.
    O cliente não precisa
    saber.
Padrões criacionais [1]
“Queremos que apenas uma instância possa existir”

   • use um módulo em vez de uma classe     Resolve 90% dos casos




    • não pode ter subclasses, métodos especiais...
   • crie somente uma instância (sem restrição)
    • necessário definir exatamente quando criar
   • singleton (“Highlander”)
    • criar sub-classes não é tão tranquilo
   • monoestado (“Borg”)
    • Guido não curte
Singleton (“Highlander”)
 class Singleton(object):
     def __new__(cls, *a, **k):
         if not hasattr(cls, '_inst'):
              cls._inst = super(Singleton,
                  cls).__new__(cls, *a, **k)
         return cls._inst

Subclasses são problemáticas, porém:
class Foo(Singleton): pass              problema
class Bar(Foo): pass                    intrínseco
f = Foo(); b = Bar(); # ...???...      do Singleton
Monoestado (“Borg”)
class Borg(object):
    _shared_state = {}
    def __new__(cls, *a, **k):
        obj = super(Borg, cls
            ).__new__(cls, *a, **k)
        obj.__dict__ = cls._shared_state
        return obj
Subclasses sem problemas, basta fazer:
class Foo(Borg): pass
class Bar(Foo): pass
class Baz(Foo):                 sobrecarga de
    _shared_state = {}          dados resolve!
Padrões criacionais [2]
• “não queremos ser forçados a instanciar uma
  classe concreta específica”
 •  injeção de dependência
     • nada se cria “dentro”, tudo vem “de fora”
     • e se múltiplas criações são necessárias?
 •  subcategoria “Factory” de PPs
     • pode criar qq. coisa ou reusar o q. já existe
     • funções factory (e outros invocáveis)
     • métodos factory (podem ser sobrescritos)
     • classes factory abstratas
Padrões Estruturais
       Subcategoria “Disfarçe/Adaptação:

• Adapter: ajustar uma interface (existem variantes
    de classe e de objetos)
•   Facade: simplificar a interface de um sub-sistema
•   ... e muitos outros que não vou abordar, como:
         •    Brige: muitas implementações de uma
              abstração, muitas implementações de uma
              funcionalidade, sem codificação repetitiva
         •    Decorator: reusar+ajustar sem herança
         •    Proxy: desacoplar acesso/localização
Adapter
• código-cliente γ exige um protocolo C
• cógido-fornecedor σ oferece um protocolo diferente
    S (com um superconjunto da funcionalide de C)
•   código-adaptador α “se infiltra entre eles”:
    • para γ, α é um fornecedor (produz o protocolo C)
    • para σ, α é um cliente (consome o protocolo S)
    • “dentro”, α implementa C (por meio de chamadas
      apropriadas a S em σ)
Exemplo simples de Adapter

  • C requer o método foobar(foo, bar)
  • S fornece o método barfoo(bar, foo)
  • por exemplo, σ poderia ser:
   class Barfooer(object):
       def barfoo(self, bar, foo):
           ...
Adapter de objeto
    • por instância, com delegação por embrulho:
class EmbrulhadorFoobar(object):
    def __init__(self, embrulhado):
        self.e = embrulhado
    def foobar(self, foo, bar):
        return self.e.barfoo(bar, foo)

foobarador = EmbrulhadorFoobar(barfooador)
Adapter de classe (direto)
    • por classe, com derivação e auto-delegação:

class Foobarador(Barfooador):
    def foobar(self, foo, bar):
        return self.barfoo(bar, foo)

foobarador = Foobarador(...qq. coisa...)
Adapter de classe (mixin)
    • flexível, bom uso de herança múltipla:
class BF2FB:
    def foobar(self, foo, bar):
        return self.barfoo(bar, foo)

class Foobarador(BF2FB, Barfooador):
    pass

foobarador = Foobarador(...qq. coisa...)
Adapter: Usos Conhecidos
• socket._fileobject: de sockets para objetos “file-
    like” (com muito código para gerenciar o buffer)
•   doctest.DocTestSuite: adapta testes doctest para
    unittest.TestSuite
•   dbhash: adapta bsddb para dbm
•   StringIO: adapta str ou unicode para “file-like”
•   shelve: adapta “dict limitado” (chaves e valores str,
    métodos básicos) para um dicionário completo
    •  via pickle para qualquer coisa <-> string
    •  + UserDict.DictMixin
Observações sobre Adapter
• alguns adapters reais podem demandar muito código
• classes mixin são uma ótima maneira de auxiliar na
    adaptação de protocolos ricos (implementam
    métodos avançados a partir de métodos
    fundamentais)
•   Adapter é encontrado em todos os níveis de
    complexidade
•   Em Python, _não_ se trata sempre de classes e suas
    instâncias (de modo algum!) -- muitas vezes
    _invocáveis_ são adaptados (via decorators e outras
    funções de ordem superior, closures, functools, ...)
Facade vs Adapter
• Adapter trata de fornecer um determinado
    protocolo exigido por código-cliente
    • ou, conquistar polimorfismo via
      homogeneidade
•   Facade trata de simplificar uma interface
    rica quando apenas um sub-conjunto é
    necessário
•   Facade frequentemente mascara um
    subsistema formado por muitas classes/
    objetos, Adapter mascara apenas um
    objeto ou classe
Padrões comportamentais
• Template Method: self-delegation (auto-delegação)
 • ... “a essência da POO”
 • algumas de suas variantes específicas em Python
Template Method
• padrão excelente, nome péssimo
 • “template” é um termo muito sobrecarregado
   • programação genérica em C++
   • geração de documento a partir de esqueleto
   • ...
• um nome melhor: self-delegation
 • auto-delegação
 • diretamente descritivo!
TM Clássico
• classe-base abstrata (ABC) oferece “método
    organizador” que invoca “métodos gancho”
•   na ABC, métodos-gancho são abstratos
•   sub-classes concretas implementam os ganchos
•   código-cliente invoca o método organizador
    • em alguma referência à ABC (injetor, ou...)
    • que obviamente refere-se a uma sub-classe
      concreta
Esqueleto de TM
class AbstractBase(object):
    def orgMethod(self):
        self.doThis()
        self.doThat()

class Concrete(AbstractBase):
    def doThis(self):
        ...
    def doThat(self):
        ...
UC: cmd.Cmd.cmdloop
def cmdloop(self):
    self.preloop() while True:
        s = self.doinput()
        s = self.precmd(s)
        finis = self.docmd(s)
        finis = self.postcmd(finis,s)
        if finis: break
    self.postloop()
                           Na implementação em Python, os
                           métodos-gancho são
                           implementados com pass na classe
                                         abstrata, porque Python é uma
                                         linguagem pragática e não
                                         ideológica.
Justificativa p/ TM Clássico
                                             Diferença entre um framework
                                             e uma bibiblioteca: uma
                                             biblioteca é um conjunto de
                                             funções que vc chama, a
                                             organização fica por sua conta.
                                             Um framework tem os métodos


 • o “método organizador” fornece “lógica
                                             de organização e que chamam os
                                             seus métodos.



     estrutural” (sequenciamento etc.)
 •   os “métodos gancho” realizam de fato as “ações
     elementares”
 •   é frequentemente apropriado para fatorar
     comportamento comuns e variações
 •   deixa claras as responsabilidades e colaborações
     entre objetos (classes): classe base invoca
     ganchos, sub-classes os implementam
 •   aplica o “Hollywood Principle”: “don't call us, we'll
     call you” - não ligue para nós, nós te ligamos
Uma escolha de ganchos
class TheBase(object):
    def doThis(self):
        # provide a default (often a no-op)
        pass
    def doThat(self):
        # or, force subclass to implement
        # (might also just be missing...)
        raise NotImplementedError

  • Implementações default são mais práticas,
    quando fazem sentido, mas “obrigatórias”
    servem como boa documentação
UC: Queue.Queue
class Queue:
    ...
    def put(self, item):
        self.not_full.acquire()
        try:
             while self._full():
                 self.not_full.wait()
             self._put(item)
             self.not_empty.notify()
        finally:
             self.not_full.release()
    def _put(self, item): ...
TM em Queue
• Não abstrata, frequentemente usada “no estado”,
    implementa todos os métodos ganchos
•   sub-classes podem customizar o comportamento
    • sem se preocupar com travas, timing...
    • comportamento default é FIFO, simples e útil
    • with no worry about locking, timing, ...
    • pode-se sobrescrever métodos gancho (__init__,
      qsize, _empty, _full, _put, _get) E...
    • ...dados (maxsize, queue), uma exclusividade
      Python!
Queue customizada
class LifoQueueA(Queue):
    def _put(self, item):
        self.queue.appendleft(item)

class LifoQueueB(Queue):
    def _init(self, maxsize):
        self.maxsize = maxsize
        self.queue = list()
    def _get(self):
        return self.queue.pop()
Fatorando os ganchos
• “método organizador” em uma classe
• “métodos gancho” em outra classe
• UC: HTML formatter vs writer
• UC: SAX parser vs handler
• adiciona um eixo de variabilidade/flexibilidade
• aproxima-se do PP Strategy:
 • Strategy: uma classe abstrata por ponto de
      decisão, e classes concretas indepententes
  •   TM fatorado: classes abstratas e concretas
      mais “agrupadas”
TM + introspection
• classe “organizadora” pode examinar classe
  “gancho” (talvez descendente) em tempo
  de execução
 • descobrir que métodos existem
 • despachar apropriadamente (incluindo
    “catch-all” e/ou outros tratamento de
    erros)
UC: cmd.Cmd.docmd

def docmd(self, cmd, a):
    ...
    try:
         fn = getattr(self, 'do_' + cmd)
    except AttributeError:
         return self.dodefault(cmd, a)
    return fn(a)
Alex Martelli's Python Design Patterns
Alex Martelli's Python Design Patterns

Mais conteúdo relacionado

Mais procurados

Conhecendo Ruby on Rails
Conhecendo Ruby on RailsConhecendo Ruby on Rails
Conhecendo Ruby on RailsSergio Henrique
 
Minicurso de Django - Desenvolvimento ágil web com Django e Python
Minicurso de Django - Desenvolvimento ágil web com Django e PythonMinicurso de Django - Desenvolvimento ágil web com Django e Python
Minicurso de Django - Desenvolvimento ágil web com Django e PythonGuilherme Garcia
 
PHP Experience 2016 - [Palestra] Rumo à Certificação PHP
PHP Experience 2016 - [Palestra] Rumo à Certificação PHPPHP Experience 2016 - [Palestra] Rumo à Certificação PHP
PHP Experience 2016 - [Palestra] Rumo à Certificação PHPiMasters
 
Django - Desenvolvimento web ágil com Python
Django - Desenvolvimento web ágil com PythonDjango - Desenvolvimento web ágil com Python
Django - Desenvolvimento web ágil com PythonIgor Sobreira
 
Aula_2_Comecando do Basico.pptx
Aula_2_Comecando do Basico.pptxAula_2_Comecando do Basico.pptx
Aula_2_Comecando do Basico.pptxMarioMinami3
 
PHP Experience 2016 - [Palestra] Vagrant, LXC, Docker, etc: Entenda as difere...
PHP Experience 2016 - [Palestra] Vagrant, LXC, Docker, etc: Entenda as difere...PHP Experience 2016 - [Palestra] Vagrant, LXC, Docker, etc: Entenda as difere...
PHP Experience 2016 - [Palestra] Vagrant, LXC, Docker, etc: Entenda as difere...iMasters
 
Desvendando a linguagem JavaScript
Desvendando a linguagem JavaScriptDesvendando a linguagem JavaScript
Desvendando a linguagem JavaScriptRodrigo Branas
 
Padrões-08 - Padrões Criacionais - Abstract Factory
Padrões-08 - Padrões Criacionais - Abstract FactoryPadrões-08 - Padrões Criacionais - Abstract Factory
Padrões-08 - Padrões Criacionais - Abstract FactoryEduardo Nicola F. Zagari
 
Despertando para o PHP
Despertando para o PHPDespertando para o PHP
Despertando para o PHPRafael Dohms
 
Padrões-12 - Padrões Estruturais - Facade
Padrões-12 - Padrões Estruturais - FacadePadrões-12 - Padrões Estruturais - Facade
Padrões-12 - Padrões Estruturais - FacadeEduardo Nicola F. Zagari
 
Padrões-10 - Padrões Criacionais - Singleton
Padrões-10 - Padrões Criacionais - SingletonPadrões-10 - Padrões Criacionais - Singleton
Padrões-10 - Padrões Criacionais - SingletonEduardo Nicola F. Zagari
 
PHP e AJAX: do Request ao Framework
PHP e AJAX: do Request ao FrameworkPHP e AJAX: do Request ao Framework
PHP e AJAX: do Request ao FrameworkRafael Dohms
 
Desenvolvendo aplicações web com python e web2py
Desenvolvendo aplicações web com python e web2pyDesenvolvendo aplicações web com python e web2py
Desenvolvendo aplicações web com python e web2pyGilson Filho
 
PHPSP TestFest 2009
PHPSP TestFest 2009PHPSP TestFest 2009
PHPSP TestFest 2009Rafael Dohms
 
Plataforma de compiladores .NET, Visual Studio 2015, C# 6 e futuro C# 7
Plataforma de compiladores .NET,Visual Studio 2015, C# 6 e futuro C# 7Plataforma de compiladores .NET,Visual Studio 2015, C# 6 e futuro C# 7
Plataforma de compiladores .NET, Visual Studio 2015, C# 6 e futuro C# 7Rogério Moraes de Carvalho
 

Mais procurados (20)

TDD com Python (Completo)
TDD com Python (Completo)TDD com Python (Completo)
TDD com Python (Completo)
 
Conhecendo Ruby on Rails
Conhecendo Ruby on RailsConhecendo Ruby on Rails
Conhecendo Ruby on Rails
 
Minicurso de Django - Desenvolvimento ágil web com Django e Python
Minicurso de Django - Desenvolvimento ágil web com Django e PythonMinicurso de Django - Desenvolvimento ágil web com Django e Python
Minicurso de Django - Desenvolvimento ágil web com Django e Python
 
Padrões-07 - Padrões Criacionais
Padrões-07 - Padrões CriacionaisPadrões-07 - Padrões Criacionais
Padrões-07 - Padrões Criacionais
 
PHP Experience 2016 - [Palestra] Rumo à Certificação PHP
PHP Experience 2016 - [Palestra] Rumo à Certificação PHPPHP Experience 2016 - [Palestra] Rumo à Certificação PHP
PHP Experience 2016 - [Palestra] Rumo à Certificação PHP
 
Django - Desenvolvimento web ágil com Python
Django - Desenvolvimento web ágil com PythonDjango - Desenvolvimento web ágil com Python
Django - Desenvolvimento web ágil com Python
 
Aula_2_Comecando do Basico.pptx
Aula_2_Comecando do Basico.pptxAula_2_Comecando do Basico.pptx
Aula_2_Comecando do Basico.pptx
 
Doctrine for Dummies
Doctrine for DummiesDoctrine for Dummies
Doctrine for Dummies
 
PHP Experience 2016 - [Palestra] Vagrant, LXC, Docker, etc: Entenda as difere...
PHP Experience 2016 - [Palestra] Vagrant, LXC, Docker, etc: Entenda as difere...PHP Experience 2016 - [Palestra] Vagrant, LXC, Docker, etc: Entenda as difere...
PHP Experience 2016 - [Palestra] Vagrant, LXC, Docker, etc: Entenda as difere...
 
Desvendando a linguagem JavaScript
Desvendando a linguagem JavaScriptDesvendando a linguagem JavaScript
Desvendando a linguagem JavaScript
 
Padrões-08 - Padrões Criacionais - Abstract Factory
Padrões-08 - Padrões Criacionais - Abstract FactoryPadrões-08 - Padrões Criacionais - Abstract Factory
Padrões-08 - Padrões Criacionais - Abstract Factory
 
Doctrine for dummies
Doctrine for dummiesDoctrine for dummies
Doctrine for dummies
 
Despertando para o PHP
Despertando para o PHPDespertando para o PHP
Despertando para o PHP
 
Padrões-12 - Padrões Estruturais - Facade
Padrões-12 - Padrões Estruturais - FacadePadrões-12 - Padrões Estruturais - Facade
Padrões-12 - Padrões Estruturais - Facade
 
Padrões-10 - Padrões Criacionais - Singleton
Padrões-10 - Padrões Criacionais - SingletonPadrões-10 - Padrões Criacionais - Singleton
Padrões-10 - Padrões Criacionais - Singleton
 
PHP e AJAX: do Request ao Framework
PHP e AJAX: do Request ao FrameworkPHP e AJAX: do Request ao Framework
PHP e AJAX: do Request ao Framework
 
Desenvolvendo aplicações web com python e web2py
Desenvolvendo aplicações web com python e web2pyDesenvolvendo aplicações web com python e web2py
Desenvolvendo aplicações web com python e web2py
 
PHPSP TestFest 2009
PHPSP TestFest 2009PHPSP TestFest 2009
PHPSP TestFest 2009
 
Plataforma de compiladores .NET, Visual Studio 2015, C# 6 e futuro C# 7
Plataforma de compiladores .NET,Visual Studio 2015, C# 6 e futuro C# 7Plataforma de compiladores .NET,Visual Studio 2015, C# 6 e futuro C# 7
Plataforma de compiladores .NET, Visual Studio 2015, C# 6 e futuro C# 7
 
Java primeiros-passos
Java primeiros-passosJava primeiros-passos
Java primeiros-passos
 

Semelhante a Alex Martelli's Python Design Patterns

Linguagens Poo
Linguagens PooLinguagens Poo
Linguagens PooInfogenius
 
Javascript para CSharpers 4 - POO
Javascript para CSharpers 4 - POOJavascript para CSharpers 4 - POO
Javascript para CSharpers 4 - POOWesley Lemos
 
Refatoração - aquela caprichada no código
Refatoração - aquela caprichada no códigoRefatoração - aquela caprichada no código
Refatoração - aquela caprichada no códigoJuciellen Cabrera
 
Três anos de Scala no NewsMonitor
Três anos de Scala no NewsMonitorTrês anos de Scala no NewsMonitor
Três anos de Scala no NewsMonitorFelipe Hummel
 
Introdução a linguagem Python
Introdução a linguagem PythonIntrodução a linguagem Python
Introdução a linguagem PythonLuciano Ramalho
 
C# 6.0 - Interopmix 2015
C# 6.0 - Interopmix 2015C# 6.0 - Interopmix 2015
C# 6.0 - Interopmix 2015Renato Groff
 
55 New Things in Java 7 - Brazil
55 New Things in Java 7 - Brazil55 New Things in Java 7 - Brazil
55 New Things in Java 7 - BrazilStephen Chin
 
Gestão automática de configuração usando puppet
Gestão automática de configuração usando puppetGestão automática de configuração usando puppet
Gestão automática de configuração usando puppetDaniel Sobral
 
Desenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine OrmDesenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine OrmGuilherme Blanco
 
POO2-Pre-32-PadroesProjetos_.pdf
POO2-Pre-32-PadroesProjetos_.pdfPOO2-Pre-32-PadroesProjetos_.pdf
POO2-Pre-32-PadroesProjetos_.pdfAndreCosta502039
 
Linguagem Python
Linguagem PythonLinguagem Python
Linguagem PythonNatã Melo
 
Python - Programando em alto nível
Python - Programando em alto nívelPython - Programando em alto nível
Python - Programando em alto nívelIgor Sobreira
 
C# 6.0 - DotNetBaixada - Novembro/2015
C# 6.0 - DotNetBaixada - Novembro/2015C# 6.0 - DotNetBaixada - Novembro/2015
C# 6.0 - DotNetBaixada - Novembro/2015Renato Groff
 

Semelhante a Alex Martelli's Python Design Patterns (20)

M2ti - Python Brasil
M2ti - Python BrasilM2ti - Python Brasil
M2ti - Python Brasil
 
Cap10
Cap10Cap10
Cap10
 
Linguagens Poo
Linguagens PooLinguagens Poo
Linguagens Poo
 
Groovy stack
Groovy stackGroovy stack
Groovy stack
 
Curso Java Basico
Curso Java BasicoCurso Java Basico
Curso Java Basico
 
Javascript para CSharpers 4 - POO
Javascript para CSharpers 4 - POOJavascript para CSharpers 4 - POO
Javascript para CSharpers 4 - POO
 
03 fundamentos java
03 fundamentos java03 fundamentos java
03 fundamentos java
 
Refatoração - aquela caprichada no código
Refatoração - aquela caprichada no códigoRefatoração - aquela caprichada no código
Refatoração - aquela caprichada no código
 
Três anos de Scala no NewsMonitor
Três anos de Scala no NewsMonitorTrês anos de Scala no NewsMonitor
Três anos de Scala no NewsMonitor
 
Introdução a linguagem Python
Introdução a linguagem PythonIntrodução a linguagem Python
Introdução a linguagem Python
 
java_avancado.pdf
java_avancado.pdfjava_avancado.pdf
java_avancado.pdf
 
C# 6.0 - Interopmix 2015
C# 6.0 - Interopmix 2015C# 6.0 - Interopmix 2015
C# 6.0 - Interopmix 2015
 
55 New Things in Java 7 - Brazil
55 New Things in Java 7 - Brazil55 New Things in Java 7 - Brazil
55 New Things in Java 7 - Brazil
 
Gestão automática de configuração usando puppet
Gestão automática de configuração usando puppetGestão automática de configuração usando puppet
Gestão automática de configuração usando puppet
 
Desenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine OrmDesenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine Orm
 
POO2-Pre-32-PadroesProjetos_.pdf
POO2-Pre-32-PadroesProjetos_.pdfPOO2-Pre-32-PadroesProjetos_.pdf
POO2-Pre-32-PadroesProjetos_.pdf
 
Linguagem Python
Linguagem PythonLinguagem Python
Linguagem Python
 
Java 05
Java 05Java 05
Java 05
 
Python - Programando em alto nível
Python - Programando em alto nívelPython - Programando em alto nível
Python - Programando em alto nível
 
C# 6.0 - DotNetBaixada - Novembro/2015
C# 6.0 - DotNetBaixada - Novembro/2015C# 6.0 - DotNetBaixada - Novembro/2015
C# 6.0 - DotNetBaixada - Novembro/2015
 

Mais de Luciano Ramalho

Iteráveis e geradores (versão RuPy)
Iteráveis e geradores (versão RuPy)Iteráveis e geradores (versão RuPy)
Iteráveis e geradores (versão RuPy)Luciano Ramalho
 
Orientação a objetos em Python (compacto)
Orientação a objetos em Python (compacto)Orientação a objetos em Python (compacto)
Orientação a objetos em Python (compacto)Luciano Ramalho
 
Encapsulamento com descritores
Encapsulamento com descritoresEncapsulamento com descritores
Encapsulamento com descritoresLuciano Ramalho
 
Arduino: hardware hacking & coding dojo
Arduino: hardware hacking & coding dojoArduino: hardware hacking & coding dojo
Arduino: hardware hacking & coding dojoLuciano Ramalho
 
Objetos Pythonicos - compacto
Objetos Pythonicos - compactoObjetos Pythonicos - compacto
Objetos Pythonicos - compactoLuciano Ramalho
 
Iteraveis e geradores em Python
Iteraveis e geradores em PythonIteraveis e geradores em Python
Iteraveis e geradores em PythonLuciano Ramalho
 
Encapsulamento com Descritores em Python
Encapsulamento com Descritores em PythonEncapsulamento com Descritores em Python
Encapsulamento com Descritores em PythonLuciano Ramalho
 
Python: Iteraveis, geradores etc
Python: Iteraveis, geradores etcPython: Iteraveis, geradores etc
Python: Iteraveis, geradores etcLuciano Ramalho
 
Jython no JavaOne Latin America 2011
Jython no JavaOne Latin America 2011Jython no JavaOne Latin America 2011
Jython no JavaOne Latin America 2011Luciano Ramalho
 
Python para quem sabe Python (aula 2)
Python para quem sabe Python (aula 2)Python para quem sabe Python (aula 2)
Python para quem sabe Python (aula 2)Luciano Ramalho
 
OO em Python sem sotaque
OO em Python sem sotaqueOO em Python sem sotaque
OO em Python sem sotaqueLuciano Ramalho
 
Python, a arma secreta do Google
Python, a arma secreta do GooglePython, a arma secreta do Google
Python, a arma secreta do GoogleLuciano Ramalho
 

Mais de Luciano Ramalho (20)

Wiki-wiki S/A
Wiki-wiki S/AWiki-wiki S/A
Wiki-wiki S/A
 
Mongodb: agregação
Mongodb: agregaçãoMongodb: agregação
Mongodb: agregação
 
Iteráveis e geradores (versão RuPy)
Iteráveis e geradores (versão RuPy)Iteráveis e geradores (versão RuPy)
Iteráveis e geradores (versão RuPy)
 
Orientação a objetos em Python (compacto)
Orientação a objetos em Python (compacto)Orientação a objetos em Python (compacto)
Orientação a objetos em Python (compacto)
 
Encapsulamento com descritores
Encapsulamento com descritoresEncapsulamento com descritores
Encapsulamento com descritores
 
Iteraveis e geradores
Iteraveis e geradoresIteraveis e geradores
Iteraveis e geradores
 
Arduino: hardware hacking & coding dojo
Arduino: hardware hacking & coding dojoArduino: hardware hacking & coding dojo
Arduino: hardware hacking & coding dojo
 
Objetos Pythonicos - compacto
Objetos Pythonicos - compactoObjetos Pythonicos - compacto
Objetos Pythonicos - compacto
 
Iteraveis e geradores em Python
Iteraveis e geradores em PythonIteraveis e geradores em Python
Iteraveis e geradores em Python
 
Encapsulamento com Descritores em Python
Encapsulamento com Descritores em PythonEncapsulamento com Descritores em Python
Encapsulamento com Descritores em Python
 
Dojo com Processing
Dojo com ProcessingDojo com Processing
Dojo com Processing
 
Dojo com Arduino
Dojo com ArduinoDojo com Arduino
Dojo com Arduino
 
Python: Iteraveis, geradores etc
Python: Iteraveis, geradores etcPython: Iteraveis, geradores etc
Python: Iteraveis, geradores etc
 
Open Library no Mongodb
Open Library no MongodbOpen Library no Mongodb
Open Library no Mongodb
 
Jython no JavaOne Latin America 2011
Jython no JavaOne Latin America 2011Jython no JavaOne Latin America 2011
Jython no JavaOne Latin America 2011
 
Python para quem sabe Python (aula 2)
Python para quem sabe Python (aula 2)Python para quem sabe Python (aula 2)
Python para quem sabe Python (aula 2)
 
OO em Python sem sotaque
OO em Python sem sotaqueOO em Python sem sotaque
OO em Python sem sotaque
 
Modelos ricos
Modelos ricosModelos ricos
Modelos ricos
 
Python, a arma secreta do Google
Python, a arma secreta do GooglePython, a arma secreta do Google
Python, a arma secreta do Google
 
Ensinando OO com Python
Ensinando OO com PythonEnsinando OO com Python
Ensinando OO com Python
 

Alex Martelli's Python Design Patterns

  • 1. Alex Martelli’s Design Patterns in Python Apresentada originalmente no Google Developer’s Day 2007 Vídeo no YouTube: http://bit.ly/okP7hh Traduzida para a PythonBrasil 7 por Luciano Ramalho com autorização de Alex Martelli gentilmente cedida em 23/08/2011
  • 2.
  • 3. Alex Martelli and Anna Martelli Ravenscroft EuroPython, Firenze, June 2011 photo by Josette Garcia
  • 4. O melhor livro sobre Python já escrito (mesmo sendo de 2006)
  • 5.
  • 6.
  • 7. Saímos cantando os pneus... • Forças: um sub-sistema rico e complexo oferece muita funcionalidade útil; componentes clientes interagem com várias partes dessa funcionali- dade, de um jeito que está “fora de controle” • isto causa muitos problemas para programadores do código cliente e também do sub-sistema (complexidade + rigidez)
  • 8.
  • 9. Solução: o padrão “Façade” • interpor um objeto/classe Django: classe do domínio versus um monte de classes de modelo, para facilitar a api exposta às views de “fachada”, expondo um sub-conjunto controlado da funcionalidade • clientes acessam somente a fachada • a fachada implementa a funcionalidade simples invocando o sub-sistema complexo • a implementação do sub-sistema ganha flexibilidade, os clientes ganham simplicidade
  • 10.
  • 11. Façade é um padrão de projeto • resumo de um problema comum de projeto + estrutura de uma solução (+ vantagens e desvantagens, alternativas, ...) e: • um nome (mais fácil de lembrar/discutir) • “descrições de objetos e classes que se comunicam, customizados para resolver um problema geral de projeto em um contexto específico” (GOF) • não é: estrutura de dados, algoritmo, arquitetura específica de domínio, recurso de uma linguagem ou de uma biblioteca Façade é uma exceção • tem que ser estudado no contexto de uma linguagem! • tem que fornecer Usos Conhecidos (UC / KU) PP não são inventados, são descobertos por arqueólogos
  • 12.
  • 13. Alguns UC de Façade • ...na biblioteca padrão de Python... • dbhash é uma fachada para o bsddb • acesso muito simplificado a uma parte da API • também atende à interface dbm (portanto, é também um exemplo do PP Adapter) • os.path: basename, dirname são fachada para split + acesso a item; isdir (etc.) fachada para os.stat + stat.S_ISDIR (etc.) • Façade é um PP estrutural (veremos outro, Adapter, depois; no exemplo do dbhash eles se fundem)
  • 14.
  • 15.
  • 16. O que é um padrão de projeto • resumo de um problema comum de projeto + estrutura de uma solução (+ vantagens e desvantagens, alternativas, ...) e: • um nome (mais fácil de lembrar/discutir) • “descrições de objetos e classes que se comunicam customizadas para resolver um problema geral de projeto em um contexto específico” (GOF) • um PP não é: estrutura de dados, algoritmo, arquitetura específica de domínio, recurso de uma linguagem ou de uma biblioteca • tem que ser estudado no contexto de uma linguagem! • tem que fornecer Usos Conhecidos (UC / KU)
  • 17. Nenhum livro bom de PP em Python
  • 19. Categorias clássicas de PP • Criacionais: formas e modos de instanciar objetos • Estruturais: composição mútua de classes ou objetos (o Façade é um PP estrutural) • Comportamental: como classes e objetos interagem e dividem responsabilidades entre si • Cada um pode ser a nível de classe ou a nível de objeto
  • 20.
  • 21. Princípios básicos de PP • “programe para uma interface, não para uma implementação” (GOF) • isto é feito principalmente através de “tipagem pato” em Python – raramente com interfaces “formais” • semelhante a “polimorfismo baseado em assinatura” nas templates de C++
  • 22.
  • 23.
  • 24. Princípios básicos de PP • “prefira composição de objetos do que herança de classes” (GOF) • em Python, segurar ou embrulhar • herdar apenas quando é realmente conveniente • expor todos os métodos da super classe (reusar + normalmente sobrescrever + talvez estender) • mas é um acoplamento muito forte!
  • 25.
  • 26.
  • 27. Python: segurar ou embrulhar? • “Segurar”: objeto O tem um sub-objeto S como um atributo (talvez uma propriedade) – só isso • usa-se self.S.method ou O.S.method • simples, direto, imediato, porém... acoplamento bem forte, frequentemente no eixo errado
  • 28.
  • 29. Python: segurar ou embrulhar? • “Embrulhar”: segurar (frequentemente com um nome privado) e delegar (de modo que se possa acessar diretamente O.metodo) • delegação explícita (def metodo(self...): self.S.metodo) • automática (via __getattr__) • acoplamento correto (Lei de Deméter) Evitar expressões do tipo a.b.c. porque isso limita a a expor um b que tem um
  • 30.
  • 31. Ex.: embrulhar para “restringir” class EmbrulhoRestritor(object): def __init__(self, embrulhado, bloqueios): self._embrulhado = embrulhado self._bloqueios = bloqueios def __getattr__(self, nome): if nome in self._bloqueios: raise AttributeError, nome return getattr(self._embrulhado, nome) ... Herança não tem o poder de restringir!
  • 32.
  • 33. Padrões criacionais • não muito comuns em Python... • ... porque basicamente Factory já vem pronto
  • 34. “Factory já vem pronto” • Em linguagens que tem o operador new, a chamada new Foo() implica que Foo é uma classe concreta específica. Isso aumenta o acoplamento. • Python é mais flexível, porque Foo() pode ser a invocação de uma classe ou de uma função factory. O cliente não precisa saber.
  • 35.
  • 36. Padrões criacionais [1] “Queremos que apenas uma instância possa existir” • use um módulo em vez de uma classe Resolve 90% dos casos • não pode ter subclasses, métodos especiais... • crie somente uma instância (sem restrição) • necessário definir exatamente quando criar • singleton (“Highlander”) • criar sub-classes não é tão tranquilo • monoestado (“Borg”) • Guido não curte
  • 37.
  • 38. Singleton (“Highlander”) class Singleton(object): def __new__(cls, *a, **k): if not hasattr(cls, '_inst'): cls._inst = super(Singleton, cls).__new__(cls, *a, **k) return cls._inst Subclasses são problemáticas, porém: class Foo(Singleton): pass problema class Bar(Foo): pass intrínseco f = Foo(); b = Bar(); # ...???... do Singleton
  • 39.
  • 40. Monoestado (“Borg”) class Borg(object): _shared_state = {} def __new__(cls, *a, **k): obj = super(Borg, cls ).__new__(cls, *a, **k) obj.__dict__ = cls._shared_state return obj Subclasses sem problemas, basta fazer: class Foo(Borg): pass class Bar(Foo): pass class Baz(Foo): sobrecarga de _shared_state = {} dados resolve!
  • 41.
  • 42. Padrões criacionais [2] • “não queremos ser forçados a instanciar uma classe concreta específica” • injeção de dependência • nada se cria “dentro”, tudo vem “de fora” • e se múltiplas criações são necessárias? • subcategoria “Factory” de PPs • pode criar qq. coisa ou reusar o q. já existe • funções factory (e outros invocáveis) • métodos factory (podem ser sobrescritos) • classes factory abstratas
  • 43.
  • 44. Padrões Estruturais Subcategoria “Disfarçe/Adaptação: • Adapter: ajustar uma interface (existem variantes de classe e de objetos) • Facade: simplificar a interface de um sub-sistema • ... e muitos outros que não vou abordar, como: • Brige: muitas implementações de uma abstração, muitas implementações de uma funcionalidade, sem codificação repetitiva • Decorator: reusar+ajustar sem herança • Proxy: desacoplar acesso/localização
  • 45.
  • 46. Adapter • código-cliente γ exige um protocolo C • cógido-fornecedor σ oferece um protocolo diferente S (com um superconjunto da funcionalide de C) • código-adaptador α “se infiltra entre eles”: • para γ, α é um fornecedor (produz o protocolo C) • para σ, α é um cliente (consome o protocolo S) • “dentro”, α implementa C (por meio de chamadas apropriadas a S em σ)
  • 47.
  • 48. Exemplo simples de Adapter • C requer o método foobar(foo, bar) • S fornece o método barfoo(bar, foo) • por exemplo, σ poderia ser: class Barfooer(object): def barfoo(self, bar, foo): ...
  • 49.
  • 50. Adapter de objeto • por instância, com delegação por embrulho: class EmbrulhadorFoobar(object): def __init__(self, embrulhado): self.e = embrulhado def foobar(self, foo, bar): return self.e.barfoo(bar, foo) foobarador = EmbrulhadorFoobar(barfooador)
  • 51.
  • 52. Adapter de classe (direto) • por classe, com derivação e auto-delegação: class Foobarador(Barfooador): def foobar(self, foo, bar): return self.barfoo(bar, foo) foobarador = Foobarador(...qq. coisa...)
  • 53.
  • 54. Adapter de classe (mixin) • flexível, bom uso de herança múltipla: class BF2FB: def foobar(self, foo, bar): return self.barfoo(bar, foo) class Foobarador(BF2FB, Barfooador): pass foobarador = Foobarador(...qq. coisa...)
  • 55.
  • 56. Adapter: Usos Conhecidos • socket._fileobject: de sockets para objetos “file- like” (com muito código para gerenciar o buffer) • doctest.DocTestSuite: adapta testes doctest para unittest.TestSuite • dbhash: adapta bsddb para dbm • StringIO: adapta str ou unicode para “file-like” • shelve: adapta “dict limitado” (chaves e valores str, métodos básicos) para um dicionário completo • via pickle para qualquer coisa <-> string • + UserDict.DictMixin
  • 57.
  • 58. Observações sobre Adapter • alguns adapters reais podem demandar muito código • classes mixin são uma ótima maneira de auxiliar na adaptação de protocolos ricos (implementam métodos avançados a partir de métodos fundamentais) • Adapter é encontrado em todos os níveis de complexidade • Em Python, _não_ se trata sempre de classes e suas instâncias (de modo algum!) -- muitas vezes _invocáveis_ são adaptados (via decorators e outras funções de ordem superior, closures, functools, ...)
  • 59.
  • 60. Facade vs Adapter • Adapter trata de fornecer um determinado protocolo exigido por código-cliente • ou, conquistar polimorfismo via homogeneidade • Facade trata de simplificar uma interface rica quando apenas um sub-conjunto é necessário • Facade frequentemente mascara um subsistema formado por muitas classes/ objetos, Adapter mascara apenas um objeto ou classe
  • 61.
  • 62. Padrões comportamentais • Template Method: self-delegation (auto-delegação) • ... “a essência da POO” • algumas de suas variantes específicas em Python
  • 63.
  • 64. Template Method • padrão excelente, nome péssimo • “template” é um termo muito sobrecarregado • programação genérica em C++ • geração de documento a partir de esqueleto • ... • um nome melhor: self-delegation • auto-delegação • diretamente descritivo!
  • 65.
  • 66. TM Clássico • classe-base abstrata (ABC) oferece “método organizador” que invoca “métodos gancho” • na ABC, métodos-gancho são abstratos • sub-classes concretas implementam os ganchos • código-cliente invoca o método organizador • em alguma referência à ABC (injetor, ou...) • que obviamente refere-se a uma sub-classe concreta
  • 67.
  • 68. Esqueleto de TM class AbstractBase(object): def orgMethod(self): self.doThis() self.doThat() class Concrete(AbstractBase): def doThis(self): ... def doThat(self): ...
  • 69.
  • 70. UC: cmd.Cmd.cmdloop def cmdloop(self): self.preloop() while True: s = self.doinput() s = self.precmd(s) finis = self.docmd(s) finis = self.postcmd(finis,s) if finis: break self.postloop() Na implementação em Python, os métodos-gancho são implementados com pass na classe abstrata, porque Python é uma linguagem pragática e não ideológica.
  • 71.
  • 72. Justificativa p/ TM Clássico Diferença entre um framework e uma bibiblioteca: uma biblioteca é um conjunto de funções que vc chama, a organização fica por sua conta. Um framework tem os métodos • o “método organizador” fornece “lógica de organização e que chamam os seus métodos. estrutural” (sequenciamento etc.) • os “métodos gancho” realizam de fato as “ações elementares” • é frequentemente apropriado para fatorar comportamento comuns e variações • deixa claras as responsabilidades e colaborações entre objetos (classes): classe base invoca ganchos, sub-classes os implementam • aplica o “Hollywood Principle”: “don't call us, we'll call you” - não ligue para nós, nós te ligamos
  • 73.
  • 74. Uma escolha de ganchos class TheBase(object): def doThis(self): # provide a default (often a no-op) pass def doThat(self): # or, force subclass to implement # (might also just be missing...) raise NotImplementedError • Implementações default são mais práticas, quando fazem sentido, mas “obrigatórias” servem como boa documentação
  • 75.
  • 76. UC: Queue.Queue class Queue: ... def put(self, item): self.not_full.acquire() try: while self._full(): self.not_full.wait() self._put(item) self.not_empty.notify() finally: self.not_full.release() def _put(self, item): ...
  • 77.
  • 78. TM em Queue • Não abstrata, frequentemente usada “no estado”, implementa todos os métodos ganchos • sub-classes podem customizar o comportamento • sem se preocupar com travas, timing... • comportamento default é FIFO, simples e útil • with no worry about locking, timing, ... • pode-se sobrescrever métodos gancho (__init__, qsize, _empty, _full, _put, _get) E... • ...dados (maxsize, queue), uma exclusividade Python!
  • 79.
  • 80. Queue customizada class LifoQueueA(Queue): def _put(self, item): self.queue.appendleft(item) class LifoQueueB(Queue): def _init(self, maxsize): self.maxsize = maxsize self.queue = list() def _get(self): return self.queue.pop()
  • 81.
  • 82. Fatorando os ganchos • “método organizador” em uma classe • “métodos gancho” em outra classe • UC: HTML formatter vs writer • UC: SAX parser vs handler • adiciona um eixo de variabilidade/flexibilidade • aproxima-se do PP Strategy: • Strategy: uma classe abstrata por ponto de decisão, e classes concretas indepententes • TM fatorado: classes abstratas e concretas mais “agrupadas”
  • 83.
  • 84. TM + introspection • classe “organizadora” pode examinar classe “gancho” (talvez descendente) em tempo de execução • descobrir que métodos existem • despachar apropriadamente (incluindo “catch-all” e/ou outros tratamento de erros)
  • 85.
  • 86. UC: cmd.Cmd.docmd def docmd(self, cmd, a): ... try: fn = getattr(self, 'do_' + cmd) except AttributeError: return self.dodefault(cmd, a) return fn(a)

Notas do Editor

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n