Ejemplo 5 - Modularización

Objetivo

Comprender algunos principios básicos de modularización

Enunciado

Se pretende comparar las ventajas y desventajas de diferentes soluciones a un mismo problema para comprender algunos principios básicos de modularización.

El problema a resolver es el siguiente:

Suponga que un pintor desea calcular el costo de mano de obra por pintar una serie de paredes.

Para tal efecto solicita la información de la cantidad de paredes con el fin de calcular el área de las mismas.

El costo de mano de obra se calcula en colones por metro cuadrado.

Solución

CASO 1: SOLUCIÓN SIN MODULARIZACIÓN

import javax.swing.*;
public class Pintor {

public static void main(String argv[]){
int paredes=Integer.parseInt(JOptionPane.showInputDialog("Cuantas paredes quiere pintar: "));
double alturaDePared=0; // Altura de la pared
double anchoDePared=0; // Ancho de la pared
double areaTotal=0; // Area total de la pared
for(int i=0; i<paredes; i++){
alturaDePared=Double.parseDouble(JOptionPane.showInputDialog("Digite la altura de la pared "+i));
anchoDePared=Double.parseDouble(JOptionPane.showInputDialog("Digite el ancho de la pared "+i));
areaTotal+=alturaDePared*anchoDePared;
}
double costoPorMetro = Double.parseDouble(JOptionPane.showInputDialog("Costo por metro?"));
areaTotal*=costoPorMetro;
System.out.println("El costo de pintar es de: "+areaTotal);
System.exit(0);
}
}

OBSERVACIONES A LA SOLUCION 1

CASO 2: SOLUCIÓN CON UN MAYOR GRADO DE MODULARIZACIÓN

 
import javax.swing.*;

public class Pintor2 {
private int paredes; // Cantidad de paredes
private double areaTotal; // Area total de las paredes
private double costoPorMetroCuadrado; // Costo por metro cuadrado de pintura
private double costoTotal; // Costo total del trabajo

private void preguntarCantidadDeParedes(){
paredes = Integer.parseInt(JOptionPane.showInputDialog("Cuantas paredes desea pintar?"));
}
private double preguntarDimension(String dimension){
return Double.parseDouble(JOptionPane.showInputDialog("Digite la "+dimension+" de la pared "));
}

private void preguntarCostoPorMetroCuadradoDePintura(){
costoPorMetroCuadrado = Double.parseDouble(JOptionPane.showInputDialog("Digite el costo por metro cuadrado de pintura "));
}
public void presentarPresupuesto(){
System.out.println("El costo de pintar es de: "+costoTotal);
}
private double calcularAreaDePared(){
double alturaDePared= preguntarDimension("altura");
double anchoDePared=preguntarDimension("ancho");
return alturaDePared*anchoDePared;
}
private void calcularAreaTotal(){
// Calcula el area de cada una de las paredes
for(int i=0; i<paredes; i++){
System.out.println("Calculando area de pared "+(i+1));
areaTotal+=calcularAreaDePared();
}
}
private void calcularCostoTotal(){
costoTotal = areaTotal * costoPorMetroCuadrado;
}
public void presupuestar(){
preguntarCantidadDeParedes();

calcularAreaTotal();
preguntarCostoPorMetroCuadradoDePintura();
calcularCostoTotal();
}

public static void main(String argv[]){
Pintor2 unPintor = new Pintor2();
unPintor.presupuestar();
unPintor.presentarPresupuesto();
System.exit(0);
}
}

OBSERVACIONES A LA SOLUCION 2

La solución 2 tiene un mayor nivel de modularización :
Existe programación por objetos, existe una instancia de Pintor, y el pintor es quien “presupuesta”.
Hay una separación clara en cuanto a funcionalidad entre las acciones privadas y públicas que lleva a cabo el Pintor.
Existen acciones donde el Pintor interactúa con el usuario (aspectos de interfaz externa a la clase) para solicitar o presentar información, y otras donde lleva a cabo “cálculos” (aspectos propios de la aplicación). Incluso se podría modularizar aún más eliminando esta interacción del usuario de la clase Pintor. (ver Solucion 3)

En este caso si se desea cambiar un aspecto específico del programa se puede ir directamente al método responsable de llevar a cabo tal acción sin tener que preocuparse por la independencia con respecto a las demás acciones.
Si se deseara restar el tamaño de las ventanas y puertas del área total a pintar, esto solo implica modificar el método calcularAreaTotal y esto no afecta en lo absoluto al método calcularCostoTotal , o si hay un cambio en el cálculo del costo no hay que revisar el cálculo del área ya que son “módulos” separados.
Es importante remarcar claramente la diferencia entre cuales métodos son públicos y cuales son privados.

 

CASO 3: SOLUCIÓN CON UN DISEÑO MÁS MODULAR INCLUYENDO VARIAS CLASES

En esta última solución se han separado los aspectos relacionados con la interacción entre el usuario y el pintor (interfaz de usuario), de los aspectos asociados a la lógica de la aplicación. Ahora si se desea hacer cualquier otro tipo de interfaz (con componentes gráficos o vía páginas HTML) el Pintor sería completamente reutilizable ya que todas las funciones están concentradas en módulos no redundantes e independientes y no se mezclan varias funciones diferentes (ni se traslapan estos fragmentos de código) con los que están presentes en otros métodos.

¿COMO IDENTIFICAR SI UN MÉTODO DEBE SER PUBLICO O PRIVADO?

Los métodos que se pretende que sean accesibles para "cualquiera" desde fuera de la clase deben ser públicos. Los privados serán aquellos que solo se crear para uso interno en la clase con el fin de modularizar.

Por ejemplo: No es lo mismo pedirle a una persona 5000 colones prestados, y que esta persona en lo “privado” tome la decisión de prestar el dinero y luego vaya al cajero automático y los saque de su cuenta y lo entregue a quien se lo solicitó, que pedirle a una persona que nos de acceso a su clave del cajero automático y a su tarjeta. Lo segundo es un claro ejemplo de un método privado.
El “sacar dinero del cajero” es un método privado que la persona puede hacer en varias circunstancias pero el “pedir prestado” es un método público al que cualquiera puede recurrir. Lo que no implica que se le vaya a prestar, en todo caso a nivel privado se “decide si se le presta” o no a esa persona.

Código Fuente

Pintor.java

Pintor2.java

Pintor3.java