Tema – 26 Programación modular.

Tema – 26 Programación modular.

1. PROGRAMACIÓN MODULAR. 2

2. DISEÑO DE FUNCIONES. 4

2.1 Procedimientos. 4

2.2 Funciones. 4

2.3 Paso de parámetros. 4

2.4 Variables locales y globales. 5

2.5 Invocaciones a un módulo. 6

2.6 Independencia funcional 6

2.7 Ejemplo de programación modular. 6

3. RECURSIVIDAD.. 6

3.1 Ejemplo clásico de recursividad simple: el factorial de un número. 7

3.2 Ejemplo de recursividad múltiple: recorrido de un árbol. 7

3.3 Aplicaciones e inconvenientes de la recursividad. 8

4. LIBRERÍAS. 9

1. PROGRAMACIÓN MODULAR

Programación clásica o convencional

Aparece con los primeros lenguajes (BASIC, COBOL y FORTRAN)

Usa instrucciones y ramificaciones.

Usaban instrucciones como If y GOTO.

Programación estructurada

Se crean bloques de instrucciones donde el flujo del programa tiene una única entrada y una única salida.

Se usan bloques de REPETIR…HASTA, MIENTRAS…HACER

Programación modular

Se divide el programa en módulos.

Cada módulo realiza una tarea determinada y se conecta con los demás módulos usando los parámetros. (ADA)

Programación orientada al objeto

Reúne tanto los módulos como los datos en un objeto.

Un objeto es una entidad que agrupa métodos (módulos) y propiedades (datos).

La programación modular se basa en la siguiente máxima: es más fácil resolver muchos problemas pequeños que un problema grande.

Se divide un programa en una serie de módulos que funcionan de forma independiente.

clip_image002

Problema de abstracción: Descomponemos un problema en otros más sencillos.

Acepta técnicas de refinamiento. Dividimos un problema en subproblemas.

Se puede aplicar el refinamiento cuantas veces se quiera.

Esta forma de trabaja se denomina Diseño descendente, estructura jerárquica y se van creando módulos de menor nivel.

VENTAJAS PROGRAMACIÓN MODULAR

Permiten el trabajo en equipo

Facilita la depuración. Más sencillo localizar errores.

Posibilitan la reutilización. Los módulos se pueden usar en más programas.

Facilita el mantenimiento. Se puede alterar el módulo sin alterar el programa.

Cada módulo es como una caja negra. No nos importa como realiza la tarea.

Facilita la creación de librerías.

CARACTERÍSTICAS DESEABLES DE UN MÓDULO

Realiza una única tarea

Tienen que ser pequeño

Conjunto de instrucciones que se ejecutan una sola vez.

Tiene un identificador para llamarlo.

Puede disponer de parámetros de E/S.

Puede ser llamado desde otro módulo.

Dispone de un único punto de entrada y de salida.

Los tipos de módulos que podemos encontrar son:

Programas

Procedimientos

Funciones

2. DISEÑO DE FUNCIONES

2 herramientas para las técnicas de modularidad:

Procedimientos

Funciones

Se dividen en 2 partes:

o Cabecera: Nombre del módulo, interface, constantes, tipos y variables que usamos.

o Cuerpo: Donde escribimos el código del módulo.

2.1 Procedimientos

PROCEDIMIENTO Ejemplo (Parámetro_Entrada1: Tipo_Parámetro1; Parámetro_Entrada2: Tipo_Parámetro2…; Parámetro_EntradaN: Tipo_ParámetroN; E/S Parámetros_Entrada_Salida1; E/S Parámetros_Entrada_Salida2; E/S Parámetro_Entrada_SalidaN);

2.2 Funciones

FUNCION Ejemplo (Parámetro_Entrada1: Tipo_Parámetro1; Parámetro_Entrada2: Tipo_Parámetro2…; Parámetro_EntradaN: Tipo_ParámetroN; E/S Parámetros_Entrada_Salida1; E/S Parámetros_Entrada_Salida2; E/S Parámetros_Entrada_SalidaN): Tipo_de_valor_salida;

Las funciones son muy parecidas a los procedimientos, pero hay 3 diferencias:

o Palabra reservada Función.

o Se define el tipo de valor que se devuelve en la cabecera.

o En una instrucción se devuelve ese valor.

¿Cuándo emplear un procedimiento o una función?

Normalmente, se usa una función cuando devolvemos un valor simple, y un procedimiento cuando devolvemos más de un valor, valor complejo o ningún valor.

2.3 Paso de parámetros

Para comunicarnos con un módulo superior y uno inferior.

1) Paso por valor: Realiza una copia del valor del parámetro en otra posición de memoria diferente. Si se modifica la variable en el módulo local nunca vamos a alterar el valor de la variable global.

2) Paso por referencia: El parámetro se sustituye por la dirección que ocupa la variable.

clip_image003

2.4 Variables locales y globales

Variable global: objeto que se declara en el programa principal. Accesible desde cualquier parte.

Variable local: objeto declarado dentro de un módulo. Solo se pueden usar dentro del módulo.

clip_image005

Efecto lateral:

La comunicación del módulo con el programa se debe realizas a través de parámetros. Si un módulo modifica una variable global (distinta de un parámetro actual) esto es un efecto lateral, por ello excepto en contadas ocasiones, no debe aparecer en la declaración del procedimiento. Si se necesita una variable temporal en un procedimiento es mejor utilizar una variable local, que habría que declarar en el módulo.

2.5 Invocaciones a un módulo

Para llamar a un procedimiento: Menu(opción); à se le pasa el parámetro opción E/S à Se emplea el paso por referencia

Para llamar a una función: Escribir(Factorial (5)); à Llamamos a la función con el valor 5. El parámetro es de entrada. à Se emplea el paso por valor.

