Sei sulla pagina 1di 26

QUE ES UN ALGORITMO

Siguiendo al concepto de informática, hoy afrontamos el concepto de


algoritmo. La historia de la informática señala a Abu Abdullah Muhammad bin
Musa al-Khwarizmi, una de las grandes figuras de la matemática árabe
medieval como descubridor del concepto de algoritmo. En su obra "aljabar wa-
al-muqabala" sienta las bases del algebra, cuyo nombre procede del comienzo
del título, así como "algoritmo" procede del nombre del autor, al-Khwarizmi.

Podemos definir algoritmo como un conjunto de pasos o instrucciones finito que


se deben seguir para realizar una determinada tarea.

Para que dicho conjunto de instrucciones sea considerado un algoritmo, ha de


cumplir algunas características:

¾ Un mismo conjunto de datos de partida se debe llegar siempre a un


mismo conjunto de resultados.
¾ Las instrucciones han de ser precisas, sin ambiguedad alguna.
¾ El conjunto ha de ser finito.

Pedagógicamente se suele dar como ejemplo de algoritmo una receta de


cocina. La analogía es clara, siempre que no olvidemos que estamos ante un
concepto matemático
LENGUAJES DE PROGRAMACIÓN

Un lenguaje de programación es un lenguaje que puede ser utilizado para


controlar el comportamiento de una máquina, particularmente una
computadora. Consiste en un conjunto de símbolos y reglas sintácticas y
semánticas que definen su estructura y el significado de sus elementos y
expresiones.

Aunque muchas veces se usa lenguaje de programación y lenguaje informático


como si fuesen sinónimos, no tiene por qué ser así, ya que los lenguajes
informáticos engloban a los lenguajes de programación y a otros más, como,
por ejemplo, el HTML (lenguaje para el marcado de páginas web).

Un lenguaje de programación permite a uno o más programadores especificar


de manera precisa: sobre qué datos una computadora debe operar, cómo
deben ser estos almacenados, transmitidos y qué acciones debe tomar bajo
una variada gama de circunstancias. Todo esto, a través de un lenguaje que
intenta estar relativamente próximo al lenguaje humano o natural, tal como
sucede con el lenguaje Léxico. Una característica relevante de los lenguajes de
programación es precisamente que más de un programador puedan tener un
conjunto común de instrucciones que puedan ser comprendidas entre ellos
para realizar la construcción del programa de forma colaborativa.

Los procesadores usados en las computadoras son capaces de entender y


actuar según lo indican programas escritos en un lenguaje fijo llamado lenguaje
de máquina. Todo programa escrito en otro lenguaje puede ser ejecutado de
dos maneras:

¾ Mediante un programa que va adaptando las instrucciones conforme


son encontradas. A este proceso se lo llama interpretar y a los
programas que lo hacen se los conoce como intérpretes.
¾ Traduciendo este programa al programa equivalente escrito en
lenguaje de máquina. A ese proceso se lo llama compilar y al
traductor se lo conoce como un malhecho compilador.
HISTORIA DE PROGRAMACIÓN

Al desarrollarse las primeras computadoras electrónicas, se vio la


necesidad de programarlas, es decir, de almacenar en memoria la información
sobre la tarea que iban a ejecutar. Las primeras se usaban como calculadoras
simples; se les indicaban los pasos de cálculo, uno por uno.

John Von Neumann desarrolló el modelo que lleva su nombre, para describir
este concepto de "programa almacenado". En este modelo, se tiene una
abstracción de la memoria como un conjunto de celdas, que almacenan
simplemente números. Estos números pueden representar dos cosas: los
datos, sobre los que va a trabajar el programa; o bien, el programa en sí.

¿Cómo es que describimos un programa como números? Se tenía el problema


de representar las acciones que iba a realizar la computadora, y que la
memoria, al estar compuesta por switches correspondientes al concepto de bit,
solamente nos permitía almacenar números binarios.

La solución que se tomó fue la siguiente: a cada acción que sea capaz de
realizar nuestra computadora, asociarle un número, que será su código de
operación (opcode) . Por ejemplo, una calculadora programable simple podría
asignar los opcodes :

1 = SUMA, 2 = RESTA, 3 = MULTIPLICA, 4 = DIVIDE.

Supongamos que queremos realizar la operación 5 * 3 + 2, en la calculadora


descrita arriba. En memoria, podríamos "escribir" el programa de la siguiente
forma:

Localidad Opcode Significado Comentario 0 5 5 En esta localidad, tenemos el


primer número de la fórmula 1 3 * En esta localidad, tenemos el opcode que
representa la multiplicación. 2 3 3 En esta localidad, tenemos el segundo
número de la fórmula 3 1 + En esta localidad, tenemos el opcode que
representa la suma. 4 2 2 En esta localidad, tenemos el último número de la
fórmula
Podemos ver que con esta representación, es simple expresar las operaciones
de las que es capaz el hardware (en este caso, nuestra calculadora
imaginaria), en la memoria.

La descripción y uso de los opcodes es lo que llamamos lenguaje de máquina.


Es decir, la lista de códigos que la máquina va a interpretar como instrucciones,
describe las capacidades de programación que tenemos de ella; es el lenguaje
más primitivo, depende directamente del hardware, y requiere del programador
que conozca el funcionamiento de la máquina al más bajo nivel.

