Aprendiento a pensar en objetos (IV)

Es decepcionante que de las 63 personas que hipotéticamente han leído el anterior artículo sobre este tema, solo una se haya aventurado a dar una respuesta a la cuestión que allí planteaba. No se si ha sido por miedo a equivocarse, a sentirse ridículo o simplemente por la comodidad de no pensar y esperar sentados la respuesta.

Por mi parte y como prometí, os dejo la respuesta. En el objeto Factura hay una referencia al objeto Forma de Pago que se hace redundante ya que el objeto Cliente ya la lleva dentro y no hay problemas por modificar sus datos en tiempo de ejecución, tal como comentaba en el artículo anterior en relación al precio del objeto Artículo.

Una vez que hemos revisado y depurado el modelo de datos, pasaremos a la redacción de las clases tal y como se comentaba en los artículos sobre Programacion orientada a objetos avanzada con xHarbour.

Dejo el código del modelo de datos propuesto, tanto para Harbour/xHarbour, como para Java y así comprobéis las similitudes que he introducido con la librería complements entre los dos entornos de desarrollo. Igual me animo y en unos días lo subo en PHP y Pyton también.

Enlaces:

Harbour/xHarbour/Xailer:

Java:

Anuncios

¿Comodidad, miedo o demasiados cambios constantes?

Traigo hoy al blog una reflexión que no por ser demasiado comentada por muchos es menos interesante. Hablaré de este tema desde el punto de vista subjetivo e imparcial de mi propia experiencia como programador por cuenta propia y ajena. Durante mi trayectoria profesional me he encontrado en todo tipo de situaciones que me llevan a pararme a hacer esta reflexión: ¿los desarrolladores de software nos acomodamos, tenemos miedo a avanzar o hay demasiados cambios constantes en nuestros desarrollos para quedarnos estancados?

Veréis, cuando yo empecé en esto de la informática, allá por 1984, aprendí RPGII, Cobol y Basic.  En aquella empresa, dedicada al proceso de datos de cámara bancaria y otras empresas, además de desarrollos de software para grandes empresas, se programaba casi todo en RPGII (o en Cobol para los bancos), pero al poco aparecieron los primeros PC’s que se programaban en BASICA y sin pensarlo dos veces se abordó el tema de aprender programarlo y desarrollar aplicaciones para esos aparatos.

Al poco me cambié de empresa y allí me pedían conocimientos de dBASEIII y Clipper, yo no tenía ni la más remota idea de que era eso, pero no me encabezoné (como hacen muchos) en obcecarme con el BASICA para programar y por mi cuenta aprendí todo lo que pude en 10 días para poder optar al puesto de trabajo que para mí significaba una importante mejora profesional.

No voy a contaros mi vida profesional desde este artículo, sería larga y aburrida, lo que si voy a contaros son los motivos que me han llevado a escribirlo.

Durante todo estos años he conocido empresarios que me contrataron, según ellos, para renovar el software y hacer avanzar la empresa; nada más lejos de la realidad, al poco tiempo de estar trabajando me encontraba parcheando programas arcaicos que costaban la misma vida mantenerlos. Como es normal, plantee en varias ocasiones a la dirección de la empresa la necesidad de renovar el software para adaptarlo a las tendencias, encontrándome con un terrible muro de miedo al cambio, de comodidad con la herramienta, de respuestas del tipo “no podemos parar el mantenimiento de las aplicaciones y ponernos a desarrollar con otra herramienta más moderna”. Lo entiendo, pero tampoco se hacía caso a la posibilidad de realizar desarrollos paralelos, dedicándole un rato cada día, para avanzar. Cuando se abordaban nuevos desarrollos, no se planteaba realizarlos con otra herramienta de programación que no fuese la que llevaban usando 10 o más años.

Yo mismo, durante una época, fui de los que se pensaban que con lo que hacía era más que suficiente y que dedicar tiempo y esfuerzo a estudiar, aprender o implementar algo nuevo era una mala inversión. No me acuerdo cual fue  el motivo, como se encendió la mecha del cambio, pero en poco tiempo ya estaba buscando libros, artículos, información, cursos y todo tipo de cosas que pudiese aprender y aplicar a mis quehaceres diarios, abriéndose un mundo de posibilidades.

