Sei sulla pagina 1di 19

Plp 1

Primeros pasos desde los unos y ceros

A fines de los 1940, las computadoras tenan memorias muy pequeas (del orden de 1K), y
por tanto se requera cdigo muy compacto.

Las computadoras de esa poca tambin eran muy lentas, por lo que se pona gran nfasis
en la eficiencia en tiempo de ejecucin.

La programacin en ese entonces se realizaba sin ningn tipo de herramientas de software


(ni siquiera ensambladores). Se programaba en lenguaje mquina (o sea, en binario). Las
principales caractersticas de estos lenguajes se pueden expresar como:

Extremadamente simple y de bajo nivel.


Un conjunto de instrucciones extremadamente irregular y por lo tanto difcil de
recordar.
Cero portabilidad. Instrucciones especficas para cada computadora en particular.
Los problemas numricos requeran de un escalamiento manual de los nmeros.
Las operaciones de punto flotante y la indizacin no se proporcionaban en
hardware.
Las instrucciones no estaban diseadas para ser ledas o escritas por humanos
(resultaban muy difciles de entender).

En base a lo anterior, resultaba una programacin sumamente tediosa y difcil.

Esto motiv el desarrollo de herramientas (llamadas notaciones de diseo), cuyo propsito


era facilitar la codificacin de programas.

John von Neumann y Herman Goldstine inventaron los diagramas de flujo. Estas ayudas
eran representaciones grficas de los algoritmos que facilitaban en cierta medida la
programacin.

Luego aparecieron los Ensambladores, que usaban letras en lugar de nmeros para denotar
las instrucciones como por ejemplo ADD 01 34. En lenguaje ensamblador los comandos
son mnemnicos y cada instruccin en ensamblador general exactamente una instruccin
en lenguaje de mquina.

Posteriormente aparecieron los interpretes de pseudo-cdigo, los que proporcionaron una


abstraccin de ms alto nivel que la dada por los ensambladores. La abstraccin pertenece a
una computadora regular y til, o mquina virtual.

Los primeros pseudo-cdigos aparecieron en 1951, inspirados sobre todo por el hecho de
que las rutinas de punto flotante y de indizacin simplificaban considerablemente el
proceso de programacin, se popularizaron pequeas rutinas desarrolladas para realizar
operaciones de estos tipos.

1
Plp 1

La manera de usar estas rutinas era llamarlas como subrutinas, entonces el programa pasa a
ser una lista de stas subrutinas y sus datos. Se insertaba el cdigo de las subrutinas como si
fuese una expansin de macros (compilacin).

Las principales ventajas del pseudo-cdigo eran:

Proporcionaba una computadora virtual, la cual era ms regular y de ms alto nivel


que las computadoras verdaderas que existan en aquellos das.

Disminua las oportunidades de equivocarse, al quitarle al programador la tarea de


repetir procesos tediosos y propensos a errores.

Incrementaba la seguridad al permitir chequeo de errores de, por ejemplo, variables


no declaradas y referencias a posiciones de un arreglo que estuviesen fuera de su
lmite de definicin.

Simplificaba la depuracin al proporcionar funciones tales como el rastreo (trace)


de una ejecucin.

La principal desventaja del pseudo-cdigo era que demoraba mucho la ejecucin de un


programa.

El surgimiento de computadoras que implementaban en hardware las operaciones de punto


flotante y las indizaciones hizo que el pseudo-cdigo se volviera obsoleto.

En su lugar, se volvi popular la idea de compilar programas a partir de bibliotecas de


subrutinas. Sin embargo, la compilacin segua siendo considerada como ineficiente y se
usaba solamente para programas cortos que se usaran muchas veces.

Los intrpretes de pseudo-cdigos se implementaban a partir de las siguientes


caractersticas:

Estructuras de datos: Memoria de datos, memoria de programa y un apuntador de


instrucciones.

Representacin: Tanto la memoria de programa como la de datos son arreglos.

Ciclo Lee-Ejecuta (esto implica que nuestro intrprete es iterativo):

o Leer una instruccin en memoria (PI).


o Avanzar el PI.
o Decodificar la instruccin.
o Obtener operandos (de ser necesario) y ejecutar la operacin.
o Ir al primer paso

2
Plp 1

La decodificacin consiste bsicamente de una extraccin de campos (a partir de una


cadena numrica) La operacin de obtencin (fetch) es manejada mediante subndices de
un arreglo. Los clculos se realizan en el lenguaje husped (lo cual hace que el proceso sea
ms lento). El flujo de control se realiza cambiando el PI.

El proceso de depuracin abarca lo siguiente:

Rastreo de ejecucin (trace), el cual puede activarse o desactivarse.

Puede rastrearse la salida del programa usando pretty printing.

Pueden colocarse puntos de quiebra y operaciones de evaluacin del contenido de


memoria.

Una de las mejoras que se fueron introduciendo a los intrpretes de pseudocdigo fueron
las etiquetas simblicas, sus clasificaciones, usos e implementacin son los siguientes:

Etiquetas para las sentencias (instrucciones). Su uso hace mucho ms fcil el poder
sumar posiciones de memoria. Sin embargo, su uso requiere de una operacin
previa de definicin de etiquetas.

Etiquetas para las variables. Se requiere una operacin para declarar variables, as
como sus tipos (arreglos contra punto flotante)

Asociacin (binding) Las declaraciones asocian una cierta etiqueta con una posicin
de memoria (del programa o de datos)

Implementacin de etiquetas simblicas:

Recorrer el listado del programa buscando una etiqueta.

Construir una tabla (simblica) que traduzca etiquetas a posiciones absolutas de


