Programación imperativa

ImprimirCitar
Tipo de paradigma de programación en la ciencia informática

En informática, la programación imperativa es un paradigma de programación de software que utiliza declaraciones que cambian el estado de un programa. De la misma manera que el modo imperativo en los lenguajes naturales expresa comandos, un programa imperativo consiste en comandos para que los ejecute la computadora. La programación imperativa se enfoca en describir cómo un programa opera paso a paso, en lugar de descripciones de alto nivel de sus resultados esperados.

El término se usa a menudo en contraste con la programación declarativa, que se centra en qué debe lograr el programa sin especificar todos los detalles de cómo el programa debe lograr el resultado.

Programación de procedimientos

La programación procedimental es un tipo de programación imperativa en la que el programa se construye a partir de uno o más procedimientos (también denominados subrutinas o funciones). Los términos a menudo se usan como sinónimos, pero el uso de procedimientos tiene un efecto dramático en cómo aparecen los programas imperativos y cómo se construyen. La programación de procedimientos pesados, en la que los cambios de estado se localizan en procedimientos o se restringen a argumentos explícitos y retornos de procedimientos, es una forma de programación estructurada. Desde la década de 1960, la programación estructurada y la programación modular en general se han promovido como técnicas para mejorar la mantenibilidad y la calidad general de los programas imperativos. Los conceptos detrás de la programación orientada a objetos intentan ampliar este enfoque.

La programación procedimental podría considerarse un paso hacia la programación declarativa. Un programador a menudo puede decir, simplemente mirando los nombres, argumentos y tipos de retorno de los procedimientos (y los comentarios relacionados), qué se supone que debe hacer un procedimiento en particular, sin necesariamente mirar los detalles de cómo logra su resultado. Al mismo tiempo, un programa completo sigue siendo imperativo ya que fija las sentencias a ejecutar y su orden de ejecución en gran medida.

Razones y fundamentos de la programación imperativa

El paradigma de programación utilizado para crear programas para casi todas las computadoras generalmente sigue un modelo imperativo. El hardware de la computadora digital está diseñado para ejecutar código de máquina, que es nativo de la computadora y generalmente está escrito en estilo imperativo, aunque existen compiladores e intérpretes de bajo nivel que usan otros paradigmas para algunas arquitecturas, como las máquinas lisp.

Desde esta perspectiva de bajo nivel, el estado del programa se define por el contenido de la memoria y las declaraciones son instrucciones en el lenguaje de máquina nativo de la computadora. Los lenguajes imperativos de nivel superior usan variables y declaraciones más complejas, pero aún siguen el mismo paradigma. Las recetas y las listas de verificación de procesos, aunque no son programas de computadora, también son conceptos familiares que tienen un estilo similar a la programación imperativa; cada paso es una instrucción, y el mundo físico mantiene el estado. Dado que las ideas básicas de la programación imperativa son conceptualmente familiares y están directamente incorporadas en el hardware, la mayoría de los lenguajes de programación tienen el estilo imperativo.

Las declaraciones de asignación, en el paradigma imperativo, realizan una operación en la información ubicada en la memoria y almacenan los resultados en la memoria para su uso posterior. Los lenguajes imperativos de alto nivel, además, permiten la evaluación de expresiones complejas, que pueden consistir en una combinación de operaciones aritméticas y evaluaciones de funciones, y la asignación del valor resultante a la memoria. Las sentencias en bucle (como en los bucles while, do while y for) permiten que una secuencia de sentencias se ejecute varias veces. Los bucles pueden ejecutar las declaraciones que contienen un número predefinido de veces, o pueden ejecutarlas repetidamente hasta que se cumpla alguna condición. Las sentencias de bifurcación condicional permiten ejecutar una secuencia de sentencias solo si se cumple alguna condición. De lo contrario, las sentencias se omiten y la secuencia de ejecución continúa desde la sentencia que les sigue. Las declaraciones de bifurcación incondicionales permiten transferir una secuencia de ejecución a otra parte de un programa. Estos incluyen el salto (llamado goto en muchos idiomas), el cambio y la llamada al subprograma, subrutina o procedimiento (que generalmente regresa a la siguiente declaración después de la llamada).

Al principio del desarrollo de los lenguajes de programación de alto nivel, la introducción del bloque permitió la construcción de programas en los que un grupo de sentencias y declaraciones podían tratarse como si fueran una sola sentencia. Esto, junto con la introducción de subrutinas, permitió expresar estructuras complejas mediante descomposición jerárquica en estructuras procedimentales más simples.

