archivo

Archivo de la etiqueta: reutilización

Ralph E. Johnson es profesor universitario y especialista en la utilización de patrones de diseño y de la programación orientada a objetos.

Precisamente por ser esa su especialidad, resulta llamativa su siguiente cita (traducción libre): “Antes de que el software sea reutilizable primero debe ser utilizable”.

Y es verdad, de nada sirve un software técnicamente perfecto si después no hace lo que el usuario quiere. Si bien todo no es ni blanco ni negro, ya que no solo se debe buscar el cumplimiento de objetivos funcionales sino que también hay que pensar que el producto software va a requerir de sucesivas evoluciones y las mismas serán tan costosas como malo haya sido el diseño y la codificación (la deuda técnica).

Cuando se habla de programación orientada a objetos se dice que un buen diseño es aquel que consigue una alta cohesión y un bajo acoplamiento. Como es lógico, estoy de acuerdo, no obstante de los dos conceptos la cohesión, tal vez por entenderse menos su utilidad, es el hermano pobre, es decir, si se tiene en cuenta alguno de los dos (algo que desgraciadamente no ocurre demasiado, ya que no se suele prestar suficiente atención a la calidad del diseño y de la codificación) se suele echar más en cuenta al acoplamiento, además de ser más inteligible por ser más evidentes los problemas existentes cuando el acoplamiento es alto.

La cohesión mide la relación entre los distintos elementos que componen una clase: atributos y métodos. Una baja cohesión da lugar a las denominadas clases tutti frutti, clases que pretenden hacer muchas cosas y diferentes.

Cuando se tienen clases con baja cohesión implica principalmente:

– Falta de comprensibilidad: La clase no sirve a un aspecto concreto, sino a muchos. Cuando pensamos en un objeto lo hacemos entendiendo que sus partes son necesarias para que exista su todo (es decir, las partes por sí solas tienen poca utilidad y es mediante su relación cuando dan entidad al objeto y hacen que en su conjunto (el todo) valga más que la suma de las partes por separado). Cuando tenemos clases cuyos elementos forman un todo, pero ese todo no es identificable con nada, nos encontraremos probablemente con clases que tienen una baja cohesión, con métodos que no guardarán relación con otros muchos de la misma y que servirán a propósitos distintos. Habrá que tener bien documentada la clase para mantenerla posteriormente, porque si la coge un equipo de desarrollo distinto o ha pasado mucho tiempo desde que se implementó resultará complicado entender para qué sirve y qué utilidad tienen muchos métodos y atributos de la misma.

– Dificulta la mantenibilidad: Además de por la disminución de la comprensibilidad de la clase, al tener más código del que debería tener, se incrementará en consecuencia la complejidad ciclomática de la misma y por tanto será más costoso realizar cambios.

– Dificulta la reutilización: Cuando tenemos una baja cohesión quiere decir que hemos modelado una realidad rara, un híbrido de muchas cosas. Se ha implementado una clase para algo muy específico y lo concreto pocas veces es reutilizable.

– Suelen tener un acoplamiento alto (en comparación a una cohesión baja): Tiene su lógica ya que la clase tendrá más métodos que si los diferentes objetos reales que están dentro de la misma se hubieran encapsulado en sus correspondientes clases. Más métodos implican por regla general llamadas a más métodos de clases y paquetes externos y en consecuencia un mayor acoplamiento.

– Tendentes a sufrir modificaciones: Como estas clases son híbridos de varias la probabilidad de tener que sufrir operaciones de mantenimiento crece (tanto como clases distintas pudieran contener en su interior), lo cual tiene su importancia sobre todo si tenemos en cuenta que este tipo de clases son más complicadas de mantener.

Una forma de medir la cohesión la tenemos con la métrica LCOM4, propuesta a partir de la métrica inicial LCOM1 de Chidamber y Kemerer. Esta métrica forma parte del conjunto de las mismas que calcula Sonar haciendo análisis estático de código.

Otra de las métricas de Chidamber y Kemerer es WMC. El cálculo para una clase es bastante sencillo ya que es el resultado de la suma de la complejidad de cada método. ¿Qué valor se coge para la complejidad? Pues depende de la convención o implementación que se utilice en cada caso, en unos casos se utiliza como base la complejidad ciclomática, en otros, se asigna el valor 1 como complejidad a cada método, lo que hace que coincida la métrica con el número de métodos de la clase.

