Skip to content

Instantly share code, notes, and snippets.

@alexandre
Last active August 29, 2015 14:26
Show Gist options
  • Select an option

  • Save alexandre/5bed42f22a639559fe14 to your computer and use it in GitHub Desktop.

Select an option

Save alexandre/5bed42f22a639559fe14 to your computer and use it in GitHub Desktop.
misturando strategy e herança.
"""
Vamos supor que temos um numero X de clientes e cada cliente tem 2 tipos de
fechamento diferentes: fechamento parcial e fechamento geral.
Além disso, cada cliente tem um padrão para esses arquivos (cada fechamento gera um), já que esses
arquivos serão utilizados em um sistema de terceiros.
A principio, eu pensei que apenas o pattern strategy solucionava o problema...
de acordo com o cliente eu devolvia uma classe especifica que geraria o
arquivo. Mas o problema é que eu esqueci que haviam 2 tipos de fechamento.
Com isso, eu pensei em utilizar herança. Por que? porque o processo básico
para chamar os arquivos de fechamento (indiferente do tipo) é o mesmo.
No final ficaria algo como:
>>> import exporters
>>> customer = Customer()
>>> exporters.ExporterA(customer=customer.name)
>>> exporter.generate_file()
>>> # o mesmo para o segundo tipo
>>> exporters.ExporterB(customer=customer.name)
>>> exporter.generate_file()
Obs.: Supondo que o meu entendimento do pattern strategy está correto. =]
"""
import collections
class Exporter():
@property
def default_exporter(self):
raise NotImplementedError('Should have implemented this')
@property
def available_exporters(self):
raise NotImplementedError('Should have implemented this')
def __new__(cls, *args, **kwargs):
if 'customer' not in kwargs.keys():
raise RuntimeError('You have to inform a customer name')
exporter_type = super(Exporter, cls).__new__(cls)
exporter = collections.defaultdict(
lambda: exporter_type.default_exporter, exporter_type.available_exporters)
return exporter[kwargs['customer']](*args, **kwargs)
class ExporterA(Exporter):
@property
def default_exporter(self):
return default_exporter_a
@property
def available_exporters(self):
return {
'Customer_foo': exporter_a_customer_foo,
'Customer_bar': exporter_a_customer_bar,
'Customer_ble': exporter_a_customer_ble,
}
class ExporterB(Exporter):
@property
def default_exporter(self):
return default_exporter_b
@property
def available_exporters(self):
return {
'Customer_foo': exporter_b_customer_foo,
'Customer_bar': exporter_b_customer_bar,
'Customer_ble': exporter_b_customer_ble,
}
@alexandre

Copy link
Copy Markdown
Author

Diego,

Deve existir um gap mesmo. =]
Mas a minha dúvida e também o motivo de usar herança é que além de ter o exporter diferente (A e B), cada cliente tem uma variação do A e uma variação do B. (available_exporters)

Eu poderia usar apenas 1 função com um dict para recuperar a variação(e.g. recuperar a variação do exporter A para o cliente foo) e passar isso para o exporter (da mesma forma que vc explicou a estratégia concreta). Faz sentido?

@alexandre

Copy link
Copy Markdown
Author

Eu acho que agora eu consegui entender melhor... eu não preciso de uma classe para cada tipo de exporter mesmo. Eu vou separar essa parte de recuperar a "variação" e simplesmente passar ela para o "closer".

@drgarcia1986

Copy link
Copy Markdown

Isso ai :)
Talvez suas estratégias sejam as "variações".

@alexandre

Copy link
Copy Markdown
Author

@drgarcia1986 e @daniloakamine-luizalabs

Apenas um rascunho mental enquanto eu não paro para ler...

# module exporters.py
import collections

EXPORTERS_A = collections.defaultdict(
     lambda: default_a_exporter,
     {
         'Customer_foo': exporter_a_customer_foo,
         'Customer_bar': exporter_a_customer_bar,
         'Customer_ble': exporter_a_customer_ble,
     }
)

EXPORTERS_B = collections.defaultdict(
     lambda: default_b_exporter,
     {
         'Customer_foo': exporter_b_customer_foo,
         'Customer_bar': exporter_b_customer_bar,
         'Customer_ble': exporter_b_customer_ble,
     }
)

class Closer:
    def __init__(self, exporter):
        self.exporter = exporter

    def generate_file(self, *args, **kwargs):
         return self.exporter.generate_file(*args, **kwargs)
customer = Customer()

# mesmo processo para o EXPORTERS_A e o EXPORTERS_B

exporter = exporters.EXPORTER_A[customer.name]()
closer = exporters.Closer(exporter)
closer.generate_file('xyz') # ... segue a vida

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment