Programación Orientada a Objetos (POO): entenderla de una vez para usarla de verdad

En muchos equipos de cloud e infraestructura acabamos escribiendo código: scripts, automatizaciones, herramientas internas, APIs… y tarde o temprano aparece la pregunta: “¿Tengo que usar Programación Orientada a Objetos para esto?”. Para unos, la POO es “lo de las clases y los objetos”; para otros, una fuente de complejidad innecesaria.

En este post vamos a aterrizar qué es la Programación Orientada a Objetos (POO), qué problemas intenta resolver, cuáles son sus ideas clave y cuándo tiene sentido aplicarla en el día a día (especialmente si vienes de infra, DevOps o cloud).


Qué es realmente la POO

La Programación Orientada a Objetos es un paradigma de programación que propone organizar el código en torno a objetos: pequeñas “unidades” que combinan datos y comportamiento. En lugar de tener por un lado estructuras de datos y por otro funciones sueltas, cada objeto agrupa qué es y qué puede hacer.

Muy resumido:

  • Un objeto es una instancia de algo con estado (datos) y métodos (funciones).
  • Una clase es el “molde” que define cómo son esos objetos.
  • La idea central es modelar partes de tu sistema como “cosas” con las que interactúas: Usuario, Servidor, Pedido, VM, BackupJob, etc.

En vez de tener un script de 800 líneas lleno de funciones globales, la POO te invita a partir en piezas más pequeñas y coherentes que se puedan entender, probar y reutilizar mejor.


Los cuatro pilares de la POO (sin humo)

Hay mil formas de explicarlos, pero la que suele funcionar mejor es con ejemplos muy concretos.

1. Encapsulación

Agrupar datos + funciones relacionadas y esconder los detalles internos.

  • Desde fuera te importa que servidor.reiniciar() funcione; no cómo lo hace por dentro.
  • Esto ayuda a que, si mañana cambias cómo almacenas credenciales o cómo llamas a la API, no tengas que tocar todo el código: sólo el interior de la clase.

2. Abstracción

Quedarte con la visión simple y esconder lo complejo detrás de una interfaz clara.

  • Una clase StorageAccount puede tener métodos como subir_archivo() o listar_contenido() sin que el consumidor se preocupe de si es Azure, S3 o un NAS on‑prem.
  • La implementación concreta está encapsulada; la interfaz es la misma.

3. Herencia

Permite que una clase “hija” reuse y especialice el comportamiento de una clase “padre”.

  • Por ejemplo, ServidorLinux y ServidorWindows podrían heredar de una clase base Servidor, compartiendo métodos comunes (obtener_estado()reiniciar()) y añadiendo los específicos.
  • Útil, pero fácil de abusar: demasiada herencia profunda hace el código difícil de seguir.

4. Polimorfismo

Que distintas clases puedan responder de forma diferente al mismo mensaje (método) sin que el consumidor tenga que saber de qué tipo son.

  • Si tienes una lista de objetos que implementan realizar_backup(), te da igual si son VMBaseDeDatos o StorageAccount. Llamas al método y cada uno hace lo suyo.
  • Esto simplifica mucho el código que orquesta operaciones sobre recursos heterogéneos.

Ejemplo mental para perfiles de cloud/infra

Imagina que tienes que gestionar distintos tipos de recursos en tu plataforma: máquinas virtuales, bases de datos y contenedores. En lugar de tener funciones sueltas como:

  • crear_vm()crear_db()crear_container()
  • borrar_vm()borrar_db()borrar_container()

Podrías tener algo así a nivel de diseño:

  • Clase base Recurso con métodos genéricos: crear()borrar()obtener_estado().
  • Clases hijas: VMBaseDeDatosContenedor, cada una implementando esos métodos según toque.

Luego, tu código de orquestación sólo sabe que tiene una lista de Recursos y les pide que se creen, borren o comprueben su estado. No necesita if/else gigantes comprobando tipos. Esa es la gracia práctica de la POO cuando se usa bien.


Cuándo tiene sentido usar POO (y cuándo no)

Cuándo sí ayuda

  • Proyectos que van a crecer: herramientas internas, APIs, automatizaciones complejas que sabes que tendrás que mantener meses o años.
  • Código que encapsula dominios claros: clientes, recursos, jobs, pipelines, integraciones con APIs externas.
  • Cuando varios desarrolladores tocan el mismo código y necesitas estructurar responsabilidades y tests.

Cuándo puede sobrar

  • Scripts cortos y de un solo uso (one‑shot) donde la complejidad añadida no aporta.
  • Tareas muy lineales donde un enfoque funcional (funciones puras, pipe de datos) es más natural.
  • Prototipos rápidos donde estás aún explorando qué quieres hacer; ya habrá tiempo de refactorizar a POO si el experimento se convierte en producto.

La clave: no usar POO “por moda”, sino porque te ayuda a que el código sea más mantenible y testeable.


POO y pruebas (testing)

Otra ventaja práctica de la POO es que facilita mucho el testing:

  • Si tienes clases pequeñas, es más fácil probar cada una de forma aislada (unit tests).
  • Puedes simular dependencias (mocks) inyectando versiones falsas de clases que representan APIs externas, servicios cloud, etc.
  • El código que orquesta (por ejemplo, una clase DespliegueAzure) puede probarse sin tocar realmente Azure en cada test, sólo usando stubs de VMVNetStorageAccount, etc.

Para infra/DevOps esto es clave: te permite validar lógica sin depender siempre de tener una suscripción o entorno de pruebas disponible.


Cómo encaja la POO en el mundo actual de IA y cloud

Aunque muchas herramientas modernas (Python, Go, Node, Terraform) permiten estilos más funcionales o declarativos, la POO sigue siendo muy útil:

  • En SDKs de cloud (Azure, AWS, GCP) la mayoría de clientes siguen modelos orientados a objetos: clientes, recursos, operaciones.
  • En frameworks web y APIs, el diseño por controladores, servicios y modelos suele estar basado en POO.
  • Incluso en el mundo de la IA, muchas librerías (clientes de APIs, wrappers de modelos, conectores) usan clases para encapsular lógica y estado.

Entender bien la POO no es una obligación para escribir scripts, pero sí marca la diferencia cuando empiezas a construir herramientas más grandes: APIs internas, servicios que orquestan despliegues, bots, agentes, etc.