Antipatrones de desarrollo de software: The Blob

También conocido como The God Class.
La película The Blob es una buena analogía para este antipatrón. Si bien hay dos películas, una de 1958 y una remake de 1988, ambas tienen casi el mismo argumento: Una forma de vida extraterrestre con forma de gelatina ataca a la tierra. Cualquier cosa que este alien coma, lo hace crecer. MIentras tanto, los incrédulos terrícolas entran en pánico e ignoran al científico loco que es el único que sabe lo que está pasando. Mucha gente es comida antes de que ellos entren en razón. Eventualmente, the blob se hace tan grande que amenaza con acabar con todo el planeta.
Tal como este alienígena, el antipatrón es conocido por haberse "devorado" enteras arquitecturas orientadas a objetos.

Forma general

Este antipatrón es encontrado en diseños donde una clase monopoliza el proceso y otras clases encapsulan datos. Se caracteriza por un diagrama de clases compuesto de un controler complejo rodeado por simples clases de datos. La clave del problema es que la mayoría de las responsabilidades están ubicadas en una única clase.
En general, el antipatrón The Blob, es un diseño procedural. Incluso puede ser representado usando notaciones de objeto e implementado en lenguajes orientados a objetos. Un diseño procedural separa los procesos de los datos mientras que un diseño orientado a objetos, mezcla los modelos de procesos y datos, junto con divisiones.




The Blobpuede ser el resultado de la inapropiada ubicación de requerimientos. Por ejemplo, puede ser un módulo de software al que se le dieron responsabilidades que se superponen con otras partes del sistema para control o gestión del mismo.
También es frecuentemente el resultado de desarrollos iterativos en donde el código de prueba de concepto evoluciona hacia un prototypo y eventualmente como código de producción. Esto es a menudo exacerbado por el uso, pricipalmente, por lenguajes centrados en la GUI, como Visual BASIC, que le permite a un simple formulario evolucionar su funcionalidad (y por lo tanto, su propósito) durante el desarrollo incremental o "prototipado".
La ubicación de responsabilidades no se reparten durante la evolución del sistema, entonces un módulo del sistema se vuelve predominante. A menudo, The Blob es acompñado por código innecesario, haciendo difícil diferenciar entre la funcionalidad útil de la clase Blob y código que ya no es más usado (ver el antipatrón Lava Flow).


Síntomas y concecuencias

  • Una sóla clase con gran cantidad de atributos, operaciones o ambas. Una clase con 60 o más atributos y operaciones usualmente indica la presencia de este antipatrón.
  • Una colección despareja de atributos sin relación y operaciones encapsuladas en una sola clase. Una falta general a la cohesividad de los atributos y operaciones es típico.
  • Una sola clase Controller con simples clases de datos asociadas.
  • Una ausencia de diseño orientado a objeto. Un bucle principal del programa dentro del Blob asociado con objetos de datos relativamente pasivos. La única clase controller a menudo contiene casi la totalidad de la funcionalidad, muy parecido a un programa procedural.
  • Un diseño migrado que no ha sido apropiadamente refactorizado a una arquitectura orientada a objetos.
  • The Blob compromete las ventajas inherentes de un diseño orientado a objetos. Por ejemplo, limita la habilidad de modificar el sistema sin afectar la funcionalidad de otros objetos encapsulados. Las modificaciones al Blob al extensivo software encapsulado dentro de él. Las modificaciones a otros objetos en el sistema también es probable que tengan impacto sobre el software de The Blob.
  • La clase Blob es típicamente muy complicada de reusar y testear. Puede ser ineficiente o introducir excesiva complejidad reutilizar esta clase para pequeñas partes de su funcionalidad.
  • La clase Blob puede ser costosa de cargar en memoria, usando recursos excesivos incluso para operaciones simples.

