associação pythonbrasil[11] django zope/plone planet Início Logado como (Entrar)

Diferenças para "ArquiteturaDeComponentes"

Diferenças entre as versões de 3 e 4
Revisão 3e 2007-12-08 08:53:18
Tamanho: 4340
Comentário:
Revisão 4e 2007-12-08 09:12:49
Tamanho: 7660
Comentário:
Deleções são marcadas assim. Adições são marcadas assim.
Linha 71: Linha 71:
Observe que você não precisa conhecer o componente, mas apenas a interface. Isto significa que qualquer um pode implementar o componente para você usar. É claro que quando se trata de algo tão banal quanto somar e dividir isto é inútil, mas você pode por exemplo criar uma interface para componentes que conversam com bancos de dados SQL, e então plugar uma utility para cada modelo de banco de dados diferente. Você pode ter quantos componentes quiser, todos implementando a mesma interface, e se eles forem registrados com nomes diferentes você pode escolher na configuração da sua aplicação qual deles deseja usar. Você tem componentes plugáveis, de um jeito muito fácil. Note que você não precisa conhecer o componente, mas apenas a interface. Isto significa que qualquer um pode implementar o componente para você usar. É claro que quando se trata de algo tão banal quanto somar e dividir isto é inútil, mas você pode por exemplo criar uma interface para componentes que conversam com bancos de dados SQL, e então plugar uma utility para cada modelo de banco de dados diferente. Você pode ter quantos componentes quiser, todos implementando a mesma interface, e se eles forem registrados com nomes diferentes você pode escolher na configuração da sua aplicação qual deles deseja usar. Você tem componentes plugáveis, de um jeito muito fácil.

Also, the ZCA has provisions for extending other components. Lets say that we also want to be able to do modulo of the integers. We define up how a component that would calculate the modulo should look. We could let it extend the previous IIntegerMaths interface, by just subclassing IIntegerMaths, but that would mean that to get Modulo functionality, we need to sublass every implementation of IIntegerMaths. But since since modulo can be calculated by using division, we can implement it as an adapter. First the new interface for modulo maths:

Além disso, a ZCA permite que você extenda outros componentes. Digamos que você precisa calcular o resto da divisão inteira, ou módulo. Primeiro definimos a aparência do componente que fará isso. Poderíamos extender a interface IOperacoesInteiros, mas isso significa que para obter a funcionalidade de módulo, teríamos que criar sub-classes de todas as implementações de IOperacoesInteiros. Porém, como o módulo pode ser calculado usando a divisão, podemos implementar isso usando um adaptador, ou ''adapter'' no jargão da ZCA. Primeiro, a nova interface:

{{{
#!python
class IModulador(interface.Interface):

    def modulo(a, b):
        "devolve o resto da divisão entre dois inteiros"
}}}

Agora, criamos e registramos o ''adapter'':

{{{
#!python
class AdaptadorDivisorModulador:

    interface.implements(IModulador)
    component.adapts(IOperacoesInteiros)

    def __init__(self, context):
        self.context = context

    def modulo(self, a , b):
        return a - (b*self.context.dividir(a, b))

component.provideAdapter(AdaptadorDivisorModulador)
}}}

Note que desta vez não instanciamos a classe. Os adaptadores são instanciados quando você adapta alguma coisa.

Agora podemos obter um componente que implementa IOperacoesInteiros:

{{{
#!python
calc = component.getUtility(IOperacoesInteiros)
}}}

e agora podemos adaptá-lo à interface IModulador e usar a funcionalidade extendida:

{{{
#!python
mod_calc = IModulador(calc)
print "Módulo:", mod_calc.modulo(23, 5)
}}}

Note que isto vai funcionar para qualquer componente IOperacoesInteiros. Basta que ele saiba dividir. Desta forma eu extendi '''todos''' os componentes IOperacoesInteiros ao mesmo tempo. Não precisei extender cada uma das implementações de IOperacoesInteiros, mas usando adaptação eu forneco a qualquer implementação existente a funcionalidade modulo.

