Introducción

¿Cuáles son los diferentes lenguajes de programación? ¿Qué tipo de conceptos están incrustados en ellos? ¿Cómo se desarrollaron? En este artículo, veremos los tipos de lenguajes de programación según los llamados niveles, desde códigos de máquina (nivel bajo, cercano al hardware de la computadora) hasta lenguajes como Java o C# (nivel alto). Cuantas menos transformaciones sufra el listado de texto del programa a lo largo del proceso de convertirse en un conjunto de ceros y unos, menor será el nivel.
Niveles de lenguajes de programación - 1
A continuación veremos:
  1. Lenguajes de bajo nivel (códigos máquina y ensamblador)
  2. Nivel intermedio (C, Fortran….)
  3. Alto nivel (C++, Java, Python, Ruby, JavaScript...)
El nivel también caracteriza cuánto detalle debe detallarse la lista del programa futuro para implementar la implementación. ¿Qué tan simple es este proceso para los humanos? El nivel de un idioma no debe considerarse un indicador inequívoco de sus capacidades. Un lenguaje de programación es una herramienta que es efectiva en un área y menos útil en otras. Tanto el carpintero como el carpintero trabajan con madera. El primero tiene una herramienta principal: un juego de cinceles, el segundo, un hacha. Sin embargo, un carpintero hará que un gabinete tallado sea más elegante y un carpintero construirá una casa más rápido. Aunque cada uno es capaz de hacer el trabajo del otro, lo hará de manera mucho menos eficiente. Varios datos en una computadora se representan como conjuntos de ceros y unos. Los comandos de control para su procesamiento son los mismos datos que contienen instrucciones que determinan la ubicación de la información necesaria y el método de modificación.

Lenguajes de máquina (Nivel más bajo)

Tendremos que realizar una breve visita desde el área de Software al área de Hardware. Veámoslo de forma simplificada. El procesador es el “cerebro” principal de la computadora. La placa base en la que está instalado contiene controladores que se utilizan para interactuar con otros dispositivos a través de buses (canales de datos para comunicación).
Niveles de lenguajes de programación - 2
Algunos funcionan a alta velocidad (flechas rojas): el procesador extrae comandos de la memoria y manipula datos, la tarjeta de video, especialmente en los juegos 3D, consume grandes cantidades de texturas, formas, coordenadas de píxeles y otros objetos para construir una imagen en la pantalla del monitor. . Otros (debido a limitaciones en la velocidad del intercambio de información) no necesitan indicadores tan altos. Varios dispositivos internos y externos están conectados en el diagrama con flechas verdes.

El mundo interior del procesador.

Todos los comandos del procesador provienen de la memoria para su ejecución en formato binario. El formato, número y subconjunto de instrucciones dependen de su arquitectura. La mayoría de ellos son incompatibles entre sí y siguen ideologías diferentes. Y también el tipo de comando depende en gran medida del modo (8/16/32... profundidad de bits) y de la fuente de datos (memoria, registro, pila...) con la que trabaja el procesador. Una misma acción puede estar representada por diferentes instrucciones. El procesador tiene instrucciones para sumar dos operandos (ADD X,Y) y sumar uno al especificado (INC X). Se puede agregar un triple a un operando como ADD X,3 o llamando tres veces a INC X. Y, para diferentes procesadores, es imposible predecir cuál de estos métodos será óptimo en términos de velocidad o huella de memoria. Por conveniencia, la información binaria se escribe en forma hexadecimal. Consideremos parte de un programa familiar (lenguaje C, cuya sintaxis es similar a Java)
int func() {
    int i = getData("7") ;
    return ++i;
   ...
}
Código que implementa las mismas acciones en forma de una secuencia de instrucciones para el procesador: ... 48 83 ec 08 bf bc 05 20 00 31 c0 e8 e8 fe ff ff 48 83 c4 08 83 c0 01 ... así es como se ve realmente el lenguaje de programación de bajo nivel para el procesador Intel. Un fragmento que llama a un método con un argumento y devuelve el resultado incrementado en uno. Este es un lenguaje de máquina (código) que se transfiere directamente, sin transformaciones, al procesador para su ejecución. Ventajas:
  • Somos completamente dueños de la situación, tenemos las más amplias posibilidades para utilizar el procesador y el hardware de la computadora.
  • Todas las opciones para organizar y optimizar el código están disponibles para nosotros.
Desventajas:
  • Es necesario tener amplios conocimientos sobre el funcionamiento de los procesadores y tener en cuenta una gran cantidad de factores de hardware a la hora de ejecutar el código.
  • La creación de programas que son un poco más complejos que el ejemplo dado lleva a un fuerte aumento en el tiempo dedicado a escribir código y depurarlo.
  • Dependencia de plataforma: un programa creado para un procesador generalmente no funcionará en otros. Es posible que para este procesador, en otros modos de funcionamiento, se requiera edición de código.
