Рубрики
Без рубрики

Padrões de Projeto Com Python

Difordição do Projeto Continuanto Essa Série De Posts Sobre Design Paills, Já Foi … Теги с Python, шаблонами.

Defordição Do Projeto

Continuanto Essa Série De Posts Sobre Design Design, Já Foi Mastrado Como Usar em Java е Идти EGORA VAMOS MOSTRAR COMO USAR COM PYTON TAMPÉM, VAMOS VEMO COMO PADRões de Projeeto Nos Ajudam A Ter Um Código Limpo, Reutilizável E De Fácil Manutenção E ALTRAACHõES CASO CASORIO. Então Vamos Pensar No Cenário, Temos UMA Applicação Que Vai Salvar Notas Fiscais (счеты), Nesse Caso Vamos Ter Entrada de Vários Tipos Diferentes de Notas e Precisamos Processar Diferentemente CADA NOTA, Precisamos Descobrir Então E Exputar o Tipo de Nota Está cálculo de exputar a lógica de cálculo de toxuta Em Um Bucket Ou Até Mesmo Ur Arquivo TXT Smples Salvo Na Máquina E PIM FIM CENTERBEMOS СКОРОЖНАЯ ДЕ ЧЕСТА PARA CADA NOTA SALVA O DETACTO FISCAL E O Financeiro Querem Ser Neetados Disso.

Фабрика

Esse Padrão está no grupo dos padrões criacionais e nos ajuda quando precisamos Крэр рюадос EMME Superclasse, no nosso exemplo temos um domínio que seria a nota fiscal mas não sabemos que tipo de nota seria essa, será icms icms outs outra que ainda nem doversimos e que poy vir a avarecer por alguma exigência legal ou fiscal. (NãO SEI NADA SOBRE NOTAS FISCAIS PRA DIZER SE ICMS É UMA NOTA SOZINHA MAS O Exemplo Aqui é Para entender que que notas diferentes mas Нет Fim São Todas Notas Fiscais) Отказ Então Com Essa Ideia Vamos Criar O Super Tipo OU Интерфейс OU CLASSE Abrata, Isso Vária Um Pouco de Linguagem Pra Linguagem Mas A Aqui aqui é term “Molde” Para As a Nossas Notas, Vamos Kriar Classe Счетчик :

from abc import ABC, abstractmethod

class Invoice(ABC):

    @abstractmethod
    def calculate_rate(self) -> str:
        pass

Aqui Temos A Nossa Classe Счетчик E ELA EMMA CLASSE ABTRATA COMM UM MÉTODO NãO ELIPEADO Chamado Calculate_rate Então Aqui Temos UMA CLASSE Que Nos Obriga A Ремонт Esse Método Para Quem Herdar Dela. Vamos Então Criar As Suas Filhas Que Serão как классы Сказочные моменты е Invoiceiss :

from factory.invoice import Invoice

class InvoiceIss(Invoice):
    def calculate_rate(self) -> str:
        return "Processing Iss tax"

Как duas segoem o mesmo modelo para o nosso exemplo, Pra Simplifificar Temos Classe Que Herda UMA Счетчик Então Essa Classe. É UMA Счетчик E A Alloginação Do Método Calculate_rate Отказ Então Até Aqui Temos Só o que seria a estrutura ainda nada реферат Счетчик Eque Saiba é Uma Сказочные моменты Ума Invoiceiss :

from factory.invoice import Invoice
from factory.invoice_iss import InvoiceIss
from factory.invoice_icms import InvoiceIcms

class InvoiceFactory:

    @staticmethod
    def create_invoice(name: str) -> Invoice:
        if name == "ICMS":
            return InvoiceIcms()
        else:
            return InvoiceIss()

A PAMEIRA VISTA UMA FACTORY DESSE TIPO NãO PARECE SER ALGO TãO Vantajoso E Que Não Tem Nada de Mais Com O Que Vemos No Nosso Dia-A-Dia Mas Para Esses Casos Eu Gosto de Citar o que is doxle bob a receito isso no livro Чистый код : «Solução é Inserir a Estrutura Shuta No Fundo de Uma Абстрактная фабрика e jamais deixar que alguém a veja. Фабрика Usará O Switch Para Criar Instâncias ApropriaDas Derivadas … Minha Revela Geral Para Estruturas Switch É Que São AceiTáveis Se Aparecerem apenas Uma rez, COMO Criação de objetos Polimórficos, E SE ESTAVEREM ESCONDIDIDAS, Atrás de Uma Relação de Herança de Mode Que o Resto Do Система Não Toxa Enxergá-ля. “