Los lenguajes más primitivos fueron los lenguajes de máquina. Esto, ya que el
hardware se desarrolló antes del software, y además cualquier software
finalmente tiene que expresarse en el lenguaje que maneja el hardware.

La programación en esos momentos era sumamente tediosa, pues el


programador tenía que "bajarse" al nivel de la máquina y decirle, paso a pasito,
cada punto de la tarea que tenía que realizar. Además, debía expresarlo en
forma numérica; y por supuesto, este proceso era propenso a errores, con lo
que la productividad del programador era muy limitada. Sin embargo, hay que
recordar que en estos momentos, simplemente aún no existía alternativa.

El primer gran avance que se dio, como ya se comentó, fue la abstracción dada
por el Lenguaje Ensamblador, y con él, el nacimiento de las primeras
herramientas automáticas para generar el código máquina. Esto redujo los
errores triviales, como podía ser el número que correspondía a una operación,
que son sumamente engorrosos y difíciles de detectar, pero fáciles de cometer.
Sin embargo, aún aquí es fácil para el programador perderse y cometer errores
de lógica, pues debe bajar al nivel de la forma en que trabaja el CPU, y
entender bien todo lo que sucede dentro de él.

Con el desarrollo en los 50s y 60s de algoritmos de más elevado nivel, y el


aumento de poder del hardware, empezaron a entrar al uso de computadoras
científicos de otras ramas; ellos conocían mucho de Física, Química y otras
ramas similares, pero no de Computación, y por supuesto, les era sumamente
complicado trabajar con lenguaje Ensamblador en vez de fórmulas. Así, nació
el concepto de Lenguaje de Alto Nivel, con el primer compilador de FORTRAN
(FORmula TRANslation), que, como su nombre indica, inició como un "simple"
esfuerzo de traducir un lenguaje de fórmulas, al lenguaje ensamblador y por
consiguiente al lenguaje de máquina. A partir de FORTRAN, se han
desarrollado innumerables lenguajes, que siguen el mismo concepto: buscar la
mayor abstracción posible, y facilitar la vida al programador, aumentando la
productividad, encargándose los compiladores o intérpretes de traducir el
lenguaje de alto nivel, al lenguaje de computadora.

Hay que notar la existencia de lenguajes que combinan características de los


de alto nivel y los de bajo nivel (es decir, Ensamblador).

Clasificación de los lenguajes de programación

Los lenguajes de programación se determinan según el nivel de abstracción,


Según la forma de ejecución y Según el paradigma de programación que
poseen cada uno de ellos y esos pueden ser:

Según su nivel de abstracción

1. Lenguajes de bajo nivel

Los lenguajes de bajo nivel son lenguajes de programación que se acercan al


funcionamiento de una computadora. El lenguaje de más bajo nivel es, por
excelencia, el código máquina. A éste le sigue el lenguaje ensamblador, ya que
al programar en ensamblador se trabajan con los registros de memoria de la
computadora de forma directa.

2. Lenguajes de medio nivel

Hay lenguajes de programación que son considerados por algunos expertos


como lenguajes de medio nivel (como es el caso del lenguaje C) al tener ciertas
características que los acercan a los lenguajes de bajo nivel pero teniendo, al
mismo tiempo, ciertas cualidades que lo hacen un lenguaje más cercano al
humano y, por tanto, de alto nivel.
3. Lenguajes de alto nivel

Los lenguajes de alto nivel son normalmente fáciles de aprender porque están
formados por elementos de lenguajes naturales, como el inglés. En BASIC, el
lenguaje de alto nivel más conocido, los comandos como "IF CONTADOR = 10
THEN STOP" pueden utilizarse para pedir a la computadora que pare si
CONTADOR es igual a 10. Por desgracia para muchas personas esta forma de
trabajar es un poco frustrante, dado que a pesar de que las computadoras
parecen comprender un lenguaje natural, lo hacen en realidad de una forma
rígida y sistemática.

Según la forma de ejecución

1. Lenguajes compilados

Naturalmente, un programa que se escribe en un lenguaje de alto nivel también


tiene que traducirse a un código que pueda utilizar la máquina. Los programas
traductores que pueden realizar esta operación se llaman compiladores. Éstos,
como los programas ensambladores avanzados, pueden generar muchas
líneas de código de máquina por cada proposición del programa fuente. Se
requiere una corrida de compilación antes de procesar los datos de un
problema.

Los compiladores son aquellos cuya función es traducir un programa escrito en


un determinado lenguaje a un idioma que la computadora entienda (lenguaje
máquina con código binario).

Al usar un lenguaje compilado (como lo son los lenguajes del popular Visual
Studio de Microsoft), el programa desarrollado nunca se ejecuta mientras haya
errores, sino hasta que luego de haber compilado el programa, ya no aparecen
errores en el código
2. Lenguajes interpretados

Se puede también utilizar una alternativa diferente de los compiladores para