Causas típicas

  • Falta de una arquitectura orientada a objetos. Los diseñadores pueden no tener un adecuado entendimiento de los principios de orientación a objetos. Alternativamente, el equipo puede carecer de habilidades apropiadas de abstracción.
  • Falta de (cualquier) arquitectura. La falta de definición de componentes del sistema, sus interacciones y el uso específico de los lenguajes de programación seleccionados. Esto permite que los programas evolucionen de una manera Ad hoc porque los lenguajes de programación son usados para una finalidad que no es la prevista.
  • Falta de cumplimiento de la arquitectura. A veces, este antipatrón crece accidentalmente, incluso luego de una bien planeada arquitectura. Esto puede ser el resultado de una inadecuada revisión de la arquitectura luego de que el desarrollo toma su lugar. Esto es especialmente frecuente con equipos que son nuevos frente a la orientación a objeto.
  • Intervención demasiado limitada. En proyectos iterativos, los desarrolladores tienden a agregar pequeñas piezas de funcionalidad a clases existentes que ya están funcionando, en lugar de agregar nuevas clases o revisar la jerarquía de clases para una ubicación más eficaz de las responsabilidades.
  • Desastre especificado. Algunas veces, The Blob, resulta de la manera en que los requerimientos son especificados. Si el requerimiento dicta una solución procedural, entonces pueden hacerse compromisos arquitectónicos durante el análisis de los requerimientos que luego se hacen difícil cambiar. Definir la arquitectura del sistema como parte del análisis del requerimiento, es usualmente inapropiado y a menudo lleva a hacia el antipatrón The Blob, o peor.

Excepciones conocidas

El antipatrón The Blob es aceptado cuando se envuelve (Wrapping) un sistema legado. No hay una partición del software requerido, sólo una capa final de código para hacer al sistema legado más accesible.


Solución refactorizada

Al igual que la mayoría de los antipatrones que se ubican en esta sección, la solución involucra una forma de refactoring. La clave es mover comportamientos afuera del Blob. Puede ser apropiado reubicar comportamientos hacia de las clases que encapsulan datos de forma que esos objetos sean más capaces y The Blob menos complejo. El método para refactorizar responsabilidades se describe a continuación:


Como primer paso, identificar o categorizar atributos relacionados y operaciones de acuerdo a sus interfaces. Dichas interfaces deben ser cohesivas. Que todos ellos se relacionen de forma directa hacia un foco, comportamiento o función en común dentro del sistema. Por ejemplo, un diagrama de arquitectura del sistema para una librería es representada con una potencial clase Blob llamada LIBRERIA.
En el ejemplo mostrado en la figura 1, la clase LIBRARY encapsula la sumatoria total de toda la funcionalidad del sistema. Por o tanto, el primer paso es identificar el conjunto de atributos y operaciones cohesivos que representen a la interfaz. En este caso, se pueden tomar las operaciones relacionadas a la gestión del catálogo como: Sort_Catalog Search_Catalog.
Se puede también identificar todas las operaciones y atributos relacionados con ítems individuales, como Print_ItemDelete_Item, etc.








El segundo paso es buscar "lugares naturales" para estas colecciones de funcionalidad basados en contratos (interfaces) y entonces migrarlos hacia allí. En este ejemplo, se toman las operaciones relacionadas a catálogos y se las migra de la clase LIBRARY a la clase CATALOG.
Se hace lo mismo con operaciones y atributos relaciondos a ítems, moviéndolos a la clase ITEM. 
Ambas cosas simplifican la clase LIBRARY y hace que las clases CATALOG e ITEM sean más que simples contenedores de datos. El resultado es un mejor diseño orientado a objetos.




El tercer paso es remover todas las asocianciones indirectas o redundantes. En este ejemplo, la clase ITEM está muy acoplada a la clase LIBRARY. En realidad cada ítem pertenece a CATALOG, que a su vez, pertenece a LIRARY.


En el cuarto paso, se migran todas las asociaciones a clases derivadas hacia una clase base común. En el ejemplo, una vez que el acoplamiento lejano ha sido removido en las clases LIBRARY e ITEM, se debe migrar a ITEM hacia CATALOG, como se muestra en la figura 4.