Esta métrica además de darnos la complejidad de una clase desde otro punto de vista diferente a las otras propuestas por Chidamber y Kemerer, puede servir de referencia para determinar la capacidad de reutilización de la misma, ya que teóricamente clases con más métodos son más específicas y por tanto de menos utilidad de cara a la reutilización.

En cualquier caso, tanto complejidad general de la clase como su capacidad de reutilización depende sobre todo de las características de los objetos que se quieren implementar con la clase y de la buena codificación que se aplique, ya que también podemos encontrarnos con clases con uno o dos métodos kilométricos que además de resultar bastante complejos de mantener, propicien que la clase no sea útil desde el punto de vista de la reutilización.

Por lo comentado anteriormente, particularmente me parece más acertado ponderar la complejidad de los métodos de una clase por su complejidad ciclomática (o utilizar cualquier otra estrategia para medir la complejidad, como por ejemplo su nivel de acoplamiento con métodos o atributos de otras clases) que darles a todos el mismo peso. La utilización de la complejidad ciclomática tiene también sus desventajas, ya que hace que la métrica real sea esa (la complejidad ciclomática) y no se tenga en cuenta a la hora de realizar la medición el número de métodos real de la clase (cuando puede ser una métrica muy sencilla para analizar el diseño de una clase), es decir, pueden ser métricas complementarias, perdiendo esa complementariedad en el momento en que todo se convierte en complejidad ciclomática.

Lo más cómodo es tender hacia el desarrollo de sistemas de información que sean islas, es decir, sistemas totalmente independientes y autosuficientes a nivel de información, que contienen en su modelo de datos todo aquello que necesitan para su funcionamiento. Es decir, en estos sistemas no se depende de ningún otro, por lo que no hay que estar pendiente de si varía el modelo de datos de otra aplicación, si deja de funcionar un determinado servicio o si hay que estudiar cómo encajar esta pieza junto con otras.

Pero claro, un modelo de sistemas de esas características tiene también importantes carencias, entre las que destaca la dificultad de mantener coherente información sobre un mismo concepto almacenada y gestionada en sistemas distintos, la dificultad de realizar consultas que afecten a más de un sistemas de información que gestionan un mismo concepto, la no reutilización tanto a nivel de modelo de datos como de código de soluciones que resuelven exáctamente la misma funcionalidad, etc…

En este artículo me voy a centrar en dos tipos de informaciones, la de terceros y la de usuarios, que son muy frecuentes en la mayor parte de sistemas de información y que también como sucede en muchos casos, se gestionan de manera independiente en los mismos.

Los terceros son como el nombre indica terceras personas físicas o jurídicas que están vinculadas a información que se gestiona en un determinado sistema de información. Si no existe un modelo único de terceros, conocer el estado de las actuaciones o la suma de la información que se tiene recopilado sobre uno concreto, implicará la consulta a multitud de sistemas, en ocasiones, un esfuerzo importante y todo ello sin que existan excesivas garantías para obtener dicha información, ya que lo mismo la información del tercero no es coherente entre sistemas y por tanto no se puede localizar alguna información (por ejemplo número de NIF o CIF referidos a un mismo tercero que no son iguales en alguno de los sistemas), bien falta algún atributo importante para identificarlo unívocamente, etc…

A lo anterior hay que sumar el esfuerzo de mantener y desarrollar modelos de datos y pantallas para gestionar dicha información, que además tendrá en la mayor parte de los casos relación con otra, como por ejemplo, información de las provincias y municipios, ya que será interesante en muchas ocasiones tener almacenada al dirección o direcciones de contacto de los terceros.

En mi organización, siendo conscientes de este problema se ha desarrollado un modelo único de terceros con el objetivo de obtener una visión global de los mismos, por lo que los nuevos sistemas que se están implementando hacen uso de ese módulo horizontal, que se va ampliando en función de información asociada a terceros que pueda ser de interés tenerla disponible de forma transversal.

Tardaremos bastante en conseguir que todos los terceros estén en un mismo sitio, ya que contamos con un gran número de sistemas de información que habría que migrar a este nuevo modelo y esto además de ser costoso, requiere su tiempo e incrustarlo dentro de la planificación y prioridades individuales de cada uno de ellos, no obstante, todo lo nuevo estamos intentando que siga este modelo y tarde o temprano empezaremos a notar buenos resultados a nivel general independientemente de que a nivel del proyecto se noten ya, al no tener que invertir esfuerzo en modelar e implementar la funcionalidad de gestión de terceros.

