# Paradigma de programación

Se denominan paradigmas de programación a las formas de clasificar los lenguajes de programación en función de sus características. Los idiomas se pueden clasificar en múltiples paradigmas.
Algunos paradigmas se ocupan principalmente de las implicancias para el modelo de ejecución del lenguaje, como permitir efectos secundarios o si la secuencia de operaciones está definida por el modelo de ejecución. Otros paradigmas se refieren principalmente a la forma en que se organiza el código, como agrupar un código en unidades junto con el estado que modifica el código. Sin embargo, otros se preocupan principalmente por el estilo de la sintaxis y la gramática.
Los paradigmas de programación comunes incluyen:
* imperativo en el que el programador instruye a la máquina cómo cambiar su estado,
** procedimental que agrupa las instrucciones en procedimientos,
** orientado a objetos que agrupa las instrucciones con la parte del estado en el que operan,
* declarativo en el que el programador simplemente declara las propiedades del resultado deseado, pero no cómo calcularlo
** funcional en el que el resultado deseado se declara como el valor de una serie de aplicaciones de función,
** lógico en la que el resultado deseado se declara como la respuesta a una pregunta sobre un sistema de hechos y reglas,
** matemático en el que el resultado deseado se declara como la solución de un problema de optimización
** reactivo en el que se declara el resultado deseado con flujos de datos y la propagación del cambio
Las técnicas simbólicas como la reflexión, que permiten que el programa se refiera a sí mismo, también pueden ser consideradas como un paradigma de programación. Sin embargo, esto es compatible con los principales paradigmas y, por lo tanto, no es un paradigma real por derecho propio.
Por ejemplo, los lenguajes que caen en el paradigma imperativo tienen dos características principales: establecen el orden en el que ocurren las operaciones, con construcciones que controlan explícitamente ese orden, y permiten efectos secundarios, en los que el estado puede modificarse en un momento determinado, dentro de una unidad de código, y luego leer en un momento diferente dentro de una unidad de código diferente. La comunicación entre las unidades de código no es explícita. Mientras tanto, en la programación orientada a objetos, el código se organiza en objetos que contienen un estado que solo es modificado por el código que forma parte del objeto. La mayoría de los lenguajes orientados a objetos también son lenguajes imperativos. Por el contrario, los lenguajes que se ajustan al paradigma declarativo no indican el orden en el que ejecutar las operaciones. En su lugar, proporcionan una serie de operaciones disponibles en el sistema, junto con las condiciones en las que se permite que se ejecute cada una. La implementación del modelo de ejecución del lenguaje rastrea qué operaciones son libres de ejecutar y elige el orden en forma independiente. Más en Comparación de lenguajes de programación de múltiples paradigmas.

### Lenguajes de programación procedimentales

El desarrollo de lenguajes procedimentales dio lugar a lenguajes sirven de vocabulario relacionado con el problema a resolver. Ejemplos de estos lenguajes son:
* COBOL (COmmon Business-Oriented Language) - hace servir términos como archivo, mover y copiar.
* FORTRAN (FORmula TRANslation) - hace servir terminología del lenguaje matemático.
* ALGOL (ALGOritmic Language) - enfocado a ser un lenguaje apropiado para definir algoritmos, también puede servir de lenguaje matemático.
* PL/I (Programing Language One) - un híbrido comercial/científico de propósito general con soporte para usuarios.
* BASIC (Begginers All purpose Symbolic Instruction Code) - se desarrolló para permitir escribir programas a más personas.
* C - un lenguaje de propósito general.
Todos estos lenguajes siguen un paradigma procedimental. Describen, paso a paso, exactamente el proceso que debe seguirse para resolver un problema específico. La eficacia y eficiencia de cada solución dependen de la experiencia, la inventiva y la habilidad del programador.

## Crítica

Algunos investigadores de lenguajes de programación critican la noción de paradigmas como clasificación de los lenguajes de programación, por ejemplo Harper, y Krishnamurthi. Sostienen que muchos lenguajes de programación no pueden clasificarse estrictamente en un paradigma, sino que incluyen características de varios paradigmas.

## Historia