memoria. Esta tabla puede chequear que las etiquetas sean nicas, as como tambin
el que se hayan definido antes de usarse.

En la primera pasada, se inicializa la tabla a no definida. Si se encuentra una


referencia antes de una definicin, entonces cambiar el valor a referenciada. Si se
encuentra una definicin de una etiqueta, entonces cambiar el valor a definida.
Una vez que termine el proceso de recorrido del programa, chequear la existencia de
los valores referenciados.

3
Plp 1

Otro punto importante y referido a la sintaxis del pseudo-cdigo era definir el formato que
implica:

Uso de caracteres. Esto es un mero cambio de la sintaxis que, sin embargo, mejora
considerablemente la legibilidad de los programas.

Formato fijo. Este formato facilita el proceso de evaluacin de expresiones (parsing)

Formato variable (libre) El ignorar los espacios en blanco da ms flexibilidad al


programador.

Implementacin. El cargador traduce los caracteres en el formato interno anterior,


usando la tabla de smbolos para las operaciones, variables y etiquetas. La vieja
sintaxis est ahora en un formato interno.

A grandes rasgos el pseudo-cdigo tiene el mismo principio bsico que los compiladores:
usa una tabla de nombres y efecta asignacin de espacios de almacenamiento.
Para disear un pseudo-cdigo se necesita entonces:

Elementos:

Operaciones de punto flotante: aritmticas, comparaciones, funciones de entrada /


salida.

Arreglos: inicializacin, indizacin.

Flujo de control (basado en resultados de comparaciones), ciclos.

Operaciones de punto flotante:

Aritmticas.

Identidad (mover)

Suma, resta, multiplicacin, divisin, elevar al cuadrado, raz cuadrada, logaritmo.

Comparacin y flujo de control: saltar si los 2 argumentos son iguales, saltar si no o


son, saltar si argumento1 es mayor o igual que argumento2, saltar si argumento1 es
menor que argumento2.

Entrada / Salida: Leer, imprimir

4
Plp 1

Operaciones con arreglos:

Inicializacin (no se hace en tiempo de ejecucin).

Indizacin (asignacin de un elemento, extraccin de elementos).

Flujo de control:

o Comparaciones (como antes)

o Ciclos. Inicializacin. Incrementar y evaluar y quizs decrementar y evaluar.

o Finalizar (programa)
El uso de ciclos es una abstraccin que evita la repeticin del cuerpo del mismo
muchas veces y pueden implementarse eficientemente.

El pseudo-cdigo diseado presenta ortogonalidad o sea que las funciones independientes


son controladas por mecanismos independientes. Este principio nos permite realizar m * n
cosas, pero teniendo que memorizar slo m + n.

Debe tenerse en cuenta, sin embargo, que el exceso de ortogonalidad tambin es malo.
Podemos llegar a tener demasiadas operaciones, algunas de las cuales sean intiles o
difciles de implementar. De hecho, algunas de ellas podran incluso ser ilegales (en cuyo
caso debern recordarse como excepciones)

Si e es el nmero de excepciones, entonces podemos decir que el principio de


ortogonalidad es til slo si: m + n + e (lo que tenemos que recordar) < m n - e (lo que
podemos hacer).

En este punto se pueden definir o establecer ciertos principios que hacen a los
lenguajes

Principio de Ortogonalidad (de MacLennan):

Funciones independientes deben ser controladas por mecanismos


independientes.

Principio de Seguridad (de MacLennan):

Ningn programa que viole la definicin del lenguaje, o su propia estructura


original, debe escapar a la deteccin.

Principio de Abstraccin (de MacLennan):

5
Plp 1

Evitar requerir que la misma cosa se tenga que definir ms de una vez;
factorizando el patrn recurrente.

Principio de Etiquetado (de MacLennan):

No requerir del usuario que tenga que saber la posicin absoluta de un elemento
en una lista. En vez de eso, asocie etiquetas con cualquier posicin que debe ser
referenciada ms adelante.

Evolucin de los conceptos en los lenguajes de programacin. El rol de la abstraccin

Como cualquier modelo, un programa es una abstraccin de la realidad. Abstraccin es el


proceso por el cual se identifica las caractersticas o propiedades importantes del fenmeno
que est siendo modelado. Con el uso del modelo abstracto, uno se concentra en las
caractersticas importantes y deja de lado las irrelevantes. Qu es relevante y qu no
depender del propsito con el cual se dise la abstraccin. Por ejemplo, alguien que est
aprendiendo a manejar puede representar un auto simplemente por cuatro propiedades: el
combustible, el freno, el acelerador y el embrague. El ingeniero que est diseando el auto,
podra usar un modelo que tambin muestre las relaciones entre los pedales y el motor. Para
la abstraccin del conductor, el motor es una propiedad irrelevante; para el ingeniero es
crucial.

Los primeros LP no reconocan el importante rol de la abstraccin. Por ejemplo, en los 50,
el nico mecanismo de abstraccin provisto por los lenguajes assembler sobre los lenguajes
de mquina era el nombrado simblico (mediante el cual el programador poda usar
trminos auto-explicatorios para nombrar cdigos de operacin y poda simblicamente
nombrar posiciones de memoria; as el programador poda abstraerse de cdigos de
operacin no mnemotcnicos y de la ubicacin exacta de las posiciones de memoria).

La contribucin de esta facilidad a la legibilidad y modificabilidad de los programas es muy