Muchos lenguajes de programación imperativos (como Fortran, BASIC y C) son abstracciones del lenguaje ensamblador.

Historia de los lenguajes imperativos y orientados a objetos

Los primeros lenguajes imperativos fueron los lenguajes de máquina de las computadoras originales. En estos lenguajes, las instrucciones eran muy simples, lo que facilitaba la implementación del hardware pero dificultaba la creación de programas complejos. FORTRAN, desarrollado por John Backus en International Business Machines (IBM) a partir de 1954, fue el primer lenguaje de programación importante que eliminó los obstáculos presentados por el código de máquina en la creación de programas complejos. FORTRAN era un lenguaje compilado que permitía nombrar variables, expresiones complejas, subprogramas y muchas otras características que ahora son comunes en los lenguajes imperativos. Las próximas dos décadas vieron el desarrollo de muchos otros importantes lenguajes de programación imperativos de alto nivel. A fines de la década de 1950 y 1960, ALGOL se desarrolló para permitir que los algoritmos matemáticos se expresaran más fácilmente e incluso sirvió como el lenguaje de destino del sistema operativo para algunas computadoras. MUMPS (1966) llevó el paradigma imperativo a un extremo lógico, al no tener declaraciones en absoluto, basándose únicamente en comandos, incluso hasta el punto de hacer que los comandos IF y ELSE fueran independientes entre sí, conectados solo por una variable intrínseca llamada $ PRUEBA. COBOL (1960) y BASIC (1964) fueron intentos de hacer que la sintaxis de programación se pareciera más al inglés. En la década de 1970, Pascal fue desarrollado por Niklaus Wirth, y C fue creado por Dennis Ritchie mientras trabajaba en Bell Laboratories. Wirth pasó a diseñar Modula-2 y Oberon. Para las necesidades del Departamento de Defensa de los Estados Unidos, Jean Ichbiah y un equipo de Honeywell comenzaron a diseñar Ada en 1978, después de un proyecto de 4 años para definir los requisitos del lenguaje. La especificación se publicó por primera vez en 1983, con revisiones en 1995, 2005 y 2012.

La década de 1980 vio un rápido crecimiento en el interés por la programación orientada a objetos. Estos lenguajes tenían un estilo imperativo, pero añadían funciones para admitir objetos. Las últimas dos décadas del siglo XX vieron el desarrollo de muchos de estos lenguajes. Smalltalk-80, originalmente concebido por Alan Kay en 1969, fue lanzado en 1980 por el Xerox Palo Alto Research Center (PARC). Basándose en conceptos de otro lenguaje orientado a objetos, Simula (que se considera el primer lenguaje de programación orientado a objetos del mundo, desarrollado en la década de 1960), Bjarne Stroustrup diseñó C++, un lenguaje orientado a objetos basado en C. Diseño de C++ comenzó en 1979 y la primera implementación se completó en 1983. A finales de los años 80 y 90, los lenguajes imperativos notables basados en conceptos orientados a objetos fueron Perl, lanzado por Larry Wall en 1987; Python, lanzado por Guido van Rossum en 1990; Visual Basic y Visual C++ (que incluían Microsoft Foundation Class Library (MFC) 2.0), publicados por Microsoft en 1991 y 1993 respectivamente; PHP, publicado por Rasmus Lerdorf en 1994; Java, de James Gosling (Sun Microsystems) en 1995, JavaScript, de Brendan Eich (Netscape), y Ruby, de Yukihiro "Matz" Matsumoto, ambos lanzados en 1995. Microsoft's.NET Framework (2002) es imperativo en esencia, al igual que sus principales lenguajes de destino, VB.NET y C# que se ejecutan en él; sin embargo, F# de Microsoft, un lenguaje funcional, también se ejecuta en él.


Ejemplos

Fortran

FORTRAN (1958) se presentó como "El sistema de traducción de fórmulas matemáticas de IBM." Fue diseñado para cálculos científicos, sin instalaciones de manejo de cuerdas. Junto con declaraciones, expresiones y sentencias, admitía:

  • arrays
  • subrutinas
  • "do" bucles

Tuvo éxito porque:

  • los costos de programación y depuración estaban por debajo de los costos de funcionamiento de la computadora
  • it was supported by IBM
  • las aplicaciones en ese momento eran científicas.

