Feedback Integracion de aplicaciones v006

Equipo 001

Buenas Prácticas de Desarrollo

  1. Estructura del proyecto: Organiza el código en módulos claros y separados por funcionalidad.
  2. Comentarios y documentación: Incluye comentarios en el código y documentación detallada para facilitar la comprensión y el mantenimiento.

Variables de Entorno

  1. Gestión segura: Utiliza archivos .env para almacenar variables de entorno sensibles, como claves de API y credenciales, y agrégalo al .gitignore.
  2. Configuración por entorno: Crea diferentes archivos de configuración para desarrollo, pruebas y producción.

Seguridad

  1. Autenticación y autorización: Implementa sistemas robustos de autenticación y autorización para proteger los recursos. Falta un nivel extra para definir el uso de roles.
  2. Validación de entradas: Valida todas las entradas del usuario para prevenir ataques como la inyección SQL y XSS.
  3. Manejo de errores: No reveles detalles del sistema en los mensajes de error. Usa un manejo centralizado de excepciones.

Diseño de Servicios Web

  1. APIs RESTful: Asegúrate de que las APIs sigan los principios REST para que sean consistentes y fáciles de usar.
  2. Documentación de APIs: Utiliza herramientas como Swagger para documentar las APIs.

Patrones de Diseño

  1. MVC (Model-View-Controller): Aplica este patrón para separar la lógica de negocio, la presentación y la gestión de datos. Minimal Flask Application using MVC Design Pattern
  2. Singleton: Utiliza el patrón Singleton para gestionar recursos compartidos, como la conexión a la base de datos. Revisar ejemplo mas abajo.

Gestión con la Base de Datos

  1. ORM (Object-Relational Mapping): Ver detalle mas abajo del porque no implementaron bien el ORM
  2. Migrations: Implementa un sistema de migraciones para gestionar los cambios en el esquema de la base de datos de manera controlada y reproducible.

Problemas Identificados

  1. Conexión Directa en el Código: No encontré un archivo explícito que configure la conexión a la base de datos usando SQLAlchemy, lo cual es crucial para una buena práctica. La configuración de la conexión debería estar en un archivo de configuración separado y usar variables de entorno para proteger la información sensible como las credenciales de la base de datos.

  2. Falta de Manejo de Sesiones: Es crucial manejar las sesiones correctamente cuando se trabaja con SQLAlchemy. No se debe abrir una sesión globalmente y dejarla abierta indefinidamente. Cada transacción debe manejarse en su propia sesión, y debe asegurarse de cerrarlas o revertirlas adecuadamente para evitar bloqueos de base de datos y asegurar la integridad de los datos.

  3. Manejo Incorrecto de Objetos del Modelo: Es importante definir y usar los modelos de SQLAlchemy correctamente. Todos los modelos deberían heredar de Base, que se crea usando declarative_base(). Además, cada transacción debe asegurarse de usar estos modelos en lugar de realizar operaciones directas en las tablas.

Equipo 002

Estructura del Proyecto

  • Excluir el entorno virtual: (myenv) del control de versiones. Añadirlo al archivo .gitignore.
  • Asegurarse de que todos los módulos de la aplicación estén bien organizados dentro de la carpeta flaskapp. Referencia ejemplo: Minimal Flask Application using MVC Design Pattern
  • requirements.txt: Super bien que lo incluyeran.

Uso de Flask

Asumiendo que la aplicación está basada en Flask, aquí hay algunas buenas prácticas:

Buenas prácticas:

  • Blueprints: Utilizar Blueprints para modularizar la aplicación.
  • Configuraciones: Separar configuraciones para desarrollo, pruebas y producción.
  • Validación de datos: Utilizar bibliotecas como Flask-WTF o Marshmallow para validar y serializar datos.
  • Gestión de errores: Implementar un manejo centralizado de errores y respuestas JSON consistentes. Ejemplos: Manejar posibles errores como duplicados de email o datos faltantes.

Diseño de Servicios Web