Será que é assim tão fácil? Se não acredita, faça easy_install zope.component, copie todo o código abaixo em um arquivo, e execute. Funciona mesmo. Tudo o que você precisa para ter a arquitetura de componentes mais bacana do planeta é fazer from zope import interfaces, component, criar interfaces para seus plugins, e passar a acessá-los através de getUtility.

Agora, é clar que há muito mais coisas e funcionalidades e operações interessantes que podem ser feitas com a arquitetura de componentes. Existe um novo projeto de documentação da ZCA que foi iniciado pelo Baiju Muthukadan. O livro "" que ele está escrevendo vai te dar mais detalhes.

''Traduzido por LucianoRamalho'' com autorização do autor, Lennart Regebro.

'''Documento original:''' http://regebro.wordpress.com/2007/11/16/a-python-component-architecture/

Uma arquitetura de componentes em Python

Autor: Lennart Regebro - 19/nov/2007

Ao construir grandes frameworks você muitas vezes deseja que tudo seja facilmente plugável e extensível. Os objetos precisam ser capazes de interagir uns com os outros mesmo quando esta interação não está prevista inicialmente. Criar este tipo de flexibilidade não é muito difícil, especialmente em uma linguagem dinâmica como Python, mas se você tem que criar um framework para plug-ins toda vez que precisa de um, você acaba não fazendo isso a menos que seja realmente muito necessário.

Assim, é bom ter uma forma padrão para a interação entre objetos e para que eles possam se inspecionar, e uma forma que você possa usar toda vez que precisar. Resumindo, o você precisa de uma arquitetura de componentes. Felizmente, já existe uma para Python, que foi bem implementada, bem testada e vem sendo usada há anos. Seu nome é Zope Component Architecture.

Ah, sim, já posso ouvir você: "Eca! Zope não... Isso só específico para Zope, não é pythonico, só serve para a Web, é cheio de XML. Argh!". Mas você estaria errado. A única coisa não pythonica e "webby" da Zope Component Architecture é que seus módulos se chamam zope.algo. Mas os módulos têm esse nome porque foram escritos pela Zope Corp. Sim, é verdade que o Zope usa XML em sua linguagem de configuração orientada a aspectos. Veja bem, na orientação a aspectos é desejável ter uma linguagem específica para conectar os componentes, e a do Zope é ZCML. Mas a arquitetura de componentes não exige ZCML de nenhuma maneira. É totalmente baseada em Python (exceto por algumas partes escritas em C para maior performance, mas elas também possuem implementações alternativas em Python).

Vamos ver um exemplo realmente estúpido de como usar a arquitetura de componentes. Vamos criar um componente que seja capaz de fazer aritmética com inteiros. Sim, é bem estúpido, porque sempre existiram jeitos de fazer isso em Python, mas foi a melhor idéia que eu tive. Primeiro, a gente define como a aparência externa do componente de aritmética, sua interface:

   1 from zope import interface, component
   2 
   3 class IOperacoesInteiros(interface.Interface):
   4 
   5     def somar(a, b):
   6         """soma dois inteiros"""
   7 
   8     def subtrair(a, b):
   9         """subtrai dois inteiros"""
  10 
  11     def multiplicar(a, b):
  12         """multiplica dois inteiros"""
  13 
  14     def dividir(a, b):
  15         """divide dois inteiros"""

É uma convenção chamar as interfaces de IAlgumaCoisa, por isso temos IOperacoesInteiros. Não é um erro de digitação. ;-) Uma vez que temos uma interface, criamos um componente que a implementa a interface, e podemos instanciá-lo:

   1 class Calculadora:
   2 
   3     interface.implements(IOperacoesInteiros)
   4 
   5     def somar(self, a, b):
   6         return a + b
   7 
   8     def subtrair(self, a, b):
   9         return a - b
  10 
  11     def multiplicar(self, a, b):
  12         return a * b
  13 
  14     def dividir(self, a, b):
  15         return a//b
  16 
  17 calc = Calculadora() # sem usar a AC

Agora podemos efetuar uma divisão com a calculadora diretamente digitando apenas calc.dividir(23,5), mas este não é o estilo de programação de componentes. Para usar a arquitetura de componentes, precisamos registrar o componente:

   1 component.provideUtility(Calculator())