2.6 Independencia funcional

Consiste en diseñar los módulos de nuestro programa de forma que realicen una función específica y tengan una interfaz sencilla.

Si los módulos son independientes à Logramos un software.

1) Fácil de desarrollar

2) Fácil de mantener

3) Fácil de probar

Se mide con 2 parámetros:

o Cohesión: Requiere poca interacción con otros módulos y realiza una tarea sencilla.

o Acoplamiento: Interconexión de los módulos de un programa. Cuanto menor sea el acoplamiento mejor.

2.7 Ejemplo de programación modular

clip_image007

3. RECURSIVIDAD

Se llama a sí misma, es decir, un programa se llama a su cabeza x veces.

3.1 Ejemplo clásico de recursividad simple: el factorial de un número

clip_image008clip_image009

Todas las funciones recursivas se caracterizan por:

Caso recursivo: Una o varias llamadas a la función para devolver un valor.

Caso o casos base: No se requiere llamada. Devolvemos directamente valor.

Tipos de recursividad

Simple: Genera como mucho otra llamada recursiva.

Múltiple: Puede generar más de una llamada a la propia función.

Forma de activar la recursividad

Directa: El módulo se llama a si mismo.

Indirecta: Esta función llama a otra, y esta, a su vez, llama a la primera.

3.2 Ejemplo de recursividad múltiple: recorrido de un árbol.

clip_image011

3.3 Aplicaciones e inconvenientes de la recursividad

Si se realizan muchas llamadas à Desbordamiento de pila (stack overflow).

Tiene muchas aplicaciones:

– Quicksort

– IA

– Torres de Hanoi

– 8 damas del tablero de ajedrez

– Árboles y listas

3.3.1 Divide y vencerás

Divide un problema de tamaño M en problemas menores de tamaño K. Tras resolver los subproblemas, se fusionan los resultados parciales hasta resolver problema global.

Ejemplo quicksort

package com.java2novice.sorting;

public class MyQuickSort {

    private int array[];

    private int length;

    public void sort(int[] inputArr) {

        if (inputArr == null || inputArr.length == 0) {

            return;

        }

        this.array = inputArr;

        length = inputArr.length;

        quickSort(0, length – 1);

    }

    private void quickSort(int lowerIndex, int higherIndex) {

        int i = lowerIndex;

        int j = higherIndex;

        // calculate pivot number, I am taking pivot as middle index number

        int pivot = array[lowerIndex+(higherIndex-lowerIndex)/2];

        // Divide into two arrays

        while (i <= j) {

            /**

             * In each iteration, we will identify a number from left side which

             * is greater then the pivot value, and also we will identify a number

             * from right side which is less then the pivot value. Once the search

             * is done, then we exchange both numbers.

             */

            while (array[i] < pivot) {

                i++;

            }

            while (array[j] > pivot) {

                j–;

            }

            if (i <= j) {

                exchangeNumbers(i, j);

                //move index to next position on both sides

                i++;

                j–;

            }

        }

        // call quickSort() method recursively

        if (lowerIndex < j)

            quickSort(lowerIndex, j);

        if (i < higherIndex)

            quickSort(i, higherIndex);

    }

    private void exchangeNumbers(int i, int j) {

        int temp = array[i];

        array[i] = array[j];

        array[j] = temp;

    }

    public static void main(String a[]){

        MyQuickSort sorter = new MyQuickSort();

        int[] input = {24,2,45,20,56,75,2,56,99,53,12};

        sorter.sort(input);

        for(int i:input){

            System.out.print(i);

            System.out.print(” “);

        }

    }

}

4. LIBRERÍAS

Agrupan funciones y procedimientos. No incluyen el programa. Se hace referencia al traductor para que incluya esa librería. Podremos usar todas las funciones directamente.

2 tipos de librerías:

Librerías estándar predefinidas por la herramienta de programación:

Facilitan al programador su tarea.

Tienen diferentes funciones.

Permiten acceso a periféricos (teclado, impresora …)

Librerías definidas por el programador:

Se pueden crear propias librerías con los procedimientos o funciones que queramos.

Cada librería tiene un nombre identificativo que nos permite usarla.

Dependiendo de la forma hay diferentes tipos:

Librerías código fuente:

Escritas en lenguaje programación.

Para usarlas, es necesario compilarlas en un módulo objeto. Luego es necesario enlazar el módulo objeto a la librería con el del programa.

Librerías compiladas:

Partimos del módulo objeto.

Para usarla, debemos enlazar el módulo objeto de la librería con el del programa.

Librerías de enlace dinámico:

Son las que usa el SO Windows.

Están ya compilados y son independientes del programa ejecutable.

Se dividen en 2 partes:

Cabecera o interface:

Se definen las cabeceras de los módulos que componen nuestra librería.

Debemos conocer el nombre de la librería, el nombre de los procedimientos o funciones y los parámetros que acepta.

Implementación o código:

Es donde realmente insertamos el código.

Tanto la cabecera o implementación están incluidas en un único fichero. Aunque una librería puede usar otras y éstas otras.

Ejemplo de una librería en código:

(*Definimos el nombre de la unidad*)

Unit Mi_Unidad;

(* Zona de interface, donde declaramos los procedimientos y funciones*)

Interface

(*Cabecera de las funciones o procedimientos que vamos a introducir en este módulo, esta parte es la única que debe conocer el usuario de la librería)

FUNCTION Factorial(N:Integer): Integer

(*Implementación, aquí es donde introducimos el código de los procedimientos, y funciones*)

IMPLEMENTATION

(* Cuerpo de la función Factorial*)

FUNCTION Factorial (N:Integer): Integer

BEGIN

If (N=0)

THEN Factorial:= 1

ELSE Factorial:= N*Factorial (N-1);

END;

END;