Programación y lenguajes
Paradigmas de programación
Cada paradigma es la respuesta a un dolor concreto: imperativo, orientado a objetos, funcional, declarativo y lógico. Qué se gana y qué se pierde con cada estilo, sin guerra santa.
Un paradigma de programación no es un lenguaje ni una herramienta, sino una forma de pensar el programa. Y no hay uno mejor que otro: cada paradigma nació como respuesta a un dolor concreto, y todos siguen vivos porque cada uno resuelve bien una clase distinta de problemas. Conocerlos no es coleccionar modas, sino ampliar el repertorio: cuanto más variado, más chances de elegir la herramienta correcta para el problema que tienes enfrente.
La pregunta de fondo que los separa es como manejan el estado, es decir, los valores que van cambiando mientras el programa corre.
Imperativo: decir el cómo, paso a paso
El paradigma imperativo es el más antiguo y el más natural: describes, paso a paso, como llegar al resultado. Asignas variables, repites con bucles, decides con condicionales y vas mutando el estado hasta llegar a la meta. Es el modelo mental de la máquina: hacer una cosa, luego otra, luego otra. La mayoría de los lenguajes clásicos, desde C hasta el Python cotidiano, son imperativos en su hueso.
Su virtud es la cercanía con la máquina y la claridad de control. Su precio es que el estado, al poder cambiar en cualquier momento, es la fuente número uno de bugs: si muchas partes del programa modifican las mismas variables, entender que paso se vuelve una pesquisa.
Orientación a objetos: agrupar datos y comportamiento
La orientación a objetos nació para domar programas grandes. La idea es organizar el código en objetos que combinan datos y comportamiento, y agrupar esos objetos en clases que sirven de molde. En vez de tener funciones sueltas operando sobre datos sueltos, modelas el dominio en términos de cosas: una Cuenta con su saldo y sus métodos depositar y girar.
Tres ideas la sostienen. El encapsulamiento esconde los detalles internos y expone solo una interfaz cuidada, protegiendo los datos. La herencia permite que una clase reaproveche el comportamiento de otra. Y el polimorfismo deja tratar objetos distintos a través de una interfaz común, de modo que cada uno responda a su manera. Con el tiempo, el campo aprendió que la herencia profunda se vuelve rígida, y cobro fuerza el principio de composición sobre herencia: armar comportamientos combinando piezas pequeñas antes que heredar de una gran clase base.
Funcional: calcular sin mutar
El paradigma funcional pone el estado bajo sitio. Parte de tratar el cálculo como la evaluación de funciones matemáticas y, para ello, privilegia las funciones puras (que para los mismos argumentos devuelven siempre el mismo resultado y no producen efectos secundarios) y la inmutabilidad: en vez de modificar un valor, creas uno nuevo.
El gancho es enorme. Si nada se muta y las funciones son puras, razonar sobre el código se vuelve casi mecánico: puedes testear cada función aislada, encadenarlas con seguridad y, sobre todo, usar concurrencia sin el pánico habitual de que dos hilos se pisen. Es el origen de ideas como el currying, que transforma una función de varios argumentos en una cadena de funciones de uno, o las mónadas, envoltorios que administran el caso vacío o el error. El precio es el desapego de lo intuitivo: requiere aprender a pensar de otra manera.
Declarativo y lógico: decir el qué, no el cómo
El paradigma declarativo invierte la consigna: describes que quieres obtener, no como. El ejemplo cotidiano es SQL: declaras que datos quieres y dejas que el motor decida como buscarlos. No escribes bucles ni llevas contadores; declaras la forma del resultado.
El paradigma lógico lleva la idea al extremo. En lenguajes como Prolog declaras hechos y reglas, y el motor deduce las respuestas a tus consultas. Le preguntas quien es progenitor de alguien y el sistema razona a partir de lo que le enseñaste. Es un cambio radical: en vez de dar instrucciones, describes un mundo y fórmulas preguntas sobre el.
La síntesis práctica
Ningún paradigma ganó la guerra porque ninguna guerra tenía sentido. Los lenguajes modernos son, casi todos, híbridos: JavaScript, Python o Scala toman lo imperativo, lo funcional y a veces lo orientado a objetos, y dejan que el programador elija según el problema. Lo importante no es ser ortodoxo, sino saber que dolor alivia cada paradigma. Si lidias con estado compartido y concurrencia, lo funcional y la inmutabilidad te ahorran dolores. Si modelas un dominio rico, los objetos ayudan. Si describes una consulta, lo declarativo brilla. Y si lo que necesitas es control fino y cercanía a la máquina, lo imperativo sigue siendo insuperable.
Los términos de este tema
25 entradas del glosario que aparecen acá. Cada una abre en su definición del índice.
- clase
- clase abstracta
- composición sobre herencia
- currificación
- efecto secundario
- encapsulamiento
- función pura
- genérico
- herencia
- inmutabilidad
- instancia
- interfaz
- lambda (función anónima)
- metaprogramación
- mónada
- mutabilidad
- objeto
- orientación a objetos
- paradigma declarativo
- paradigma funcional
- paradigma imperativo
- paradigma lógico
- polimorfismo
- recursión
- sobrecarga