Paradigmas de la programación
¿Qué es un paradigma de programación?
Un paradigma de programación es como un estilo o una forma de pensar para resolver problemas con código. Es el enfoque que usamos para organizar y estructurar nuestras ideas cuando programamos.
Imaginate que tenés que armar un mueble de Hyper Theuelche o en Chuar. Podés:
- Seguir las instrucciones paso a paso (estructurado)
- Usar herramientas especializadas para cada tarea (funcional)
- Pensar en cada pieza como un componente con sus propias características (orientado a objetos)
¡Todos los caminos te llevan al mismo mueble armado, pero la forma de pensarlo es diferente!
En este artículo vamos a explorar los tres paradigmas más importantes que vas a usar en tu carrera como programador.
Programación Estructurada

La programación estructurada es como seguir un mapa para llegar a un destino.
Supongamos que querés ir de tu casa al parque Manuel Belgrano. Un mapa te muestra el camino a seguir, con instrucciones paso a paso:
- Salir de tu casa
- Caminar 3 cuadras hacia el norte
- Girar a la izquierda
- Caminar 2 cuadras hacia el oeste
- Llegar al parque
En la programación estructurada, el mapa es el código y las instrucciones son las líneas de código que se ejecutan una después de la otra, en un orden lógico.
El código se divide en bloques o módulos, como las secciones del mapa, y cada bloque tiene una función específica, como “caminar hacia el norte” o “girar a la izquierda”.
Las tres estructuras fundamentales
La programación estructurada se basa en tres herramientas fundamentales:
-
Secuencias: Son las instrucciones que se ejecutan una después de la otra, en un orden lógico.
-
Decisiones (o Condicionales): Son las instrucciones que permiten tomar decisiones basadas en condiciones específicas, como “si” o “si no”. Por ejemplo, “si es mayor de edad, entonces…”
-
Iteraciones (o Bucles): Son las instrucciones que se repiten mientras se cumple una condición específica. Por ejemplo, “mientras que la variable sea menor que 10, hacé tal cosa…”
Herramientas adicionales
Además, la programación estructurada también utiliza:
- Subrutinas (o Funciones): Son bloques de código que realizan una tarea específica y pueden ser reutilizados en diferentes partes del programa.
- Estructuras de datos: Son contenedores que almacenan datos de diferentes tipos (string, entero, flotante, booleano, etc.) y permiten manipularlos en el programa.
Ejemplo práctico: Control de temperatura
Imaginate que estás programando un sistema de control de temperatura para un invernadero en El Calafate (¡donde hace frío!). Acá tenés un ejemplo en Python:
def controlar_temperatura(temperatura_actual):
"""
Controla la temperatura del invernadero
"""
# Secuencia: definimos las temperaturas ideales
temp_minima = 15
temp_maxima = 25
# Decisión: verificamos la temperatura
if temperatura_actual < temp_minima:
encender_calefaccion()
print(f"🔥 Calefacción encendida. Temp: {temperatura_actual}°C")
elif temperatura_actual > temp_maxima:
encender_ventilacion()
print(f"💨 Ventilación encendida. Temp: {temperatura_actual}°C")
else:
print(f"✅ Temperatura óptima: {temperatura_actual}°C")
def encender_calefaccion():
# Aquí iría el código para activar el relé de la calefacción
pass
def encender_ventilacion():
# Aquí iría el código para activar el relé de ventilación
pass
# Iteración: monitoreamos la temperatura cada hora
temperaturas = [12, 18, 22, 28, 20, 16]
for temp in temperaturas:
controlar_temperatura(temp)
Ventajas de la programación estructurada:
- ✅ Código claro y fácil de seguir
- ✅ Ideal para problemas secuenciales
- ✅ Fácil de aprender para principiantes
- ✅ Perfecto para scripts y automatizaciones simples
Programación Funcional