COMO NãO Temos Переключатель EM Python Vamos Usar A Estrutura Если/else Отказ POM FIM TEMOS COMO COMO CRIAR OS NOSSOS OBJETOS DE UMA FORMA MAIS Centralizada E Quem Chama A фабрика NãO SE PREOCUPA COM A FORMA QUE OS OBJETOS SãO Criados MAS SE PREOCUPAM SOMETE NA IDEIA DE USAR OS OBJETOS CRIADOS:

invoice_icms = "ICMS"
invoice_iss = "ISS"

invoice = InvoiceFactory.create_invoice(invoice_icms)

print(invoice.calculate_rate())

invoice = InvoiceFactory.create_invoice(invoice_iss)

print(invoice.calculate_rate())

Agora temos a nossa Счетчик Certa Sendo Construída e o Cálculo Correeto Pra Cada Tipo.

Адаптер

Agora Vamos Pensar Na Seguinte Situação, Temos o Nosso Cálculo Sendo Feito E O Processamento Acontecendo Mas Precisamos Heargar Esse Dado Em Algum Lugar, Mas Onde? Эм, Банко де Дадо, Мас Е.М. Enviz Esse Dado Em Um Sistema de Mensageria, Mas Qual? Кафка? Rabbitmq? Será que is élgo devemos nos precupar agora?

Pensando Na Ideia de AdvolationAção Tardia, OSDE ОС ДЕТАЛЬНЫЕ СЕРАО ПЕНСАНАДОС No Futuro E Que a nossa solução tem que ser pensada nogócio e nas nas tecnologias Envolvildas o Padrão Адаптер Nos Ajuda E Muito Com Isso.

IDEia Aqui é Que Eu Exponha Um Contrato DO Que Eu Preciso Que Seja Feito Esormente Será Alpeardada Solução, Vamos Cateçar A CRAR PARA Exemplififianar Melhor:

from abc import ABC
from factory.invoice import Invoice

class Repository(ABC):
    def save(self, invoice: Invoice):
        pass

    def get_one(self, identity: int) -> str:
        pass

Aqui Nós Temos a nossa Репозиторий Que Funciona Como O Nosso Contrato Talkenando Asinatura Dos Nossos Métodos SEM Axamplyação. Vamos Então Para A Aqui aqui aqui vamos SUPOR QUE PARA O NOSSO DESENVOLVEMATEMA E TESTES SOMENTE SALVANDO OS DADOS EM Им .текст É O Suficatee Para Nós, Então Criamos Assim:

from adapter.repository import Repository
from factory.invoice import Invoice

class FileSystemStorage(Repository):

    def save(self, invoice: Invoice):
        print(f"Saving with class {type(invoice). __name__ }")

    def get_one(self, identity: int) -> str:
        return f'FileSystemStorage#get_one'

Aqui é Só Um Emplo Básico Onde No Método спасти EU Exibo O Nome Da Classe Que Foi Passado E no get_one é devolvido uma string fixa, mas mesmo Essa Adverysação é Aderente Ao Contrato Do Nosso Адаптер Отказ AINDA VAMOS CRAR MAIS UMA CAMADA AQUI SO PARA EMAULE O CASO EM QUE Precisamos Fazer Alguma Proadação Pro Nosso Репозиторий :

from adapter.repository import Repository
from factory.invoice import Invoice

def save(repository: Repository, invoice: Invoice) -> None:
    print("Preparing to save")
    repository.save(invoice)

def get_one(repository: Repository, identity: int) -> str:
    print("Preparing to get from storage")
    repository.get_one(identity)

PRONTO, COM ISSO JA PODEMOS USAR O NOSSO Адаптер EA Vantagem que temos é que conseguitimos seguir o nosso desenvollomos seguir o nosso desenvolvimento sem fiacar acoplado ou preso nenhuma tecnologia, se depois da nossa entrega для определения que vão unsar o banco de dados x ou o o trabalho que temos é clase outra classe que que use resse banco de Dados Mas que реализация носа Репозиторий E COM ISSO FICA TRASSPARENTE PRA QUEM USA ESSES DECHALHSES DE AIMLIESACãA, AQUI ABAIXO SEGE UM EMPELLO CASO USSSE UM BANCO DE DADOS:

from adapter.repository import Repository
from factory.invoice import Invoice

class Database(Repository):

    def save(self, invoice: Invoice):
        print(f"Loading specifics configs for the Database X")
        print(f"Saving with class {type(invoice). __name__ }")

    def get_one(self, identity: int) -> str:
        print(f"Loading specifics configs for the Database X")
        return f'Database#get_one'

E A Utilização Do Nosso Адаптер :

repository = Database()

save(repository, invoice)

get_one(repository, 1)

repository = FileSystemStorage()

save(repository, invoice)

get_one(repository, 1)

Наблюдатель