traducir lenguajes de alto nivel. En vez de traducir el programa fuente y grabar
en forma permanente el código objeto que se produce durante la corrida de
compilación para utilizarlo en una corrida de producción futura, el programador
sólo carga el programa fuente en la computadora junto con los datos que se
van a procesar. A continuación, un programa intérprete, almacenado en el
sistema operativo del disco, o incluido de manera permanente dentro de la
máquina, convierte cada proposición del programa fuente en lenguaje de
máquina conforme vaya siendo necesario durante el proceso de los datos. No
se graba el código objeto para utilizarlo posteriormente.

La siguiente vez que se utilice una instrucción, se le debe interpretar otra vez y
traducir a lenguaje máquina. Por ejemplo, durante el procesamiento repetitivo
de los pasos de un ciclo, cada instrucción del ciclo tendrá que volver a ser
interpretado cada vez que se ejecute el ciclo, lo cual hace que el programa sea
más lento en tiempo de ejecución (porque se va revisando el código en tiempo
de ejecución) pero más rápido en tiempo de diseño (porque no se tiene que
estar compilando a cada momento el código completo). El intérprete elimina la
necesidad de realizar una corrida de compilación después de cada
modificación del programa cuando se quiere agregar funciones o corregir
errores; pero es obvio que un programa objeto compilado con antelación
deberá ejecutarse con mucha mayor rapidez que uno que se debe interpretar a
cada paso durante una corrida de producción.
History of Programming Languages
1954 1960 1965 1970 1975 1980 1985 1990 1995 2000 2001 2002 2003 2004

1986 1990 1990 1991 1991 1993 1994 1995 1996 1996 1997 1997 2000 2001 2001 2003 2003 2004
For more than half of the fifty years computer programmers have been This timeline includes fifty of the more than 2500 documented
writing code, O’Reilly has provided developers with comprehensive, programming languages. It is based on an original diagram created
in-depth technical information. We’ve kept pace with rapidly changing by Éric Lévénez (www.levenez.com), augmented with suggestions
www.oreilly.com technologies as new languages have emerged, developed, and
matured. Whether you want to learn something new or need
from O’Reilly authors, friends, and conference attendees.
For information and discussion on this poster,
answers to tough technical questions, you’ll find what you need
go to www.oreilly.com/go/languageposter.
in O’Reilly books and on the O’Reilly Network.
©2004 O’Reilly Media, Inc. O’Reilly logo is a registered trademark of O’Reilly Media, Inc. All other trademarks are property of their respective owners. part#30417
Programación estructurada

La programación estructurada es una forma de escribir programación de


computadora de forma clara, para ello utiliza únicamente tres estructuras:
secuencial, selectiva e iterativa; siendo innecesario y no permitiéndose el uso
de la instrucción o instrucciones de transferencia incondicional ( GOTO ).

Hoy en día las aplicaciones informáticas son mucho más ambiciosas que las
necesidades de programación existentes en los años 60, principalmente debido
a las aplicaciones gráficas, por lo que las técnicas de programación
estructurada no son suficientes lo que ha llevado al desarrollo de nuevas
técnicas tales como la programación orientada o objetos y el desarrollo de
entornos de programación que facilitan la programación de grandes
aplicaciones.

Orígenes de la programación estructurada

A finales de los años sesenta surgió una nueva forma de programar que no
solamente daba lugar a programas fiables y eficientes, sino que además
estaban escritos de manera que facilitaba su comprensión posterior.

El teorema del programa estructurado, demostrado por Böhm-Jacopini,


demuestra que todo programa puede escribirse utilizando únicamente las tres
instrucciones de control siguientes:

¾ Secuencia
¾ Instrucción condicional.
¾ Iteración (bucle de instrucciones) con condición al principio.

Solamente con estas tres estructuras se pueden escribir todos los programas y
aplicaciones posibles. Si bien los lenguajes de programación tienen un mayor
repertorio de estructuras de control, éstas pueden ser construidas mediante las
tres básicas.
Por ejemplo, en Visual Basic la secuencia de instrucciones consiste en la
escritura de una instrucción debajo de otra (también se pueden poner en la
misma línea separadas por el símbolo de dos puntos ":" aunque no es
recomendable). La instrucción condicional es la instrucción If y la iteración con
condición al inicio sería la instrucción do-while-loop o while-wend.

Ventajas de la programación estructurada

Con la programación estructurada, elaborar programas de computador sigue


siendo una labor que demanda esfuerzo, creatividad, habilidad y cuidado. Sin
embargo, con este estilo podemos obtener las siguientes ventajas:

1. Los programas son más fáciles de entender, ya que pueden ser leído de
forma secuencial, sin necesidad de hacer seguimiento a saltos de línea
(GOTO) dentro de los bloques de código para entender la lógica.
2. La estructura del programa es clara puesto que las instrucciones están
más ligadas o relacionadas entre sí.
3. Reducción del esfuerzo en las pruebas. El seguimiento de los fallos o
errores del programa ("debugging") se facilita debido a la estructura más
visible, por lo que los errores se pueden detectar y corregir más
fácilmente.
4. Reducción de los costos de mantenimiento de los programas.
5. Programas más sencillos y más rápidos (ya que es más fácil su
optimización).
6. Los bloques de código son auto explicativos, lo que facilita a la
documentación.
7. Los GOTO se reservan para construir las instrucciones básicas. Aunque
no se usan de forma directa, por estar prohibida su utilización, están
incluidas implícitamente en las instrucciones de selección e iteración.
Inconvenientes de la programación estructurada