Imaginate que querés hacer una torta. En la programación funcional, cada ingrediente es una función que hace una cosa específica, como mezclar harina, agregar azúcar o batir huevos.
Cada función recibe ingredientes (entradas) y produce un resultado (salida). No cambia los ingredientes originales, solo crea un nuevo resultado.
Principios clave
- Funciones puras: Una función siempre devuelve el mismo resultado para las mismas entradas, sin efectos secundarios.
- Inmutabilidad: Los datos no se modifican, se crean nuevos datos.
- Composición: Las funciones se combinan como piezas de LEGO para crear soluciones más complejas.
Ejemplo práctico: Procesamiento de datos de sensores
Imaginate que tenés varios sensores de temperatura en diferentes puntos de una planta industrial y necesitás procesar esos datos:
# Funciones puras: siempre devuelven lo mismo para las mismas entradas
def celsius_a_fahrenheit(celsius):
"""Convierte temperatura de Celsius a Fahrenheit"""
return (celsius * 9/5) + 32
def filtrar_temperaturas_criticas(temperaturas, limite=30):
"""Filtra temperaturas que superan el límite"""
return list(filter(lambda t: t > limite, temperaturas))
def calcular_promedio(numeros):
"""Calcula el promedio de una lista de números"""
return sum(numeros) / len(numeros) if numeros else 0
def aplicar_descuento_termico(temperatura, descuento=0.5):
"""Aplica un factor de corrección a la temperatura"""
return temperatura - descuento
# Composición: combinamos funciones para resolver el problema
def procesar_datos_sensores(temperaturas_celsius):
"""
Procesa datos de sensores:
1. Filtra temperaturas críticas
2. Aplica corrección térmica
3. Convierte a Fahrenheit
4. Calcula promedio
"""
# Cada paso crea nuevos datos sin modificar los originales
criticas = filtrar_temperaturas_criticas(temperaturas_celsius)
corregidas = list(map(aplicar_descuento_termico, criticas))
en_fahrenheit = list(map(celsius_a_fahrenheit, corregidas))
promedio = calcular_promedio(en_fahrenheit)
return {
'criticas': criticas,
'corregidas': corregidas,
'fahrenheit': en_fahrenheit,
'promedio': promedio
}
# Uso
sensores = [22, 31, 28, 35, 26, 33, 29]
resultado = procesar_datos_sensores(sensores)
print(f"Temperaturas críticas: {resultado['criticas']}")
print(f"Promedio corregido: {resultado['promedio']:.2f}°F")
Ventajas de la programación funcional:
- ✅ Código más predecible y fácil de probar
- ✅ Menos errores por modificaciones accidentales
- ✅ Ideal para procesamiento de datos
- ✅ Facilita el trabajo en paralelo
Programación Orientada a Objetos (POO)