AGORA JA PODEMOS КУРАБР АС NOSSAS СЧЕТЫ Occentendo Da Sua Entrada E Conseguimos Salvar SEM NOS Precupar COM ОС DEMALHS DE AIMINGASAS MAS AINDA FALTA O úLTIMO REQUISITO que é EnviR Para OS DEATADEDOS Interessados a Neetação de que Salvamos As СЧЕТЫ Отказ PodeMos Ao Fim de Cada Método Сохранить Fazer Algo Como:

sendEmail("dpt_financial")
sendEmail("dpt_fiscal")

E ISSO VAI FUNCIONAR MAS VAMOS PENSAR QUE DRENTOU MAIS UM DETATEADO INTERESSADO NA CRIAçãO DE Счета OU ENTãO MUDOU REVERA E AGORA CADA PESSOA DESSES EALLADESESOS IRãAS CHEENBER E SãO 50 PESSOAS EM CADA SATETADETO.

Vamos FiCar Enthrando Semper No Código E Aumentar O Método Ou Fazer UM для EMMA LISTA de Emails Ou Departamentos? E SE Tivesse Como Eu Me Increver Como Interessado Nesse Assunto E Toda Vez Que ЕС Им Сохранить Ocorerer ЕС Seja Notificado? Acredito que Seria Mais Smple Até Mesmo Caso Onde Eu Não Queira Mais Casher Onde Eu Não Queira Mais Main Me Desinscrever Nesse Assunto SEM Nenhuma.

Esse Seria O Padrão Наблюдатель Onde Eu Crio Crio Em Objeto Que Fica Lebalmente LuceAndo E Получение уверенности NoS Nos Assuntos Que Eu Me Inscrevi.

Então Vamos Crysar Criando A Nossa Classe Наблюдатель Que Vai Ser Repestyável POR КРИРПРАМЕНТ ДИДО ОС ОСУЩЕСТВЕННОСТИ E TEM TEM O MÉTODO QUE DIZ O QUE DEVE ACONTECER QUANDO UMA NETIFISACãO для ENVIADA:

class EmailObserver:

    def __init__ (self, email):
        self.__email = email

    def update(self, invoice):
        print(f'For {self.__email}, send report about {invoice}')

AQUI SO TEMOS O NOSSO INALIZADOR QUE REEACE BEA EMACT E O MÉTODO Обновление que получают Счетчик Para Montar Mensagem. EGORA VAMOS КРИАР О НОСО Тема que представление o nosso assunto a ser inscrito e que contém os métodos para se inscrever, desinscrever e neetifistar:

class EmailSubject:

    def __init__ (self):
        self.__subscribers = []

    def add_email(self, subject):
        self.notify_subscribers(subject)

    def subscribe(self, subscriber):
        self.__subscribers.append(subscriber)

    def unsubscribe(self, subscriber):
        return self.__subscribers.remove(subscriber)

    def subscribers(self):
        return self.__subscribers

    def notify_subscribers(self, subject):
        for sub in self.__subscribers:
            sub.update(subject)

O Estado Interno Dessa Classe Contém Array de Подписчики Onde EU ADICONO UM NOVO OU REMOVO COM OS MÉTODOS Подписаться e Отписаться E O Método Para Notifitar Todos Os Inscritos Com notify_subscribers Отказ E Para Fazer Uso Dele Podemos Fazer O Seguinte:

fiscal = EmailObserver("dept_fiscal")
financial = EmailObserver("dept_financial")
subject.subscribe(fiscal)
subject.subscribe(financial)
subject.add_email("ICMS")

E COM ISSO Temos o Ganho de Inscrever Somente Uma Vez e Toda Vez que o add_email Для invocado Irá Notifearar Ados.

Projeto Complete

Segue Abaixo o Projeto Cellio E O Projeto нет Github :

from adapter.database import Database
from adapter.file_system_storage import FileSystemStorage
from adapter.adapter import save, get_one
from factory.factory import InvoiceFactory
from observer.email_observer import EmailObserver
from observer.email_subject import EmailSubject

invoice_icms = "ICMS"
invoice_iss = "ISS"

subject = EmailSubject()
fiscal = EmailObserver("dept_fiscal")
financial = EmailObserver("dept_financial")
subject.subscribe(fiscal)
subject.subscribe(financial)

invoice = InvoiceFactory.create_invoice(invoice_icms)

print(invoice.calculate_rate())

repository = Database()

save(repository, invoice)

subject.add_email(type(invoice). __name__ )

get_one(repository, 1)

invoice = InvoiceFactory.create_invoice(invoice_iss)

print(invoice.calculate_rate())

repository = FileSystemStorage()

save(repository, invoice)

subject.add_email(type(invoice). __name__ )

get_one(repository, 1)

Оригинал: “https://dev.to/guilhermegarcia86/padroes-de-projeto-com-python-62f”