He visto empresas de software que poco a poco han ido perdiendo posición en el mercado por haberse casado con una herramienta de desarrollo única, que no daba más de sí que lo que tenía. Directivos de empresa que en vez de dedicar esfuerzos a formar a sus empleados para mejorar su producto de cara al cliente, se han cerrado en banda con la única intención de reducir costes y así hacerse la ilusión de ingresar más.

Hoy en día veo empresas (dirigidas por personas que conozco, aprecio y con las que tengo amistad) que han convertido su software en el monstruo de las mil cabezas, imposible de mantener, imposible de entender. Veo directivos a los que se les ofrece la oportunidad de mejorar con poco desembolso económico que se aferran al desarrollo que tienen hecho y con el que llevan un montón de años sin darse cuenta que cada día que pasa es otro día perdido y otra oportunidad de mejorar que se evapora.

Y todos esto es por que se han acomodado dentro de un hueco que aún les da para vivir; por que tienen miedo a hacer cambios, a aprender algo nuevo, a soportar algún tipo de curva de aprendizaje que les incomode; por que no paran de hacer cambios a la aplicación que les da de comer, diariamente hacen muchos cambios, cambios que les llevan un tiempo cada vez mayor por que la aplicación es incomprensible y está tan enredada que seguirla es un caos; o bien, sencillamente, una mezcla de los tres casos.

Aprendiendo a pensar en Objetos (III)

En el último artículo vimos como se definían los objetos correspondientes a los datos del Cliente, el Artículo y la Forma de Pago. Ahora veremos como definir los objetos Linea de Factura, Linea de IVA y Linea de Vencimiento.

Objeto Linea de Factura

Objeto Linea de Factura

Objeto linea de IVA

Objeto linea de IVA

Objeto Linea de Vencimiento

Objeto Linea de Vencimiento

Estos tres objetos definen cada uno a una única línea, para poder usarlos en la aplicación debemos contar con algún mecanismo que nos permita tener agrupados varios en forma de lista, cada lenguaje de programación dispone de su propio mecanismo, generalmente un array. En la librería complements para Harbour contamos con mecanismos para manejar listas de objetos, además de otras muchas cosas.

Al mirar detenidamente el objeto Linea de Venta podréis echar en falta que no están definidos los datos de Precio e IVA, aunque si lo pensáis con atención veréis que si están, dentro del Objeto Artículo. Pero… ¿y si hay necesidad de modificarlos? Ante todo, recordemos que estamos trabajando con Objetos, por lo que el Objeto Artículo puede ser modificado sin que se altere el valor original que haya almacenado en la base de datos.

¿Por qué hay métodos para el cálculo del importe de la linea de venta o de la cuota de IVA? Una de las ventajas de trabajar con Objetos es que podemos invocar a los métodos que necesitemos para que realicen un cálculo y nos lo devuelva de forma inmediata, así ahorraremos código para realizar los cálculos y nuestro Objeto funcionará de forma inteligente.

¿Dónde se calculan los datos de las lineas de IVA y de los vencimientos? Si nos fijamos en la estructura del Objeto Factura, veremos que tiene un método que se llama “Cálculo del Total Factura”; desde este método recorreremos todas las líneas de la lista de Objetos Linea de Factura y realizaremos los cálculos correspondientes, generando, cada vez que se invoque, las correspondientes lineas de IVA y de Vencimientos.

Ya hemos diseñado nuestro Modelo de Datos pensando completamente en Objetos, para nada hemos hablado de estructuras de tablas ni nos importa como estarán los datos almacenados en la base de datos. Es posible que esta forma de plantear y resolver un problema de programación sea difícil de ver, ya que, al estar acostumbrados a trabajar a partir de tablas, no paramos de pensar como van a guardarse los datos. Insisto: no debe importarnos lo más mínimo como serán (o son) las tablas de la base de datos; para programar usando POO hay que pensar en objetos.

Ahora toca depurar el modelo antes de construir las Clases. Os animo a hacerlo y, ya os aviso, he cometido un pequeño error que me gustaría descubráis. Dejadme un comentario con la respuesta y luego desvelo el misterio.

Aprendiendo a pensar en Objetos (II)

En el artículo anterior vimos como comenzar a pensar en objetos a partir de la factura que nuestro hipotético cliente nos presentó. Recordemos que consideramos la factura un objeto que contendría dentro lo siguiente:

Objeto factura.

Para continuar con el estudio del modelo de datos de la aplicación, identificaremos los objetos Forma de Pago, Cliente y Artículo:

Objeto forma de pago

Objeto forma de pago

Objeto cliente

Objeto cliente

Objeto artículo

Objeto artículo

Nota: Para simplificar, en el objeto artículo se indicará el porcentaje de IVA, aunque lo correcto sería tener una Clase IVA y un objeto IVA dentro del artículo.

En el próximo artículo veremos los objetos Linea de Factura, IVA y Vencimiento.

Aprendiendo a pensar en Objetos (I)

En algunos artículos anteriores, e incluso en los vídeos, hago especial hincapié en la necesidad de estudiar los proyectos directamente como objetos en vez de hacerlo basándonos en la estructura de tablas a la que estamos acostumbrados.

Actualmente, cuando abordamos un nuevo proyecto, después de estudiarnos las especificaciones y tener un par de reuniones con el cliente, lo primero que hacemos es diseñar directamente la estructura de las tablas de la base de datos. No es que hacerlo está mal, es lo que estamos acostumbrados a hacer después de años de trabajo y era lo que aprendimos entonces. Pero pensándolo desde el punto de vista POO no nos vale ese planteamiento.

Después de escribir aquellos artículos recibí algún que otro correo en el que se me preguntaba que era eso de “pensar en objetos” y que como se hacía. El algunos de aquellos correos, los autores confesaban que no veían otra forma de hacer las cosas que no fuese diseñando las tablas primero.

Pues bien, hoy vamos a plantear un sencillo problema y a partir de ahí vamos a aprender a pensar en objetos olvidando el diseño de aplicaciones basado en tablas.

El problema

El cliente Cetanito,S.L, dedicado a la distribución de productos de consumo, nos ha  contratado para que le hagamos un sistema para poder efectuar facturas de sus productos a sus clientes. Cada cliente tiene acordada una forma de pago habitual que puede cambiar a la hora de hacer la factura por el motivo que sea (no nos importa) y debe especificarse en el documento de factura. Dependiendo de las formas de pago se generan una serie de vencimientos que deben aparecer en la factura. Los artículos tienen diferentes tipos de IVA que deben salir desglosados en la factura. Nos presenta el siguiente modelo de factura:

Factura

Factura

en cuanto a los artículos, nos indica que disponen de la siguiente información: código, descripción, precio y tipo de iva. Los datos que guarda de los clientes son el CIF/NIF, nombre, domicilio completo, teléfono, persona de contacto, teléfono de la persona de contacto y dirección de correo electrónico. Las formas de pago son simples y los vencimientos son regulares (generalmente de 30 en 30 días).

La solución

En este momento, y después de resolver las dudas que se nos hubiesen planteado, es cuando nos ponemos a trabajar y, siguiendo el modelo tradicional lo primero que se nos viene a la mente hacer es diseñar las tablas, y generalmente empezamos por las tablas maestras.

Pues bien, para pensar en objetos y empezar a solucionar el problema, en vez de basarnos en la estructura de las tablas maestras, lo primero que vamos a hacer es observar detenidamente la factura, que a fin y al cavo es el documento que debe generar nuestro sistema, e identificar las partes que la componen.

En primer lugar identificamos un objeto, la propia factura. Es un objeto físico y es susceptible de ser convertido en un objeto dentro de nuestro sistema. Vayamos poco a poco identificando las partes que componen la factura:

  • Los datos identificativos de la factura, número y fecha.
  • Los datos identificativos del cliente.
  • El detalle de la factura, con los productos que compra el cliente.
  • La forma de pago.
  • Los vencimientos generados por la forma de pago.
  • Los desgloses de los tipos de IVA aplicados.
  • El total de la factura.

Ahora veamos que elementos pueden ser objetos:

  • Los datos del cliente es un objeto Cliente.
  • Cada linea del detalle es un objeto Linea de Factura.
  • La forma de pago es un objeto Forma de Pago.
  • Cada vencimiento es un objeto Vencimiento.
  • Cada desglose de IVA es un objeto IVA.

Hay otros elementos de la factura que no son objetos y que son datos:

  • Dato Número.
  • Dato Fecha.
  • El total de la Factura es un dato que vendrá recalculado mediante un método.

