Lista de verificación de decisiones de arquitectura de proyectos
Utilice esta lista de verificación al iniciar o reestructurar un servicio Python para que las decisiones sobre diseño, límites y herramientas se tomen deliberadamente antes de que el código se endurezca en torno a accidentes.
Cómo usar esta lista de verificación
- Recorra los niveles en orden: las decisiones posteriores dependen de las anteriores.
- Registre cada decisión en una breve ADR o sección de README para que el equipo no vuelva a litigar los valores predeterminados.
- Vuelva a revisar después del primer despliegue en producción; las suposiciones de "greenfield" rara vez sobreviven al contacto con los usuarios.
- Trate los elementos no marcados como deuda con un propietario y una fecha objetivo, no como lagunas silenciosas.
Decisiones Fundamentales
- Fijación de la versión de ejecución: Python 3.14.0 (o el nivel de soporte de su organización) fijado en
pyproject.toml, CI e imágenes Docker.- 3.14+: servicios "greenfield", últimas características de tipado y stdlib.
- Mantenimiento 3.13: bibliotecas que deben admitir destinos de despliegue más antiguos.
- Gestor de paquetes:
uv 0.6+para archivos de bloqueo e instalaciones rápidas frente apipsimple +requirements.txt.- uv: equipos que desean entornos reproducibles y monorepos de espacio de trabajo.
- pip: scripts mínimos sin requisito de archivo de bloqueo.
- Diseño: diseño
src/frente a paquete plano en la raíz del repositorio.- Diseño src: bibliotecas y servicios probados como paquetes instalados.
- Plano: solo utilidades diminutas de un solo archivo.
- Modelo de distribución: paquete instalable frente a aplicación desplegable (o ambos).
- Paquete: biblioteca compartida consumida por múltiples servicios.
- Aplicación: despliegue único con un punto de entrada
main.
- Monorepo vs polyrepo: un repositorio con múltiples paquetes frente a un servicio por repositorio.
- Monorepo: modelos de dominio compartidos y lanzamientos coordinados.
- Polyrepo: equipos y cadencias de lanzamiento independientes.
Decisiones de Límites
- Capa de dominio: módulo(s) Python puro(s) sin importaciones de frameworks.
- Sí: las reglas de negocio de larga duración sobreviven a FastAPI/Django/Flask.
- No: scripts y notebooks desechables.
- Framework HTTP: FastAPI 0.115+, Django 5.2, o Flask 3.1.
- FastAPI: APIs asíncronas, OpenAPI-first, modelos Pydantic 2.
- Django: admin, ORM, aplicaciones web "todo incluido".
- Flask: aplicaciones WSGI mínimas y crecimiento gradual.
- Límite de persistencia: capa de repositorio/DAO frente a llamadas ORM dispersas en los manejadores.
- Repositorio: dominio comprobable sin base de datos.
- ORM directo: prototipos y herramientas internas.
- Fuente de configuración: variables de entorno +
pydantic-settingsfrente a archivos de configuración cargados en git.- Env + pydantic-settings: despliegues 12-factor en dev/stage/prod.
- Archivos: solo herramientas de desarrollo locales sin secretos.
- Manejo de secretos: almacén de secretos de plataforma frente a
.envexcluido de git.- Almacén: credenciales de producción nunca en disco en la imagen.
.env: solo máquinas de desarrollador locales.
Calidad y Herramientas
- Linter/formateador:
ruff 0.9+como la herramienta todo en uno predeterminada. - Comprobación de tipos: mypy o pyright en CI con una estrategia de trinquete (código nuevo estricto, legado gradual).
- Ejecutor de pruebas:
pytestcon fixtures colocalizadas bajotests/. - Umbral de cobertura: umbral mínimo en líneas modificadas, no un objetivo vanidoso del 100%.
- Ganchos pre-commit: formatear, lintar y comprobar tipos antes de hacer push.
- Matriz de CI: probar en Python fijado más una versión de mantenimiento (ej. 3.13).
Datos e Integración
- Pila de datos tabulares: pandas 2.2+ frente a Polars 1.x.
- pandas: el ecosistema más amplio y familiaridad con los notebooks.
- Polars: ETL crítico para el rendimiento y pipelines perezosos.
- Límite de inferencia de ML: PyTorch 2.6+ cargado en un adaptador, no dentro de entidades de dominio.
- Clientes HTTP externos: módulo cliente dedicado con tiempos de espera, reintentos y respuestas tipadas.
- Mensajería/trabajo asíncrono: tareas en segundo plano dentro del proceso frente a un trabajador de cola (Celery, ARQ, Dramatiq).
Operaciones
- Registro: logs JSON estructurados con IDs de correlación, no
printen código de biblioteca. - Endpoints de salud: liveness frente a readiness separados para los orquestadores.
- Punto de entrada del contenedor: comando explícito
python -m packageo uvicorn/gunicorn documentado. - Estrategia de migración: migraciones Alembic/Django ejecutadas como un paso de despliegue, no SQL manual.
- Observabilidad: métricas y trazas en el límite del middleware del framework, no dentro de funciones de dominio.
Aplicando la lista de verificación en orden
- Fundamentos (1-5): más difíciles de revertir: decida antes de la primera fusión.
- Límites (6-10): establece la testeabilidad y el costo de cambio de framework.
- Calidad (11-16): barato de añadir temprano, caro de adaptar.
- Datos/Ops (17-25): alinee con las habilidades del equipo y la plataforma de producción.
Preguntas Frecuentes
¿Debería un nuevo proyecto de API usar FastAPI o Django por defecto?
Elija FastAPI cuando la superficie principal sea una API JSON/HTTP con documentación OpenAPI y E/S asíncrona. Elija Django cuando necesite el ecosistema de administración, autenticación y ORM como una pila cohesiva. Cualquiera puede crecer, pero cambiar más tarde es costoso.
¿Vale la pena el diseño src para un servicio pequeño?
Sí, para cualquier cosa instalada en CI o Docker. El diseño src obliga a las pruebas a importar el paquete como lo hace producción, detectando errores de "funciona localmente porque el hack de PYTHONPATH" temprano.
¿Cuándo puedo omitir una capa de dominio dedicada?
Omítala para scripts de ~300 líneas sin una vida útil esperada más allá de un trimestre. Una vez que varios puntos finales comparten reglas, extraiga la lógica de dominio antes de que la duplicación gane.
¿Necesito tanto pandas como Polars?
Generalmente no. Elija un motor tabular principal por servicio. Use el otro solo en los límites de integración si un pipeline asociado lo requiere.
¿Dónde pertenecen los modelos Pydantic?
En los límites: DTOs de solicitud/respuesta HTTP, configuraciones y formas de API externas. Mantenga los tipos de dominio principales como dataclasses o clases simples a menos que la validación esté inherentemente enfocada en los límites.
¿Qué tan estricta debe ser la comprobación de tipos desde el primer día?
Habilite la comprobación en CI inmediatamente, pero permita anulaciones en módulos heredados. Trinquete: los archivos nuevos deben pasar reglas estrictas; ajuste la configuración global en cada sprint.
¿Deben los secretos vivir en pydantic-settings?
Las clases de configuración deben leer secretos del entorno o de un backend de secretos. Nunca confirme valores secretos; documente los nombres de variables requeridos en .env.example.
¿Monorepo o polyrepo para dos servicios relacionados?
Monorepo cuando comparten modelos y se lanzan juntos. Polyrepo cuando los equipos, SLAs y permisos de despliegue son independientes.
¿Cuál es la matriz mínima de CI para Python 3.14?
Ejecute pruebas en 3.14.0 más 3.13 si distribuye bibliotecas. Los repositorios solo de aplicaciones pueden fijar una sola versión para que coincida con las imágenes de producción.
¿Cuándo debo escribir una ADR para un elemento de la lista de verificación?
Escriba una ADR corta cuando la decisión afecte a múltiples equipos, sea difícil de revertir o sorprenda a alguien durante la revisión. Una nota de una línea en el README es suficiente para valores predeterminados obvios como "usamos ruff".
¿Cómo registro los elementos no marcados?
Agregue un problema rastreado por cada brecha: propietario, nivel de riesgo y si bloquea la producción. Revise en la planificación del sprint en lugar de dejar casillas sin marcar silenciosamente.
¿Se aplica esta lista de verificación a los notebooks y experimentos de ML?
Utilice los niveles de Fundación y Calidad. Los niveles de Límites y Ops se aplican cuando un experimento se promueve a un trabajo programado o una API.
Relacionados
- Diseño src y Estructura de Paquetes - higiene de importación después de la elección del diseño
- Configuración y Ajustes - patrones de configuración basados en entorno
- Arquitectura Limpia / Hexagonal - detalles de puertos y adaptadores
- Decisiones de Refactorización - cuándo la elección temprana incorrecta necesita corrección
- Mejores Prácticas de Arquitectura - hábitos de diseño continuos
Versiones de la pila: Esta página se escribió 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+.