En este artículo voy a resolver un caso donde explicare como aplicar el análisis orientado a objetos y la programación orientada a servicios.
PROYECTO PROPUESTO
La empresa STORE FOR MODELS necesita una aplicación para calcular el precio de venta de un producto, teniendo en cuenta el precio de costo, los gastos administrativos y la ganancia que se espera obtener.
Cuando la empresa compra un producto, lo que realiza es comprar un lote, y el precio que tiene es el precio del lote. Se estima que en un lote el 10% de productos se encuentre defectuoso, por lo tanto, solo el 90% podrá ser comercializado.
ANÁLISIS DEL REQUERIMIENTO
Julio Contreras, que se desempeña como analista funcional en la empresa, ha realizado el siguiente análisis de lo que debe ser el INPUT y OUTPUT del requerimiento.
El análisis se ilustra con un ejemplo.
Los datos correspondientes al INPUT serían:
- Nombre del producto: Pantalón de verano para damas
- Tamaño del lote: 1000 Unidades
- Precio del lote (Soles): 50,000.00
- Porcentaje de gastos administrativos (%): 25
- Porcentaje de ganancia por unidad (%): 200
Con estos datos se obtiene el siguiente OUTPUT:
- Unidades a comercializar: 900
- Gastos administrativos (Soles): 12,500.00
- Costo total del lote (Soles): 62,500.00
- Costo por unidad (Soles): 69.44 Soles
- Ganancia por unidad (Soles): 138.88 Soles
- Precio de Venta (Soles): 208.32 Soles
ARQUITECTURA DE LA APLICACIÓN
La arquitectura para desarrollar la aplicación será un desarrollo en capas:
Capa Service: | Donde se tendrá el o los servicios necesarios para solucionar el requerimiento. |
Capa View: | La capa view es la interfaz de la aplicación con el usuario, sirve para mostrar datos al usuario y para solicitar datos al usuario. |
Capa Controller: | Esta capa es la responsable de gestionar las peticiones del usuario. Responde enviando a la vista los datos solicitados. |
ANÁLISIS Y DISEÑO DEL SERVICIO
La mejor alternativa es encapsular los datos del INPUT y OUTPUT en un objeto, de esta manera se desarrolla un solo servicio para procesar todos los datos y obtener los resultados esperados.
A la clase que encapsule todos los datos le llamaremos LoteModel.
A continuación se tiene el diseño del servicio:
DIAGRAMA DE SECUENCIA
A continuación tienes en diagrama de secuencia del proceso normal:
CODIGO FUENTE - EUREKA-CS-ORACLE-JDBC
En esta sección te presento un video de una aplicación CLIENTE-SERVIDOR desarrollada con Java y Oracle.
Tú tienes acceso al código fuente de esta aplicación, después del video tienes el enlace.
ANÁLISIS DE LA CLASE MODEL
Se trata de una clase que encapsula los datos del INPUT y el OUTPUT.
A continuación se tiene el script de esta clase:
package pe.egcc.preciodeventa.model; public class LoteModel { // INPUT private String producto; private Integer tamanio; private Double precio; private Double porcGasAdm; private Double porcGanancia; // OUTPUT private Integer unidades; private Double gasAdm; private Double cosLote; private Double cosUni; private Double ganUni; private double preVenta; public LoteModel() { } public LoteModel(String producto, Integer tamanio, Double precio, Double porcGasAdm, Double porcGanancia) { this.producto = producto; this.tamanio = tamanio; this.precio = precio; this.porcGasAdm = porcGasAdm; this.porcGanancia = porcGanancia; } public String getProducto() { return producto; } public void setProducto(String producto) { this.producto = producto; } public Integer getTamanio() { return tamanio; } public void setTamanio(Integer tamanio) { this.tamanio = tamanio; } public Double getPrecio() { return precio; } public void setPrecio(Double precio) { this.precio = precio; } public Double getPorcGasAdm() { return porcGasAdm; } public void setPorcGasAdm(Double porcGasAdm) { this.porcGasAdm = porcGasAdm; } public Double getPorcGanancia() { return porcGanancia; } public void setPorcGanancia(Double porcGanancia) { this.porcGanancia = porcGanancia; } public Integer getUnidades() { return unidades; } public void setUnidades(Integer unidades) { this.unidades = unidades; } public Double getGasAdm() { return gasAdm; } public void setGasAdm(Double gasAdm) { this.gasAdm = gasAdm; } public Double getCosLote() { return cosLote; } public void setCosLote(Double cosLote) { this.cosLote = cosLote; } public Double getCosUni() { return cosUni; } public void setCosUni(Double cosUni) { this.cosUni = cosUni; } public Double getGanUni() { return ganUni; } public void setGanUni(Double ganUni) { this.ganUni = ganUni; } public double getPreVenta() { return preVenta; } public void setPreVenta(double preVenta) { this.preVenta = preVenta; } }
CAPA SERVICE
A continuación tienes la implementación de clase correspondiente a la capa de servicio:
package pe.egcc.preciodeventa.service; import pe.egcc.preciodeventa.model.LoteModel; public class LoteService { public LoteModel procesarLote(LoteModel bean) { // Variables Integer unidades; Double gasAdm, costoLote, cosUni, ganUni, preVenta; // Proceso unidades = (int) Math.round(bean.getTamanio() * 0.90) ; gasAdm = bean.getPrecio() * ( bean.getPorcGasAdm() / 100 ); costoLote = bean.getPrecio() + gasAdm; cosUni = costoLote / unidades; ganUni = cosUni * (bean.getPorcGanancia() / 100.0); preVenta = cosUni + ganUni; // Preparar salida bean.setUnidades(unidades); bean.setGasAdm(dosDec(gasAdm)); bean.setCosLote(dosDec(costoLote)); bean.setCosUni(dosDec(cosUni)); bean.setGanUni(dosDec(ganUni)); bean.setPreVenta(dosDec(preVenta)); // Retorno return bean; } private double dosDec(double valor){ valor = Math.round( valor * 100.0 ); valor = valor / 100.0; return valor; } }
PRUEBA DEL SERVICIO
Es muy importante probar el servicio, de esta manera podemos hacer las correcciones si encontramos algún error.
La clase de prueba que he elaborado es la siguiente:
package pe.egcc.preciodeventa.prueba; import pe.egcc.preciodeventa.model.LoteModel; import pe.egcc.preciodeventa.service.LoteService; public class Prueba01 { public static void main(String[] args) { // datos String producto = "Pantalón de verano para damas"; int tamanio = 1000; double precio = 50000.0; double porcGasAdm = 25.0; double porcGanancia = 200.0; LoteModel bean = new LoteModel(producto, tamanio, precio, porcGasAdm, porcGanancia); // Proceso LoteService service = new LoteService(); bean = service.procesarLote(bean); // Reporte System.out.println("Unidades a comercializar: " + bean.getUnidades()); System.out.println("Gastos administrativos: " + bean.getGasAdm()); System.out.println("Costo del lote: " + bean.getCosLote()); System.out.println("Costo por unidad: " + bean.getCosUni()); System.out.println("Ganancia por unidad: " + bean.getGanUni()); System.out.println("Precio de venta: " + bean.getPreVenta()); } }
El resultado es el siguiente:
run-single: Unidades a comercializar: 900 Gastos administrativos: 12500.0 Costo del lote: 62500.0 Costo por unidad: 69.44 Ganancia por unidad: 138.89 Precio de venta: 208.33
CAPA CONTROLLER
A continuación tienes el script de la clase controladora:
package pe.egcc.preciodeventa.controller; import pe.egcc.preciodeventa.model.LoteModel; import pe.egcc.preciodeventa.service.LoteService; public class LoteController { public LoteModel procesarLote(LoteModel bean) { LoteService service = new LoteService(); return service.procesarLote(bean); } }
CAPA VIEW
A continuación tienes el formulario que se ha implementado:
Para programar el formulario ha sido necesario la implementación de dos métodos que sirven de soporte para su funcionamiento:
private void activarControles(boolean estado) { // Botones btnProcesar.setEnabled(estado); btnLimpiar.setEnabled(!estado); // Cuadros de texto txtPorcGana.setEnabled(estado); txtPorcGasAdm.setEnabled(estado); txtPrecio.setEnabled(estado); txtProducto.setEnabled(estado); txtTamanio.setEnabled(estado); } private void limpiarForm() { txtCosLote.setText(""); txtCosUni.setText(""); txtPorcGana.setText(""); txtPorcGasAdm.setText(""); txtPrecio.setText(""); txtPreVenta.setText(""); txtProducto.setText(""); txtTamanio.setText(""); txtUnidades.setText(""); txtGanUni.setText(""); txtGasAdm.setText(""); txtProducto.requestFocus(); }
Programación del botón Procesar:
// datos String producto = txtProducto.getText(); int tamanio = Integer.parseInt(txtTamanio.getText()); double precio = Double.parseDouble(txtPrecio.getText()); double porcGasAdm = Double.parseDouble(txtPorcGasAdm.getText()); double porcGanancia = Double.parseDouble(txtPorcGana.getText()); LoteModel bean = new LoteModel(producto, tamanio, precio, porcGasAdm, porcGanancia); // Proceso LoteController control = new LoteController(); bean = control.procesarLote(bean); // Reporte txtUnidades.setText("" + bean.getUnidades()); txtGasAdm.setText("" + bean.getGasAdm()); txtCosLote.setText("" + bean.getCosLote()); txtCosUni.setText("" + bean.getCosUni()); txtGanUni.setText("" + bean.getGanUni()); txtPreVenta.setText("" + bean.getPreVenta()); activarControles(false);
Programación del botón Limpiar:
activarControles(true); limpiarForm();
Finalmente, espero que este ejemplo te sea útil para entender la programación en capas y programación orientada a servicios.
CODIGO FUENTE - EUREKA-WEB-MYSQL-SPRING
En esta sección te presento un video de una aplicación web desarrollada SPRING FRAMEWORK y MYSQL.
Tú tienes acceso al código fuente de esta aplicación, después del video tienes el enlace.
No hay comentarios:
Publicar un comentario