El principal inconveniente de este método de programación, es que se obtiene


un único bloque de programa, que cuando se hace demasiado grande puede
resultar problemático su manejo, esto se resuelve empleando la programación
modular, definiendo módulos interdependientes programados y compilados por
separado. Un método un poco más sofisticado es la programación por capas,
en la que los módulos tienen una estructura jerárquica muy definida y se
denominan capas.

Programación Orientada a Objetos.

La programación Orientada a objetos (POO) es una forma especial de


programar, más cercana a como expresaríamos las cosas en la vida real que
otros tipos de programación.

Con la POO tenemos que aprender a pensar las cosas de una manera distinta,
para escribir nuestros programas en términos de objetos, propiedades,
métodos.

Motivación

Durante años, los programadores se han dedicado a construir aplicaciones muy


parecidas que resolvían una y otra vez los mismos problemas. Para conseguir
que los esfuerzos de los programadores puedan ser utilizados por otras
personas se creó la POO. Que es una serie de normas de realizar las cosas de
manera que otras personas puedan utilizarlas y adelantar su trabajo, de
manera que consigamos que el código se pueda reutilizar.

La POO no es difícil, pero es una manera especial de pensar, a veces subjetiva


de quien la programa, de manera que la forma de hacer las cosas puede ser
diferente según el programador. Aunque podamos hacer los programas de
formas distintas, no todas ellas son correctas, lo difícil no es programar
orientado a objetos sino programar bien. Programar bien es importante porque
así nos podemos aprovechar de todas las ventajas de la POO.
Cómo se piensa en objetos

Pensar en términos de objetos es muy parecido a cómo lo haríamos en la vida


real. Por ejemplo vamos a pensar en un coche para tratar de modelizarlo en un
esquema de POO. Diríamos que el coche es el elemento principal que tiene
una serie de características, como podrían ser el color, el modelo o la marca.
Además tiene una serie de funcionalidades asociadas, como pueden ser
ponerse en marcha, parar o aparcar.

Pues en un esquema POO el coche sería el objeto, las propiedades serían las
características como el color o el modelo y los métodos serían las
funcionalidades asociadas como ponerse en marcha o parar.

Por poner otro ejemplo vamos a ver cómo modelizaríamos en un esquema


POO una fracción, es decir, esa estructura matemática que tiene un numerador
y un denominador que divide al numerador, por ejemplo 3/2.

La fracción será el objeto y tendrá dos propiedades, el numerador y el


denominador. Luego podría tener varios métodos como simplificarse, sumarse
con otra fracción o número, restarse con otra fracción, etc.

Estos objetos se podrán utilizar en los programas, por ejemplo en un programa


de matemáticas harás uso de objetos fracción y en un programa que gestione
un taller de coches utilizarás objetos coche. Los programas Orientados a
objetos utilizan muchos objetos para realizar las acciones que se desean
realizar y ellos mismos también son objetos. Es decir, el taller de coches será
un objeto que utilizará objetos coche, herramienta, mecánico, recambios, etc.

Clases en POO

Las clases son declaraciones de objetos, también se podrían definir como


abstracciones de objetos. Esto quiere decir que la definición de un objeto es la
clase. Cuando programamos un objeto y definimos sus características y
funcionalidades en realidad lo que estamos haciendo es programar una clase.
En los ejemplos anteriores en realidad hablábamos de las clases coche o
fracción porque sólo estuvimos definiendo, aunque por encima, sus formas.
Propiedades en clases

Las propiedades o atributos son las características de los objetos. Cuando


definimos una propiedad normalmente especificamos su nombre y su tipo. Nos
podemos hacer a la idea de que las propiedades son algo así como variables
donde almacenamos datos relacionados con los objetos.

Métodos en las clases

Son las funcionalidades asociadas a los objetos. Cuando estamos


programando las clases las llamamos métodos. Los métodos son como
funciones que están asociadas a un objeto.

Objetos en POO

Los objetos son ejemplares de una clase cualquiera. Cuando creamos un


ejemplar tenemos que especificar la clase a partir de la cual se creará. Esta
acción de crear un objeto a partir de una clase se llama instancia (que viene de
una mala traducción de la palabra instace que en inglés significa ejemplar). Por
ejemplo, un objeto de la clase fracción es por ejemplo 3/5. El concepto o
definición de fracción sería la clase, pero cuando ya estamos hablando de una
fracción en concreto 4/7, 8/1000 o cualquier otra, la llamamos objeto.

Para crear un objeto se tiene que escribir una instrucción especial que puede
ser distinta dependiendo el lenguaje de programación que se emplee, pero será
algo parecido a esto.

miCoche = new Coche()

Con la palabra new especificamos que se tiene que crear una instancia de la
clase que sigue a continuación. Dentro de los paréntesis podríamos colocar
parámetros con los que inicializar el objeto de la clase coche.
Estados en objetos

Cuando tenemos un objeto sus propiedades toman valores. Por ejemplo,


cuando tenemos un coche la propiedad color tomará un valor en concreto,
como por ejemplo rojo o gris metalizado. El valor concreto de una propiedad de
un objeto se llama estado.

Para acceder a un estado de un objeto para ver su valor o cambiarlo se utiliza