El diseño sigue principios RESTful con métodos HTTP adecuados. Se recomienda implementar paginación, filtros, y versionado de API, así como mejorar la validación de datos y el manejo centralizado de errores.

  • Es crucial manejar los errores de manera adecuada y devolver códigos de estado HTTP significativos (404, 500, etc.). El proyecto debería asegurarse de tener un manejo de errores robusto.
  • El diseño del servicio parece seguir principios RESTful, utilizando métodos HTTP apropiados (GET, POST, PUT, DELETE) para interactuar con los recursos. Esto es esencial para la interoperabilidad y la escalabilidad del servicio.
  • Implementar el versionado de API (por ejemplo, /api/v1/) es una buena práctica para manejar actualizaciones y cambios en la API sin afectar a los clientes existentes.
  • Utilizar bibliotecas como Marshmallow o Flask-WTF para validar datos de entrada y evitar errores.

Base de Datos

Utiliza SQLAlchemy como ORM, lo cual es adecuado. Debería enfocarse en la normalización, creación de índices, y manejo de transacciones. La seguridad de datos es crucial, con validación y sanitización de entradas.

  • Utiliza migraciones para gestionar cambios en la estructura de la base de datos. Herramientas como Flask-Migrate pueden ser útiles para este propósito.
  • Utiliza SQLAlchemy como ORM, lo cual es una buena práctica para abstraer la lógica de la base de datos y facilitar el trabajo con objetos Python.
  • Crear índices en columnas que se utilicen frecuentemente en consultas para mejorar el rendimiento.
  • Utilizar transacciones para operaciones que modifiquen múltiples registros, asegurando así que las operaciones sean atómicas.
  • Asegurarse de que todos los datos recibidos sean validados y sanitizados para prevenir inyecciones SQL.
  • Implementar controles de acceso adecuados para proteger los datos sensibles y asegurar que solo usuarios autorizados puedan realizar modificaciones.

Seguridad y Dependencias

Buenas prácticas de seguridad:

  • Variables de entorno: No almacenar configuraciones sensibles (como claves secretas) directamente en el código, sino en variables de entorno.
  • CORS: Configurar adecuadamente CORS si la API será consumida desde diferentes dominios.
  • Autenticación y Autorización: Utilizar métodos seguros para la autenticación y autorización (JWT, OAuth).

Revisión de código

  • Variables y Funciones: Usar nombres descriptivos y seguir la convención de nombres de PEP 8.
  • Documentación: Asegurarse de que todas las funciones y módulos tengan docstrings explicativos.
  • Manejo de Excepciones: Usar bloques try-except adecuadamente para manejar excepciones.

Archivos adicionales

  • README.md: Proveer una documentación clara sobre cómo configurar y ejecutar el proyecto.
  • .gitignore: Asegurarse de que los archivos y directorios que no deben ser versionados estén incluidos aquí.

Equipo 003

1. Diseño de Servicios Web

Antipatrón: Servicio Monolítico

  • Descripción: Todos los servicios están agrupados en un solo módulo, lo que dificulta la escalabilidad y mantenimiento.
  • Ejemplo: En lugar de tener servicios separados para Carrito, Ferretera, y Login, están integrados en un solo módulo.
  • Solución: Adoptar una arquitectura de microservicios donde cada funcionalidad esté separada en diferentes servicios independientes.
# Monolithic approach
class FerreteriaService:
    def __init__(self):
        self.carrito = CarritoService()
        self.login = LoginService()

# Microservices approach
class CarritoService:
    pass

class LoginService:
    pass

2. Buenas Prácticas de Código

Antipatrón: Código Repetido

  • Descripción: Múltiples secciones del código realizan la misma lógica, aumentando el riesgo de errores y dificultando el mantenimiento.
  • Ejemplo: Funciones de validación de usuarios duplicadas en Login y Ferretera.
  • Solución: Crear funciones reutilizables y centralizar la lógica común.

3. Manejo de Errores

Antipatrón: Errores Silenciosos

  • Descripción: Errores son capturados y suprimidos sin informar al usuario o registrar los detalles para análisis futuro.
  • Ejemplo: Uso de try/except sin un manejo adecuado del error.
  • Solución: Implementar un sistema de logging y manejo de excepciones informativo.

4. Seguridad