conocida. Una cantidad muy grande del trabajo de mantenimiento requerido en los
lenguajes de mquina se realiza automticamente por el traductor, el cual hace a la
programacin ms fcil y menos propensa a errores. Por ejemplo en un programa de
modelado geomtrico, el usuario puede usar libremente nombres auto-explicatorios, tales
como VOLUME, AREA, SIZE, para denotar los valores de entidades geomtricas, sin
necesidad de llevar registro de las posiciones de memoria donde tales valores son
almacenados realmente. Adems algunos chequeos simples de correccin sobre el
programa pueden ser realizados en tiempo de traduccin. Por ejemplo, se pueden detectar
smbolos no definidos y smbolos definidos ms de una vez, lo cual ayudar al programador
a producir programas ms correctos. Tambin se puede proveer ayuda adicional mediante
herramientas simples como las tablas de referencias cruzadas. En nuestro ejemplo, la fuente
de un error en la evaluacin del volumen de un objeto se puede descubrir examinando la
lista de sentencias que asignan valores a la variable VOLUME. Tal lista puede ser
suministrada por la tabla de referencias cruzadas.

6
Plp 1

Los subprogramas (y las macros) fueron introducidos por los lenguajes ensambladores
como un medio para nombrar a una actividad descripta por un grupo de acciones y
considerarla como una accin simple. En nuestro ejemplo, la reduccin de escalas,
perspectivas, proyecciones, etc. podran ser dibujadas por los subprogramas apropiados.

Los subprogramas son herramientas tiles para la programacin metdica porque ellos son
mecanismos para implementar abstracciones. Un subprograma es la implementacin de una
abstraccin y la llamada a un subprograma representa el uso de la abstraccin.

Cuando disea el subprograma el programador se concentra en cmo trabaja, cuando lo usa


se concentra en qu hace y puede ignorar el cmo. Este es otro ejemplo del uso de la
abstraccin en programacin. El subprograma puede ser visto como una extensin del LP
mediante una nueva operacin. Cuando usa la operacin, el programador se abstrae de su
implementacin real. La mquina se ve como un procesador abstracto, de propsito
especial, cuyo repertorio de instrucciones contienen una nueva operacin.

A finales de 1950 aparecieron LP con un conjunto muy rico de mecanismos para definir
abstracciones. Estos mecanismos pueden ser usados para definir abstracciones de datos y
abstracciones de control o procedurales.

Abstraccin de datos. Abstraccin de datos en los primeros lenguajes

Los lenguajes de mquina ven a los datos almacenados como cadenas de bits que pueden
ser manejadas por las instrucciones de mquina. el repertorio de instrucciones incluye
desplazamientos, operaciones lgicas, aritmtica de punto fijo, y varias operaciones ms.

En FORTRAN, COBOL y ALGOL 60, la informacin almacenada en una posicin de