A lo largo del tiempo se han desarrollado diferentes enfoques de programación, que se han identificado como tales en su momento o retrospectivamente. Uno de los primeros enfoques conscientemente identificado como tal es la programación estructurada, defendida desde mediados de la década de 1960. El concepto de "paradigma de programación" como tal data al menos de 1978, en la conferencia Premio Turing de Robert W. Floyd, titulada Los paradigmas de la programación, que cita la noción de paradigma utilizada por Thomas Kuhn en su La estructura de las revoluciones científicas (1962). Los primeros lenguajes de programación no tenían paradigmas de programación claramente definidos y a veces los programas hacían un uso extensivo de las sentencias goto, el uso liberal de estas sentencias conducía a "código espagueti" con el que era difícil trabajar. Esto llevó al desarrollo de paradigmas de programación estructurados que no permitían el uso de sentencias goto y sólo permitían el uso de construcciones de programación claramente definidas.

### Código máquina

Los paradigmas de programación de nivel más bajo son el código máquina, que representa directamente el instrucciones (el contenido de la memoria del programa) como una secuencia de números, y el lenguaje ensamblador, en el que las instrucciones de la máquina se representan mediante mnemónicos y las direcciones de memoria pueden recibir etiquetas simbólicas. A veces se denominan primera generación y segunda generación.
En la década de 1960, los lenguajes ensambladores se desarrollaron para soportar COPIADO de bibliotecas y capacidades de generación y preprocesamiento de macros condicionales bastante sofisticadas, LLAMADAS a (subrutinas), variables externas y secciones comunes (globales), permitiendo una reutilización significativa del código y el aislamiento de las especificidades del hardware mediante el uso de operadores lógicos como READ/WRITE/GET/PUT. El ensamblador se utilizaba, y aún se utiliza, en sistemas en los que el tiempo es un factor crítico y, a menudo, en sistemas embebidos, ya que ofrece el control más directo de lo que hace la máquina.

### Programación orientada a objetos

Tras el uso generalizado de los lenguajes procedimentales, se crearon los lenguajes de programación orientada a objetos (POO), como Simula, Smalltalk, C++, Eiffel, Python, PHP, Java, y C#. En estos lenguajes, los datos y los métodos para manipularlos se mantienen como una unidad llamada object. Con una perfecta encapsulación, una de las características distintivas de la programación orientada a objetos, la única forma de que otro objeto o usuario pueda acceder a los datos es a través de los métodos del objeto. Así, el funcionamiento interno de un objeto puede ser cambiado sin afectar a ningún código que utilice el objeto. Todavía existe cierta controversia planteada por Alexander Stepanov, Richard Stallman y otros programadores, sobre la eficacia del paradigma de programación orientada a objetos frente al paradigma procedimental. La necesidad de que cada objeto tenga métodos asociativos lleva a algunos escépticos a asociar la POO con hinchazón del software; un intento de resolver este dilema llegó a través del polimorfismo.
Dado que la programación orientada a objetos se considera un paradigma, no un lenguaje, es posible crear incluso un lenguaje ensamblador orientado a objetos. Ensamblador de alto nivel (HLA) es un ejemplo de esto que soporta completamente tipos de datos avanzados y programación en lenguaje ensamblador orientada a objetos – a pesar de sus orígenes tempranos. Por lo tanto, los diferentes paradigmas de programación pueden verse más bien como memes motivacionales de sus defensores, en lugar de representar necesariamente el progreso de un nivel al siguiente. Las comparaciones precisas de la eficacia de los paradigmas en competencia a menudo son más difíciles debido a la terminología nueva y diferente aplicada a entidades y procesos similares, junto con numerosas distinciones de implementación entre idiomas.

### Otros paradigmas