Antipatrón: Credenciales en el Código

  • Descripción: Las credenciales de base de datos o API keys están hardcodeadas en el código fuente.
  • Ejemplo: Usuario y contraseña de la base de datos están visibles en el archivo api_ferreteria.sql.
  • Solución: Utilizar variables de entorno para manejar credenciales sensibles.

5. Base de datos

  • ORM: SQL en duro. Deben utilizar las soluciones disponibles para manejar correctamente la conexion e interaccion con la DB.

6. Patrones de Diseño

  1. MVC (Model-View-Controller): Aplica este patrón para separar la lógica de negocio, la presentación y la gestión de datos. Minimal Flask Application using MVC Design Pattern
  2. Singleton: Utiliza el patrón Singleton para gestionar recursos compartidos, como la conexión a la base de datos. Revisar ejemplo mas abajo.

Equipo 004

1. Diseño de Servicios Web

Antipatrones:

  • Acoplamiento excesivo: El código muestra un fuerte acoplamiento entre las capas, lo que dificulta la separación de responsabilidades y la escalabilidad. Un mejor diseño implicaría una arquitectura más modular y desacoplada.
  • Falta de RESTful: Los endpoints podrían no seguir las convenciones REST, lo que complica la comprensión y el uso de la API. Es importante usar verbos HTTP correctamente y estructurar las URLs de manera intuitiva.

2. Buenas Prácticas de Código

Antipatrones:

  • Código repetido: Se puede observar código duplicado en varias partes del proyecto. La refactorización para crear funciones reutilizables mejoraría la mantenibilidad.
  • Nombres de variables y funciones no descriptivos: Usar nombres que no describen claramente su propósito dificulta la lectura y el mantenimiento del código.

3. Patrones de Diseño

Antipatrones:

  • God Object: Algunas clases parecen tener demasiadas responsabilidades, centralizando mucha lógica. Esto va en contra del principio de responsabilidad única. Dividir estas clases en componentes más pequeños y específicos ayudaría a mejorar la estructura.
  • Singleton abusivo: El uso excesivo del patrón Singleton puede llevar a un estado global no controlado y dificultar las pruebas unitarias. Solucion es Inyeccion de dependencia.

Lista de archivos con instancias new Conexiones() ./WSIntegracionPlataformas.DAL/Implementacion/ProductosImpl.cs: using (var db = new Conexiones()) ./WSIntegracionPlataformas.DAL/Implementacion/ProductosImpl.cs: using (var db = new Conexiones()) ./WSIntegracionPlataformas.DAL/Implementacion/ProductosImpl.cs: using (var db = new Conexiones()) ./WSIntegracionPlataformas.DAL/Implementacion/ProductosImpl.cs: using (var db = new Conexiones()) ./WSIntegracionPlataformas.DAL/Implementacion/ProductosImpl.cs: using (var db = new Conexiones()) ./WSIntegracionPlataformas.DAL/Implementacion/ProductosImpl.cs: using (var db = new Conexiones()) ./WSIntegracionPlataformas.DAL/Implementacion/ProductosImpl.cs: using (var db = new Conexiones()) ./WSIntegracionPlataformas.DAL/Implementacion/ProductosImpl.cs: using (var db = new Conexiones()) ./WSIntegracionPlataformas.DAL/Implementacion/ProductosImpl.cs: using (var db = new Conexiones()) ./WSIntegracionPlataformas.DAL/Implementacion/ProductosImpl.cs: using (var db = new Conexiones()) ./WSIntegracionPlataformas.DAL/Implementacion/ProductosImpl.cs: using (var db = new Conexiones()) ./WSIntegracionPlataformas.DAL/Implementacion/ProductosImpl.cs: using (var db = new Conexiones()) ./WSIntegracionPlataformas.DAL/Implementacion/UserImpl.cs: using (var db = new Conexiones())

4. Seguridad

Antipatrones:

  • Configuraciones sensibles en el código: Información sensible como credenciales de base de datos o claves API deben manejarse a través de variables de entorno y no estar hardcodeadas en el repositorio.
  • Falta de validación de entrada: No validar adecuadamente la entrada del usuario puede llevar a vulnerabilidades como SQL Injection o XSS. Es crucial implementar validaciones y sanitización de inputs.