Ahora, cuando hemos apartado la vista de la estructura de tablas y nos hemos centrado en objetos, podemos ver el problema desde otro punto de vista y tal como se muestra en la imagen:

Estudio del Objeto Factura

Estudio del Objeto Factura

Sospechosos habituales SEO (by http://www.e-interactive.es/)

Reflexión: Modelo de datos y clases basadas en estructura de tablas o en aspecto visual.

Ha llegado la hora de migrar otra de las aplicaciones que tengo en producción y desarrollo constante a MVC usando la librería complements en Xailer, por lo que he empezado a estudiar el modelo de datos que necesitaré para la aplicación. Actualmente la aplicación funciona con MySQL y un sistema de clases basado en la estructura de las tablas de la base de datos.

Ahora bien, estoy planteándome si debo reconstruir el modelo de datos basándome en la estructura de las tablas (parece que es lo más correcto según la forma de trabajo tradicional) o bien adaptar el modelo de datos a los aspectos visuales de la aplicación. Intentaré explicar que es esto del aspecto visual de la aplicación.

Tengamos nuestra pantalla de edición de datos de una tabla maestra, la de formas de pago por ejemplo; aquí no hay duda, la estructura de la tabla coincide completamente con  el aspecto visual de la pantalla de edición.

Veamos ahora que ocurre con otra tabla, maestra también, pero que además de sus propios datos, toma datos de otra tabla. Por ejemplo, la tabla de clientes que lleva asociada una forma de pago. Este caso es un poco más complejo, pero está también claro que la clase a usar en el modelo de datos se asemeja mucho al aspecto de la pantalla de edición.

Avanzamos un poco más y tengamos el caso de un maestro/detalle (un albarán, una factura, un pedido…) que lleva mucha más información y que en el diseño de tablas de la base de datos está repartido en varias: cabecera, lineas, vencimientos …. Aquí se nos presenta el problema de crear una clase que en su interior contenga todos los datos que deseamos mostrar en la pantalla de edición, adaptándola a ella de forma que desde un objeto tengamos acceso a toda la información que necesitamos editar. Si en este caso usamos clases basadas en la estructura de tablas, deberemos tener en cuenta muchos aspectos a la hora de realizar mantenimiento (bajas, modificaciones, altas), controlando que todo se corresponda completamente. En cambio, al usar clases basadas en el aspecto visual y tener todo programado en varias capas, con hacer miFactura:update() se actualizarán todos los datos correspondientes (cabeceras, lineas, vencimientos, etc.). Como ejemplo, una clase que contendrá una factura, podría tener en su estructura los siguientes objetos:

  • Objeto cliente. (Necesaria una clase cliente).
  • Objeto forma de pago. (Necesaria una clase forma de pago).
  • Lista de objetos de lineas de detalle. (Necesaria una clase lineaDetalleFactura).
  • Lista de objetos de lineas de vencimientos. (Necesaria una clase lineasVencimiento).

Al realizar la carga de datos desde la base de datos, y dependiendo de como estén creadas nuestras tablas, cargaremos los objetos con los datos almacenados. Así si tenemos los datos del cliente en la tabla de cabecera, cargaremos el objeto cliente con esos datos; igual para las formas de pago, para los artículos, etc.).

Un caso algo más complejo: una agenda de citas de una consulta médica. Parece fácil a primera vista, pero si queremos controlar fácilmente desde nuestro código cada item de la agenda debemos, necesariamente, pensar en adaptar la clase del modelo de datos al aspecto visual de la agenda. Por regla general, mostraremos los items de la agenda dentro de una (o varias) celdas de un browse, en la que será necesario indicar datos como el nombre del paciente, su teléfono, algún comentario, etc. Si lo hacemos usando la estructura de tablas, cada dato puede venir de una tabla distinta, complicando mucho su uso (máxime si queremos permitir arrastrar y soltar items de la agenda entre celdas del browse). Usando una clase que contenga la lista de objetos a presentar en el browse de forma coordinada, conseguiremos que todo se pueda controlar más fácilmente, incluso la edición del item para realizar modificaciones o su eliminación.

Mi decisión, después de pensarlo detenidamente y escribir este artículo, es la de usar un modelo de datos adaptado a los aspectos visuales de la aplicación y así poder controlar cada elemento como una entidad completa compuesta de otros objetos.