el operador punto.

miCoche.color = rojo

El objeto es miCoche, luego colocamos el operador punto y por último el


nombre e la propiedad a la que deseamos acceder. En este ejemplo estamos
cambiando el valor del estado de la propiedad del objeto a rojo con una simple
asignación.

Mensajes en objetos

Un mensaje en un objeto es la acción de efectuar una llamada a un método.


Por ejemplo, cuando le decimos a un objeto coche que se ponga en marcha
estamos pasándole el mensaje “ponte en marcha”.

Para mandar mensajes a los objetos utilizamos el operador punto, seguido del
método que deseamos invocar.

miCoche.ponerseEnMarcha()

En este ejemplo pasamos el mensaje ponerseEnMarcha(). Hay que colocar


paréntesis igual que cualquier llamada a una función, dentro irían los
parámetros.
Otras cosas

Hay mucho todavía que conocer de la POO ya que sólo hemos hecho
referencia a las cosas más básicas. También existen mecanismos como la
herencia y el polimorfismo que son unas de las posibilidades más potentes de
la POO.

La herencia sirve para crear objetos que incorporen propiedades y métodos de


otros objetos. Así podremos construir unos objetos a partir de otros sin tener
que reescribirlo todo.

El polimorfismo sirve para que no tengamos que preocuparnos sobre lo que


estamos trabajando, y abstraernos para definir un código que sea compatible
con objetos de varios tipos.

Son conceptos avanzados que cuesta explicar en las líneas de ese informe. No
hay que olvidar que existen libros enteros dedicados a la POO y aquí solo
pretendemos dar un repaso a algunas cosas para que os suenen cuando
tengáis que poneros delante de ellas en los lenguajes de programación que
debe conocer un desarrollador del web.

Programación funcional

Los lenguajes funcionales son modelos basados en la noción de las funciones


matemáticas, las cuales pueden considerarse como un mecanismo para aplicar
ciertas operaciones sobre algunos valores (argumentos), y con esto obtener un
resultado (valor de la función para dichos argumentos). En los lenguajes
funcionales puros no se permiten asignaciones a variables globales ni efectos
laterales: sólo operan sobre funciones.

Aunque normalmente estamos acostumbrados a que los argumentos y el


resultado de una función sean constantes numéricas, existe también la
posibilidad de que, tanto los argumentos como el resultado de la función,
pudiesen ser otra función o incluso la misma, lo que puede interpretarse como
una forma de recursividad, que constituye una de las herramientas más
poderosas de las que se sirve la programación funcional.
El primero, y todavía más común lenguaje funcional, es el LISP, basado en el
cálculo lambda de Alonzo Church; y en el cual se basa toda la teoría de la
programación funcional. Aunque en la época en la que aparece este tipo de
cálculo aún no existían las computadoras, resulta ser una herramienta que se
adelanta a su época y que resulta muy simple, ya que sólo consta de dos
operaciones básicas:

¾ Definir alguna(s) función(es) de un solo argumento y con un cuerpo


específico, en donde x determina el parámetro y B el cuerpo de la
función.

Es decir: f(x) = B.

¾ Aplicar alguna de las funciones creadas, sobre un argumento real (A); lo


que es conocido también con el nombre de reducción, y que no es otra
cosa que sustituir las ocurrencias del argumento formal (x) que
aparezcan en el cuerpo

(B) de la función, con el argumento real (A).

Cuando ya no es posible reducir una función, se dice que está en su estado


normal, o que hemos encontrado el valor de la función. Éste siempre
dependerá de los argumentos y siempre tendrá la consistencia de regresar al
mismo valor para los mismos argumentos. Lo anterior se conoce como
transparencia referencial y, al no contar con variables globales, permite al
sistema la ejecución de procesos de forma paralela para incrementar su
eficiencia. Sobre estos conceptos que se muestran como muy sencillos se basa
la programación funcional. Existen además otras características que sirven
para identificarla y aumentar su potencial en el desarrollo de aplicaciones:

a) Funciones de orden superior: cuando una función puede servir como


argumento de otra o puede almacenarse como valor en una estructura de
datos, o bien cuando el resultado de una función es otra función. Esto
proporciona una herramienta que maximiza el uso de la recursividad y el
anidamiento, y permite un desarrollo más eficiente de aplicaciones.
b) Sistemas de interferencias de tipos: mecanismo que exime al
programador de la responsabilidad de declarar los tipos de las funciones
declaradas, y le permite al compilador deducir el tipo de datos al que están
asociadas las expresiones, basándose en la evidencia que presenta el código
al tiempo de la compilación del programa.

c) Polimorfismo paramétrico: permite que una determinada función tenga la


capacidad de aceptar como parámetros una variedad de tipos distintos cada
vez que sea llamada, sin que esto influya en que la función pueda obtener y
regresar el resultado esperado.

d) Evaluación perezosa: una función intentará evaluar los parámetros con los
que fue definida, para efectuar las reducciones que nos permitan obtener el
valor de la función. Del LISP han surgido más tarde muchas implementaciones,
como el Franz LISP, Zeta LISP, InterLISP, o Common LISP. El dialecto
SCHEME es más cercano al cálculo lambda que los otros. SASL, KRC, Haskell
y Miranda son otros lenguajes basados en el lambda, que han incluido nuevas
funciones, algunas de ellas imperativas. Un segundo grupo de lenguajes
funcionales está más basado en la notación matemática común que en el
cálculo lambda. El pionero de éstos es APL, cuyo tipo fundamental de datos
está muy relacionado con operaciones. El sucesor más prometedor para APL
es el lenguaje FP.
Lenguaje de programación java