5. Manejo de Errores

Antipatrones:

  • Captura genérica de excepciones: Usar bloques catch genéricos (catch (Exception ex)) sin diferenciar el tipo de excepción puede esconder errores críticos y dificultar el debugging. Es mejor capturar excepciones específicas y manejar cada caso adecuadamente.
  • Mensajes de error poco informativos: Proveer mensajes de error claros y específicos es vital para el diagnóstico y la resolución de problemas.

6. Base de Datos

Antipatrones:

  • Consultas SQL en el código: Incluir consultas SQL directamente en el código de la lógica de negocio es una mala práctica. Es preferible usar ORM (Object-Relational Mapping) para abstraer las interacciones con la base de datos. En su caso es la referencia directa a los procedimientos de almacenado.
  • Falta de transacciones: No manejar transacciones en operaciones críticas puede llevar a inconsistencias en la base de datos. Es importante asegurarse de que todas las operaciones relacionadas se completen exitosamente o ninguna se aplique.

Equipo 005

1. Diseño de Servicios Web

Antipatrones Identificados:

  1. API sin versionar: No se observa una estructura de versionamiento en las rutas de las APIs.
  2. Endpoints monolíticos: Algunos endpoints manejan múltiples responsabilidades.
  3. Falta de documentación: No hay documentación clara sobre los endpoints y sus usos.

2. Buenas Prácticas de Código

Antipatrones Identificados:

  1. Nombres de variables no descriptivos: Variables con nombres poco descriptivos.
  2. Código comentado en exceso: Comentarios excesivos y redundantes.
  3. Funciones largas y complejas: Algunas funciones superan las 50 líneas de código.

3. Patrones de Diseño

Antipatrones Identificados:

  1. Uso inapropiado del Singleton: Uso incorrecto del patrón Singleton.
  2. Falta de patrones MVC: No se observa una clara separación entre lógica de negocios, presentación y acceso a datos.
  3. Acoplamiento excesivo: Clases y módulos demasiado acoplados.

4. Seguridad

Antipatrones Identificados:

  1. Manejo inseguro de contraseñas: No se implementa hashing para las contraseñas.
  2. Validación insuficiente de entradas: Falta de sanitización y validación adecuada de entradas del usuario.
  3. Exposición de información sensible: Información sensible expuesta en el código fuente.

5. Manejo de Errores

Antipatrones Identificados:

  1. Errores silenciados: Bloques try-except que silencian los errores sin loguearlos.
  2. Mensajes de error genéricos: Mensajes de error que no proporcionan suficiente información.
  3. Falta de manejo de excepciones específicas: Uso de except Exception sin capturar excepciones específicas.

6. Base de Datos

Antipatrones Identificados:

  1. Consultas SQL en el código: Consultas SQL incrustadas directamente en el código. Implementacion de ORM
  2. Falta de índices: No se mencionan índices en las tablas de base de datos.
  3. Conexiones no gestionadas: Conexiones a la base de datos no gestionadas adecuadamente.

Equipo 006

1. Diseño de Servicios Web

  • Acoplamiento Fuerte: Componentes altamente acoplados dificultan mantenimiento y escalabilidad.

2. Buenas Prácticas de Código

  • Código Repetido: Lógica duplicada puede llevar a inconsistencias.
  • Falta de Documentación: Ausencia de comentarios y documentación clara.

3. Seguridad

  • Inyección de SQL: Consultas SQL no parametrizadas son vulnerables.
  • Exposición de Credenciales: Información sensible en settings.py sin protección adecuada.

4. Manejo de Errores

  • Captura General de Excepciones: Cláusulas try-except generales ocultan errores.
  • Falta de Logueo: Sin logueo adecuado, difícil rastrear errores.

Equipo 007

1. Diseño de Servicios Web

Antipatrones:

  • Endpoint Bloat: Exceso de endpoints para operaciones específicas, complicando la mantenibilidad y escalabilidad.
  • Falta de versionado: Ausencia de versionado en los endpoints, dificultando actualizaciones y compatibilidad.
  • Uso incorrecto de verbos HTTP: Métodos HTTP inapropiados (GET, POST, PUT, DELETE) para las acciones realizadas.