Agora, quem precisar fazer operações com inteiros pode encontrar o componente que presta este serviço:

   1 calc = component.getUtility(IOperacoesInteiros)
   2 print "Divisão:", calc.dividir(23, 5)

Note que você não precisa conhecer o componente, mas apenas a interface. Isto significa que qualquer um pode implementar o componente para você usar. É claro que quando se trata de algo tão banal quanto somar e dividir isto é inútil, mas você pode por exemplo criar uma interface para componentes que conversam com bancos de dados SQL, e então plugar uma utility para cada modelo de banco de dados diferente. Você pode ter quantos componentes quiser, todos implementando a mesma interface, e se eles forem registrados com nomes diferentes você pode escolher na configuração da sua aplicação qual deles deseja usar. Você tem componentes plugáveis, de um jeito muito fácil.

Also, the ZCA has provisions for extending other components. Lets say that we also want to be able to do modulo of the integers. We define up how a component that would calculate the modulo should look. We could let it extend the previous IIntegerMaths interface, by just subclassing IIntegerMaths, but that would mean that to get Modulo functionality, we need to sublass every implementation of IIntegerMaths. But since since modulo can be calculated by using division, we can implement it as an adapter. First the new interface for modulo maths:

Além disso, a ZCA permite que você extenda outros componentes. Digamos que você precisa calcular o resto da divisão inteira, ou módulo. Primeiro definimos a aparência do componente que fará isso. Poderíamos extender a interface IOperacoesInteiros, mas isso significa que para obter a funcionalidade de módulo, teríamos que criar sub-classes de todas as implementações de IOperacoesInteiros. Porém, como o módulo pode ser calculado usando a divisão, podemos implementar isso usando um adaptador, ou adapter no jargão da ZCA. Primeiro, a nova interface:

   1 class IModulador(interface.Interface):
   2 
   3     def modulo(a, b):
   4         "devolve o resto da divisão entre dois inteiros"

Agora, criamos e registramos o adapter:

   1 class AdaptadorDivisorModulador:
   2 
   3     interface.implements(IModulador)
   4     component.adapts(IOperacoesInteiros)
   5 
   6     def __init__(self, context):
   7         self.context = context
   8 
   9     def modulo(self, a , b):
  10         return a - (b*self.context.dividir(a, b))
  11 
  12 component.provideAdapter(AdaptadorDivisorModulador)

Note que desta vez não instanciamos a classe. Os adaptadores são instanciados quando você adapta alguma coisa.

Agora podemos obter um componente que implementa IOperacoesInteiros:

   1 calc = component.getUtility(IOperacoesInteiros)

e agora podemos adaptá-lo à interface IModulador e usar a funcionalidade extendida:

   1 mod_calc = IModulador(calc)
   2 print "Módulo:", mod_calc.modulo(23, 5)

Note que isto vai funcionar para qualquer componente IOperacoesInteiros. Basta que ele saiba dividir. Desta forma eu extendi todos os componentes IOperacoesInteiros ao mesmo tempo. Não precisei extender cada uma das implementações de IOperacoesInteiros, mas usando adaptação eu forneco a qualquer implementação existente a funcionalidade modulo.

Será que é assim tão fácil? Se não acredita, faça easy_install zope.component, copie todo o código abaixo em um arquivo, e execute. Funciona mesmo. Tudo o que você precisa para ter a arquitetura de componentes mais bacana do planeta é fazer from zope import interfaces, component, criar interfaces para seus plugins, e passar a acessá-los através de getUtility.

Agora, é clar que há muito mais coisas e funcionalidades e operações interessantes que podem ser feitas com a arquitetura de componentes. Existe um novo projeto de documentação da ZCA que foi iniciado pelo Baiju Muthukadan. O livro "" que ele está escrevendo vai te dar mais detalhes.

Traduzido por LucianoRamalho com autorização do autor, Lennart Regebro.

Documento original: http://regebro.wordpress.com/2007/11/16/a-python-component-architecture/