Patrones básicos de Asignación de responsabilidades
Cuando construimos aplicaciones orientadas-objetos uno de los retos más importantes es decidir de quién es la responsabilidad de realizar alguna acción. Estas decisiones responden a las preguntas:
- “¿En cuál clase se debe definir tal o cuál método?” o
- “¿De quién es la responsabilidad de ocuparse de tal o cuál acción?”
En el siguiente diagrama de clases podemos preguntarnos:
- ¿Quién es el responsable de crear un nuevo estudiante?
- ¿Quién es el responsable de calcular cuáles son los créditos totales de un programa dado?
- ¿Quién es el responsable de cambiar la información sobre una universidad?
- ¿Quién es el responsable de informar cuántas mujeres hay inscritas en un curso?
Las responsabilidades son las obligaciones o contratos de una clase. Estas se pueden clasificar en dos grandes grupos: La responsabilidad de conocer una información y la responsabilidad de hacer alguna acción.
Conocer
- Conocer la información privada del objeto
- Conocer acerca de los objetos relacionados
- Conocer acerca de lo que se puede calcular o derivar
Responsabilidades de conocer:
¿Cuáles son los créditos totales de un programa dado?
¿Cuántas mujeres hay inscritas en un curso?
Hacer
- Realizar algo él mismo
- Iniciar acciones en otros objetos
- Controlar o coordinar actividades en otros objetos.
Responsabilidades de hacer:
Crear un nuevo estudiante.
Cambiar la información sobre una universidad
Para ayudar a resolver preguntas como las anteriores existen los patrones generales de software para asignación de responsabilidades, es el acrónimo de "GRASP (object-oriented design General Responsibility Assignment Software Patterns)". El primero en hablar de estos patrones de asignación de responsabilidades básicos fue Craig Larman quien ha escrito varios libros sobre el tema:
- 1997 - Applying UML and Patterns - ISBN 0-13-748880-7
- 2001 - Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and the Unified Process - ISBN 0-13-092569-1
- 2004 - Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development - ISBN 0-13-148906-2
Estos patrones básicos o principios básicos de asignación de responsabilidades son unas guías o buenas prácticas que nos ayudan a tomar algunas decisiones sobre en qué clase definir un método.
Lo que queremos es que, la decisión que tomemos nos permita construir un sistema más entendible y fácil de cambiar. Vamos a estudiar algunos de estos patrones:
- Bajo Acoplamiento
- Alta Cohesión
- Creador
- Experto
Acoplamiento
Acoplamiento es la medida de cuánto una clase esta conectada (tiene conocimiento) de otras clases.
Un alto acoplamiento en un sistema es problemático porque, debido a la cantidad de relaciones entre las clases, va a se más difícil:
- Entender el sistema
- Cambiar el sistema Cuando se necesite cambiar un sistema muy acoplado, por ejemplo cambiar una clase
El impacto del cambio va a ser más difícil de evaluar y de realizar debido a las múltiples relaciones que esa clase pueda tener con las demás. Potencialmente todas las demás se pueden ver afectadas por el cambio.
Patrón de Bajo Acoplamiento
: Este patrón nos dice que debemos tratar de mantener el nivel de acoplamiento bajo minimizando el conocimiento que unas clases deben tener de otras.
Quiere decir que cuando tomamos una decisión si esta decisión implica establecer una nueva relación entre las clases tenemos que evaluar si realmente eso es necesario porque al hacerlo vamos a aumentar el nivel de acoplamiento. No puede ser considerado aisladamente pero sí es una guía para tomar decisiones
Es un patrón evaluativo
:
un bajo acoplamiento permite que el diseño de clases sea más independiente.
Reduce el impacto de los cambios y aumenta la reutilización.
Cohesión
Vamos a explicar el concepto de Cohesión utilizando como ejemplo la navaja de la figura.
Esta navaja tiene muchas funciones (responsabilidades en nuestros términos). Esta sirve como tijeras, cortador, lupa, lima, sierra, abridor de botellas, destornillador, pinzas, etc.
En este caso decimos que esta navaja no es muy “cohesiva” ya que se ocupa de demasiadas funciones distintas en el mismo aparato. Esas funciones no están relacionadas entre sí. Fíjese que para cada una de ellas hay un elemento distinto que se ha agregado a la navaja. Si debo contestar qué hace la navaja? La respuesta no es simple, debo contestar utilizando muchos verbos: cortar, limar, descorchar, etc. Esto, en l caso de la navaa, quizas sea considerado muy útil, sin embargo, en el caso del software acarrea muchos problemas de entendimiento y por ende de mantenimiento.
Cohesión funcional dentro de una clase es una medida que indica cuán relacionadas están las responsabilidades de una clase entre sí.
Entre más relacionadas estén las responsabilidades de una clase más fácil será entender la clase y en general todo el sistema. Significa que cuando el sistema se deba cambiar, más fácil será encontrar dónde hacer el cambio.
Alta Cohesión
: Este patrón nos dice que debemos tratar de mantener el nivel de cohesión al interior de una clase lo más alto posible.Es un patrón evaluativo: entre más alta cohesión más fácil de entender, de cambiar, de reutilizar.
Volviendo al ejemplo de la navaja, la de esta figura es mucho más cohesiva porque tiene una sola función: “cortar”. No puede ser considerado aisladamente pero sí es una guía para tomar decisiones.
Patrón Experto
Cada objeto es responsable por mantener su propia información (principio de encapsulamiento):
- conoce y puede informar el valor de sus atributos
- puede modificar el valor de sus atributos
Uno espera que los atributos de una clase sean privados o protegidos, que nunca sean públicos y que para cada uno de ellos su información esté encapsulada detrás de los metodos getters/setters.
Si tiene relaciones de composición con otros objetos (sus partes), también será responsable de conocer la información de ellos, de crearlos (Creator pattern) y de delegarles las operaciones. Por ejemplo, dado el siguiente fragmento de diagrama de clases y las preguntas:
- De quién es la responsabilidad de saber cuántos estudiantes hay en total en una universidad?
- De quién es la responsabilidad de saber cuál es el promedio de edad de todos los estudiantes de una universidad?
La respuesta es la clase Universidad
porque ella, a través de la relación de composición hacia Estudiante
es la dueña de la información implicada en las preguntas. Entonces podemos agregar ala clase los métodos siguientes:
Note que con el patrón experto estamos construyendo clases cohesivas porque las responsabilidades que estamos definiendo hacen referencia a acciones que manipulan sus propias propiedades. Además, no estamos aumentando el acoplamiento entre clases porque no estamos definiendo relaciones nuevas entre las clases a las que les estamos definiendo las responsabilidades.
Patron Creador
El patrón creador es una especialización del patrón experto. Este patrón nos ayuda a guiar la decisión de quién debe crear un objeto de otra clase. La guía es la siguiente con prioridad en el orden que se presenta: Un objeto de la clase B tiene la responsabilidad de crear objetos de la clase A si:
La clase B tiene una relación de composición con la clase A | |
La clase B agrega objetos de la clase A | |
B usa (exhaustivamente) objetos A | |
B posee la información necesaria para inicializar A |
Con esa guía, lo que se busca es evitar crear nuevas dependencias entre las clases. Estamos indicando que ya hay asociaciones establecidas entre estas dos clases y que estamos buscando la responsabilidad de creación entre clases muy cercanas.