2. Buenas Prácticas de Código

Antipatrones:

  • Código duplicado: Repetición de lógica en diferentes partes en lugar de funciones reutilizables.
  • Falta de comentarios: Ausencia de comentarios explicativos en el código.
  • Funciones largas: Funciones que realizan demasiadas acciones, dificultando su entendimiento y mantenimiento.

3. Patrones de Diseño

Antipatrones:

  • No usar patrones de diseño: Falta de uso de patrones como Singleton, Factory o Decorator.
  • God Object: Clases con demasiadas responsabilidades, violando el principio de responsabilidad única. Ej Fn: ObtainTokenView
  • Spaghetti Code: Lógica entrelazada y difícil de seguir, sin separación clara de responsabilidades.

4. Seguridad

Antipatrones:

  • Falta de validación de entrada: Datos de entrada no validados adecuadamente, susceptible a inyecciones SQL o XSS.
  • Manejo de contraseñas inseguro: Contraseñas en texto plano en lugar de usar técnicas de hash seguro.
  • No uso de HTTPS: Tráfico no cifrado, vulnerable a ataques de interceptación.

5. Manejo de Errores

Antipatrones:

  • Errores silenciosos: Capturar excepciones sin realizar ninguna acción o registro.
  • Falta de manejo de errores específicos: Excepciones genéricas que no brindan información útil.
  • Mensajes de error ambiguos: Mensajes de error poco informativos.

6. Base de Datos

Antipatrones:

  • Consultas N+1: Múltiples consultas en lugar de optimización con joins. Ejemplo funcion PedidoDetailView con:
# Linea original
detalles_pedido = DetallePedido.objects.filter(pedido=instance)
# propuesta
detalles_pedido = DetallePedido.objects.filter(pedido=instance).select_related('producto')
  • Falta de índices: No uso de índices en columnas frecuentemente consultadas.
  • Dependencia fuerte de la base de datos: Lógica de negocio en procedimientos almacenados en lugar de en la aplicación.

Equipo 008

SIN PROYECTO

Ejemplos FLASK

Como se deberia ver SQLAclvhemy como ORM

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

class Usuario(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    nombre = db.Column(db.String(80), nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)

# Suponiendo que ya tienes una instancia de Flask y SQLAlchemy configurada
from your_application import db, Usuario

# Realizando una consulta para obtener todos los usuarios
usuarios = Usuario.query.all()

# Imprimiendo los usuarios obtenidos
for usuario in usuarios:
    print(f"ID: {usuario.id}, Nombre: {usuario.nombre}, Email: {usuario.email}")

Ejemplos Buenas practicas de codigo

Antipatrón: Credenciales en el Código

  • Descripción: Las credenciales de base de datos o API keys están hardcodeadas en el código fuente.
  • Ejemplo: Variables en duro en codigo *.py.
  • Solución: Utilizar variables de entorno para manejar credenciales sensibles.
# Inseguro
DB_USER = "user"
DB_PASSWORD = "password"

# Seguro
import os
DB_USER = os.getenv("DB_USER")
DB_PASSWORD = os.getenv("DB_PASSWORD")

Antipatrón: Errores Silenciosos

  • Descripción: Errores son capturados y suprimidos sin informar al usuario o registrar los detalles para análisis futuro.
  • Ejemplo: Uso de try/except sin un manejo adecuado del error.
  • Solución: Implementar un sistema de logging y manejo de excepciones informativo.
# Manejo de errores incorrecto
try:
    # código
except Exception:
    pass

# Correcto
import logging

try:
    # código
except Exception as e:
    logging.error(f"Error occurred: {e}")
    raise

Antipatrón: DB multi-instanciacion

  • Descripción: Uso incorrecto de la instancia de conexion
  • Ejemplo: Instanciacion en cada metodo que requiere conexion a la db
  • Solución: Implementar un patron singleton para la conexion. Este debe ir acompañado de un patron de diseño: Inyeccion de dependencia.
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
import os

DATABASE_URL = os.getenv('DATABASE_URL')

engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

# Uso de la sesión en una función
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

Link de interes