La programación literaria, como una forma de programación imperativa, estructura los programas como una red centrada en el ser humano, como en un ensayo de hipertexto: la documentación es parte integral del programa, y el programa se estructura siguiendo la lógica de la exposición en prosa, en lugar de la conveniencia del compilador.
Independientemente de la rama imperativa, se desarrollaron paradigmas de programación declarativa. En estos lenguajes, se le dice al ordenador cuál es el problema, no cómo resolverlo – el programa se estructura como un conjunto de propiedades a encontrar en el resultado esperado, no como un procedimiento a seguir. Dada una base de datos o un conjunto de reglas, el ordenador intenta encontrar una solución que cumpla todas las propiedades deseadas. Un arquetipo de lenguaje declarativo es el lenguaje de cuarta generación SQL. SQL, y la familia de los lenguajes funcionales y la programación lógica.
La programación funcional es un subconjunto de la programación declarativa. Los programas escritos con este paradigma utilizan funciones, bloques de código destinados a comportarse como funciones matemáticas. Los lenguajes funcionales desalientan los cambios en el valor de las variables a través de asignación, haciendo un gran uso de recursión en su lugar.
El paradigma de programación lógica considera la computación como razonamiento automatizado sobre un cuerpo de conocimiento. Los hechos sobre el dominio del problema se expresan como fórmulas lógicas, y los programas se ejecutan aplicando reglas de inferencia sobre ellas hasta que se encuentra una respuesta al problema, o se demuestra que el conjunto de fórmulas es inconsistente.
La programación simbólica es un paradigma que describe programas capaces de manipular fórmulas y componentes del programa como datos. Los programas pueden modificarse a sí mismos y parecer que "aprenden", lo que los hace adecuados para aplicaciones como la inteligencia artificial, los sistemas expertos, el procesamiento del lenguaje natural y los juegos de ordenador. Los lenguajes que soportan este paradigma incluyen Lisp y Prolog.
La programación diferenciable estructura los programas para que puedan ser diferenciados en todo momento, normalmente mediante diferenciación automática.

## Soporte para múltiples paradigmas

La mayoría de lenguajes de programación soportan más de un paradigma de programación para permitir a los programadores utilizar el estilo de programación más adecuado y las construcciones del lenguaje asociadas para un trabajo determinado.

## Resumen

Así como la ingeniería de software (como proceso) se define mediante diferentes metodologías, los lenguajes de programación (como modelos de computación) se definen mediante diferentes paradigmas. Algunos lenguajes están diseñados para admitir un paradigma (Smalltalk admite programación orientada a objetos, Haskell admite programación funcional), mientras que otros lenguajes de programación admiten múltiples paradigmas (como Object Pascal, C++, Java, JavaScript, C#, Scala, Visual Basic, Common Lisp, Scheme, Perl, PHP, Python, Ruby, Oz y F# ). Por ejemplo, los programas escritos en C ++, Object Pascal o PHP pueden ser puramente procedimentales, puramente orientados a objetos o pueden contener elementos de ambos u otros paradigmas. Los diseñadores y programadores de software deciden cómo utilizar esos elementos paradigmáticos.
En la programación orientada a objetos, los programas se tratan como un conjunto de objetos que interactúan. En la programación funcional, los programas se tratan como una secuencia de evaluaciones de funciones sin estado. Cuando se programan computadoras o sistemas con muchos procesadores, en la programación orientada a procesos, los programas se tratan como conjuntos de procesos concurrentes que actúan sobre estructuras de datos compartidas lógicas.
Muchos paradigmas de programación son tan conocidos por las técnicas que prohíben como por las que habilitan. Por ejemplo, la programación funcional pura no permite el uso de efectos secundarios, mientras que la programación estructurada no permite el uso de la instrucción "go to". En parte por esta razón, los nuevos paradigmas a menudo son considerados doctrinarios o demasiado rígidos por quienes están acostumbrados a estilos anteriores. Sin embargo, evitar ciertas técnicas puede facilitar la comprensión del comportamiento del programa y demostrar teoremas sobre la corrección del programa.
Los paradigmas de programación también se pueden comparar con modelos de programación, lo que permite invocar un modelo de ejecución utilizando solo una API. Los modelos de programación también se pueden clasificar en paradigmas según las características del modelo de ejecución.
Para la computación paralela, es común usar un modelo de programación en lugar de un lenguaje. La razón es que los detalles del hardware paralelo se filtran en las abstracciones utilizadas para programar el hardware. Esto hace que el programador tenga que mapear patrones en el algoritmo sobre patrones en el modelo de ejecución (que se han insertado debido a una fuga de hardware en la abstracción). Como consecuencia, ningún lenguaje de programación paralelo se adapta bien a todos los problemas de cálculo. Por lo tanto, es más conveniente utilizar un lenguaje secuencial base e insertar llamadas a la API en modelos de ejecución paralela a través de un modelo de programación. Dichos modelos de programación paralela se pueden clasificar de acuerdo con abstracciones que reflejan el hardware, como la memoria compartida, la memoria distribuida con paso de mensajes, nociones de lugar visibles en el código, etc. Estos pueden considerarse sabores del paradigma de programación que se aplican solo a lenguajes y modelos de programación paralelos.