memoria, ya no se vea como una secuencia de bits annimos, sino como un valor real,
entero o booleano. La decisin acerca de las abstracciones de datos particulares a ser
incluidas en un LP eran principalmente establecidas por la mquina para la cual el lenguaje
estaba concebido (por ej. un mquina con aritmtica de punto fijo y punto flotante) y por el
espectro de aplicaciones que los lenguajes supuestamente deban cubrir (por ej.: el lenguaje
deba cubrir aplicaciones cientficas.

Como consecuencia, ningn lenguaje era adecuado para todas las aplicaciones porque el
programador est limitado por el poder expresivo de un conjunto fijo de abstracciones
suministradas por el lenguaje. Por ejemplo, FORTRAN, no es el lenguaje apropiado para
manipulacin de strings, ni COBOL lo es para resolver un sistema de ecuaciones
diferenciales; y ninguno de los dos es particularmente apropiado para la manipulacin de
matrices o aplicaciones que requieren estructuras de datos altamente dinmicas con una
variedad de formas de acceso.

PL/I que trat de ser un lenguaje universal, incorporando gran cantidad de abstracciones
incluidas en el lenguaje, en lugar de un mecanismo que permita definir nuevas
abstracciones se convirti en un lenguaje difcil de dominar e inseguro.

7
Plp 1

Abstraccin de datos en ALGOL 68, Pascal y SIMULA 67

Estos lenguajes, con un enfoque menos ambicioso pero ms efectivo, trataron de lograr
generalidad suministrando mecanismos flexibles y fciles de usar (mediante los cuales el
programador puede definir nuevas abstracciones) en lugar de intentar suministrar un
conjunto exhaustivo de abstracciones ya incluidas en el lenguaje. Tal enfoque ajusta muy
naturalmente con una metodologa de diseo basada en el reconocimiento de abstracciones.
Adems, las abstracciones identificadas para el diseo del software llegarn a estar
reflejadas por la estructura resultante del programa. Consecuentemente los programas son
ms fciles de leer y modificar y tienen una probabilidad mayor de ser correctos.

ALGOL 68 y Pascal permiten al programador usar los tipos de datos y constructores ya


incorporados al lenguaje (arreglos, registros, etc.) para definir nuevos tipos.
Usando la notacin Pascal, la siguientes definiciones y declaraciones definen dos nuevos
tipos (student y course) y tres variables del tipo course (comp_sci_15, comp_sci_140,
comp_sci_240)

Ej. : type student= record


first_name: array [1.10] of char;
mid_init: char;
last_name: array [1..15] of char;
end;
course= record
no_of_student: 0..20;
attendants: array [1..20] of student;
end;

var comp_sci_15, comp_sci_140, comp_sci_240: course;

El tipo recientemente definido student es una estructura de datos con tres componentes
usados para almacenar la identificacin del estudiante. El tipo curso est definido como una
tabla de estudiantes (attendants), junto con el nmero de estudiantes (no_of_students: un
entero entre 0 y 20) registrados para el curso.

Una pregunta natural es porqu elegimos representar los estudiantes y cursos como lo
describimos anteriormente? Mas an, porque necesitamos una estructura de datos para los
estudiantes y los cursos? Las respuestas a estas preguntas estn en las motivaciones del
programa y las abstracciones que son identificadas durante la etapa de diseo. Es imposible
contestar simplemente investigando en el programa. Podra ser til tener un lenguaje que
permite la clarificacin de tales cuestiones como parte del programa.

Por ejemplo, podemos imaginar que el programa resuelve una aplicacin para un profesor
de ciencias de la computacin, quien ensea comp_sci_15, comp_sci_140 y comp_sci_240.
Este profesor recibe de la oficina de registraciones una pila de tarjetas que contienen los

8
Plp 1

datos de los estudiantes que se registraron para estos cursos y desea obtener listados
ordenados de los estudiantes, ordenados por curso.

Podemos tambin imaginar que el tipo course ha sido definido porque se necesita para
operar sobre objetos de datos como comp_sci_15, mediante insercin de un nuevo
estudiante (en el orden apropiado) y impresin de los nombres de los estudiantes
registrados. La versin inicial abstracta del programa podra ser:

para cada tarjeta en la pila hacer


sea S la identificacin del estudiante y C el nombre del curso;
insertar S en la tabla para el curso C en el orden apropiado;
end-of-do;
imprimir la tabla para comp_sci_15;
imprimir la tabla para comp_sci_140;
imprimir la tabla para comp_sci_240;

El enfoque (imaginario) seguido por el diseador consiste en la caracterizacin de un


conjunto de operaciones lgicas sobre las tablas de los cursos antes de decidir como
implementar tales tablas en la computadora. Cualquier forma particular de implementar las
tablas de los cursos debe proporcionar una representacin para las tablas, como tambin,
las operaciones concretas, es decir los algoritmos expresados en el LP correspondiente a
las operacin lgicas sobre las tablas de cursos. Sin embargo, la decisin de cmo
representar las tablas de cursos y como implementar las operaciones estn a un nivel ms
bajo de abstraccin que la decisin de que las tablas de los cursos son necesarias para
almacenar la identificacin de los estudiantes.

En Pascal (y similarmente, en ALGOL 68) estas decisiones llevan a la declaracin de


nuevos tipos, y a la implementacin de los procedimientos siguientes, uno para cada
operacin lgica:

Insert: toma un parmetro de tipo course y un parmetro de tipo student e inserta el


valor de student en curso.

Print: toma un parmetro de tipo course e imprime su resultado.

Los procedimientos insert y print estn muy relacionados con el tipo course. Ellos son
operaciones concretas que manejan datos de tipo course. Sin embargo, tanto en ALGOL 68
como en Pascal, aunque se permita definir nuevos tipos de datos, no se los relacionaba de
una forma explcita con los procedimientos que los manejaban.

Por otro lado, SIMULA 67 provee una construccin (la clase) que permite que la
representacin y las operaciones concretas sean especificadas en una unidad sintctica
simple. Esto mejora considerablemente la legibilidad de los programas, porque las
entidades relacionadas que implementan una cierta abstraccin son agrupadas juntas.

9
Plp 1

Avanzando hacia los tipos de datos abstractos

Hay similaridades entre los tipos de datos definidos por el usuario de Pascal, ALGOL 68 y
SIMULA 67 y los tipos de datos predefinidos de estos lenguajes (por ejemplo los integers y
el tipo course definido antes.

Ambos tipos son abstracciones construidas sobre una representacin subyacente (una
cadena de bits para los integers y un record para course); ambos tipos tienen un conjunto
asociado de operaciones (operaciones aritmticas y de comparacin para los integers; insert
y print para course)

En un punto importante, sin embargo, estos dos tipos difieren: los tipos predefinidos
ocultan al programador la representacin subyacente: no pueden ser directamente
manipulados. Por ejemplo: el programador no puede acceder a un bit particular de los que
representa un integer. Por otra parte los procedimientos insert y print no son la nica forma
de acceder y manipular un dato del tipo course. El programador puede acceder directamente
a los componentes de objetos del tipo course y no est forzado a utilizar los procedimientos
que el mismo defini para dicho tipo. Por ejemplo:

comp_sci_240.no_of_student:=17;

podra ser una operacin legal (pero muy probablemente no deseable) que modifique el
nmero de estudiantes registrados en comp_sci_240. En otras palabras, no hay una
distincin forzada por el lenguaje entre los dos niveles de abstraccin: el nivel en el cual
uno puede usar courses como objetos nuevos, y el nivel en el cual uno implementa courses
en trminos de abstracciones de bajo nivel. Al mismo tiempo, el programador puede ver
courses como un objeto abstracto manipulable mediante las operaciones print y insert y
como un agregado de datos particular cuyos componentes pueden ser accedidos y
modificados individualmente.

Esta confusin entre niveles de abstraccin puede llevar a la produccin de programas que
sean difciles de leer. Y an ms importante, reduce la modificabilidad de los programas.
Supongamos que decidimos cambiar la representacin de tablas a una estructura de lista
secuencial o a un rbol binario. Los cambios no estn localizados dentro de las declaracin
de los datos y las operaciones concretas. Es adems necesario chequear todos los accesos
directos a la representacin de los datos, los cuales pueden aparecer en todo el programa.

Por lo tanto, el lenguaje debera tener caractersticas que permitan:

a) La asociacin de la representacin a las operaciones concretas en una unidad de


lenguaje adecuada que implemente los nuevos tipos.
b) El ocultamiento de la representacin del nuevo tipo a las unidades que usan el
nuevo tipo.

Los tipos de datos definidos por el usuario que satisfacen las propiedades a y b se llaman
tipos de datos abstractos. La propiedad a) hace que la versin final de un programa refleje