Es un lenguaje de programación orientado a objetos desarrollado por Sun


Microsystems a principios de los años 90. El lenguaje en sí mismo toma mucha
de su sintaxis de C y C++, pero tiene un modelo de objetos más simple y
elimina herramientas de bajo nivel, que suelen inducir a muchos errores, como
la manipulación directa de punteros o memoria.

Las aplicaciones Java están típicamente compiladas en un bytecode, aunque la


compilación en código máquina nativo también es posible. En el tiempo de
ejecución, el bytecode es normalmente interpretado o compilado a código
nativo para la ejecución, aunque la ejecución directa por hardware del bytecode
por un procesador Java también es posible.

La implementación original y de referencia del compilador, la máquina virtual y


las librerías de clases de Java fueron desarrollados por Sun Microsystems en
1995. Desde entonces, Sun ha controlado las especificaciones, el desarrollo y
evolución del lenguaje a través del Java Community Process, si bien otros han
desarrollado también implementaciones alternativas de estas tecnologías de
Sun, algunas incluso bajo licencias de software libre.

Entre noviembre de 2006 y mayo de 2007, Sun Microsystems liberó la mayor


parte de sus tecnologías Java bajo la licencia GNU GPL, de acuerdo con las
especificaciones del Java Community Process, de tal forma que prácticamente
todo el Java de Sun es ahora software libre (aunque la biblioteca de clases de
Sun que se requiere para ejecutar los programas Java todavía no es software
libre).

Entornos de funcionamiento

El diseño de Java, su robustez, el respaldo de la industria y su fácil portabilidad


han hecho de Java uno de los lenguajes con un mayor crecimiento y amplitud
de uso en distintos ámbitos de la industria de la informática.
En dispositivos móviles y sistemas empotrados

Desde la creación de la especificación J2ME (Java 2 Platform, Micro Edition),


una versión del entorno de ejecución Java reducido y altamente optimizado,
especialmente desarrollado para el mercado de dispositivos electrónicos de
consumo se ha producido toda una revolución en lo que a la extensión de Java
se refiere.

Es posible encontrar microprocesadores específicamente diseñados para


ejecutar bytecode Java y software Java para tarjetas inteligentes (JavaCard),
teléfonos móviles, buscapersonas, set-top-boxes, sintonizadores de TV y otros
pequeños electrodomésticos.

El modelo de desarrollo de estas aplicaciones es muy semejante a las applets


de los navegadores salvo que en este caso se denominan MIDlets.

En el navegador web

Desde la primera versión de java existe la posibilidad de desarrollar pequeñas


aplicaciones (Applets) en Java que luego pueden ser incrustadas en una
página HTML para que sean descargadas y ejecutadas por el navegador web.
Estas mini-aplicaciones se ejecutan en una JVM que el navegador tiene
configurada como extensión (plug-in) en un contexto de seguridad restringido
configurable para impedir la ejecución local de código potencialmente
malicioso.

El éxito de este tipo de aplicaciones (la visión del equipo de Gosling) no fue
realmente el esperado debido a diversos factores, siendo quizás el más
importante la lentitud y el reducido ancho de banda de las comunicaciones en
aquel entonces que limitaba el tamaño de las applets que se incrustaban en el
navegador. La aparición posterior de otras alternativas (aplicaciones web
dinámicas de servidor) dejó un reducido ámbito de uso para esta tecnología,
quedando hoy relegada fundamentalmente a componentes específicos para la
intermediación desde una aplicación web dinámica de servidor con dispositivos
ubicados en la máquina cliente donde se ejecuta el navegador.
Las applets Java no son las únicas tecnologías (aunque sí las primeras) de
componentes complejos incrustados en el navegador. Otras tecnologías
similares pueden ser: ActiveX de Microsoft, Flash, Java Web Start, etc.

En sistemas de servidor

En la parte del servidor, Java es más popular que nunca, desde la aparición de
la especificación de Servlets y JSP (Java Server Pages).

Hasta entonces, las aplicaciones web dinámicas de servidor que existían se


basaban fundamentalmente en componentes CGI y lenguajes interpretados.
Ambos tenían diversos inconvenientes (fundamentalmente lentitud, elevada
carga computacional o de memoria y propensión a errores por su interpretación
dinámica).

Los servlets y las JSPs supusieron un importante avance ya que:

• El API de programación es muy sencilla, flexible y extensible.

• Los servlets no son procesos independientes (como los CGIs) y por


tanto se ejecutan dentro del mismo proceso que la JVM mejorando
notablemente el rendimiento y reduciendo la carga computacional y de
memoria requeridas.

• Las JSPs son páginas que se compilan dinámicamente (o se pre-


compilan previamente a su distribución) de modo que el código que se
consigue una ventaja en rendimiento substancial frente a muchos
lenguajes interpretados.

La especificación de Servlets y JSPs define un API de programación y los


