Desde que comecei minha jornada com programação, percebi um padrão interessante: a maioria das aplicações são templates. Sim, é um fato puro! Pare aqui mesmo, no início deste artigo, e comece a pensar em todos os projetos que você desenvolveu.
O que eles têm em comum? Se você olhar com atenção, verá que muitas funcionalidades principais são reutilizadas em diferentes projetos. Essas funcionalidades principais geralmente incluem autenticação de usuário, processamento de pagamentos, gerenciamento de usuários e muito mais.
Neste artigo, gostaria de salientar que todos esses padrões já foram criados por programadores do passado. Na verdade, quase tudo que estamos usando agora já foi implementado. Apenas modificamos algumas funcionalidades com base no projeto específico.
Apresentarei exemplos da perspectiva de desenvolvimento de back-end em Python, mas isso pode ser aplicado a qualquer linguagem de programação ou qualquer campo da engenharia de software.
Então, o que todos os aplicativos de back-end têm em comum? Vamos dar uma olhada!
Nota : Se você estiver familiarizado com OOP (Programação Orientada a Objetos), considere seus módulos de modelo como o nível mais alto de abstração, mas no nível do aplicativo , para que sejam escritos de acordo com este princípio.
Gostaria de dividir cada seção adicional em componentes básicos, que podem ser aplicados a quase qualquer aplicativo de back-end.
Componentes básicos
2.1 Modelo de usuário
Estamos definindo a classe mais genérica do User
com atributos que podem ser aplicados a qualquer usuário específico.
from werkzeug.security import generate_password_hash, check_password_hash class User: def __init__(self, username, password, email): self.username = username self.password_hash = generate_password_hash(password) self.email = email self.roles = [] def set_password(self, password): self.password_hash = generate_password_hash(password) def check_password(self, password): return check_password_hash(self.password_hash, password)
2.2 Gerenciamento de Tokens
Usar JWT para autenticação baseada em token é uma boa escolha em termos de segurança cibernética e práticas recomendadas no desenvolvimento de back-end.
def generate_token(user): payload = { 'username': user.username, 'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=1) } return jwt.encode(payload, SECRET_KEY, algorithm='HS256') def verify_token(token): try: payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256']) return payload['username'] except jwt.ExpiredSignatureError: return None except jwt.InvalidTokenError: return None
2.3 Decoradores
from functools import wraps from flask import request, jsonify, session def is_authenticated(func): @wraps(func) def decorated_function(*args, **kwargs): if 'user' not in session: return jsonify({"error": "User not authenticated"}), 401 return func(*args, **kwargs) return decorated_function
def roles_required(*roles): def decorator(func): @wraps(func) def decorated_function(*args, **kwargs): user_roles = session.get('roles', []) if not any(role in user_roles for role in roles): return jsonify({"error": "User does not have the required role"}), 403 return func(*args, **kwargs) return decorated_function return decorator
E basicamente é isso! Você pode usar esta funcionalidade predefinida para autenticação em todos os projetos!
Quase todos os aplicativos lidam com transações financeiras. Quer se trate de um açougue local ou de uma grande empresa gigante, você precisará usar um sistema eficaz para receber pagamentos.
Componentes básicos
Stripe
ou PayPal
3.1 Integração do Gateway de Pagamento
Isto pode ser usado como base para integração de diferentes gateways de pagamento, com uma implementação concreta para Stripe. Geralmente, minha preferência pessoal é usar StripeAPI
para pagamentos, pois já está no mercado há muito tempo e é muito fácil de integrar em qualquer projeto.
class PaymentGateway(ABC): @abstractmethod def create_payment_intent(self, amount, currency='gbp'): pass @abstractmethod def confirm_payment(self, payment_id): pass @abstractmethod def handle_webhook(self, payload, sig_header): pass
Este é o exemplo mais genérico de gateway de pagamento, e você pode focar na implementação específica de acordo com suas necessidades.
3.2 Modelos de Pagamento
Defina modelos para armazenar informações de pagamento. Este exemplo pode ser adaptado para uso com ORM. Você pode criar uma hierarquia de classes mais complexa, se necessário, mas para este exemplo, o trecho a seguir deve ser suficiente.
class Payment: def __init__(self, user_id, amount, currency): self.id = uuid.uuid4() self.user_id = user_id self.amount = amount self.currency = currency self.status = status payments = []
Salve todos os pagamentos no banco de dados e configure uma tarefa Celery
para processamento de transações, para a seção 3.3. Os registros do banco de dados devem ser parecidos com os seguintes:
id | user_id | amount | currency | status --------------------------------------+-----------------------------------+--------+----------+---------- e532d653-7c8b-453a-8cd4-3ab956863d72 | 1ff9efb3-d5e8-4e53-854f-4246ba9ff638 | 100.00 | USD | Failed 35985d41-5d54-4021-bed6-82d7233cc353 | a0984002-bace-478e-b6f9-6e4459e1b5ba | 250.50 | EUR | Pending 1ff9efb3-d5e8-4e53-854f-4246ba9ff638 | 9f896874-dc43-4592-8289-d0f7f8b8583a | 99.99 | GBP | Completed
Agora criamos um sistema complexo que pode ser integrado a qualquer projeto. Você ainda segue o padrão? Isso pode ser usado em qualquer lugar!
Afinal, você pode definir outra aplicação para visualização desses dados. Você entendeu o que quero dizer sobre modelos! 😉
Email e notificações mantêm os usuários informados e envolvidos na vida do seu aplicativo. Seja para verificação de conta, redefinição de senha ou comunicações de marketing, um serviço de e-mail confiável é essencial para qualquer tipo de projeto.
SendGrid
ou Amazon SES
.
4.1 Integração de serviços de e-mail
Defina a lógica principal do SendGrid
para envio de emails dentro da classe EmailService
.
import sendgrid from sendgrid.helpers.mail import Mail class EmailService: def __init__(self, api_key): self.sg = sendgrid.SendGridAPIClient(api_key) def send_email(self, from_email, to_email, subject, html_content): email = Mail( from_email=from_email, to_emails=to_email, subject=subject, html_content=html_content ) try: response = self.sg.send(email) return response.status_code except Exception as e: return str(e)
Tal como acontece com o gateway de pagamento, você não precisa se concentrar em nenhum utilitário ou produto específico do mercado. Este é apenas um exemplo de como pode ser generalizado e modelado para qualquer projeto.
4.2 Modelos de e-mail
Meu padrão favorito para sistemas como esse é o padrão manipuladores; você apenas adiciona mais e mais chaves ao dicionário como um tipo de e-mail e o caminho para o arquivo com conteúdo.
email_templates = { 'welcome': “welcome.html”, 'reset_password': "<h1>Reset Your Password</h1><p>Click <a href='{link}'>here</a> to reset your password.</p>" }
Caso contrário, seria bom definir um Enum
para os mesmos fins.
4.3 Envio de e-mails
Precisamos de uma função para fazer a mágica acontecer! Vamos escrever o seguinte:
def send_email(email_service, from_email, to_email, subject, template_name, **template_vars): """ Send an email using the specified email service. """ html_content = get_email_template(template_name, **template_vars) return email_service.send_email(from_email, to_email, subject, html_content)
Outro ponto importante seria adicionar vários arquivos a todos os projetos backend, como README
.env
config.py
, pyproject.toml,
.pre-commit.yml
e criar a estrutura base dos arquivos dentro do projeto.
Embora a estrutura sugerida seja um pouco restrita à implementação do Python, como mencionei antes, você pode fazer o mesmo para qualquer outra linguagem ou campo.
Também é importante notar que a modelagem no mais alto nível de abstração e a manutenção de uma boa estrutura da aplicação podem ser
reutilizado para outros projetos como um pacote ou um acréscimo à arquitetura de microsserviços.
TUDO PODE SER MODELO!
Os exemplos fornecidos aqui são apenas o começo: esses padrões podem ser estendidos e refinados para cobrir cenários mais complexos à medida que seus projetos evoluem. Você pode adicionar caching
para estabelecer k8s
, docker
, infraestrutura Devops
, CI/CD
e pipelines.
Lembre-se de uma afirmação simples: depois de realizar seu trabalho corretamente, você poderá usar o mesmo trabalho enquanto conclui outro.
O objetivo é tornar o projeto, a infraestrutura, os componentes e os serviços reutilizáveis em diferentes aplicações!
Prepare uma xícara de chá e pense em quais partes de seus aplicativos podem ser reutilizadas em diferentes aplicativos. Tente criar serviços semelhantes e automatizar seu trabalho, ajustando apenas alguns trechos de código!
Obrigado pela leitura e bons modelos!