archivo

Archivo de la etiqueta: clase

Hace poco un programador me comentó que una tarea de mantenimiento le estaba llevando más tiempo del previsto debido a que la mayoría de los métodos de las clases que estaba tocando tenían un nombre que daba lugar a una mala interpretación con respecto a su función real y que en otros casos no tenía absolutamente nada que ver (algo así como si en lugar de crear un método nuevo se hubiera reutilizado otro ya obsoleto y no se hubiera cambiado su nombre).

Pueden parecer detalles pequeños, sin importancia, pero la realidad es que cuestan dinero no solo porque se requiera más tiempo para realizar un mantenimiento sino porque la probabilidad de que se produzcan errores en el mismo se multiplica.

La programación no es solo crear y encajar piezas. Es muy importante tener en cuenta que otras personas después tendrán que trabajar con él y no solo eso, escribir código de forma clara e inteligible es una señal de calidad que puede marcar la diferencia entre un tipo de programadores y otros o entre una empresa y otra.

Existe la tentación, cuando se hace uso de la técnica de tarjetas CRC de aprovechar e incluir en la misma la implementación de la clase (aunque sea en pseudocódigo), convirtiéndose automáticamente la tarjeta CRC (Class-Responsibility-Collaboration) en CRCI (Class-Responsibility-Collaboration-Implementation).

Pues bien, esa práctica se considera un antipatrón, ya que se considera que se puede estar perdiendo el tiempo realizando la implementación de una clase, cuando todavía no está totalmente diseñado el sistema y por tanto no se tiene una visión todavía a nivel de detalle del mismo, lo que obligará más que probablemente a tener que rehacer la implementación especificada en la tarjeta en reiteradas ocasiones.

La utilización de tarjetas CRC (Class-Responsibility-Collaboration) es una técnica de diseño orientado a objetos propuesta por Kent Beck (introductor de la metodología de programación extrema) y Ward Cunningham (también muy conocido entre otras muchas materias, por sus aportaciones a dicha metodología).

El objetivo de la misma es hacer, mediante tarjetas, un inventario de las clases que vamos a necesitar para implementar el sistema y la forma en que van a interactuar, de esta forma se pretende facilitar el análisis y discusión de las mismas por parte de varios actores del equipo de proyecto con el objeto de que el diseño sea lo más simple posible verificando las especificaciones del sistema.

Un esquema típico de tarjeta CRC puede ser aquel en el que se indiquen los siguientes datos:

– Nombre de la clase.
– Nombre de las superclases y subclases (si procede).
– Las responsabilidades de la clase.
– Las clases con las que va a colaborar para poder realizar las responsabilidades indicadas.
– Autor, fecha, etc…

Este antipatrón se basa en la utilización dentro de un mismo sistema de diferentes “clases de propósito general”, “clases hombre-orquesta” o “clases multicasuística” en las cuales están definidos una amplia gama de comportamientos con el objeto de poder ser utilizados por otras.

También es frecuente encontrarlo en implementaciones de componentes en los que se delegan funcionalidades de otros, con el objeto de dar un amplio rango de alternativas posibles al cliente.

El problema no es dar esas facilidades, sino que el problema se encuentra en la complejidad que se le añade al código como consecuencia de las mismas (generalmente alto acoplamiento, baja cohesión, alta complejidad ciclomática, etc…).

En el antipatrón “objeto todopoderoso“, la funcionalidad de la aplicación pivota generalmente sobre una de estas clases, mientras que en la navaja suiza se trata de diferentes clases (generalmente, de utilidad) que contiene el sistema.

Este antipatrón es una mala práctica de programación y se llega a él a través de la implementación de métodos que intentan ser lo suficientemente flexibles como para ser adaptado su comportamiento a multitud de circunstancias, sobrepasando el umbral de una mantenibilidad adecuada del mismo (elevado número de parámetros donde la mayoría de ellos a veces se usan y otras no, alta complejidad ciclomática, etc…).

Presenta una analogía con el antipatrón “objeto todopoderoso“, pero teniendo como protagonista a un método y no a una clase.