requisitos para un contenedor (servidor) dentro del cual se puedan desplegar
estos componentes para formar aplicaciones web dinámicas completas. Hoy
día existen multitud de contenedores (libres y comerciales) compatibles con
estas especificaciones.

A partir de su expansión entre la comunidad de desarrolladores, estas


tecnologías han dado paso a modelos de desarrollo mucho más elaborados
con frameworks (pe Struts, Webwork) que se sobreponen sobre los servlets y
las JSPs para conseguir un entorno de trabajo mucho más poderoso y
segmentado en el que la especialización de roles sea posible (desarrolladores,
diseñadores gráficos, ...) y se facilite la reutilización y robustez de código. A
pesar de todo ello, las tecnologías que subyacen (Servlets y JSPs) son
substancialmente las mismas.

Este modelo de trabajo se ha convertido en un estándar de-facto para el


desarrollo de aplicaciones web dinámicas de servidor y otras tecnologías (pe.
ASP) se han basado en él.

En aplicaciones de escritorio

Hoy en día existen multitud de aplicaciones gráficas de usuario basadas en


Java. El entorno de ejecución Java (JRE) se ha convertido en un componente
habitual en los PCs de usuario de los sistemas operativos más usados en el
mundo. Además, muchas aplicaciones Java lo incluyen dentro del propio
paquete de la aplicación de modo que su ejecución en cualquier PC.

En las primeras versiones de la plataforma Java existían importantes


limitaciones en las APIs de desarrollo gráfico (AWT). Desde la aparición de la
librería Swing la situación mejoró substancialmente y posteriormente con la
aparición de librerías como SWT hacen que el desarrollo de aplicaciones de
escritorio complejas y con gran dinamismo, usabilidad, etc. sea relativamente
sencillo.

Plataformas soportadas

Una versión del entorno de ejecución Java JRE (Java Runtime Environment)
está disponible en la mayoría de equipos de escritorio. Sin embargo, Microsoft
no lo ha incluido por defecto en sus sistemas operativos. En el caso de Apple,
éste incluye una versión propia del JRE en su sistema operativo, el Mac OS.
También es un producto que por defecto aparece en la mayoría de las
distribuciones de Linux. Debido a incompatibilidades entre distintas versiones
del JRE, muchas aplicaciones prefieren instalar su propia copia del JRE antes
que confiar su suerte a la aplicación instalada por defecto. Los desarrolladores
de applets de Java o bien deben insistir a los usuarios en la actualización del
JRE, o bien desarrollar bajo una versión antigua de Java y verificar el correcto
funcionamiento en las versiones posteriores.

Industria relacionada

Sun Microsystem, como creador del lenguaje de programación Java y de la


plataforma JDK, mantiene fuertes políticas para mantener una especificación
del lenguaje1 así como de la máquina virtual2 a través del JCP. Es debido a
este esfuerzo que se mantiene un estándar de facto.

Son innumerables las compañías que desarrollan aplicaciones para Java y/o
están volcadas con esta tecnología:

• La industria de la telefonía móvil está fuertemente influenciada por la


tecnología Java.
• El entorno de desarrollo Eclipse ha tomado un lugar importante entre la
comunidad de desarrolladores Java.
• La fundación Apache tiene también una presencia importante en el
desarrollo de librerías y componentes de servidor basados en Java.
• IBM, BEA, IONA, Oracle,... son empresas con grandes intereses y
productos creados en y para Java.

Críticas

Harold dijo en 1995 que Java fue creado para abrir una nueva vía en la gestión
de software complejo, y es por regla general aceptado que se ha comportado
bien en ese aspecto. Sin embargo no puede decirse que Java no tenga grietas,
ni que se adapta completamente a todos los estilos de programación, todos los
entornos, o todas las necesidades.

General

• Java no ha aportado capacidades estándares para aritmética en punto


flotante. El estándar IEEE 754 para “Estándar para Aritmética Binaria en
Punto Flotante” apareció en 1985, y desde entonces es el estándar para
la industria. Y aunque la aritmética flotante de Java (cosa que cambió
desde el 13 de Noviembre de 2006, cuando se abrió el código fuente y
se adoptó la licencia GPL, aparte de la ya existente) se basa en gran
medida en la norma del IEEE, no soporta aún algunas características.
Más información al respecto puede encontrarse en la sección final de
enlaces externos.

El lenguaje

• En un sentido estricto, Java no es un lenguaje absolutamente orientado


a objetos, a diferencia de, por ejemplo, Ruby o Smalltalk. Por motivos de
eficiencia, Java ha relajado en cierta medida el paradigma de orientación
a objetos, y así por ejemplo, no todos los valores son objetos.
• El código Java puede ser a veces redundante en comparación con otros
lenguajes. Esto es en parte debido a las frecuentes declaraciones de
tipos y conversiones de tipo manual (casting). También se debe a que
no se dispone de operadores sobrecargados, y a una sintaxis
relativamente simple. Sin embargo, J2SE 5.0 introduce elementos para
tratar de reducir la redundancia, como una nueva construcción para los
bucles ‘’’foreach’’’.

• A diferencia de C++, Java no dispone de operadores de sobrecarga