Sin embargo, los proveedores que no son de IBM también escribieron compiladores de Fortran, pero con una sintaxis que probablemente fallaría en el compilador de IBM. El American National Standards Institute (ANSI) desarrolló el primer estándar Fortran en 1966. En 1978, Fortran 77 se convirtió en el estándar hasta 1991. Fortran 90 admite:

  • registros
  • punteros a los arrays

COBOL

COBOL (1959) significa "Lenguaje común orientado a los negocios." Símbolos manipulados en Fortran. Pronto se dio cuenta de que los símbolos no tenían por qué ser números, por lo que se introdujeron las cadenas. El Departamento de Defensa de EE. UU. influyó en el desarrollo de COBOL, y Grace Hopper fue una de las principales contribuyentes. Las declaraciones eran parecidas a las inglesas y detalladas. El objetivo era diseñar un lenguaje para que los gerentes pudieran leer los programas. Sin embargo, la falta de declaraciones estructuradas obstaculizó este objetivo.

El desarrollo de COBOL estuvo estrictamente controlado, por lo que no surgieron dialectos que requirieran estándares ANSI. Como consecuencia, no se modificó durante 15 años hasta 1974. La versión de la década de 1990 sí realizó cambios importantes, como la programación orientada a objetos.

Algo

ALGOL (1960) significa "Lenguaje ALGOrítmico." Tuvo una profunda influencia en el diseño de lenguajes de programación. Surgido de un comité de expertos en lenguajes de programación europeos y estadounidenses, utilizaba notación matemática estándar y tenía un diseño estructurado legible. Algol fue el primero en definir su sintaxis utilizando la forma Backus-Naur. Esto condujo a compiladores dirigidos por la sintaxis. Agregó características como:

  • estructura de bloques, donde las variables eran locales a su bloque
  • arrays con límites variables
  • "para" bucles
  • funciones
  • recursión

Los descendientes directos de Algol incluyen Pascal, Modula-2, Ada, Delphi y Oberon en una rama. En otra rama hay C, C++ y Java.

Básica

(feminine)

BASIC (1964) significa "Código de instrucción simbólica multipropósito para principiantes". Fue desarrollado en Dartmouth College para que todos sus estudiantes lo aprendan. Si un estudiante no pasara a un idioma más poderoso, el estudiante aún recordaría Básico. Se instaló un intérprete básico en las microcomputadoras fabricadas a fines de la década de 1970. A medida que crecía la industria de las microcomputadoras, también lo hacía el lenguaje.

Basic fue pionera en la sesión interactiva. Ofrecía comandos del sistema operativo dentro de su entorno:

  • El comando 'nuevo' creó una pizarra vacía
  • Declaraciones evaluadas inmediatamente
  • Las declaraciones podrían programarse precediéndolas con un número de línea
  • El comando 'list' muestra el programa
  • El comando 'run' ejecutó el programa

Sin embargo, la sintaxis básica era demasiado simple para programas grandes. Los dialectos recientes agregaron estructura y extensiones orientadas a objetos. Visual Basic de Microsoft todavía se usa ampliamente y produce una interfaz gráfica de usuario.

C

El lenguaje de programación C (1973) recibió su nombre porque el lenguaje BCPL se reemplazó con B, y AT&T Bell Labs llamó a la próxima versión "C" Su propósito era escribir el sistema operativo UNIX. C es un lenguaje relativamente pequeño, lo que facilita la escritura de compiladores. Su crecimiento reflejó el crecimiento del hardware en la década de 1980. Su crecimiento también se debió a que tiene las facilidades del lenguaje ensamblador, pero utiliza una sintaxis de alto nivel. Agregó características avanzadas como:

  • ensamblador inline
  • aritmética sobre punteros
  • apuntadores a funciones
  • bit operations
  • combinando libremente operadores complejos
Mapa de memoria computarizada

C permite al programador controlar qué región de datos de memoria se almacenará. Las variables globales y las variables estáticas requieren la menor cantidad de ciclos de reloj para almacenar. La pila se usa automáticamente para las declaraciones de variables estándar. La memoria del montón se devuelve a una variable de puntero desde la función malloc().

  • El datos globales y estáticos región se encuentra justo encima de programa región. (La región del programa se llama técnicamente texto región. Es donde se almacenan las instrucciones de la máquina.)
  • La región de datos mundial y estática es técnicamente dos regiones. Una región se llama segmento inicial de datos, donde se almacenan variables declaradas con valores predeterminados. La otra región se llama bloque iniciado por segmento, donde se almacenan variables declaradas sin valores predeterminados.
  • Variables almacenadas en datos globales y estáticos la región tiene sus direcciones establecidas a tiempo de compilación. Conservan sus valores a lo largo de la vida del proceso.
  • La región global y estática almacena la variables globales que se declaran en la parte superior de (fuera) main() función. Las variables globales son visibles main() y cualquier otra función en el código fuente.
