3.z.1 - Conocer la Programación Estructurada

Objetivo

Conocer los fundamentos de la Programación Estructurada, su historia, conceptos clave, personas relevantes y las estructuras básicas que la componen.

1. Contenidos

1.1 ¿Qué es la Programación Estructurada?

La programación estructurada es una teoría orientada a mejorar la claridad, calidad y tiempo de desarrollo utilizando únicamente subrutinas o funciones. Se trata de un paradigma de programación que nació con la vocación de facilitar la vida de los programadores, sobre todo cuando estos debían abordar fases de mejora posteriores a la creación del programa, y de ordenar la forma en la que se creaba cualquier tipo de software.

Junto con la programación orientada a objetos, es uno de los paradigmas de programación más populares que ejecutan los lenguajes más potentes que seguro conoces, incluidos, entre otros, Java, C, Python y C++.

La programación estructurada surgió como alternativa al llamado "código espagueti", programas antiguos que tenían una estructura de control de flujo compleja e incomprensible debido al uso excesivo de saltos incondicionales.

1.2 Historia y personas relevantes

El teorema de Böhm y Jacopini (1966)

En 1966, los matemáticos Corrado Böhm y Giuseppe Jacopini propusieron el teorema del programa estructurado, con el que demostraron que cualquier programa puede ser escrito utilizando solo tres instrucciones de control. ¡Esto fue toda una revolución! Implicaba la construcción de programas más sencillos y más rápidos, en los que disminuía la complejidad de las pruebas y el testing para ponerlos en funcionamiento.

Edsger Dijkstra y la carta contra el GOTO (1968)

En 1968, el científico holandés Edsger Dijkstra publicó un célebre artículo que impactó en la computación moderna: "Go To Statement Considered Harmful" (La sentencia GOTO es perjudicial). Dijkstra promovió activamente el uso de lenguajes de programación estructurada, fomentando la verificación formal de programas y la eliminación de la sentencia GOTO. De hecho, Dijkstra participó en el comité que diseñó Algol 60, el primer lenguaje de programación estructurado.

Curiosidad: El artículo de Dijkstra, publicado como una carta en la revista Communications of the ACM, generó un intenso debate que duró años. Hoy en día, prácticamente ningún lenguaje moderno utiliza la sentencia GOTO como mecanismo principal de control de flujo.

1.3 Características y ventajas

La programación estructurada ofrece numerosas ventajas respecto al estilo de programación anterior:

  • Mayor claridad: Los programas son más sencillos de entender, ya que tienen una estructura secuencial y desaparece la necesidad de rastrear los complejos saltos de líneas dentro de los bloques de código.
  • Estructura clara: Las sentencias están ligadas y relacionadas entre sí, formando bloques lógicos bien definidos.
  • Depuración optimizada: La fase de prueba y depuración se simplifica, facilitando la detección y corrección de errores.
  • Mantenimiento reducido: El coste del mantenimiento es menor, ya que modificar o extender los programas es más fácil al estar formados por una estructura secuencial y modular.
  • Mayor productividad: Al ser más sencillos los programas, son más rápidos de crear y los programadores aumentan su rendimiento.

1.4 Tipos de estructuras: secuencia, selección y repetición

El teorema del programa estructurado postula que, simplemente con la combinación de tres estructuras básicas, es suficiente para expresar cualquier función computable. Estas estructuras son:

1. Estructura secuencial

La estructura secuencial es la que se da de forma natural en el lenguaje, porque las sentencias se ejecutan en el orden en el que aparecen en el programa, es decir, una detrás de la otra.

Ejemplo en PSeInt (pseudocódigo):


Algoritmo EstructuraSecuencial
    Escribir "Primero se ejecuta esto"
    suma <- 5 + 3
    Escribir "Luego esto: ", suma
    Escribir "Y finalmente esto"
FinAlgoritmo
                

Ejemplo en Java:


// Ejemplo de estructura secuencial
System.out.println("Primero se ejecuta esto");
int suma = 5 + 3;
System.out.println("Luego esto: " + suma);
System.out.println("Y finalmente esto");
                

2. Estructura de selección o condicional

La estructura condicional se basa en que una sentencia o bloque de sentencias se ejecuta según el valor de una condición (expresión booleana). Permite que el programa tome decisiones y ejecute diferentes caminos.

Ejemplo en PSeInt (if-else):


Algoritmo EstructuraSeleccion
    Definir nota Como Entero
    nota <- 7
    Si nota >= 5 Entonces
        Escribir "Aprobado"
    Sino
        Escribir "Suspenso"
    FinSi
