Introducción a las secuencias de comandos en Java, parte 1

Extracto de Scripting en Java: lenguajes, marcos y patrones .

Por Dejan Bosanac

Publicado por Addison Wesley Professional

ISBN-10: 0-321-32193-6

ISBN-13: 978-0-321-32193-0

Hasta hace poco, solo los expertos estaban entusiasmados con la creación de scripts en la plataforma Java, pero eso fue antes de que Sun aumentara el soporte del JRE para lenguajes de tipado dinámico como Python, Ruby y JavaScript. En este extracto de dos partes del próximo Scripting in Java: Languages, Frameworks, and Patterns (Addison Wesley Professional, agosto de 2007), Dejan Bosanac se centra en lo que diferencia a la mayoría de los lenguajes de scripting de un lenguaje de programación como Java, luego explica por qué el scripting es un adición valiosa a su conjunto de habilidades de programación Java.

Introducción a las secuencias de comandos en Java: lenguajes, marcos y patrones

El tema principal de este libro es la sinergia de las tecnologías de scripting y la plataforma Java. Describo los proyectos que los desarrolladores de Java pueden utilizar para crear un entorno de desarrollo más potente y algunas de las prácticas que hacen que las secuencias de comandos sean útiles.

Antes de comenzar a discutir la aplicación de scripting en el mundo de Java, resumo parte de la teoría detrás de scripting en general y su uso en la infraestructura de tecnología de la información. Este es el tema de los dos primeros capítulos del libro y nos da una mejor perspectiva de la tecnología de scripting, así como también de cómo esta tecnología puede ser útil dentro de la plataforma Java.

Para empezar, debemos definir qué son los lenguajes de script y describir sus características. Sus características determinan en gran medida los roles en los que podrían (deberían) utilizarse. En este capítulo, explico qué significa el término lenguaje de secuencias de comandos y analizo sus características básicas.

Al final de este capítulo, analizo las diferencias entre los lenguajes de programación de scripts y de sistemas y cómo estas diferencias los hacen adecuados para ciertos roles en el desarrollo.

Antecedentes

La definición de un lenguaje de secuencias de comandos es imprecisa y, a veces, inconsistente con la forma en que se usan los lenguajes de secuencias de comandos en el mundo real, por lo que es una buena idea resumir algunos de los conceptos básicos sobre programación y computación en general. Este resumen proporciona una base necesaria para definir lenguajes de scripting y discutir sus características.

Vamos a empezar desde el principio. Los procesadores ejecutan instrucciones de máquina , que operan con datos en los registros de los procesadores o en la memoria externa. En pocas palabras, una instrucción de máquina consta de una secuencia de dígitos binarios (0 y 1) y es específica del procesador particular en el que se ejecuta. Las instrucciones de la máquina consisten en el código de operación que le dice al procesador qué operación debe realizar y los operandos que representan los datos en los que se debe realizar la operación.

Por ejemplo, considere la simple operación de agregar un valor contenido en un registro al valor contenido en otro. Ahora imaginemos un procesador simple con un conjunto de instrucciones de 8 bits, donde los primeros 5 bits representan el código de operación (digamos, 00111 para la suma del valor del registro), y los registros se direccionan mediante un patrón de 3 bits. Podemos escribir este simple ejemplo de la siguiente manera:

00111001010

En este ejemplo, utilicé 001 y 010 para direccionar los registros número uno y dos (R1 y R2, respectivamente) del procesador.

Este método básico de computación ha sido bien conocido durante décadas y estoy seguro de que lo conoce. Varios tipos de procesadores tienen diferentes estrategias con respecto a cómo deben verse sus conjuntos de instrucciones (arquitectura RISC o CISC), pero desde el punto de vista del desarrollador de software, el único hecho importante es que el procesador es capaz de ejecutar solo instrucciones binarias. Independientemente del lenguaje de programación que se utilice, la aplicación resultante es una secuencia de instrucciones de la máquina ejecutadas por el procesador.

Lo que ha ido cambiando con el tiempo es cómo las personas crean el orden en el que se ejecutan las instrucciones de la máquina. Esta secuencia ordenada de instrucciones de la máquina se llama programa de computadora . A medida que el hardware se vuelve más asequible y más potente, las expectativas de los usuarios aumentan. Todo el propósito del desarrollo de software como disciplina científica es proporcionar mecanismos que permitan a los desarrolladores crear aplicaciones más complejas con el mismo (o incluso menos) esfuerzo que antes.

El conjunto de instrucciones de un procesador específico se denomina lenguaje de máquina . Los lenguajes de máquina se clasifican como lenguajes de programación de primera generación. Los programas escritos de esta manera suelen ser muy rápidos porque están optimizados para la arquitectura del procesador en particular. Pero a pesar de este beneficio, es difícil (si no imposible) para los humanos escribir aplicaciones grandes y seguras en lenguajes de máquina porque los humanos no son buenos para lidiar con grandes secuencias de 0 y 1.

En un intento por resolver este problema, los desarrolladores comenzaron a crear símbolos para ciertos patrones binarios y, con esto, se introdujeron los lenguajes ensambladores . Los lenguajes ensambladores son lenguajes de programación de segunda generación . Las instrucciones en lenguajes ensambladores están solo un nivel por encima de las instrucciones de la máquina, ya que reemplazan dígitos binarios con palabras clave fáciles de recordar como ADD, SUB, etc. Como tal, puede reescribir el ejemplo de instrucción simple anterior en lenguaje ensamblador de la siguiente manera:

AÑADIR R1, R2