Finalmente, se remueven todas las asociaciones transitorias, reemplazándolas, según corresponda, con los especificadores de tipo de asociaciones y argumentos de las operaciones.
En este ejemplo, Check_Out_Item Search_For_Item serían procesos transitorios y podrían ser movidos a una clase separada con atributos locales que establezcan la ubicación específica o el criterio de búsqueda para una instancia específica de un check-out o search. Este proceso es mostrado en la figura 5.




Variaciones

Algunas veces, con un sistema compuesto de una clase The Blob y sus objetos de datos, se necesita invertir demasiado trabajo para posibilitar el refactoring de la arquitectura de la clase. Un enfoque alternativo puede proporcionar un "80%" de la solución.
En lugar de refactorizar completamente la jerarquía de clases, puede resultar posible reducir el tamaño de la clase Blob de un controller a una clase coordinadora. La clase Blob original gestiona la funcionalidad del sistema; las clases de datos son extendidas con algunos de sus propios procesos.
Las clases de datos operan bajo la dirección de la clase modificada como coordinadora. Este proceso puede permitir de la jerarquía de clases original, excepto para las migraciones de procesos de la clase Blob hacia alguna de las clases que encapsulaban datos.
Riel identifica dos forma principales del antipatrón Blob. El llama a estas dos formas God ClassesBehavioral Form y Data Form.
Behavioral Form es un objeto que contiene un proceso centralizado e interactúa con muchas otras partes del sistema. Data Form es un objeto que contiene datos compartidos que son usados por muchos objetos en el sistema. Riel introduce un número de herurísticas orientadas a objetos para detectar y refactorizar diseños God Class.

Aplicacbilidad a otros puntos de vista y escalas

Ambos puntos de vista, arquitectónica y administrativa, juegan papeles claves en la prevención inicial del antipatrón The Blob. Evitarlo puede requerir un seguimiento sobre la arquitectura para asegurar una adecuada distribución de las responsabilidades.
Es a través de un punto de vista arquitectónico que un emergente Blob es reconocido. Con un análisis orientado a objetos y un proceso de diseño maduros, y un Manager alerta que entienda el diseño, los desarrolladores pueden prevenir el crecimiento de un Blob.
El factor más importante es que, en la mayoría de los casos, es mucho menos costoso crear un diseño apropiado que rehacerlo luego de implementado. Invertir tiempo por adelantado en una buena arquitectura y educar al equipo, puede asegurar a un proyecto contra The Blob y muchos otros antipatrones.


Ejemplo

Una interfaz de usuario, cuya intención fue ser el punto de entrada para un proceso, gradualmente toma la funcionalidad de los módulos de proceso en segundo plano. Un ejemplo de esto es una pantalla PowerBuilder para que los clientes puedan ingresar y obtener datos. La pantalla puede:
1.- Mostrar datos.2.- Editar datos.3.- Ejecutar validaciones simples. Entonces, el desarrollador agrega funcionalidad a lo que estaba destinado ser el motor de decisión:
  • Validaciones complejas
  • Algoritmos que usan los datos validados para evaluar las siguientes acciones.
4.- El desarrollador toma nuevos requerimientos para:
  • Extender la interfaz de usuario a tres formularios.
  • Hacer que se maneje con scripts (y el desarrollo de un motor de scripts)
  • Agregar nuevos algoritmos al motor de decisiones.
El desarrollador extiende el módulo actual para incorporar toda la nueva funcionalidad. Entonces, en lugar de desarrollar muchos módulos, es desarrollado sólo uno. Si la aplicación planeada es pensada y diseñada, es mucho más fácil de mantener y extender.




0 comentarios:

Publicar un comentario

Muchas gracias por leer el post y comentarlo.

 
Copyright 2009 Programación SOLIDa
BloggerTheme by BloggerThemes | Design by 9thsphere