Buenas Prácticas de Arquitectura
Reglas permanentes para servicios de Python que se mantienen testeables, desplegables y comprensibles a medida que cambian los frameworks y los equipos.
Cómo Usar Esta Lista
- Trata los elementos no marcados como hallazgos de revisión en PRs y documentos de diseño.
- Prefiere reglas aplicables (CI, lint, ADR) sobre acuerdos informales.
- Revisa cuando agregues un nuevo punto de entrada (API, worker, CLI) o almacén de datos.
A - Límites
- Mantén la lógica de dominio libre de importaciones de FastAPI, Django, Flask, boto3 y pandas. Las reglas de negocio deben compilar y probarse sin frameworks de IO.
- Mapea las formas de HTTP/ORM a tipos de dominio en el borde. Los DTOs de Pydantic 2 pertenecen a los adaptadores, no a los constructores de entidades utilizados por los workers.
- Define puertos con
Protocolpara dependencias externas. Los repositorios, relojes y notificadores obtienen interfaces explícitas. - Usa una única raíz de composición por desplegable.
main,lifespanobuild_container()conectan adaptadores concretos, no globales dispersos.
B - Empaquetado e Importaciones
- Adopta la estructura
srcpara servicios instalables. CI ejecutauv syncopip install -e .antes de las pruebas. - Prohibir trucos de
PYTHONPATH=.en flujos de trabajo de desarrollo documentados. Si las importaciones lo necesitan, los metadatos de empaquetado son incorrectos. - Rompe ciclos de importación extrayendo módulos de tipos hoja. Las importaciones perezosas son un puente temporal, no arquitectura.
- Expón una API pública estrecha a través de
__all__o exportaciones de paquetes documentadas. Los módulos internos permanecen refactorizables.
C - Configuración y Seguridad
- Carga la configuración a través de
pydantic-settingstipado una vez por proceso. No usesos.getenvsin formato en módulos de negocio. - Almacena secretos solo en el entorno o en el gestor de secretos.
.env.examplelista los nombres, nunca los valores. - Valida valores predeterminados peligrosos al inicio. Los valores de marcador de posición
SECRET_KEYdeben fallar rápidamente en la configuración de producción. - Establece tiempos de espera y reintentos del cliente HTTP en los módulos adaptadores. Las llamadas de red ilimitadas son deuda operativa.
D - Modelado de Datos y Dominio
- Modela dinero, cantidades e IDs como objetos de valor. Evita primitivas paralelas que divergen.
- Protege las transiciones de entidades con métodos (
place(),cancel()). La mutación de atributos públicos omite invariantes. - Mantén pandas 2.2+ y Polars 1.x en adaptadores ETL. Las funciones de dominio aceptan colecciones de Python simples.
- Aísla la carga/inferencia de PyTorch 2.6+ detrás de puertos. Importar torch en el momento de la importación del dominio ralentiza las pruebas y los workers.
E - Puertas de Calidad
- Ejecuta el formato y lint de ruff 0.9+ en CI. Los debates de estilo pertenecen a la configuración, no a los hilos de revisión.
- Ajusta los tipos estáticos en los archivos modificados. Los nuevos módulos cumplen reglas de mypy/pyright más estrictas que los heredados.
- Prueba unitariamente los casos de uso con adaptadores falsos. Las pruebas de integración son un nivel separado y delgado.
- Documenta las decisiones irreversibles en ADRs. El diseño, el framework y las opciones de almacén de datos necesitan un rastro de papel.
F - Operaciones y Evolución
- Emite logs estructurados con IDs de correlación en el middleware HTTP. La depuración con
printno escala a producción. - Separa las comprobaciones de estado de "liveness" y "readiness". Los orquestadores necesitan señales distintas.
- Ejecuta las migraciones de base de datos como un paso de despliegue automatizado. El SQL manual es una pesadilla para revertir.
- Prefiere migraciones "strangler" sobre reescrituras "big-bang". Entrega rebanadas verticales con pruebas de caracterización.
Preguntas Frecuentes
¿Qué tan estrictas deben ser las reglas de límites para los scripts?
Los scripts de unos pocos cientos de líneas pueden coexistir con la lógica y la E/S. Promuévelos a paquetes con límites cuando aparezca un segundo punto de entrada o el script sobreviva un trimestre.
¿Todos los servicios necesitan carpetas hexagonales?
No. Necesitas una dirección de dependencia clara. Los nombres de las carpetas importan menos que "el dominio no importa FastAPI".
¿Cuándo es aceptable un singleton global de configuración?
Cuando se accede solo desde las raíces de composición y los adaptadores. Los casos de uso reciben valores o protocolos, no from app.settings import settings.
¿Debe cada PR actualizar esta lista?
Úsala en la revisión de diseño y auditorías trimestrales. Los PRs diarios hacen referencia a reglas específicas ("se agregó importación de dominio - rechazado") en lugar de ejecutar la lista completa.
¿Cómo interactúan las mejores prácticas con Django?
Los proyectos de Django aún se benefician de puertos para E/S externa y configuración tipada. Los modelos ORM pueden permanecer "gordos" para CRUD intensivo de administración; agrega mapeo cuando las reglas se multipliquen.
¿Cuál es el conjunto mínimo de fakes de prueba?
Los repositorios en memoria y los notificadores/mailers de registro cubren la mayoría de los casos de uso. Agrega pruebas de contrato cuando el SQL del adaptador sea complejo.
¿Cómo puedo forzar los límites de importación automáticamente?
Herramientas como import-linter o reglas personalizadas de ruff pueden prohibir que domain importe adapters. Conéctalo a CI después de que las convenciones se estabilicen.
¿Se requieren microservicios para una buena arquitectura?
No. Un monolito bien delimitado con módulos claros a menudo supera la dispersión distribuida. Divide por desencadenantes de equipo o escala, no por moda.
¿Con qué frecuencia se deben escribir los ADRs?
Para decisiones costosas de revertir: almacén de datos, modelo de autenticación, bus de eventos, framework principal. Omite los ADRs para selecciones de herramientas obvias como ruff.
¿Pueden la configuración de Pydantic servir como validación de dominio?
La configuración valida el entorno. El dominio valida las reglas de negocio. La superposición es rara: mantén las capas separadas.
¿Qué pasa con los notebooks que exploran la arquitectura?
Los notebooks son desechables o candidatos a promoción. No permitas que las importaciones experimentales se conviertan en límites de producción de facto sin empaquetado.
¿Cómo encaja uv en la práctica de arquitectura?
Los archivos de bloqueo de uv 0.6+ hacen que CI y Docker reproduzcan el mismo grafo de dependencias, una base para el diseño evolutivo.
Relacionado
- Lista de Decisiones de Arquitectura de Proyecto - decisiones iniciales
- Arquitectura Limpia / Hexagonal - detalle del patrón de límites
- Lista de Auditoría de Código - verifica que las prácticas se mantengan
- Decisiones de Refactorización - corrige violaciones
- Configuración y Ajustes - inmersión profunda en las mejores prácticas de configuración
Versiones de Stack: Esta página fue escrita para Python 3.14.0 (estable 3.14, mantenimiento 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+ y uv 0.6+.