La programación orientada a objetos es como crear moldes o plantillas para representar cosas del mundo real en tu código.
Imaginate que estás creando un sistema de control para una planta industrial. Tenés diferentes dispositivos: sensores, actuadores, válvulas, motores. Cada uno tiene características propias y puede hacer cosas específicas.
Conceptos fundamentales
-
Clase: Es el molde o plantilla que define cómo es un objeto. Por ejemplo, la clase “Sensor” define qué características y habilidades tiene un sensor.
-
Objeto (o Instancia): Es una creación específica a partir de una clase. Por ejemplo, “sensor_temperatura_1” es un objeto de la clase Sensor.
-
Atributos: Son las características del objeto. Por ejemplo, un sensor tiene: nombre, ubicación, valor actual, unidad de medida.
-
Métodos: Son las acciones que puede hacer el objeto. Por ejemplo, un sensor puede: leer valor, calibrarse, enviar alerta.
Los 4 pilares de la POO
- Encapsulamiento: Guardar datos y métodos juntos, protegiendo la información interna.
- Abstracción: Mostrar solo lo necesario, ocultar la complejidad.
- Herencia: Crear nuevas clases basadas en clases existentes.
- Polimorfismo: Diferentes objetos pueden responder al mismo mensaje de formas distintas.
Ejemplo práctico: Sistema de monitoreo industrial
class Sensor:
"""Clase base para todos los sensores"""
def __init__(self, nombre, ubicacion, unidad):
# Atributos: características del sensor
self.nombre = nombre
self.ubicacion = ubicacion
self.unidad = unidad
self.valor_actual = 0
self.activo = True
# Métodos: acciones que puede hacer el sensor
def leer_valor(self, nuevo_valor):
"""Lee y almacena un nuevo valor del sensor"""
if self.activo:
self.valor_actual = nuevo_valor
return True
return False
def obtener_estado(self):
"""Devuelve el estado actual del sensor"""
estado = "🟢 Activo" if self.activo else "🔴 Inactivo"
return f"{self.nombre} ({self.ubicacion}): {self.valor_actual}{self.unidad} - {estado}"
def desactivar(self):
"""Desactiva el sensor"""
self.activo = False
# Herencia: SensorTemperatura hereda de Sensor
class SensorTemperatura(Sensor):
"""Sensor especializado en temperatura"""
def __init__(self, nombre, ubicacion):
# Llamamos al constructor de la clase padre
super().__init__(nombre, ubicacion, "°C")
self.temp_minima = -10
self.temp_maxima = 50
def verificar_rango(self):
"""Verifica si la temperatura está en rango seguro"""
if self.valor_actual < self.temp_minima:
return f"⚠️ ALERTA: Temperatura muy baja ({self.valor_actual}°C)"
elif self.valor_actual > self.temp_maxima:
return f"⚠️ ALERTA: Temperatura muy alta ({self.valor_actual}°C)"
else:
return f"✅ Temperatura normal ({self.valor_actual}°C)"
class SensorPresion(Sensor):
"""Sensor especializado en presión"""
def __init__(self, nombre, ubicacion):
super().__init__(nombre, ubicacion, " bar")
self.presion_maxima = 10
def verificar_presion(self):
"""Verifica si la presión es segura"""
if self.valor_actual > self.presion_maxima:
return f"🚨 PELIGRO: Presión crítica ({self.valor_actual} bar)"
return f"✅ Presión normal ({self.valor_actual} bar)"
# Polimorfismo: diferentes sensores, misma interfaz
class SistemaMonitoreo:
"""Sistema que gestiona múltiples sensores"""
def __init__(self):
self.sensores = []
def agregar_sensor(self, sensor):
"""Agrega un sensor al sistema"""
self.sensores.append(sensor)
def mostrar_todos(self):
"""Muestra el estado de todos los sensores"""
print("\n📊 ESTADO DEL SISTEMA")
print("=" * 50)
for sensor in self.sensores:
print(sensor.obtener_estado())
# Uso del sistema
sistema = SistemaMonitoreo()
# Creamos objetos (instancias) de diferentes sensores
temp1 = SensorTemperatura("Temp-Caldera", "Sala de máquinas")
temp2 = SensorTemperatura("Temp-Ambiente", "Oficina")
presion1 = SensorPresion("Presion-Linea-1", "Tubería principal")
# Agregamos sensores al sistema
sistema.agregar_sensor(temp1)
sistema.agregar_sensor(temp2)
sistema.agregar_sensor(presion1)
# Simulamos lecturas
temp1.leer_valor(85)
temp2.leer_valor(22)
presion1.leer_valor(7.5)
# Mostramos el estado
sistema.mostrar_todos()
# Verificamos rangos
print("\n🔍 VERIFICACIÓN DE SEGURIDAD")
print("=" * 50)
print(temp1.verificar_rango())
print(temp2.verificar_rango())
print(presion1.verificar_presion())
Ventajas de la POO:
- ✅ Código organizado que refleja el mundo real
- ✅ Fácil de mantener y extender
- ✅ Reutilización de código mediante herencia
- ✅ Ideal para sistemas complejos con muchos componentes
Comparación práctica: El mismo problema, tres soluciones
Veamos cómo resolver el mismo problema (calcular el promedio de temperaturas válidas) con los tres paradigmas:
Versión Estructurada
def calcular_promedio_estructurado(temperaturas):
total = 0
contador = 0
# Iteramos sobre cada temperatura
for temp in temperaturas:
# Decisión: solo contamos temperaturas válidas
if temp >= -50 and temp <= 100:
total += temp
contador += 1
# Calculamos y retornamos el promedio
if contador > 0:
return total / contador
return 0
temps = [22, -100, 25, 28, 150, 24]
print(f"Promedio: {calcular_promedio_estructurado(temps):.2f}°C")
Versión Funcional
def es_temperatura_valida(temp):
return -50 <= temp <= 100
def calcular_promedio_funcional(temperaturas):
validas = list(filter(es_temperatura_valida, temperaturas))
return sum(validas) / len(validas) if validas else 0
temps = [22, -100, 25, 28, 150, 24]
print(f"Promedio: {calcular_promedio_funcional(temps):.2f}°C")
Versión Orientada a Objetos
class AnalizadorTemperaturas:
def __init__(self, temp_min=-50, temp_max=100):
self.temp_min = temp_min
self.temp_max = temp_max
self.temperaturas = []
def agregar_temperatura(self, temp):
if self.temp_min <= temp <= self.temp_max:
self.temperaturas.append(temp)
def calcular_promedio(self):
if self.temperaturas:
return sum(self.temperaturas) / len(self.temperaturas)
return 0
analizador = AnalizadorTemperaturas()
temps = [22, -100, 25, 28, 150, 24]
for temp in temps:
analizador.agregar_temperatura(temp)
print(f"Promedio: {analizador.calcular_promedio():.2f}°C")
¿Cuándo usar cada paradigma?
Usá Programación Estructurada cuando:
- 🎯 El problema es simple y secuencial
- 🎯 Estás haciendo scripts de automatización
- 🎯 Necesitás algo rápido y directo
- 🎯 Ejemplo: un programa que lee datos de un archivo y los procesa
Usá Programación Funcional cuando:
- 🎯 Necesitás procesar muchos datos
- 🎯 Querés código predecible y fácil de probar
- 🎯 Trabajás con transformaciones de datos
- 🎯 Ejemplo: análisis de datos de sensores, reportes estadísticos
Usá Programación Orientada a Objetos cuando:
- 🎯 Modelás sistemas complejos del mundo real
- 🎯 Tenés muchos componentes que interactúan
- 🎯 Necesitás reutilizar y extender código
- 🎯 Ejemplo: sistema SCADA, control de procesos industriales, simuladores
🎮 Desafío para vos
Ejercicio 1: Creá una clase Valvula que tenga:
- Atributos: nombre, estado (abierta/cerrada), porcentaje de apertura
- Métodos: abrir(), cerrar(), ajustar_apertura(porcentaje)
Ejercicio 2: Escribí una función pura que reciba una lista de presiones y devuelva solo las que están en rango seguro (0-10 bar).
Ejercicio 3: Hacé un programa estructurado que controle un semáforo (verde, amarillo, rojo) con tiempos específicos.
Conclusión
Los paradigmas de programación son herramientas en tu caja de herramientas como programador. No hay uno “mejor” que otro, sino que cada uno es más adecuado para diferentes situaciones.
En tu carrera de Automatización y Control de Procesos Industriales, vas a usar los tres:
- Estructurado para scripts de control simples
- Funcional para procesar datos de sensores
- Orientado a Objetos para sistemas SCADA complejos
¡Lo importante es conocerlos todos y saber cuándo aplicar cada uno! 🚀
Próximo paso: Practicá creando pequeños programas con cada paradigma. Empezá simple y andá aumentando la complejidad a medida que te sientas más cómodo.
¿Tenés dudas? ¡Preguntá en clase o dejá un comentario! 💬