Anexo:Patrones GRASP adicionales

Patrones GRASP adicionales.
Información sobre la plantilla
Grasp.JPG

Patrones GRASP adicionales. Existen 4 Patrones GRASP adicionales: Polimorfismo, Fabricación Pura, Indirección, No Hables con Extraños.

Polimorfismo

Significa “asignar el mismo nombre a servicios en varios objetos”, cuando los servicios se parecen o están relacionados entre sí.

Solución: Cuando por el tipo varían las alternativas o comportamientos afines, las responsabilidades del comportamiento se asignarán - mediante operaciones polimórficas - a los tipos en que el comportamiento presenta variantes.

  • Corolario: no realizar pruebas con el tipo de un objeto ni utilizar lógica condicional para plantear diversas alternativas basadas en el tipo.

Problema: ¿Cómo manejar las alternativas basadas en el tipo? ¿De qué manera crear componentes de software conectables?

  • Alternativas basadas en el tipo. La variación condicional es un tema esencial en la programación. Si se diseña un programa mediante la lógica condicional if-then-else o case, habrá que modificar la lógica del case cuando surja una variante.
    • Este procedimiento dificulta extender un programa con otras variantes, porque los cambios tienden a requerirse en varios lugares donde exista la lógica condicional.
  • Componentes de software conectables. Viendo los componentes en las relaciones cliente - servidor, ¿cómo se puede remplazar un componente servidor sin afectar al cliente?
    • Ejemplo: En la aplicación del punto de venta, ¿quién debería encargarse de autorizar las diversas clases de pagos?
      • El comportamiento de autorización varía con el tipo de pago: en efectivo, con tarjeta de crédito o con cheque; por eso, conforme al polimorfismo se debe asignar esa responsabilidad a cada tipo de pago, implementado con una operación polimórfica autorizar.

El uso del patrón Polimorfismo está acorde al espíritu del patrón Experto. En vez de operar externamente sobre un pago para autorizarlo, el pago se autoriza a sí mismo; esto constituye la esencia de la orientación a objetos. Si se puede caracterizar a Experto como el patrón fundamental táctico, Polimorfismo será el más importante patrón estratégico en el diseño orientado a objetos. Es un principio fundamental en que se fundan las estrategias globales, o planes de ataque, al diseñar cómo organizar un sistema para que se encargue del trabajo.

Beneficios: Es fácil agregar las futuras extensiones que requieren las variaciones imprevistas.

Fabricación Pura

Solución: Asignar un conjunto altamente cohesivo de responsabilidades a una clase artificial que no representa nada en el dominio del problema: una cosa inventada para dar soporte a una alta cohesión, un bajo acoplamiento y reutilización.

  • Esa clase es una fabricación de la imaginación.
  • Finalmente, una fabricación pura exige algo, y esto se hace cuando se está desesperado.

Problema: ¿A quién asignar la responsabilidad cuando uno está desesperado y no quiere violar los patrones Alta Cohesión y Bajo Acoplamiento?

  • Los diseños orientados a objetos se caracterizan por implementar como clases de software las representaciones de conceptos en el dominio de un problema del mundo real; por ejemplo, una clase Venta y Cliente.
  • Pese a ello, se dan muchas situaciones donde el asignar responsabilidades exclusivamente a las clases del dominio origina problemas de mala cohesión o acoplamiento o bien por un escaso potencial de reutilización.
  • Ejemplo: Suponiendo, por ejemplo, que se necesita soporte para guardar las instancias Venta en una base de datos relacional.
    • En virtud del patrón Experto, en cierto modo se justifica asignar esta responsabilidad a la clase Venta.
    • Pero no sería una buena idea por lo siguiente:
      • La tarea requiere un número relativamente amplio de operaciones de soporte orientadas a la base de datos, ninguna de las cuales se relaciona con el concepto de vender.
      • La clase Venta ha de ser acoplada a la interfaz de la base de datos relacional; de ahí que mejore su acoplamiento.
      • Guardar los objetos en una base de datos relacional es una tarea muy general en que debemos brindar soporte a muchas clases.

En conclusión, aunque en virtud del patrón Experto Venta es un candidato lógico para guardarse a sí misma en una base de datos, da origen a un diseño de baja cohesión, alto acoplamiento y bajo potencial de reutilización. Una solución razonable consiste en crear una clase nueva que se encargue tan sólo de guardar los objetos en algún tipo de almacenamiento persistente: una base de datos relacional.