10
Plp 1

las abstracciones descubiertas durante el diseo del programa. La estructura resultante de


los programas llega a ser auto-explicatoria. La propiedad b) fuerza las distinciones entre los
niveles de abstraccin y favorece la modificabilidad de los programas.

Los lenguajes tradicionales han fallado en alguno de los dos puntos. La clase de SIMULA
67 satisface el punto a, pero no el b. Lenguajes ms recientes como CLU y ADA proveen
facilidades para definir TDAs (tipos de datos abstractos) que satisfacen ambas propiedades.

El concepto de tipo de dato abstracto deriva del principio ms general de ocultamiento de la


informacin; la parte de un programa que implementa un tipo de dato abstracto es un
ejemplo de un mdulo de ocultamiento de la informacin. Los tipos de datos abstractos
ocultan los detalles de la representacin y dirigen los accesos a los objetos abstractos va
procedimientos. La representacin queda protegida de cualquier intento de manipularla
directamente. Un cambio en la implementacin de un tipo de dato abstracto est confinado
a la parte del programa que describe la implementacin y no afecta el resto del programa.

Abstraccin de control

Las EC (estructuras de control) describen el orden en el cual las sentencias o grupos de


sentencias (unidades de programa) van a ser ejecutadas. Los mecanismos de control de
abstraccin determinan la adecuabilidad de un lenguaje para un rea de aplicacin
particular.

Las EC se pueden clasificar en EC a nivel de sentencia (aquellas que son usadas para
ordenar la activacin de sentencias individuales) y EC a nivel de unidad (aquellas que son
usadas para ordenar la activacin de unidades de programa)

Evolucin de las estructuras de control a nivel de sentencia:

El hardware convencional provee dos mecanismos simples para gobernar el flujo de control
sobre instrucciones individuales: secuencia y bifurcacin. La secuencia se implementa
incrementando automticamente el contador del programa luego de cada instruccin. Esto
permite que las instrucciones se almacenen en posiciones de memoria consecutivas para ser
ejecutadas una luego de la otra. El contador del programa puede tambin ser explcitamente
alterado por una instruccin de bifurcacin que transfiere el control a una posicin
especificada distinta que la prxima en la secuencia.

En los lenguajes ensambladores, las instrucciones a ser ejecutadas en secuencia se escriben


una luego de la otra, y la bifurcacin est representada por la instruccin jump. Por
ejemplo, un ciclo de N veces sobre un cierto conjunto de instrucciones requiere inicializar,
modificar y evaluar el valor de un contador (a menudo almacenado en un registro), como en
el siguiente esquema:

set register to N;
loop : if el valor en el registro es cero jump to after;
<cuerpo del ciclo>;
restaurar el valor del contador en el registro (si es necesario);

11
Plp 1

y decrementarlo en 1;
jump to loop;
after : .....................

Las estructuras de control a nivel de mquina son difciles de usar y tienden a incorporar
errores. Los programas resultantes son difciles de leer y mantener, porque estas estructuras
no son naturales para los humanos. Los humanos organizan sus procesos computacionales
de acuerdo a algunos patrones estndares, tales como la repeticin o seleccin entre
diferentes opciones. Una forma ms natural de describir el programa anterior, sera:

hacer lo siguiente N veces


<cuerpo del ciclo>

Estructuras de control orientadas a los usuarios han sido incorporadas en lenguaje de alto
nivel para facilitar la programacin y promover un mejor estilo de programacin. Sin
embargo, los lenguajes de alto nivel retienen la bifurcacin, en la forma de sentencias goto,
y por lo tanto, tambin soportan un estilo de programacin de bajo nivel. La sentencia goto
es una fuente de oscuridad en la programacin. La controversia del goto (1970) no di una
solucin definitiva al problema de cules estructuras de control deberan ser incluidas en un
lenguaje de programacin. Pero hay un acuerdo general de que las sentencias goto deberan
ser usadas slo como una tcnica para sintetizar estructuras de control legtimas si el
lenguaje no lo permite.

Evolucin de las estructuras de control a nivel de unidad.

Subprogramas y bloques

Los LP proveen facilidades para agrupar sentencias implementando una accin abstracta en
una unidad de programa adecuada. El ejemplo ms simple y til es el subprograma. La
definicin de un subprograma le da un nombre a una cierta unidad de programa. Una
llamada al subprograma invoca a la unidad de programa, es decir, transfiere el control a la
unidad llamada. Las convenciones de paso de parmetros permiten que las unidades
explcitamente intercambien informacin.

Otro ejemplo, es el bloque de ALGOL 60 o C, el cual provee agrupamiento de acciones,


pero no nombra al grupo. Un bloque, por lo tanto, no puede ser invocado explcitamente y
es ejecutado cuando se encuentra durante la progresin normal de la ejecucin.

Los subprogramas, y en menor grado, los bloques; son herramientas tiles para la
estructuracin de un programa. En particular, los subprogramas soportan la distincin entre
la definicin de una accin abstracta (el cuerpo del subprograma) y su uso (la llamada al
subprograma)

12
Plp 1

Manejo de excepciones

Los eventos que una unidad de programa puede encontrar durante su ejecucin pueden ser
ordinarios o excepcionales (por ejemplo: error de divisin por cero, error en el protocolo de
comunicaciones)

Para hacer el programa ms fcil de leer e indicar las suposiciones del programador acerca
de los hechos inesperados, es deseable poder dividir el programa en varias unidades.
Algunas unidades manejan los eventos ordinarios y pueden detectar la ocurrencia de
condiciones anmalas o excepcionales (llamadas excepciones). La ocurrencia de una
excepcin implcitamente transfiere el control a una unidad apropiada, llamada 'manejador
de excepciones', que se encarga de tratar a la excepcin.