Los códigos de máquina se utilizaron ampliamente en los albores de las computadoras; no existían otros métodos de programación en la era de los pioneros de las computadoras. Actualmente, los ingenieros en microelectrónica los utilizan ocasionalmente cuando desarrollan o realizan pruebas de bajo nivel de procesadores.

Lenguaje ensamblador (nivel bajo)

A diferencia de una computadora, usted y yo percibimos mejor la información en forma textual/semántica que en forma digital. Puede nombrar fácilmente cincuenta nombres de contactos en su teléfono inteligente, pero es poco probable que pueda escribir de memoria sus números de teléfono correspondientes. Lo mismo ocurre con la programación. Ascendemos en la escala de tipos siguiendo tres pasos básicos:
  • Asociemos una instrucción simbólica a grupos de instrucciones de procesador digital que realizan acciones correspondientes.
  • Resaltemos los argumentos de las instrucciones del procesador por separado.
  • Introduzcamos la capacidad de nombrar áreas de memoria, variables y la ubicación de comandos individuales.
Comparemos fragmentos del programa anterior en código máquina (centro) y en lenguaje ensamblador (derecha):
2004b0     48 83 ec 08      sub    $0x8,%rsp
2004b4     bf bc 05 20 00   mov    $0x2005bc,%edi
2004b9     31 c0            xor    %eax,%eax
2004bb     e8 e8 fe ff ff   callq  getData
2004c0     48 83 c4 08      add    $0x8,%rsp
2004c4     83 c0 01         add    $0x1,%eax
Como puede ver, el proceso de escritura de un programa se ha simplificado: no es necesario utilizar libros de referencia para generar valores de comandos digitales, calcular longitudes de transición, distribuir datos en la memoria entre sus celdas y otras funciones del procesador. Describimos la acción requerida a partir de un conjunto de comandos simbólicos y los argumentos necesarios para la lógica de ejecución, y luego el programa traductor traduce el archivo de texto a un conjunto de ceros y unos comprensibles para el procesador. Ventajas:
  • Se ha simplificado el proceso de escritura y modificación de código.
  • Se mantuvo el control sobre todos los recursos de hardware.
  • Es relativamente más fácil trasladar el programa a otras plataformas, pero requieren modificaciones según la compatibilidad del hardware.
Desventajas:
  • El lenguaje ensamblador es un lenguaje de programación de bajo nivel. Crear incluso pequeñas secciones de código es difícil. Además, también es necesario tener en cuenta el funcionamiento específico del equipo.
  • Dependencia de la plataforma.
El ejemplo de demostración de Java más popular:
public static void main(String[] args) {
    System.out.println("Hello World!");
}
se verá (sintaxis NASM, usando la API de Windows y kernel32.lib) de la siguiente manera:
global _main
	extern  _GetStdHandle@4
	extern  _WriteFile@20
	extern  _ExitProcess@4

	section .text
_main:
	; DWORD  bytes;
	mov 	ebp, esp
	sub 	esp, 4

	; hStdOut = GetstdHandle( STD_OUTPUT_HANDLE)
	push	-11
	call	_GetStdHandle@4
	mov 	ebx, eax

	; WriteFile( hstdOut, message, length(message), &bytes, 0);
    push	0
	lea 	eax, [ebp-4]
	push	eax
	push	(message_end - message)
	push	message
	push	ebx
	call	_WriteFile@20

	; ExitProcess(0)
	push	0
	call	_ExitProcess@4

	; never here
	hlt
message:
	db  	'Hello, World', 10
message_end:
Al igual que los códigos de máquina, los ingenieros y programadores de sistemas utilizan con mayor frecuencia el lenguaje ensamblador. Se utiliza para escribir partes del kernel del sistema operativo que dependen del hardware y que son críticas en el tiempo o críticas para las funciones de implementación de los controladores para varios dispositivos periféricos. Pero últimamente cada vez recurren menos a él, ya que su uso reduce mucho la portabilidad de los programas a otras plataformas. A veces utilizan el proceso de desmontaje: crean una lista de ensamblaje de un programa a partir de códigos digitales para analizar la lógica de ejecución de pequeños fragmentos. En casos excepcionales, si el código original de alto nivel no está disponible: análisis de virus para combatirlos o pérdida del código fuente. El lenguaje ensamblador se considera de primera/segunda generación (no consideraremos por separado los pseudocódigos anteriores a la aparición del ensamblador y su diferencia con los comandos simbólicos). Me gustaría destacar el uso del ensamblador en Demo Scene: una fusión de arte, matemáticas y codificación de bajo nivel, que plasma las ideas artísticas de sus creadores en forma de programas que generan videoclips con limitaciones de recursos. A menudo, el tamaño total del programa y del archivo de datos no debe exceder los 256 bytes (el formato de 4/64 kilobytes también es popular). A continuación se muestra un ejemplo de un programa de 4 KB:

Idiomas grupo C/Fortran (nivel intermedio/alto)

Con el desarrollo de las capacidades de la tecnología informática, el volumen de funcionalidad y los plazos de implementación del código en ensamblador ya no eran satisfactorios. Los costos de escribir, probar y mantener programas crecieron un orden de magnitud más rápido que sus capacidades. Era necesario reducir las exigencias del programador en cuanto a conocimiento del funcionamiento del equipo, para darle una herramienta que le permitiera escribir en lenguajes cercanos a la lógica humana. Pase a un nuevo nivel de tipos de lenguajes de programación. Proporcionar la capacidad de dividirse en varios módulos con llamadas secuenciales adicionales (paradigma de programación procedimental), proporcionar varios tipos de datos con la capacidad de construirlos, etc. Además, estas medidas trajeron una mejor portabilidad del código a otras plataformas, una organización más cómoda de trabajo en equipo. Uno de los primeros lenguajes que apoyó todo lo anterior fue Fortran, desarrollado en los años 50 del siglo pasado . La capacidad de crear en forma de texto una descripción de la lógica de ejecución utilizando bucles, ramas, subrutinas y operando con matrices y presentando datos en forma de números reales, enteros y complejos deleitó a ingenieros y científicos. En poco tiempo se crearon “marcos” científicos y bibliotecas. Todo esto fue una consecuencia del hecho de que Fortran sigue siendo relevante hoy, aunque en un entorno científico limitado, y se está desarrollando, ya que el bagaje de desarrollos es muy grande, solo la biblioteca IMSL se ha estado desarrollando activamente desde 1970 (!), como ¿Puedes recordar muchos programas relevantes similares? -¿Los veteranos? Otra rama del desarrollo de lenguajes a este nivel es C. Si Fortran se convirtió en una herramienta para los científicos, entonces C se creó para ayudar a los programadores a crear software de aplicaciones: sistemas operativos, controladores, etc. El lenguaje le permite controlar manualmente la asignación de memoria y brinda acceso directo a los recursos de hardware. Los programadores de C tienen que controlar entidades de bajo nivel, por lo que muchos opinan que C es un lenguaje ensamblador avanzado y a menudo se le llama lenguaje de "nivel medio". Habiendo introducido la tipificación de datos en ensamblador, elementos de programación procedimental y modular, el lenguaje C sigue siendo uno de los principales lenguajes para la programación de sistemas, lo que también se ve facilitado por el rápido desarrollo de la microelectrónica en los últimos tiempos. Todo tipo de dispositivos, controladores, redes y otros dispositivos necesitan controladores, implementación de protocolos de colaboración y otro software de nivel relativamente bajo para implementar la interacción con el equipo. Todo lo anterior contribuye a la demanda del idioma en la actualidad. Los principios funcionales y orientados a objetos se desarrollaron aún más en forma de C++, C#, Java, tomando mucho de la sintaxis de C. Ventajas:
  • Simplificación del proceso de creación de código: introducción de tipos, división en módulos, reducción de listados de programas.
  • Lógica transparente del algoritmo subyacente debido al alejamiento de los códigos de máquina hacia comandos más legibles por humanos en un estilo semánticamente descriptivo.
  • Portabilidad. Fue suficiente volver a compilar el texto del programa para ejecutarlo en otra plataforma (posiblemente con una ligera modificación).
  • Velocidad de los programas compilados.
Desventajas:
  • Falta de gestión automática de la memoria y necesidad de un seguimiento constante.
  • Falta de implementación de conceptos de programación funcional y orientada a objetos.

Desarrollo de lenguajes de alto nivel.