Explicación: Para diseñar una Fabricación Pura debe buscarse ante todo un gran potencial de reutilización, asegurándose para ello de que sus responsabilidades sean pequeñas y cohesivas. Una fabricación pura suele partirse atendiendo a su funcionalidad y, por lo mismo, es una especie de objeto de función central. Generalmente se considera que la fabricación es parte de la capa de servicios orientada a objetos de alto nivel en una arquitectura.

Problemas:

  • Puede perderse el espíritu de los buenos diseños orientados a objetos que se centran en los posibles objetos y no en las funciones.
  • Las clases de Fabricación Pura casi siempre se dividen atendiendo a su funcionalidad; dicho con otras palabras, se confeccionan clases destinadas a conjuntos de funciones.
  • Si se abusa de ello, la creación de clases de Fabricación Pura, originará un diseño centrado en procesos o funciones que se implementa en un lenguaje orientado a objetos.

Indirección

Solución: Se asigna la responsabilidad a un objeto intermedio para que medie entre otros componentes o servicios, y éstos no terminen directamente acoplados. El intermediario crea una indirección entre el resto de los componentes o servicios.

Problema: ¿A quién se asignarán las responsabilidades a fin de evitar el acoplamiento directo?

  • ¿De qué, manera se desacoplarán los objetos de modo que se obtenga un Bajo Acoplamiento y se conserve un alto potencial de reutilización?
    • Ejemplo: AgentedeAlmacenamientoPersistente
    • El ejemplo de Fabricación Pura para desacoplar la Venta y los servicios de la base de datos relacional introduciendo la clase AgentedeAlmacenamientoPersistente es también un ejemplo de asignar responsabilidades para apoyar la Indirección.
    • El AgentedeAlmacenamientoPersistente sirve de intermediario entre la Venta y la base de datos.

No Hables Con Extraños

Solución: Se asigna la responsabilidad a un objeto directo del cliente para que colabore con un objeto indirecto, de modo que el cliente no necesite saber nada del objeto indirecto.

  • En un método los mensajes sólo deberían ser enviados a los siguientes objetos:
    • El objeto this (o self).
    • Un parámetro del método.
    • Un atributo de self.
    • Un elemento de una colección que sea atributo de self.
    • Un objeto creado en el interior del método.
  • Con esto se busca no acoplar un cliente al conocimiento de objetos indirectos, ni a las representaciones internas de objetos directos.
  • Los objetos directos son "conocidos" del cliente, los objetos indirectos son “extraños", y un cliente debería tener sólo conocidos, no extraños.
  • Cumplir con las restricciones anteriores significa que los objetos directos pueden requerir nuevas operaciones que actúen como intermediarios, a fin de que el cliente pueda evitar “hablar con extraños”.

Problema: ¿A quién asignar las responsabilidades para evitar conocer la estructura de los objetos indirectos?

  • Si un objeto conoce las conexiones internas y las estructuras de otros, entonces presentará alto acoplamiento.
  • Si un objeto cliente tiene que usar un servicio u obtener información a partir de un objeto indirecto, ¿cómo podrá hacerlo sin acoplarse al conocimiento de la estructura interna de su servidor directo o d e los objetos indirectos?
  • Ejemplo: En una aplicación del punto de venta, suponga que una instancia TPDV posee un atributo referente a una Venta, la cual cuenta con un atributo referente a un Pago.

Y además suponga que:

  • Las instancias TPDV soportan la operación montodePago, que devuelve el actual monto ofrecido como pago.
  • Las instancias Venta soportan la operación pago, la cual devuelve la instancia Pago asociada a la Venta.

Una forma de devolver el monto del pago es:

  • Esta solución constituye una violación del principio “No Hables con Extraños”, porque la instancia TPDV envía un mensaje a un objeto indirecto: el Pago no es uno de los cinco candidatos “conocidos”.
  • La solución, como lo indica el patrón, consiste en agregar la responsabilidad al objeto directo - la Venta, en este caso - para que devuelva a TPDV el monto del pago.
    • Por tanto, se agrega una operación montodePago, de modo que la instancia TPDV no tenga que hablar con un extraño.

Explicación: No Hables con Extraños se refiere a no obtener una visibilidad temporal frente a objetos indirectos, que son de conocimiento de otros objetos pero no del cliente.

  • La desventaja de conseguir visibilidad ante extraños es la siguiente: la solución se acopla entonces a la estructura interna de otros objetos.
    • Ello origina un alto acoplamiento, que hace el diseño menos robusto y más propenso a requerir un cambio si se alteran las relaciones estructurales indirectas.

Fuentes