FinAlgoritmo
                

Ejemplo en Java (if-else):


// Ejemplo de estructura de selección (if-else)
int nota = 7;
if (nota >= 5) {
    System.out.println("Aprobado");
} else {
    System.out.println("Suspenso");
}
                

Ejemplo en PSeInt (selección múltiple - según):


Algoritmo SeleccionMultiple
    Definir dia Como Cadena
    dia <- "lunes"
    Segun dia Hacer
        "lunes":
            Escribir "Inicio de semana"
        "viernes":
            Escribir "Fin de semana"
        De Otro Modo:
            Escribir "Día entre semana"
    FinSegun
FinAlgoritmo
                

Ejemplo en Java (switch):


// También existe la selección múltiple (switch)
String dia = "lunes";
switch (dia) {
    case "lunes":
        System.out.println("Inicio de semana");
        break;
    case "viernes":
        System.out.println("Fin de semana");
        break;
    default:
        System.out.println("Día entre semana");
}
                

3. Estructura de iteración (ciclo o bucle)

La estructura de repetición ejecuta una o un conjunto de sentencias mientras una condición sea verdadera. Permite repetir bloques de código de forma controlada.

Ejemplo en PSeInt (Mientras):


Algoritmo IteracionMientras
    Definir contador Como Entero
    contador <- 1
    Mientras contador <= 5 Hacer
        Escribir "Vuelta número ", contador
        contador <- contador + 1
    FinMientras
FinAlgoritmo
                

Ejemplo en Java (while):


// Ejemplo de iteración con while (condicional al inicio)
int contador = 1;
while (contador <= 5) {
    System.out.println("Vuelta número " + contador);
    contador++;
}
                

Ejemplo en PSeInt (Repetir - Hasta Que):


Algoritmo IteracionRepetir
    Definir opcion Como Entero
    Repetir
        Escribir "Menú: pulse 1 para continuar, 0 para salir"
        Leer opcion
    Hasta Que opcion = 0
FinAlgoritmo
                

Ejemplo en Java (do-while):


// Ejemplo de do-while (condicional al final, ejecuta al menos una vez)
int opcion;
do {
    System.out.println("Menú: pulse 1 para continuar, 0 para salir");
    // Lectura de opcion
} while (opcion != 0);
                

Ejemplo en PSeInt (Para):


Algoritmo IteracionPara
    Definir i Como Entero
    Para i <- 1 Hasta 5 Con Paso 1 Hacer
        Escribir "Valor de i: ", i
    FinPara
FinAlgoritmo
                

Ejemplo en Java (for):


// Ejemplo de iteración con for (iteración determinada)
for (int i = 1; i <= 5; i++) {
    System.out.println("Valor de i: " + i);
}
                

Importante: Y solamente con estas tres estructuras de control, ¡se pueden escribir todos los programas y aplicaciones posibles! Si estás pensando que los lenguajes de programación tienen más estructuras, es cierto, pero cualquiera de ellas puede ser construida gracias a estas tres básicas.

1.5 La eliminación del GOTO

Antes de la programación estructurada, era común el uso de la sentencia GOTO, que permitía saltar incondicionalmente a cualquier parte del programa. Esto provocaba:

  • Código espagueti: Flujos de ejecución tan enmarañados que era imposible seguir la lógica.
  • Dificultad de depuración: Los errores eran muy difíciles de rastrear.
  • Mantenimiento casi imposible: Modificar una parte del programa podía tener efectos imprevisibles en otras.

La programación estructurada demostró que no se necesita GOTO si se usan correctamente las tres estructuras básicas (secuencia, selección e iteración). Hoy en día, el uso de GOTO está prácticamente desterrado de los lenguajes modernos, o se limita a casos muy específicos.

Ejemplo de "código espagueti" con GOTO (solo para entender el problema):


// ¡Esto es lo que se hacía ANTES de la programación estructurada!
10 INPUT "Introduce un número: ", N
20 IF N = 0 GOTO 60
30 IF N < 0 GOTO 80
40 PRINT "Positivo"
50 GOTO 10
60 PRINT "Es cero"
70 GOTO 10
80 PRINT "Negativo"
90 GOTO 10
                

Como puedes ver, el flujo del programa da saltos constantemente, haciendo muy difícil seguir la lógica. ¡Imagina un programa con cientos o miles de estas instrucciones!

2. Bibliografía