Los LP convencionales proveen poca ayuda a la hora de tratar excepciones. Un


subprograma con probabilidades de elevar una excepcin podra ser codificado incluyendo
un parmetro de retorno adicional (por ej. un entero) que denote un cdigo de excepcin
(por ej. 0:OK, 1:nmero de excepcin1, etc). La unidad llamadora explcitamente testea el
cdigo de excepcin luego de cada llamada y luego transfiere el control al manejador
apropiado para la excepcin, si es necesario. Esta limitacin de la potencia de expresin de
un lenguaje, fuerza al programador a establecer sus intenciones y suposiciones en una
forma confusa que oscurece la lgica del programa.

PL/I fue el primer lenguaje de alto nivel en suministrar caractersticas para el manejo de
excepciones.

Corrutinas

Los subprogramas convencionales no pueden describir unidades de programa que se


ejecutan concurrentemente como sucede en simulaciones discretas. Por ejemplo la
simulacin de un juego de cartas de cuatro jugadores, podra implementarse con cuatro
unidades de programa, una para cada jugador. Luego de cada movida, una unidad debera
activar la unidad que corresponde al prximo jugador, la cual retoma su ejecucin, desde el
punto en el cual fue interrumpida, hasta que tiene que transferir el control a otra unidad.

Varios lenguajes de programacin proveen una facilidad - la corrutina - para implementar


esta forma de ejecucin intercalada.

Cada corrutina que representa un jugador del juego de cartas podra tener la siguiente
estructura general, observe la pgina siguiente.

coroutine for player y


declaraciones de los datos locales (por ej., las cartas del jugador y);
while game_not_finished do
select card;
play card;
reanudar la ejecucin de la corrutina correspondiente al prximo jugador;

13
Plp 1

end_of_do

Los subprogramas convencionales estn subordinados a su llamador y luego de terminar,


retornan al llamador. En la mayora de los LP, este retorno causa que se pierdan los datos
locales del subprograma llamado. En nuestro ejemplo esto significa que la informacin
acerca de las cartas del jugador sera perdida. A diferencia de los subprogramas, las
corrutinas son unidades simtricas que explcitamente se reanudan entre ellas. Ellas no
retornan, sino que reanudan a las otras unidades, sin perder los datos locales.

Unidades concurrentes

Las corrutinas se ajustan perfectamente para modelar actividades que son ejecutadas en
forma intercalada. Sin embargo, en muchas aplicaciones, es til modelar un sistema como
un conjunto de unidades, llamadas unidades concurrentes, cuya ejecucin procede en
paralelo (aunque realmente se ejecuten o no en paralelo). Esta facilidad es particularmente
importante en reas tales como los sistemas operativos. En la descripcin de las unidades
concurrentes, es necesario abstraerse de la arquitectura fsica de la mquina subyacente. La
mquina podra ser un multiprocesador con cada procesador dedicado a una unidad simple,
o podra ser un uniprocesador multiprogramado. Permitir esto, significa que la correccin
de un sistema concurrente no puede estar basada en alguna suposicin sobre la velocidad de
ejecucin de las unidades.

Las corrutinas son una construccin de bajo nivel para describir unidades concurrentes.
Ellas pueden ser usadas para estimular el paralelismo sobre un nico procesador
intercalando explcitamente la ejecucin de un conjunto de unidades concurrentes. Por lo
tanto, ellas no describen un conjunto de unidades concurrentes, sino una forma particular de
compartir procesador para estimular la concurrencia. Muchos de los lenguajes de
programacin ms recientes suministran caractersticas especializadas para tratar con la
concurrencia.

Correccin de un programa

La correccin y confiabilidad son dos objetivos importantes en la produccin de software.


En las primeras pocas de la computacin, estos objetivos eran implcitos y obvios. Hoy esa
visin es considerada como muy ingenua. Ahora se reconoce que si uno espera lograr tales
objetivos debe tomar cuidados y medidas especiales. La evolucin de las consideraciones
de correccin desde tangenciales a centrales ha afectado el desarrollo de las metodologas
de software y los lenguajes de programacin. El efecto en los lenguajes de programacin
tambin se ha sentido indirectamente a travs de las nuevas metodologas. En esta seccin,
seguiremos el desarrollo de las ideas sobre correcin en los lenguajes de programacin.

Un programa ser correcto si este cumple con sus especificaciones. Por otro lado un
programa es confiable si es altamente probable que cuando demandamos un servicio del

14
Plp 1

sistema, este lo realice a nuestra satisfaccin. La confiabilidad es difcil de cuantificar


porque est relacionada a la calidad del sistema tal cual es percibida por el usuario. Muchas
veces un sistema es considerado confiable an cuando no es estrictamente correcto; esto
puede suceder cuando:

1. El error no afecta la usabilidad del sistema y es fcilmente detectado y corregido por el


usuario. Por ejemplo: un error de ortografa en el mensaje:

PRAMETER N. 3 OUT OF RANGE

no afecta la confiabilidad del sistema. Por el contrario, sealar un nmero de parmetro


incorrecto s afectara la confiabilidad del sistema.

2. El error no se manifiesta muy a menudo, o no ocurre en situaciones crticas. Por ej. ser
admisible perder algunos paquetes en un sistema de conmutacin de mensajes en casos
de sobrecarga del sistema. Por el contrario, la prdida de datos puede ser inaceptable si
los datos son usados para monitorear una planta nuclear en tiempo real, y las
situaciones de emergencia deben ser manejadas tan pronto como los datos crticos sean
recibidos por el computador.