Con los usuarios pasa algo parecido y además provoca que si alguno de ellos tiene que trabajar con distintos sistemas de información, al final tenga que mantener una maraña de información de nombres de usuario y palabras de paso que atentará contra la seguridad (ya que en muchos casos se recurirá a anotarlos en algún medio físico) y que tendrá asociado un coste de gestión (reseteo de claves, recordatorio de nombres de usuario, etc…). Si la autenticación es con certificado digital se simplificará la necesidad de que el usuario requiera recordar tantos usuarios y claves, pero por detrás los sistemas, si no existe un modelo unificado de gestión de usuarios, tendrán que seguir gestionando los mismos, con el coste de gestión inherente a esta situación y con los costes de desarrollo que ha tenido modelarlo en cada sistema.

La solución para este caso es similar a la que se ha buscado para el caso de terceros, es decir, un módulo que puede ser común a todos los sistemas en los que se mantiene dicha información y que garantizará una gestión única de usuarios (independientemente de que los perfiles de acceso se mantengan en cada sistema) y una visión coherente de los mismos. Como en los terceros, los nuevos sistemas se están implementando haciendo uso de este módulo y traerá bastante tiempo tener la mayoría de los sistemas haciendo uso de él, pero también como en el caso anterior, tardará más o tardará menos, pero terminaremos beneficiándonos de la decisión de tener un modelo unificado de gestión de usuarios.

¿En cuántos proyectos en los que ha participado o desarrollado tu organización habéis empezado desde cero, es decir, desde el framework (si es que hay framework)?.

Si se tiende a cero, mala cosa, por muy potente o poderoso que sea el framework.

Me pongo a analizar algunas empresas desarrolladoras de software de éxito, sobre todo alguna emergente en los últimos años y no me canso de ver el mismo producto base revendido hasta la saciedad o bien adaptaciones del mismo (sin ser productos excepcionales, ni novedosos). Por muy baratos que los vendan (que además no siempre se venden baratos), el beneficio es prácticamente íntegro.

Hay muchos proyectos que por necesidades del cliente sí que se tienen que hacer desde cero e incluso con variaciones en el framework si así lo estiman las normas de desarrollo del cliente. En esto no entro. Sí que entro en otros proyectos donde el cliente tenga unas normas de desarrollo más relajadas y lo que le interese sea obtener un producto que colme sus necesidades, con un precio y plazo de ejecución razonable.

Salvo proyectos muy específicos, en la mayoría de los casos siempre hay partes que se pueden reutilizar de un proyecto a otro. En muchos posts he hablado ya no solo de la necesidad de disponer de un framework lo más potente posible, sino de disponer de un catálogo de componentes de más alto nivel reutilizables. En este post voy más allá, existirán proyectos donde lo que se puede reutilizar es la misma aplicación en sí, variando lo que se tenga que cambiar en la capa cliente (ya sabemos todos que simplemente cambiando la capa cliente una misma aplicación puede parecer otro totalmente distinta aunque la funcionalidad sea la misma) y en la capa de negocio o de acceso a datos. Para que un analista pueda hacer eso, necesita tener un conocimiento general de las aplicaciones que se desarrollan en la casa. Es por esto (aunque el objetivo no sea enseñar los productos para que se reutilicen) por lo que muchas empresas, de vez en cuando (una vez cada cuatro meses o semestralmente), hacen unas jornadas de divulgación entre los empleados, enseñándole a los mismos los proyectos más significativos que han terminado su ejecución en ese período o que están a punto de terminar.

También es cierto que es más complicado reutilizar cuando eres agente pasivo en una contratación, es decir, ganas un concurso (con esto no quiero decir que no se pueda reutilizar, pero digamos que la iniciativa, la lleva como es lógico el que contrata y te puede poner una serie de restricciones en el proyecto que te impidan en gran medida la reutilización), pero es más sencillo si eres agente activo, es decir, tienes un software que resuelve una temática concreta de un negocio y lo vendes a un tercero. Eso sí, en el acuerdo de venta debe quedar muy claro, hasta donde va a llegar la personalización, ya que en caso contrario, te puedes encontrar con que te desvistan entero el producto y sea lo mismo que empezar desde cero.