En este ejemplo, la palabra clave ADD representa el código de operación de la instrucción, y R1 y R2 definen los registros involucrados en la operación. Incluso si observa este simple ejemplo, es obvio que los lenguajes ensambladores hicieron que los programas fueran más fáciles de leer para los humanos y por lo tanto permitieron la creación de aplicaciones más complejas.

Aunque están más orientados a las personas, los lenguajes de segunda generación no amplían las capacidades del procesador de ninguna manera.

Introduzca lenguajes de alto nivel , que permiten a los desarrolladores expresarse en formas semánticas de alto nivel. Como habrás adivinado, estos lenguajes se conocen como lenguajes de programación de tercera generación . Los lenguajes de alto nivel proporcionan varios bucles potentes, estructuras de datos, objetos, etc., lo que hace que sea mucho más fácil crear muchas aplicaciones con ellos.

Con el tiempo, se introdujeron una amplia gama de lenguajes de programación de alto nivel y sus características variaron mucho. Algunas de estas características categorizan los lenguajes de programación como lenguajes de scripting (o dinámicos), como veremos en las próximas secciones.

Además, existe una diferencia en cómo se ejecutan los lenguajes de programación en la máquina host. Por lo general, los compiladores traducen construcciones de lenguaje de alto nivel en instrucciones de máquina que residen en la memoria. Aunque los programas escritos de esta manera inicialmente eran ligeramente menos eficientes que los programas escritos en lenguaje ensamblador debido a la incapacidad de los primeros compiladores para usar los recursos del sistema de manera eficiente, a medida que pasaba el tiempo, los compiladores y las máquinas mejoraron, haciendo que los lenguajes de programación del sistema fueran superiores a los lenguajes ensambladores. Con el tiempo, los lenguajes de alto nivel se hicieron populares en una amplia gama de áreas de desarrollo, desde aplicaciones comerciales y juegos hasta software de comunicaciones e implementaciones de sistemas operativos.

Pero hay otra forma de transformar construcciones semánticas de alto nivel en instrucciones de máquina, y es interpretarlas a medida que se ejecutan. De esta manera, sus aplicaciones residen en scripts, en su forma original, y las construcciones son transformadas en tiempo de ejecución por un programa llamado intérprete . Básicamente, estás ejecutando el intérprete que lee las declaraciones de tu aplicación y luego las ejecuta. Estos lenguajes, denominados scripting o lenguajes dinámicos , ofrecen un nivel de abstracción aún mayor que el ofrecido por los lenguajes de programación de sistemas, y los discutiremos en detalle más adelante en este capítulo.

Los lenguajes con estas características se adaptan naturalmente a determinadas tareas, como la automatización de procesos, la administración de sistemas y la unión de componentes de software existentes; en resumen, en cualquier lugar la sintaxis estricta y las restricciones introducidas por los lenguajes de programación de sistemas se interponían entre los desarrolladores y sus trabajos. Una descripción de las funciones habituales de los lenguajes de secuencias de comandos es un tema central del Capítulo 2, "Aplicaciones apropiadas para lenguajes de secuencias de comandos".

Pero, ¿qué tiene que ver todo esto contigo como desarrollador de Java? Para responder a esta pregunta, primero resumamos brevemente la historia de la plataforma Java. A medida que las plataformas se volvieron más diversas, a los desarrolladores les resultó cada vez más difícil escribir software que pueda ejecutarse en la mayoría de los sistemas disponibles. Fue entonces cuando Sun desarrolló Java, que ofrece la simplicidad de "escribir una vez, ejecutar en cualquier lugar".

La idea principal detrás de la plataforma Java era implementar un procesador virtual como un componente de software, llamado máquina virtual . Cuando tenemos una máquina virtual de este tipo, podemos escribir y compilar el código para ese procesador, en lugar de la plataforma de hardware o el sistema operativo específicos. El resultado de este proceso de compilación se denomina código de bytes y prácticamente representa el código de la máquina virtual de destino. Cuando se ejecuta la aplicación, se inicia la máquina virtual y se interpreta el código de bytes. Es obvio que una aplicación desarrollada de esta manera puede ejecutarse en cualquier plataforma con una máquina virtual apropiada instalada. Este enfoque del desarrollo de software encontró muchos usos interesantes.

La principal motivación para la invención de la plataforma Java fue crear un entorno para el desarrollo de software cliente fácil, portátil y compatible con la red. Pero principalmente debido a las limitaciones de rendimiento introducidas por la máquina virtual, Java es ahora más adecuado en el área del desarrollo de software de servidor. Está claro que a medida que las computadoras personales aumentan en velocidad, se escriben más aplicaciones de escritorio en Java. Esta tendencia solo continúa.

Uno de los requisitos básicos de un lenguaje de scripting es tener un intérprete o algún tipo de máquina virtual. La plataforma Java viene con Java Virtual Machine (JVM), que le permite ser un host para varios lenguajes de scripting. Actualmente, existe un creciente interés en esta área en la comunidad Java. Existen pocos proyectos que intenten proporcionar a los desarrolladores de Java la misma potencia que tienen los desarrolladores de los lenguajes de scripting tradicionales. Además, existe una forma de ejecutar su aplicación existente escrita en un lenguaje dinámico como Python dentro de la JVM e integrarla con otra aplicación o módulo Java.

Esto es lo que discutimos en este libro. Adoptamos un enfoque de scripting para la programación, mientras discutimos todas las fortalezas y debilidades de este enfoque, cómo usar mejor los scripts en una arquitectura de aplicación y qué herramientas están disponibles hoy en día dentro de la JVM.