Responsibility-driven design es una técnica de diseño orientado a objetos propuesta por Rebecca J. Wirfs-Brock and Brian Wilkerson.

Rebecca J. Wirfs-Brock es una autora y consultora americana especializada en los ámbitos del diseño y programación orientada a objetos, con una gran experiencia desarrollada en diferentes empresas.

Brian Wilkerson es otro especialista en programación y diseño orientado a objetos, que ha desarrollado su carrera profesional en el mundo de la consultoría.

A principio de los 90 fueron coautores de los libros en los que formulaban esta técnica de diseño.

El diseño orientado a la responsabilidad se basa en dar respuesta para cada tipo de objeto a las siguientes preguntas:

– ¿De qué acciones es responsable el objeto?
– ¿Qué información comparte el objeto?

Proporcionando una alternativa a los diseños que consideraban a los objetos como datos y algoritmos. En este caso los objetos se consideran como la conjunción de roles y responsabilidades, los cuales conviven cooperando dentro de la aplicación.

Esta técnica de diseño está claramente inspirada en la mecánica de funcionamiento cliente/servidor, en la cual se define un contrato que rige el funcionamiento de los objetos implicados de manera que el cliente solo puede realizar los tipos de solicitudes/peticiones que se hayan definido y el servidor debe responder.

Es una técnica que también huye del conocimiento de los detalles de cómo un objeto realiza una acción u obtiene un resultado, fomentando de esta forma el concepto de encapsulamiento. Además, para reforzar esta cualidad, Wirfs-Brock y Wilkerson abogan por la existencia de un control de grano fino de visibilidad de los objetos.

No solo es una técnica que persigue el encapsulamiento sino la abstracción al ocultar, al menos en términos de diseño, la relación entre datos y comportamiento, ya que solo se debe pensar en responsabilidades a nivel de conocer, hacer y decidir.

En la técnica, por tanto, tendremos una comunidad de objetos que tienen asignadas responsabilidades específicas y que conforman un modelo colaborativo de funcionamiento en el que los mecanismos de colaboración están claramente definidos constituyendo de esta forma una arquitectura en la que existe un comportamiento distribuido.

De esta forma podemos realizar las siguientes definiciones:

¿Qué es una aplicación? Un conjunto de objetos que interactúan.
¿Qué es un objeto? La implementación de uno o más roles.
¿Qué es un rol? Un conjunto de responsabilidades
¿Qué es una responsabilidad? La obligación de realizar una tarea o de conocer un determinado tipo de información.
¿Qué es una colaboración? A la interección entre objetos y/o roles.

Tal y como se ha comentado anteriormente, esta técnica considera a los objetos como algo más que paquetes que solo encierran lógica y datos, ahora se en función de los roles que desempeñen a controladores, proveedores de servicios, titulares de información, interfaces con el exterior, etc…

En mi organización vamos a realizar un estudio de una serie de sistemas de información (entre el 50 y el 75% aproximadamente de los mismos) con el objeto de detectar en ellos una serie de clases que pueden resultar conflictivas desde el punto de vista de la mantenibilidad.

Cualquier clase que cumpla alguna de las siguientes condiciones la consideraremos sospechosa (son solo métricas, que pueden encender determinadas alarmas, pero después resulta aconsejable revisar si existe justificación o no en que tomen esos valores) y será objeto de estudio con la finalidad de tomar una decisión sobre la necesidad de su refactorización:

1) Acoplamiento. Utilizaremos como base la métrica RFC de Chidamber y Kemerer.

RFC(clase)>=50 y RFC(clase)/Nº Métodos(clase)>=10

2) Cohesión. Utilizaremos como base la métrica LCOM4 de Chidamber y Kemerer.

LCOM4(clase)>=2

3) Complejidad Ciclomática de Thomas J. McCabe.

Complejidad Ciclomática(clase)/Nº Métodos(clase)>=10

Los valores anteriores por cada clase se obtendrán utilizando las métricas obtenidas a partir de Sonar.