Desde que comencé mi viaje con la programación, noté un patrón interesante: la mayoría de las aplicaciones están basadas en plantillas. ¡Sí, es un hecho puro! Simplemente deténte aquí, al comienzo de este artículo, y comienza a pensar en todos los proyectos que has desarrollado.
¿Qué tienen en común? Si observa detenidamente, verá que muchas funcionalidades principales se reutilizan en diferentes proyectos. Estas funcionalidades principales suelen incluir autenticación de usuarios, procesamiento de pagos, gestión de usuarios y más.
En este artículo, me gustaría señalar que todos estos patrones ya fueron creados por programadores del pasado. Realmente, casi todo lo que estamos usando ahora mismo ya estaba implementado. Simplemente modificamos algunas funciones según el proyecto específico.
Le presentaré ejemplos desde la perspectiva del desarrollo backend en Python, pero esto se puede aplicar a cualquier lenguaje de programación o cualquier campo en el ámbito de la ingeniería de software.
Entonces, ¿qué tienen en común todas las aplicaciones backend? ¡Vamos a ver!
Nota : Si está familiarizado con la programación orientada a objetos (OOP), considere sus módulos con plantilla como el nivel más alto de abstracción pero en el nivel de aplicación, por lo que debe escribirse de acuerdo con este principio.
Me gustaría dividir cada sección adicional en los componentes básicos, que se pueden aplicar a casi cualquier aplicación backend.
Componentes básicos
2.1 Modelo de usuario
Estamos definiendo la clase más genérica de User
con atributos que se pueden aplicar a cualquier usuario 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 Gestión de tokens
Usar JWT para la autenticación basada en tokens es una buena opción en términos de ciberseguridad y mejores prácticas en el desarrollo backend.
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
Y básicamente, ¡eso es todo! ¡Puede utilizar esta funcionalidad predefinida para la autenticación en todos los proyectos!
Casi cualquier aplicación maneja transacciones financieras. Ya sea una carnicería local o una gran empresa gigante, necesitará utilizar un sistema eficaz para cobrar los pagos.
Componentes básicos
Stripe
o PayPal
3.1 Integración de pasarela de pago
Esto se puede utilizar como base para integrar diferentes pasarelas de pago, con una implementación concreta para Stripe. Generalmente, mi preferencia personal es usar StripeAPI
para pagos, ya que lleva mucho tiempo en el mercado y es realmente fácil de integrar en cualquier proyecto.
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 es el ejemplo más genérico de pasarela de pago y usted puede centrarse en una implementación específica según sus necesidades.
3.2 Modelos de pago
Definir modelos para almacenar información de pago. Este ejemplo se puede adaptar para su uso con ORM. Puede crear una jerarquía de clases más compleja si es necesario, pero para este ejemplo, el siguiente fragmento debería 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 = []
Guarde todos los pagos en la base de datos y configure una tarea Celery
para procesar transacciones, para la sección 3.3. Los registros de la base de datos deberían verse como los siguientes:
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
Ahora hemos creado un sistema complejo que se puede integrar en cualquier proyecto. ¿Sigues siguiendo el patrón? ¡Esto se puede usar EN TODAS PARTES!
Después de todo, puedes definir otra aplicación para visualizar estos datos. ¡Tienes razón sobre las plantillas! 😉
El correo electrónico y las notificaciones mantienen a los usuarios informados y comprometidos con la vida de su aplicación. Ya sea para verificación de cuenta, restablecimiento de contraseña o comunicaciones de marketing, un servicio de correo electrónico confiable es esencial para cualquier tipo de proyecto.
SendGrid
o Amazon SES
.
4.1 Integración del servicio de correo electrónico
Defina la lógica principal de SendGrid
para enviar correos electrónicos dentro de la clase 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)
Al igual que con la pasarela de pago, no es necesario centrarse en ninguna utilidad o producto específico del mercado. Este es solo un ejemplo de cómo se puede generalizar y crear plantillas para cualquier proyecto.
4.2 Plantillas de correo electrónico
Mi patrón favorito para sistemas como este es el patrón de controladores; simplemente agrega más y más claves al diccionario como un tipo de correo electrónico y la ruta al archivo con un contenido.
email_templates = { 'welcome': “welcome.html”, 'reset_password': "<h1>Reset Your Password</h1><p>Click <a href='{link}'>here</a> to reset your password.</p>" }
De lo contrario, sería bueno definir una Enum
para los mismos propósitos.
4.3 Envío de correos electrónicos
¡Necesitamos una función para que la magia suceda! Escribamos lo siguiente:
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)
Otro punto importante sería agregar varios archivos a todos los proyectos backend, como README
.env
config.py
, pyproject.toml,
.pre-commit.yml
y crear la estructura base de los archivos dentro del proyecto.
Aunque la estructura sugerida se ajusta un poco a la implementación de Python, como mencioné antes, puedes hacer lo mismo con cualquier otro lenguaje o campo.
También es importante tener en cuenta que crear plantillas en el nivel más alto de abstracción y mantener una buena estructura de la aplicación puede ser
reutilizado para otros proyectos como un paquete o una adición a la arquitectura de microservicio.
¡TODO SE PUEDE PLANTAR!
Los ejemplos proporcionados aquí son solo el comienzo: estos patrones se pueden ampliar y perfeccionar para cubrir escenarios más complejos a medida que evolucionan sus proyectos. Puede agregar caching
establecer k8s
, docker
, infraestructura Devops
, CI/CD
y canalizaciones.
Recuerde una afirmación simple: una vez que haya hecho su trabajo correctamente, puede utilizar el mismo trabajo mientras realiza otro.
¡El objetivo es hacer que el proyecto, la infraestructura, los componentes y los servicios sean reutilizables en diferentes aplicaciones!
Prepárate una taza de té y piensa qué partes de tus aplicaciones se pueden reutilizar en diferentes aplicaciones. ¡Intenta crear servicios similares y automatiza tu trabajo, ajustando solo algunas partes del código!
¡Gracias por leer y felices plantillas!