Por otro lado, declaraciones variables dentro de main(), otras funciones o dentro { } bloque delimitadores variables locales. Las variables locales también incluyen variables de parámetro formal. Las variables de parámetro se adjuntan dentro de la paréntesis de las definiciones de función. Proporcionan una interfaz a la función.
  • Variables locales declarado utilizando static prefijo también se almacenan en el datos globales y estáticos región. A diferencia de las variables globales, las variables estáticas sólo son visibles dentro de la función o bloque. Las variables estaticas siempre conservan su valor. Un uso de ejemplo sería la función int increment_counter(){ static int counter = 0; counter++; return counter;}
  • La región de la pila es un bloque contiguo de memoria situado cerca de la dirección de memoria superior. Las variables colocadas en la pila se poblan de arriba a abajo. Un puntero de pila es un registro de propósito especial que mantiene la pista de la última dirección de memoria poblada. Las variables se colocan en la pila a través de la idioma de reunión Instrucción PUSH. Por lo tanto, las direcciones de estas variables se establecen durante el tiempo de ejecución. El método para apilar variables para perder su alcance es a través de la instrucción POP.
  • Variables locales declarado sin static prefijo, incluyendo variables de parámetro formales, se llaman variables automáticas y se almacenan en la pila. Son visibles dentro de la función o bloque y pierden su alcance al salir de la función o bloque.
  • La región del montón se encuentra debajo de la pila. Está poblada desde abajo hasta arriba. El sistema operativo maneja el montón usando un Heap pointer y una lista de bloques de memoria asignados. Como la pila, las direcciones de las variables del montón se establecen durante el tiempo de ejecución. Un error de memoria se produce cuando el puntero del montón y el puntero de la pila se encuentran.
  • C proporciona el malloc() función bibliotecaria para asignar la memoria del montón. Popular el montón con datos es una función de copia adicional. Las variables almacenadas en el montón se pasan económicamente a funciones usando punteros. Sin punteros, todo el bloque de datos tendría que pasar a la función a través de la pila.

C++

En la década de 1970, los ingenieros de software necesitaban soporte lingüístico para dividir grandes proyectos en módulos. Una característica obvia era descomponer proyectos grandes físicamente en archivos separados. Una característica menos obvia era descomponer proyectos grandes lógicamente en tipos de datos abstractos. En ese momento, los lenguajes admitían tipos de datos concretos (escalares) como números enteros, números de coma flotante y cadenas de caracteres. Los tipos de datos concretos tienen su representación como parte de su nombre. Los tipos de datos abstractos son estructuras de tipos de datos concretos, con un nuevo nombre asignado. Por ejemplo, una lista de enteros podría llamarse integer_list.

En la jerga orientada a objetos, los tipos de datos abstractos se denominan clases. Sin embargo, una clase es solo una definición; no se asigna memoria. Cuando la memoria se asigna a una clase, se denomina objeto.

Lenguajes imperativos orientados a objetos desarrollados combinando la necesidad de clases y la necesidad de una programación funcional segura. Una función, en un lenguaje orientado a objetos, se asigna a una clase. Una función asignada se denomina método, función miembro u operación. La programación orientada a objetos ejecuta operaciones en objetos.

Los lenguajes orientados a objetos admiten una sintaxis para modelar relaciones de subconjunto/superconjunto. En la teoría de conjuntos, un elemento de un subconjunto hereda todos los atributos contenidos en el superconjunto. Por ejemplo, un estudiante es una persona. Por lo tanto, el conjunto de estudiantes es un subconjunto del conjunto de personas. Como resultado, los estudiantes heredan todos los atributos comunes a todas las personas. Además, los estudiantes tienen atributos únicos que otras personas no tienen. Los lenguajes orientados a objetos modelan las relaciones subconjunto/superconjunto utilizando la herencia. La programación orientada a objetos se convirtió en el paradigma de lenguaje dominante a fines de la década de 1990.

C++ (1985) originalmente se llamaba "C con clases." Fue diseñado para expandir las capacidades de C's agregando las funciones orientadas a objetos del lenguaje Simula.

Un módulo orientado a objetos se compone de dos archivos. El archivo de definiciones se denomina archivo de encabezado. Aquí hay un archivo de encabezado de C++ para la clase GRADE en una aplicación escolar simple:

// grado. h-----// Se utiliza para permitir que varios archivos de origen incluyan// este archivo de encabezado sin errores de duplicación.// ----------#ifndef GRADE_H#define GRADE_Hclase GRADE {}público: // Esta es la operación del constructor. // - Sí. GRADE () const char carta ); // Es una variable de clase. // ------- char carta; // Esta es una operación miembro. // --------- int grade_numeric() const char carta ); // Es una variable de clase. // ------- int numérico;};#endif

Una operación constructora es una función con el mismo nombre que el nombre de la clase. Se ejecuta cuando la operación de llamada ejecuta la instrucción new.

El otro archivo de un módulo es el archivo fuente. Aquí hay un archivo fuente de C++ para la clase GRADE en una aplicación escolar sencilla:

// grade.cpp// -------#include "grado.h"GRADE::GRADE() const char carta ){} // Referencia al objeto usando la palabra clave 'esto'. // ---------- esto-carta = carta; // Esta es la Cohesión Temporal // ------- esto-numérico = grade_numeric() carta );}int GRADE::grade_numeric() const char carta ){} si () () carta == 'A ' Silencio carta == 'a' ) ) retorno 4; más si () () carta == B ' Silencio carta == 'b ' ) ) retorno 3; más si () () carta == 'C' Silencio carta == 'c ' ) ) retorno 2; más si () () carta == 'D' Silencio carta == 'd ' ) ) retorno 1; más si () () carta == 'F ' Silencio carta == 'f ' ) ) retorno 0; más retorno -1;}

Aquí hay un archivo de encabezado de C++ para la clase PERSONA en una aplicación escolar simple:

// persona. h-------#ifndef PERSON_H#define PERSON_Hclase PERSONAL {}público: PERSONAL () const char *Nombre ); const char *Nombre;};#endif

Aquí hay un archivo fuente de C++ para la clase PERSONA en una aplicación escolar simple:

// person.cpp// ----------#include "persona".PERSONAL::PERSONAL () const char *Nombre ){} esto-Nombre = Nombre;}

Aquí hay un archivo de encabezado de C++ para la clase ESTUDIANTE en una aplicación escolar simple:

// estudiante. h// -------#ifndef STUDENT_H#define STUDENT_H#include "persona".#include "grado.h"// Un STUDENT es un subconjunto de PERSONA.//.clase ESTUDIO : público PERSONAL{}público: ESTUDIO () const char *Nombre ); GRADE *grado;};#endif

Aquí hay un archivo fuente de C++ para la clase ESTUDIANTE en una aplicación escolar sencilla:

// student.cpp// ---------#include "Student.h"#include "persona".ESTUDIO::ESTUDIO () const char *Nombre ): // Ejecute al constructor de la superclase PERSON. // - Sí. PERSONAL() Nombre ){} // Nada más que hacer. // ---}

Aquí hay un programa controlador para demostración:

// student_dvr.cpp// ---------------#include ■iostream#include "Student.h"int principal() vacío ){} ESTUDIO *estudiante = nuevo ESTUDIO() "El Estudiante" ); estudiante-grado = nuevo GRADE() 'a' ); std::Cout  // Aviso estudiante hereda el nombre de PERSON .. estudiante-Nombre .. ": grado numérico = " .. estudiante-grado-numérico .. "n";retorno 0;}

Aquí hay un archivo MAKE para compilar todo:

# makefile# --------Todos: estudiante_dvrlimpio: rm estudiante_dvr *.o

estudiante_dvr: estudiante_dvr.cpp grado.o estudiante.o persona.o c++ student_dvr.cpp grado.o estudiante.o persona.o -o estudiante_dvr

grado.o: grado.cpp grado.h c++ -c grado.cpp

estudiante.o: estudiante.cpp estudiante.h c++ -c estudiante.cpp

persona.o: persona.cpp persona.h c++ -c person.cpp

Contenido relacionado

Arte ASCII

Arte ASCII es una técnica de diseño gráfico que utiliza computadoras para la presentación y consiste en imágenes ensambladas a partir de los 95...

Sistema de confianza

En la subespecialidad de ingeniería de seguridad de la informática, un sistema confiable es uno en el que se confía hasta cierto punto para hacer cumplir...

KHTML

KHTML es un motor de navegador discontinuado que fue desarrollado por el proyecto KDE. Se originó como el motor del navegador Konqueror a fines de la década...
Más resultados...
Tamaño del texto:
Copiar