definidos por el usuario. Sin embargo esta fue una decisión de diseño
que puede verse como una ventaja, ya que esta característica puede
hacer los programas difíciles de leer y mantener.

Apariencia

La apariencia externa (el ‘’’look and feel’’’) de las aplicaciones GUI (Graphical
User Interface) escritas en Java usando la plataforma Swing difiere a menudo
de la que muestran aplicaciones nativas. Aunque el programador puede usar el
juego de herramientas AWT (Abstract Windowing Toolkit) que genera objetos
gráficos de la plataforma nativa, el AWT no es capaz de funciones gráficas
avanzadas sin sacrificar la portabilidad entre plataformas; ya que cada una
tiene un conjunto de APIs distinto, especialmente para objetos gráficos de alto
nivel. Las herramientas de Swing, escritas completamente en Java, evitan este
problema construyendo los objetos gráficos a partir de los mecanismos de
dibujo básicos que deben estar disponibles en todas las plataformas. El
inconveniente es el trabajo extra requerido para conseguir la misma apariencia
de la plataforma destino. Aunque esto es posible (usando GTK+ y el Look-and-
Feel de Windows), la mayoría de los usuarios no saben cómo cambiar la
apariencia que se proporciona por defecto por aquella que se adapta a la de la
plataforma. Mención merece la versión optimizada del lenguaje.

Rendimiento

El rendimiento de una aplicación está determinado por multitud de factores, por


lo que no es fácil hacer una comparación que resulte totalmente objetiva. En
tiempo de ejecución, el rendimiento de una aplicación Java depende más de la
eficiencia del compilador, o la JVM, que de las propiedades intrínsecas del
lenguaje. El bytecode de Java puede ser interpretado en tiempo de ejecución
por la máquina virtual, o bien compilado al cargarse el programa, o durante la
propia ejecución, para generar código nativo que se ejecuta directamente sobre
el hardware. Si es interpretado, será más lento que usando el código máquina
intrínseco de la plataforma destino. Si es compilado, durante la carga inicial o la
ejecución, la penalización está en el tiempo necesario para llevar a cabo la
compilación.

Algunas características del propio lenguaje conllevan una penalización en


tiempo, aunque no son únicas de Java. Algunas de ellas son el chequeo de los
límites de arrays, chequeo en tiempo de ejecución de tipos, y la indirección de
funciones virtuales.

El uso de un recolector de basura para eliminar de forma automática aquellos


objetos no requeridos, añade una sobrecarga que puede afectar al rendimiento,
o ser apenas apreciable, dependiendo de la tecnología del recolector y de la
aplicación en concreto. Las JVM modernas usan recolectores de basura que
gracias a rápidos algoritmos de manejo de memoria, consiguen que algunas
aplicaciones puedan ejecutarse más eficientemente.
El rendimiento entre un compilador JIT y los compiladores nativos puede ser
parecido, aunque la distinción no está clara en este punto. La compilación
mediante el JIT puede consumir un tiempo apreciable, un inconveniente
principalmente para aplicaciones de corta duración o con gran cantidad de
código. Sin embargo, una vez compilado, el rendimiento del programa puede
ser comparable al que consiguen compiladores nativos de la plataforma
destino, inclusive en tareas numéricas. Aunque Java no permite la expansión
manual de llamadas a métodos, muchos compiladores JIT realizan esta
optimización durante la carga de la aplicación y pueden aprovechar información
del entorno en tiempo de ejecución para llevar a cabo transformaciones
eficientes durante la propia ejecución de la aplicación. Esta recompilación
dinámica, como la que proporciona la máquina virtual HotSpot de Sun, puede
llegar a mejorar el resultado de compiladores estáticos tradicionales, gracias a
los datos que sólo están disponibles durante el tiempo de ejecución.

Java fue diseñado para ofrecer seguridad y portabilidad, y no ofrece acceso


directo al hardware de la arquitectura ni al espacio de direcciones. Java no
soporta expansión de código ensamblador, aunque las aplicaciones pueden
acceder a características de bajo nivel usando librerías nativas (JNI, Java
Native Interfaces).

Recursos

El JRE (Java Runtime Environment, o Entorno en Tiempo de Ejecución de


Java) es el software necesario para ejecutar cualquier aplicación desarrollada
para la plataforma Java. El usuario final usa el JRE como parte de paquetes
software o plugins (o conectores) en un navegador Web. Sun ofrece también el
SDK de Java 2, o JDK (Java Development Kit) en cuyo seno reside el JRE, e
incluye herramientas como el compilador de Java, Javadoc para generar
documentación o el depurador. Puede también obtenerse como un paquete
independiente, y puede considerarse como el entorno necesario para ejecutar
una aplicación Java, mientras que un desarrollador debe además contar con
otras facilidades que ofrece el JDK.
Conclusiones

Es de esperarse que los lenguajes Visuales dominen el mundo de las PCs


durante mucho tiempo, por lo menos mientras no evolucionen de otra manera
los Sistemas Operativos. Los lenguajes de programación evolucionan a medida
que lo hacen los Sistemas Operativos en que funcionan, siempre ha sido así.
Nunca un lenguaje de programación determinó un Sistema Operativo, por el
contrario los Sistemas Operativos determinaron los lenguajes de programación.

Potrebbero piacerti anche