Capítulo 1. La programación de computadoras. 1. Introducción. 2. Ciclo de vida de una aplicación informática. 2.1. Diseño del programa. 2.1.1. Fase de análisis. 2.1.2. Fase de programación. 2.1.3. Fase de codificación. 2.2. Instalación y explotación del programa. 2.2.1. Fase de edición. 2.2.2. Fase de compilación. 2.2.3. Fase de montaje. 2.2.4. Fase de prueba de ejecución. 2.2.5. Fase de explotación y mantenimiento. 2.3. Errores. 2.4. Calidad de los programas. 2.5. Documentación de los programas. 2.5.1. Documentación interna. 2.5.2. Documentación externa. 3. Lenguajes de programación. 3.1. Definición de lenguaje de programación. 3.2. Clasificación de lenguajes de programación. 3.2.1. Lenguaje máquina. 3.2.2. Lenguaje ensamblador. 3.2.3. Lenguajes de alto nivel. 3.3. Lenguajes interpretados y compilados. 4. Técnicas de programación. 4.1. Programación estructurada. 4.2. Programación modular. 4.3. Programación orientada a objetos. 1. Introducción. Una computadora es una máquina de origen electrónico que puede realizar una gran variedad de trabajos, aunque a partir de tres operaciones básicas: - Sumar, restar, multiplicar y dividir dos valores numéricos. - Comparar dos valores. - Almacenar y recuperar información. Las principales ventajas de una computadora son la rapidez, precisión y memoria. El objetivo de la programación es, a partir de un problema dado, diseñar una solución que pueda ejecutarse en una computadora. Para ello se necesita una notación o lenguaje de programación, que permita expresar la solución de forma entendible por la computadora. 2. Ciclo de vida de una aplicación informática. Una aplicación informática es un conjunto de programas relacionados que permiten automatizar la realización de una determinada tarea. Los pasos seguidos desde que se plantea el problema hasta que se obtiene la solución en una computadora se denominan ciclo de vida de la aplicación. En el ciclo de vida se distingue dos etapas principales. La primera consiste en realizar el diseño de la aplicación; y la segunda consiste en realizar la instalación y explotación de la misma. 2.1. Diseño del programa. Consta de 3 fases. 2.1.1. Fase de análisis. Esta fase consiste en examinar detenidamente el problema propuesto y realizar una descripción detallada de los aspectos como el equipo a utilizar, el personal informático, los datos de entrada, los resultados a obtener, la descomposición en módulos, etc. El resultado de esta fase se denomina la especificación del problema. 2.1.2. Fase de programación. Esta fase consiste en expresar en forma de algoritmo la solución del problema, aplicando técnicas como programación estructurada y modular. Por lo tanto, el resultado de esta fase es el algoritmo, es decir la descripción del conjunto de acciones que debe realizar la computadora. Para facilitar esta tarea se utilizan notaciones como diagramas de flujo y pseudocódigos. 2.1.3. Fase de codificación. Esta fase consiste en escribir el algoritmo en un lenguaje de programación concreto, obteniéndose el programa. 2.2. Instalación y explotación del programa. Esta etapa consta de las siguientes fases. 2.2.1. Fase de edición. Esta fase consiste en escribir dentro de un fichero, llamado programa fuente, el programa anterior, utilizando para ello un editor. 2.2.2. Fase de compilación. Esta fase consiste en traducir el programa fuente a lenguaje máquina, obteniéndose el programa objeto, utilizando para ello un compilador o intérprete, que informa sobre los errores sintácticos cometidos. 2.2.3. Fase de montaje. Esta fase consiste en enlazar los distintos programas objetos que pueden componer una aplicación, así como las rutinas necesarias del sistema, obteniéndose el programa ejecutable, utilizando para ello un montador o "linker". 2.2.4. Fase de prueba de ejecución. Esta fase consiste en ejecutar el programa utilizando un juego de datos de entrada lo suficientemente amplio y diverso para poder asegurar que el programa funciona de forma adecuada, proporcionando los resultados correctos. 2.2.5. Fase de explotación y mantenimiento. Esta fase consiste en el uso cotidiano del programa por parte de los usuarios del mismo, así como en la comprobación periódica de su buen funcionamiento y en la realización de las modificaciones necesarias para que se mantenga actualizado. 2.3. Errores. Durante todas las fases comentadas pueden cometerse errores, que se pueden clasificar como sigue: - Errores de compilación: son los errores sintácticos cometidos al escribir el programa en un lenguaje de programación determinado. Este lenguaje impone unas reglas sintácticas que deben ser cumplidas, ya que en caso contrario aparece este tipo de error. Estos son los más fáciles de corregir, ya que el propio compilador informa de los mismos. - Errores de ejecución: son los errores causados por la ejecución de una operación no permitida, como dividir por cero, exceder un rango de valores, etc. Cuando ocurren, se suele decir que el programa ha sido "abortado" por el sistema. Estos son más difíciles de detectar que los anteriores, ya que ocurren en función de los datos de entrada utilizados, por lo que para descubrirlos debe probarse el programa exhaustivamente. - Errores de lógica: son los errores en los resultados, por ejemplo se espera un listado ordenado y aparece desordenado. Como en el caso anterior, para detectarlos debe probarse el programa en su totalidad y verificar que los resultados son correctos. - Errores de especificación: son los errores causados por una especificaciones incorrectas, debidas a un malentendido entre el programador y quien plantea el problema. En ocasiones, estos son muy costosos de corregir, ya que obligan a repetir gran parte del trabajo. 2.4. Calidad de los programas. La solución automatizada de un problema se puede obtener con distintos programas, entre los que debe seleccionarse el de mayor calidad. Para medir la calidad de un programa se utilizan las siguientes características: - Legibilidad: el programa fuente debe ser claro y sencillo, para facilitar su lectura y comprensión. - Fiabilidad: el programa debe ser robusto, o sea capaz de recuperarse frente a errores o usos inadecuados. - Portabilidad: el programa debe permitir su utilización en distintos sistemas. - Modificabilidad: el programa debe ser fácil de mantener y actualizar, para que la realización de modificaciones sean poco costosas. - Eficiencia: el programa debe ser rápido, a la vez que pequeño, para ocupar poca memoria. 2.5. Documentación de los programas. Un programa debe ir acompañado de una documentación que facilite su explotación y mantenimiento. Existen dos tipos de documentación, como vamos a detallar. 2.5.1. Documentación interna. Esta documentación consiste básicamente en un listado del programa fuente. Este debe contener los comentarios adecuados para facilitar su lectura y compresión. Además debe utilizarse el llamado código autodocumentado, es decir identificar a los objetos del programa con nombres autoexplicativos, de forma que a través del nombre se pueda conocer qué función tiene el objeto. 2.5.2. Documentación externa. Esta documentación está constituida por los siguientes documentos: las especificaciones del análisis, la descripción del diseño, el manual del usuario y el manual de mantenimiento. 3. Lenguajes de programación. Se denomina "hardware" a todo elemento físico relacionado con el ordenador. Por el contrario, se llama "software" a todo elemento lógico, como puede ser un programa, un conjunto de datos y también un lenguaje de programación. 3.1. Definición de lenguaje de programación. Un lenguaje de programación es un conjunto de símbolos (alfabeto) y un conjunto de reglas (gramática) que nos indican cómo se pueden mezclar esos símbolos, que será utilizado para escribir programas. 3.2. Clasificaciones de los lenguajes de programación. Se utilizan diferentes criterios de clasificación. Atendiendo al criterio de proximidad a la computadora se pueden clasificar en: - Lenguajes de bajo nivel: lenguaje máquina. - Lenguajes de nivel medio: lenguaje ensamblador. - Lenguajes de alto nivel: Cobol, C, Pascal, etc. Atendiendo al tiempo de aparición, los lenguajes se pueden clasificar en generaciones, como sigue: - Primera generación: lenguaje máquina y ensamblador. - Segunda generación: primeros lenguajes de alto nivel (Fortran, Cobol). - Tercera generación: lenguajes de alto nivel (C, Pascal). - Cuarta generación: lenguajes orientados a bases de datos (SQL). - Quinta generación: lenguajes orientados a la inteligencia artificial. Veamos algunos ejemplos de lenguajes de programación. 3.2.1. Lenguaje máquina. El primer lenguaje de programación utilizado fue el lenguaje máquina, que es el único que entiende la computadora. Emplea el alfabeto binario, que consta sólo de dos símbolos, el 0 y el 1, denominados bits. Este es un lenguaje muy difícil de aprender y con el que se suelen cometer muchos errores. Ej. 0001 0011 0110 0010 0100 1001 0011 1101 ... 3.2.2. Lenguaje ensamblador. Este lenguaje es el primer intento de sustituir el lenguaje máquina por otro más fácil de utilizar. Para ello cada instrucción en lenguaje máquina se corresponde con una instrucción en ensamblador, que se escribe con palabras nemotécnicas en lugar de cadenas de bits, con lo que se facilita la escritura del programa. Ej. ADD A,2 MOV A,B CMP B,E ... Tanto el lenguaje máquina como el ensamblador tienen las siguientes características: - Son distintos para cada modelo de procesador, por lo que un programa sólo funcionará en el procesador para el que se programó, lo cual es un inconveniente. - Manejan directamente posiciones de memoria, registros del procesador, etc., por lo que el programador debe conocer bien el hardware del equipo, lo cual es otro inconveniente. - Utilizan instrucciones muy elementales, que realizan operaciones básicas, por lo que debe describirse el programa con el máximo detalle, que también es otra desventaja. - Permiten que los programas ocupen muy poca memoria y tengan una alta velocidad de ejecución, lo cual es una gran ventaja. 3.2.3. Lenguajes de alto nivel. Para evitar, al menos en parte, los inconvenientes de los lenguajes anteriores, surgen los lenguajes de alto nivel, que presentan las siguientes características: - Permiten crear programas ejecutables en distintos modelos de procesador. - Permiten obviar muchos detalles del hardware utilizado, evitando de esta manera que el programador deba tener un alto conocimiento del mismo. - Ofrecen una escritura cercana al lenguaje natural, con lo que se evitan muchos errores. - Incluyen rutinas de uso frecuente, como funciones de entrada/salida, funciones matemáticas, etc., en las llamadas librerías, permitiendo su uso sin tener que programarlas cada vez. Veamos algunos ejemplos de lenguajes de alto nivel. FORTRAN: Su nombre es la abreviatura de FORmula TRANslator (traductor de fórmulas). Se creó en 1955 por la compañía IBM en Estados Unidos y es el más antiguo de los lenguajes de alto nivel. Está especializado en aplicaciones técnicas y científicas. COBOL: Su nombre es la abreviatura de COmmon Business Oriented Language (lenguaje orientado al negocio común). Se creó en 1960 por el grupo CODASYL en Estados Unidos y está orientado a aplicaciones comerciales. BASIC: Su nombre es la abreviatura de Beginner’s All-purpose Symbolic Instruction Code (código de instrucción simbólico de propósito general para principiantes). Se creó en 1965 en el Dartmouth College de Estados Unidos, para que los principiantes pudieran aprender un lenguaje fácilmente. Es un lenguaje interpretado que se puede usar tanto en aplicaciones técnicas como de gestión. PASCAL: Su nombre proviene del matemático francés Blaise Pascal. Fue creado en 1970 por el matemático suizo Nicklaus Wirth para la enseñanza de los conceptos de la programación. Se ha utilizado ampliamente en todo tipo de aplicaciones. Con este lenguaje aparecen conceptos como tipos de datos, programación estructurada y diseño descendente. C: Este es su nombre por estar basado en un lenguaje previo llamado B. Fue creado en 1972 por Dennis Ritchie y Ken Thompson en los laboratorios Bell Telephone. Fue concebido como lenguaje para la programación de sistemas, concretamente para escribir el sistema operativo UNIX, aunque posteriormente se extendió enormemente su uso para todo tipo de aplicaciones. Utiliza la programación estructurada y una amplia librería de rutinas. Visual Basic: Este es uno de los lenguajes más utilizados actualmente y permite la programación orientada a objetos. Es un lenguaje de propósito general y con él se pueden desarrollar aplicaciones de una forma muy sencilla y rápida. Se pueden crear programas complejos sin apenas teclear código, sino simplemente a base de añadir formularios y controles que podrán ser asociados a bases de datos, accesos a internet o cualquier otra acción. Además los programas funcionarán sobre el entorno gráfico Windows. Delphi: Este lenguaje tiene las mismas características que el anterior, pero su aprendizaje es más complejo. En determinadas tareas es más potente que Visual Basic. Delphi es el eslabón más avanzado del lenguaje Pascal. Java: Este es hoy en día el lenguaje por excelencia para el desarrollo de aplicaciones en Internet, aunque inicialmente su fin no era ese. Es un lenguaje interpretado, por lo que la puesta a punto de programas se realiza de un modo muy rápido y además permite gran exportabilidad, al no tener un programa objeto, así no hay problemas al pasar, por ejemplo, de un equipo UNIX a uno Windows, si se tiene el traductor (navegador) correcto para cada caso. 3.3. Lenguajes interpretados y compilados. Como se ha mencionado previamente, un programa debe ser traducido a código máquina para poder ser ejecutado. Para esta tarea se usan los llamados traductores. Estos son de dos tipos: intérpretes y compiladores. El lenguaje de programación que traduce sus programas usando un intérprete se denomina lenguaje interpretado, mientras que el que usa un compilador se llama lenguaje compilado. Cuando se usa un lenguaje compilado, la programación se realiza de la siguiente manera: - Con el editor se escribe el programa fuente. - Con el compilador se traduce el fuente a programa objeto. - Con el editor se corrigen los errores que devuelva el compilador y se vuelve a compilar. Así sucesivamente hasta que no haya errores. Después de ese proceso se obtiene el programa objeto, que se podrá ejecutar directamente las veces que se desee (algunos compiladores requieren un enlazador - linker -, que se le aplica al programa ya compilado para obtener el ejecutable). Se puede deducir que el proceso de traducción y el de ejecución son independientes. Algunos lenguajes compilados son: COBOL, PASCAL, C, etc.. Cuando se usa un lenguaje interpretado, la programación se realiza de la siguiente manera: - Con un editor se escribe una instrucción del programa - El intérprete inmediatamente traduce la instrucción y la ejecuta, informando de los errores, para que sean corregidos antes de escribir la siguiente instrucción. Una vez que el programa ha sido escrito completo sin errores, se almacena, teniendo el código fuente. En este caso no se crea un programa objeto. Cada vez que se desee ejecutar el programa, el intérprete irá traduciendo y ejecutando cada instrucción. Como vemos, la traducción y ejecución no son independientes. Algunos lenguajes interpretados son: BASIC, JAVA, etc. Las ventajas de un lenguaje compilado son: - La ejecución del programa es más rápida, ya que no hay que traducir las instrucciones. El programa objeto contiene las instrucciones ya traducidas, mientras que con el intérprete, cada instrucción debe traducirse antes de ejecutarse. - Durante la ejecución no es necesario tener el compilador en memoria funcionando. Al contrario ocurre con el intérprete, éste debe coexisitir con el programa fuente en la memoria RAM de la computadora para ejecutar el programa. Las ventajas de un lenguaje interpretado son: - El desarrollo y puesta a punto de un programa es más fácil y rápido, ya que se puede ir corrigiendo los errores a medida que se teclean instrucciones. - La modificación de programas es más sencilla, ya que no hay que crear el programa objeto después de ser modificado, como ocurre con el compilador. - Un intérprete ocupa menos memoria que un compilador. - No existe un programa objeto almacenado, sólo el fuente. 4. Técnicas de programación. Con la programación convencional, sin seguir un método de programación riguroso, se pueden obtener programas que funcionen, pero con una gran cantidad de deficiencias, como poca legibilidad, poca exportabilidad, dificultad al modificarlos, gran gasto de tiempo en la corrección de errores, etc. Con el avance de la informática se han ido desarrollando técnicas de programación que han facilitado el proceso completo de elaboración de programas. Así se han podido desarrollar programas cada vez más complejos. Los lenguajes de programación se han ido adaptando a esas nuevas técnicas para poder ponerlas en práctica. Así los programas actuales se crean más rápidamente, se interpretan más fácilmente, se pueden modificar de un modo más sencillo, son más exportables, etc. Veamos esas técnicas de programación. 4.1. Programación estructurada. Un programa con una estructura es fiable y eficiente, además de adaptable, manejable, comprensible y transportable. La programación estructurada actual establece que con las tres estructuras de control básicas se puede crear cualquier programa. Estas estructuras son: secuencial, alternativa y repetitiva. Por lo tanto, otro tipo de instrucciones como el salto incondicional nunca deberá usarse en la programación estructurada. 4.2. Programación modular. Se basa en dividir un programa en módulos, lo que se llama diseño descendente o “top-down”, dividiendo el programa en partes más sencillas que a la vez podrán ser divididas en otras subpartes o módulos. Cada módulo realiza una tarea más o menos sencilla y todos juntos solucionan el problema global. Los módulos deben ser independientes, por lo que existirá un módulo principal o base que controla y relaciona a todos los demás. Esta técnica tiene ventajas como la facilidad en las modificaciones, ya que sólo hay que revisar el módulo a modificar, sin necesidad de tocar el resto. Otra ventaja es que puede distribuirse mejor la tarea entre distintos programadores. Además un módulo puede ser reutilizado en diversos programas, sin necesidad de volver a crearlos. 4.3. Programación Orientada a Objetos (POO). La POO ha tomado las mejores ideas de la programación estructurada y modular y las ha combinado con conceptos nuevos. Así con la POO la programación se realiza desde un punto de vista muy distinto. Podría decirse que se trata de dividir el problema en subgrupos relacionados denominados objetos, que serán unidades encapsuladas con un nivel de protección para otros objetos del programa. Con ello se evitan accesos no deseados de una parte del programa a otra, cometiéndose por tanto menos errores. Además se consiguen objetos muy independientes y por tanto muy fácilmente exportables entre distintos programas.