Los lenguajes de programación de alto nivel, en términos de creación de software, han comenzado cada vez más a alejarse de los códigos de máquina e implementar varios paradigmas de programación además de los procedimentales. Estos también incluyen la implementación de principios orientados a objetos. C++, Java, Python, JavaScript, Ruby... - la gama de lenguajes de este tipo es la más popular y demandada en la actualidad. Brindan más oportunidades para implementar una variedad de software y es imposible determinar claramente la "especialización" de cada uno de ellos. Pero la popularidad de la aplicación en áreas relevantes se debe a las bibliotecas/marcos para trabajar con ellas, por ejemplo: JavaScript - Frontend. El lenguaje fue diseñado para la interacción entre un navegador web cliente y un usuario y un servidor remoto. Las bibliotecas más populares son Angular, React y VUE. Actualmente, se utiliza de forma relativamente activa en la web y otros servidores (backend), Node.js es especialmente popular. Rubí : backend. Se utiliza para crear scripts (archivos de servicio) y en servidores web. El marco principal es Ruby On Rails. Python es un dominio científico y de ingeniería (además del dominio web). Es una alternativa a los paquetes informáticos y matemáticos estándar (Mathematica, Octave, MatLab...), pero tiene la semántica habitual del lenguaje y una gran cantidad de bibliotecas. Tiene muchos seguidores en el campo de los sistemas de aprendizaje automático, la estadística y la inteligencia artificial. Las bibliotecas de uso frecuente incluyen django, numpy, pandas y tensorflow. C++ : desarrollo universal y evolutivo del lenguaje C. Proporciona capacidades de programación funcionales y orientadas a objetos sin perder la capacidad de interactuar con hardware de bajo nivel. Gracias a esto, se logra productividad y flexibilidad a la hora de crear software, pero el precio también corresponde: una alta barrera de entrada debido a la compleja especificación del lenguaje, la necesidad de un control independiente de los recursos al ejecutar el programa. Con él se escriben muchos software monousuario y de sistema: módulos de sistema operativo (Windows, Symbian...), juegos, editores (Adobe Photoshop, Autodesk Maya...), bases de datos (MSSQL, Oracle...), reproductores ( WinAmp...), etc. Cabe señalar que el software moderno es un producto complejo, en cuyo desarrollo se utilizan varios lenguajes de programación a la vez, y puede resultar muy difícil determinar el grado de participación de cada uno de ellos en el resultado global.

Mayor progreso

Recientemente, otro tipo de programación está ganando popularidad: funcional (mayor desarrollo del nivel del lenguaje) . Aquí hay otro tipo de abstracción para los cálculos: funciones que toman un conjunto de funciones como argumentos y devuelven otra. El papel de las variables lo desempeñan las mismas funciones (las variables que nos son familiares son simplemente expresiones constantes, similares a final antes de una declaración de tipo en Java). La función en sí tiene un alcance cerrado, el resultado de su operación depende únicamente de los argumentos pasados. De esto se desprenden dos propiedades notables:
  • Para las pruebas, solo necesitamos argumentos de función (el resultado del trabajo no depende de variables externas, etc.).
  • Un programa de estilo funcional está milagrosamente preparado para la concurrencia: las llamadas a funciones secuenciales se pueden emitir en subprocesos vecinos (ya que no se ven afectados por factores externos) y no requieren bloqueos (es decir, no hay problemas de sincronización). Un buen incentivo para dedicar tiempo a este tema, dada la adopción generalizada de procesadores multinúcleo.
Sin embargo, el umbral de entrada es más alto que para la programación orientada a objetos: para que el código sea eficaz es necesario crear un programa que describa el algoritmo de ejecución en forma de funciones. Pero también para un estilo puramente funcional sería bueno conocer los conceptos básicos de lógica y teoría de categorías. Los más populares son Haskell, Scala y F#. Pero no tenga miedo, en Java (así como en otros lenguajes modernos de tercera generación) han aparecido elementos de programación funcional que se pueden combinar con la programación orientada a objetos. Conocerás todos estos detalles con más detalle en la pasantía en línea de JavaRush. El campo de la programación lógica (el siguiente nivel de lenguajes) aún no ha encontrado una amplia aplicación práctica debido a su baja demanda. La creación de programas requiere conocimiento de los fundamentos de las matemáticas discretas, la lógica de predicados, las herramientas de restricciones y otras ramas de la lógica matemática. El lenguaje activo más popular es Prolog.

Conclusión

Actualmente, los lenguajes más comunes son la programación orientada a objetos. Java, desde sus inicios, siempre ha estado entre los principales lenguajes populares, generalmente entre los tres principales. Además de POO, contiene elementos de programación funcional y puede combinar diferentes estilos de escritura de sus programas. La gama de aplicaciones de Java es muy amplia: se trata de tareas comerciales, la implementación de servidores web (backend), el lenguaje principal para crear aplicaciones de Android, entornos de programación y lugares de trabajo multiplataforma (IDE/AWM) y modelado, y mucho más. . La posición de Java es especialmente fuerte en el sector empresarial, un área de software corporativo que requiere código duradero y de alta calidad y la implementación de la lógica empresarial más compleja.