Por otro lado, softwares que son estrictamente correctos pueden no ser confiables. De
hecho, la correccin de un programa se define con relacin a sus especificaciones, as
que el programa puede ser correcto an si no logra satisfacer las necesidades de los
usuarios.

Las razones bsicas son:

1. Las especificaciones reflejan incorrecta o incompletamente los requerimientos


del sistema. Por ejemplo: los requerimientos podran especificar que se requiere
una cierta autorizacin para leer el monto de depsitos de cada cliente de un
banco, pero la especificacin falla al especificar cmo y cuando se chequea tal
autorizacin.

2. Las especificaciones no establecen lo que se supone que debe hacer el sistema en


situaciones anmalas como fallas en el hardware o errores en la entrada de
datos. Por lo tanto el sistema se comporta correctamente se mantienen varias
suposiciones acerca el ambiente, pero datos de entrada inesperados (y no
detectados) podran causar serias violaciones a la correccin del sistema, porque
no se proveen manejadores de excepciones.

Aunque la confiabilidad es el objetivo principal, es difcil de cuantificar; y la correccin se


usa a menudo como una aproximacin con la esperanza de que las especificaciones
capturen adecuadamente las propiedades deseadas del sistema. Adems, la correccin de un
programa ha sido establecida en trminos precisos, y se han desarrollado metodologas
adecuadas para probarla.

15
Plp 1

Hay dos enfoques diferentes para la produccin de programas correctos: El primero es


correccin de errores (consiste de la modificacin de un programa ya escrito cada vez que
se descubre un error). El segundo es prevencin de errores y consiste en tratar de
desarrollar programas que sean correctos desde el primer intento.

Obviamente ningn programa se puede desarrollar tan cuidadosamente como para estar
seguro que no tiene errores. La mayora del costo de la produccin de software proviene de
la correccin de errores, pero la adopcin de enfoques sistemticos apropiados en el diseo
del software puede ayudar a prevenir la introduccin de errores.

Una forma de favorecer la produccin de programas correctos es hacer fcilmente


manejables las etapas de diseo y codificacin, para que podamos confiar en el
comportamiento deseado que tendr el sistema. Herramientas para esto son las
abstracciones en los datos y en el control y las estructuras del lenguaje que permiten el
mapeo de abstracciones de diseo en estructuras del programa facilitando la produccin de
programas estructurados y correctos. Tales estructuras de programas hacen posible facilitar
la tarea compleja de razonar acerca de un objeto demasiado grande (el programa completo)
razonando acerca de objetos abstractos ms pequeos, manejables y autnomos. Adems
las unidades de programa individuales deben ser fciles de escribir y entender, para que los
posibles errores puedan ser localizados y corregidos fcilmente.

An los programas sistemticamente diseados pueden contener errores, por lo tanto es


necesario desarrollar estrategias para aislar y remover tales errores. Los LP proveen
algunos conceptos slidos para la certificacin sistemtica de programas: en el nivel ms
bajo tenemos los chequeos de consistencia, los cuales verifican que el programa se ajuste a
la definicin del lenguaje. Por ejemplo, los programas deben estar sintcticamente bien
formados, las variables deben ser usadas en una forma consistente con su tipo, y los
subprogramas deben ser llamados con los parmetros actuales respetando en cantidad y tipo
los parmetros formales.

Los chequeos de consistencia realizados antes de la ejecucin del programa son llamados
chequeos estticos, mientras que los realizados durante la ejecucin son llamados chequeos
en tiempo de corrida (o dinmicos) Los chequeos sintcticos realizados por el intrprete
son un ejemplo de chequeos estticos, al igual que los chequeos de tipo. El siguiente
fragmento de programa Pascal ilustra estos puntos:

var x, y: integer;
z: char;
.
.
.
x:= (((x + y) * 5 + x * y);
if x < 0 then y:=z;
.
.

16
Plp 1

La sentencia de asignacin contiene un error de sintaxis porque falta un parntesis que


cierra. La sentencia if contiene un error de tipo porque se asigna una variable char a una
integer. Ambos errores pueden ser detectados estticamente.

Aunque cualquier error detectable estticamente podra ser tambin detectado en tiempo de
ejecucin, podra ser no conveniente retardar tal chequeo de error hasta el momento de la
ejecucin por dos razones. Primero, fuentes potenciales de error podran slo ser detectadas
en tiempo de ejecucin con datos de entrada que causan que surja el error; por ejemplo, el
fragmento incorrecto antes citado sealara el error de tipo slo si x es negativo. Segundo,
los chequeos dinmicos hacen ms lenta la ejecucin del programa.

No todos los lenguajes permiten que se pueda realizar el chequeo de tipos completamente
sobre un programa antes de su ejecucin. En APL el tipo de una variable est determinado
por el valor actual de la variable, y por lo tanto puede cambiar durante la ejecucin del
programa, como lo muestra el siguiente fragmento de programa.

A <-- STRING
.
.
A <-- 3.77

Como una consecuencia, sumar un valor numrico a A ser correcto slo si el valor actual
de A es un nmero y no un string de caracteres. Pero, generalmente, esto slo se puede
testear en tiempo de ejecucin.

Como conclusin, la correccin de un programa puede ser mejorada por un lenguaje cuya
definicin requiera chequeos intensivos sobre los programas, y mejor an si ellos pueden
ser realizados estticamente. Los primeros lenguajes de programacin no reconocan la
necesidad de caractersticas del lenguaje que soporten la certificacin de programas. La
mayora de los lenguajes recientes, por otra parte, han sido diseados con el objetivos de
soportar chequeos de programas intensivos.

An con chequeos intensivos el programador puede producir un programa que no cumpla


con sus especificaciones. El programa es por lo tanto, gradualmente modificado hasta que
pueda ser certificado. El enfoque tradicional para la certificacin del programa consiste en
testearlo con diferentes conjuntos de entradas tomados de los documentos de especificacin
del programa y ver si la salida produce los resultados esperados segn sus especificaciones.
Los resultados correctos, sin embargo, no implican que el programa sea correcto, porque
solo podemos decir que el programa se comporta correctamente para los conjuntos de datos
de entrada utilizados. As, siguiendo un comentario de Dijkstra, podemos decir que el testeo
puede ser usado para probar la presencia de errores pero no su ausencia!.

Esta deficiencia intrnseca del testeo de programas ha estimulado la investigacin en la


verificacin de programas. La verificacin consiste en verificar que un programa sea
correcto independientemente de su ejecucin. En el sentido estricto prueba que la
implementacin de un programa es consistente con sus especificacin. La especificacin, a

17
Plp 1

su vez, se entiende aqu como una descripcin formal y precisa de lo que el programa tiene
que hacer.

La verificacin de programas puede ser hecha manualmente, pero en ese caso la confianza
de que el programa sea correcto depende de la confianza en que la prueba en s misma sea
correcta. Tambin se implementaron sistemas automticos para la verificacin automtica
de programas, pero todava es limitada la experiencia con su uso en sistemas prcticos y
grandes. Un ejemplo se informa en (Walker et al. 1979). Los autores de este experimento
llegan a la conclusin de que parece haber razones no tcnicas, distintas de la necesidad
por un sistema de verificacin (asistido por computadora) apropiado, por las cuales no se
utilizaran los mtodos de prueba de programas para el desarrollo de software donde la
operacin correcta es crtica... Sin embargo, las tcnicas actuales, todava no son apropiadas
para uso general. La verificacin de programas slo es posible si la semntica del lenguaje
ha sido definida formalmente.

Ni el testeo ni la verificacin proveen las respuestas definitivas a las necesidades de probar


la correccin de los programas. La verificacin de programas parece tericamente ms
fuerte que el testeo. Sin embargo, en las primeras etapas del desarrollo de un programa,
cuando es probable que haya muchos errores en el programa, el testeo puede ser ms
econmico que la prueba. En otras palabras, las tcnicas con complementarias y juntas
aseguran en mayor medida la correccin del programa. Desafortunadamente, todava no
hay una metodologa bien fundada tericamente y prcticamente utilizable que encierre las
ventajas de los dos enfoques.

Programando sistemas grandes

En un nivel ms bajo de tamao y complejidad, los proyectos que requieren la produccin


de sistemas grandes (varias miles de sentencias, 5 a 20 programadores y dos a tres aos),
son cada vez mas comunes. Manejar el diseo y produccin de sistemas grandes requiere
metodologas y herramientas apropiadas para mantener la complejidad bajo control.

Implcitamente, hemos asumido que los sistemas grandes estn compuestos de


componentes individuales llamados mdulos. La modularidad, de hecho, es muchas veces
reconocida como la nica forma de trabajo disponible para dominar la complejidad de
diseo e implementacin de sistemas grandes y complejos. Sin embargo, la modularidad es
una palabra que se utiliza muy a menudo para denotar varias propiedades del software. En
muchos casos, la modularidad est definida en trminos del tamao de las unidades de
programa que comprenden un sistema. As, por ejemplo, hay organizaciones que adoptan
estndares de produccin tal como Cada subrutina FORTRAN debe estar contenida en una
pgina de salida impresa. Restricciones que se aplican slo al tamao de los mdulos no
mejora la calidad de los programas en ningn sentido real: dividir una porcin grande de
texto de un programa en una secuencia de piezas ms pequeas no hace mejor al programa.

18
Plp 1

Una nocin mas til de modularidad se da en trminos de independencia. Esto significa que
cada mdulo debera ser entendido y posiblemente, implementado independientemente de
los otros mdulos del sistema. Cada mdulo debera realizar una funcin conceptual simple
y singular del sistema. Consecuentemente las restricciones en el tamao de un mdulo se
satisfacen automticamente como una consecuencia del proceso de diseo. El ocultamiento
de la informacin como un principio de diseo favorece la produccin de mdulos
altamente independientes. De hecho, las decisiones de diseo internas a un mdulo, estn
ocultas y no afectan la cooperacin correcta entre los mdulos. Una vez que las interfaces
del mdulo han sido (cuidadosamente) diseadas, los mdulos pueden ser desarrollados
independientemente unos de otros, almacenados en una librera, y ms tarde ensamblados
para construir un nico programa.

El objetivo de disear software modular ejerce una fuerte influencia sobre los LP. Los LP
deberan proveer facilidades para la definicin de los mdulos y para el ocultamiento de
informacin. Adems deberan proveer facilidades para estructurar una coleccin de
mdulos en un nico sistema. Finalmente debera ser posible desarrollar y certificar los
mdulos separadamente. Algunos diseos de lenguajes recientes (por ej. Ada) han sido
fuertemente influenciados por estos conceptos.

La necesidad de producir sistemas de software grandes, complejos y confiables tambin ha


influenciado el desarrollo de un nmero de herramientas que pueden asistir al programador
en el diseo, codificacin, certificacin y mantenimiento de programas individuales. Los
LP y las metodologas de desarrollo de programas aisladas no son suficientes para
incrementar significativamente la productividad del programador. La combinacin de un
LP apropiado, con un nmero de herramientas potentes, integradas, fciles de usar y
sensibles al lenguaje -es decir, un ambiente de desarrollo de software- puede llegar a ser el
factor clave en el mejoramiento de la calidad de los programas.

19

Potrebbero piacerti anche