Logo de CursoIA
CursoIA Curso de Inteligencia Artificial

Programación orientada a datos con Python, Unidad 8 — Modelado de datos con clases, 8.2 — Separación de datos y lógica ·

Antipatrones comunes

Antipatrones comunes en la separación de datos y lógica

Introducción

La separación clara entre los datos y la lógica es un pilar fundamental para cualquier proyecto orientado a datos. No solo facilita la mantenibilidad y escalabilidad del código, sino que también mejora la comprensión y colaboración en equipos de desarrollo. Sin embargo, incluso con la mejor intención, hay varios antipatrones comunes que pueden obstaculizar esta separación. Este artículo examina algunos de los más frecuentes e ilustra cómo evitarlos.

Explicación principal

Cuando modelamos datos y procesos relacionados en Python, es esencial mantener una clara distinción entre lo que representan nuestros datos (objetos o estructuras de datos) y la lógica que actúa sobre esos datos. Sin embargo, a menudo podemos caer en ciertos patrones de diseño que pueden desvirtuar esta separación.

Ejemplo básico

Supongamos que estamos trabajando con un conjunto de clientes para una empresa de comercio electrónico:

class Cliente:
    def __init__(self, nombre, email):
        self.nombre = nombre
        self.email = email
    
    def enviar_email(self, mensaje):
        print(f"Enviando correo a {self.email}: {mensaje}")

Esta implementación es simple y efectiva para un uso básico. Sin embargo, en una aplicación real, podríamos encontrarnos con antipatrones que nos obliguen a refactorizar este diseño.

Errores típicos / trampas

1. Lógica incrustada en los atributos

Una de las trampas más comunes es incrustar lógica dentro de los atributos de una clase, como hacerlo en el método enviar_email:

class Cliente:
    def __init__(self, nombre, email):
        self.nombre = nombre
        self.email = email
    
    def enviar_email(self, mensaje):
        if self.email_valido():
            print(f"Enviando correo a {self.email}: {mensaje}")
        else:
            print("Email no válido")

    def email_valido(self):
        return "@" in self.email

Este patrón incrusta la lógica de validación directamente en el atributo email, lo que puede resultar en código poco legible y difícil de mantener.

2. Acciones sobre datos directamente

Otro antipatrn es realizar acciones directas sobre los datos dentro del método, sin proporcionar una interfaz clara:

class Cliente:
    def __init__(self, nombre, email):
        self.nombre = nombre
        self.email = email
    
    def enviar_email(self, mensaje):
        if "@" in self.email:  # Acción directa sobre el atributo
            print(f"Enviando correo a {self.email}: {mensaje}")

3. Usar propiedades de clara lógica

Usar propiedades para almacenar lógicas complejas puede resultar en un diseño poco claro y difícil de entender:

class Cliente:
    def __init__(self, nombre, email):
        self.nombre = nombre
        self.email = email
    
    @property
    def es_email_valido(self):
        return "@" in self.email

    def enviar_email(self, mensaje):
        if self.es_email_valido:  # Usar la propiedad
            print(f"Enviando correo a {self.email}: {mensaje}")

Checklist accionable

Para evitar estos antipatrones y mantener una separación clara entre datos y lógica:

  1. Evita incrustar lógica en atributos: No realices acciones o validaciones directamente sobre los atributos de clase.
  2. Proporcione métodos para todas las operaciones: Cada acción que se realiza con los datos debe ser accesible a través de un método bien definido.
  3. Usa propiedades solo para lectura: Evita usar propiedades para almacenar lógica compleja o realizar acciones; asegúrate de que estén diseñadas principalmente para devolver valores.
  4. Documenta claramente las interfaces: Asegúrate de que cada método tenga una descripción clara y precisa, indicando cuáles son los datos de entrada y la salida esperada.
  5. Evita el uso excesivo de métodos mágicos o propiedades: Estos pueden hacer que el código sea menos legible y más difícil de mantener.

Cierre

Siguientes pasos

  • Refactoriza el código existente: Si detectas algún antipatrón en tu código, empieza por refactorizarlo.
  • Implementa una interfaz clara para tus clases: Asegúrate de que cada clase tenga un método para interactuar con los datos y realizar acciones sobre ellos.
  • Mantiene el código limpio y legible: Continúa revisando y mejorando tu diseño de clases, asegurándote siempre de seguir estos principios.

Siguiendo estas prácticas, podrás garantizar que tu código sea no solo efectivo, sino también fácil de mantener y escalar en el futuro.

Contacto

Indica tu objetivo (ChatGPT, RAG, agentes, automatización) y tu stack (web/backend).