Discusiones sobre Patrones de Diseño

Anuncio
Ingeniería del Software II
Curso 2005/2006
Cuaderno de discusiones de Patrones de Diseño: Preguntas y
respuestas de la lista de discusión de la asignatura
Este cuaderno contiene las preguntas y respuestas de la lista de discusión
(http://servidor/mailman/listinfo/isw2-dist) de la asignatura con algunos comentarios de
los profesores.
Índice
Boletín 3.1: Introducción a los Patrones de Diseño.......................................................... 3
Boletín 3.2: Patrones de Asignación de responsabilidades (GRASP)............................ 12
Boletín 3.3.1: Façade y Template Method ..................................................................... 18
Boletín 3.3.2: Patrones Factory ...................................................................................... 26
Boletín 3.3.3: Strategy y Adapter ................................................................................... 29
Boletín 3.3.4: Decorator ................................................................................................. 32
Boletín 3.1: Introducción a los Patrones de Diseño
Cuestión 1: Enuncie las diferencias entre modelos de análisis y diseño
1) El modelo de análisis es un modelo conceptual cuya parte estática está definida por
diagramas de clases y cuya parte dinámica por diagramas de secuencia,..., mientras que
el diseño aunque también se representa mediante diagramas de clases estos están
orientados a la implementación.
2) En primer lugar los modelos de análisis tratan de definir cual es el problema a
solucionar, mientras que el objetivo de un modelo de diseño es indicar cómo se va a
solucionar este problema, es decir, construir una solución para el problema del análisis.
Ambos utilizan diagramas de clases, pero en los modelos de análisis las
responsabilidades de qué clase hace cada cosa para solucionar el problema no aparece.
3) Los modelos de análisis son modelos conceptuales que representan la situación del
mundo real que se quiere sistematizar: Modelo estático de clases (diagrama de clases),
modelo dinámico (casos de uso, diagramas de secuencia) y modelo funcional
(diagramas de actividad). Los de diseño son modelos para la implementación:
Principios GRASP, PPDD,...
Todos dais la definición de ambos modelos, pero no sus diferencias.
Los modelos de análisis muestran conceptos del mundo real, mientras que los de
implementación introducen conceptos artificiales que son necesarios por usar una
implementación orientada a objetos. Las implementaciones orientadas a objetos
permiten asignar responsabilidades (métodos) a conceptos que en el mundo real no
serían activos y por tanto, capaces de realizarlas. Esta es otra de las diferencias: en los
modelos de clases de análisis los objetos no tienen responsabilidades, mientras que en
diseño sí.
Además, dado que en la mayoría de los casos hay que añadir conceptos artificiales para
conseguir un buen diseño, los modelos de clases de análisis suelen tener menos clases
que los de diseño.
Cuestión 2: ¿Qué factores motivaron la aparición de los patrones de diseño?
1) Existen a la hora de diseñar la solución a un problema una serie de dificultades que
reaparecen de una manera recurrente y que eran tradicionalmente solucionados
individualmente por cada diseñador.
Esta manera de actuar hacía que el conocimiento no fuera compartido de una manera
clara y exitosa, obligando a cada nuevo diseñador a reinventar la rueda tratando de
buscar solución a problemas ya superados anteriormente por otros.
Para paliar esta situación surgen los patrones de diseño, una forma efectiva de
comunicar recetas exitosas probadas suficientemente como válidas para resolver estas
dificultades.
Correcto
2) La necesidad de que los diseños fuesen mas reutilizables, fáciles de modificar,
comprender y usar, mas robustos y mas eficientes.
Esa necesidad existía y existe, pero no es la principal motivación.
3) Además de los mencionados anteriormente por los compañeros, otro factor fue la
necesidad de transmitir conocimiento debido a que en el diseño la experiencia es muy
importante y se observo que se utilizaban “recetas” para los problemas habituales para
no estar reinventando la rueda continuamente. Por lo que surgieron como una forma de
poder transmitir dichas recetas.
Correcto
Cuestión 3: ¿Cómo define un patrón de diseño un problema? ¿Y la solución?
1) En los patrones de diseño el problema aparece definido en el campo "intención"
(aparece una breve reseña sobre qué resuelve) y en "motivación"
(En donde aparece un ejemplo concreto en el que la aplicación del patrón de diseño
resuelve el problema planteado).
La solución aparece como un diagrama de objetos (en el apartado "estructura") que
resuelven el problema que se quiere tratar de una manera general, permitiendo
generalizarlo a las condiciones del problema actual (recogidas en el análisis).
Aunque los patrones de diseño deben ser casi independientes de la implementación se
dan pistas y ayudas sobre cómo implementar la solución aportada.
2) En la plantilla de descripción de la GOF los problemas vienen definidos
principalmente por los puntos:
2. Intención: frase corta que responde a qué hace y qué resuelve 4. Motivación: un
escenario que ilustra como el PD resuelve un problema 5. Aplicabilidad: otras
situaciones en las que resulta aplicable el PD concreto Y la solución a su vez se
encuentra definida por los puntos:
6. Estructura: diagramas de clases
7. Participantes: responsabilidad de cada clase participante 8. Colaboraciones: diagrama
de colaboración y/o de secuencias 9. Consecuencias: ventajas e inconvenientes
10. Implementación: dificultades, técnicas y trucos a tener en cuenta al aplicar el PD
3) Problema es como "algo" que se repite continuamente y en diferentes contextos
Creo que preguntan esta definición porque los "problemas" definidos en los patrones no
son siempre problemas. Es decir, creo que los patrones no resuelven problemas como
tales, simplemente hacen que no aparezcan problemas debidos a un mal diseño,
aplicando para ello la experiencia de muchos diseñadores.
Tienes razón en parte. Es cierto que la idea es intentar evitar problemas, pero realmente
si identifican un problema. Por ejemplo, el problema de tener un código repetido en
varios sitios pero presentando pequeñas diferencias (para el caso del template method).
Lo importante aquí es que la definición dada es general (con un nivel de abstracción
alto). Esto facilita su reutilización, es decir aumenta la probabilidad de poder aplicarlos.
Además, son más fáciles de entender por no proporcionar detalles de soluciones
concretas que solo desviarían la atención hacia detalles poco reutilizables.
Con respecto a la solución, entre otras cosas se propone un diseño genérico (diagrama
de clases), que puede ser adaptado a cada caso (esto lo ejemplificamos en clase con los
patrones de costura y los ajustes que se le hacían).
Solución son los pasos a seguir, como una especie de receta para resolver un problema.
Más que pasos a seguir, yo lo veo como una serie de ideas que debes tener claras para
aplicarlas en caso de ser necesarios.
De acuerdo en esto (hay que conocer las ideas para poder aplicarlas). Pero debes ser
capaz de llevar estas ideas a un diseño (diagrama de clases). Lo de las ideas estaría más
en concordancia con los GRASP, no tanto con los patrones. Aunque repito, en los dos
casos esas ideas o principios hay que manejarlos.
Cuestión 4: ¿Qué característica(s) de los patrones de diseño facilitan su reutilización?
1) Pues que suelen ofrecer soluciones a problemas recurrentes (suelen aparecer mucho)
y estos son solucionados de una forma abstracta, por lo que "puede utilizarse un millón
de veces sin hacer dos veces lo mismo"
Correcto, pero ¿cuál es la característica?
2) Para empezar la solución descrita en los patrones de diseño es una solución general
que ha de ser especificada para poder ser aplicada, con lo que se puede adaptar a
muchas situaciones concretas favoreciendo así la reutilización.
En segundo lugar es digno de resaltar que se presenta una solución que es (o debe serlo)
independiente de la implementación (se trata de reutilizar conocimiento para resolver un
problema, no software).
El hecho de que aparezcan reseñadas las consecuencias del uso del patrón (ventajas e
inconvenientes) y la aplicabilidad (cuándo se puede usar), hace que sea posible mejorar
el mantenimiento y facilita saber en qué situaciones el patrón ha demostrado ser útil
para resolver un determinado problema.
Perfecto. El punto clave es que sea una definición general (abstracta). Eso hace que
aumente las posibilidades de poder aplicarse.
3) Los patrones de diseño son un par problema/solución, por tanto la descripción del
problema nos ayudara a saber cuando podemos utilizar un patrón de diseño. Un ejemplo
concreto seria el patrón de diseño singleton, según la plantilla de descripción de GOF, la
aplicabilidad nos dice cuando lo podemos usar.
Cuestión 5: ¿A que documentos o modelos se le aplican los patrones de diseño?
1) Se aplican en el diseño a los diagramas de clases.
2) En los patrones de diseño la solución aparece como una estructura de clases con
asignaciones de responsabilidad, por ello se aplica en los diagramas de clases en la
etapa de diseño (la asignación de responsabilidades es una de las tareas más importantes
del diseño).
Se aplica tanto a los diagramas de clase de análisis (justo al comenzar la fase de diseño),
como a los diagramas de clases de diseño para mejorarlos/aumentarlos, y a al código de
aplicaciones existentes a la hora de refactorizarlo para mejorar su diseño.
Cuestión 6: ¿Es posible aplicar un patrón de manera aislada, es decir, sin tener en
cuenta ningún otro? ¿Es habitual hacerlo?
1) Sí es posible aplicar un patrón de forma aislada (pero siempre tenemos que tener en
cuenta los principios evaluativos), como ejemplo podemos encontrar el ejemplo de los
montaditos del patrón template method descrito en clases de teoría que no necesitaba de
otro patrón. Sin embargo, no es habitual que los patrones de diseño sean aplicados de
forma aislada, es por ello que existen relaciones entre estos las cuales son descritas en
sus plantillas de descripción.
2) Bueno, como posible es posible, ¿por qué no íbamos a poder aplicar un patrón
singleton únicamente? ¿O un patrón façade? Sin embargo esto no es lo habitual.
Dependerá del problema a tratar y la complejidad de éste. Sin embargo hay que reseñar
que existen relaciones entre los distintos patrones e incluso en la plantilla de la Gang of
Four aparece un apartado para "patrones relacionados".
Perfecto
Cuestión 7: ¿Cómo debemos estudiar para ser un buen diseñador?
1) La calidad como diseñador es adquirida con la experiencia, por lo que no es posible
estudiar para ser un buen diseñador aunque si podemos adquirir parte de la experiencia
de otros diseñadores mediante los patrones, por lo que deberíamos estudiar patrones de
diseño para intentar ser un buen diseñador.
2) A día de hoy el buen diseñador es un diseñador con experiencia, un experto. La única
manera de adquirir experiencia consiste en hacer nosotros mismos los diseños
necesarios para conseguirla y sobre todo estudiar los diseños exitosos (y también sus
fracasos) de diseñadores ya expertos. Puesto que el diseño aún está en una etapa más
cercana al arte que a unas reglas "fijas" es importante observar el trabajo de los
"maestros" antes de poder dedicarnos a hacer buenos diseños por nuestra cuenta. Por
supuesto esto pasa por estudiar patrones de diseño y antipatrones.
Bien las dos respuestas. Yo añadiría que es importante manejar todos los patrones sin
tener que consultarlos y conocer bien las diferencias y similitudes entre unos y otros
para poder decidir antes de aplicar cual es la mejor opción.
Cuestión 8: Indique las razones por las que el diseño es una actividad difícil.
1) Para empezar en la etapa de diseño aparecen grandes rupturas entre el mundo real y
la analogía que representamos en nuestro diagrama de clases, asignando tareas y
responsabilidades a objetos inanimados.
Además pueden existir discrepancias entre el documento de análisis y lo que realmente
se quiere resolver, o puede que los propios requisitos varíen a lo largo del proyecto,
obligando a modificar el diseño.
Por otro lado existe una necesidad de obtener un equilibrio entre los distintos requisitos
no funcionales que aparecen en el documento de análisis.
Todo esto, unido a la situación planteada en la repuesta a la pregunta anterior en la que
se trataba la importancia de la experiencia y el estado cercano al arte del diseño, hace
que la experiencia sea un valor realmente decisivo a la hora de conseguir un buen
diseño.
Perfecto
Cuestión 9: ¿Cuándo se debería empezar a tener en cuenta los requisitos no
funcionales?
Cuanto antes. Los requisitos no funcionales son complicados de manejar y encajar en el
diseño (número de accesos concurrentes a una base de datos, tiempo medio de
acceso,...) por lo que se deben intentar resolver cuanto antes. Si bien esto es lo ideal, no
es lo habitual.
Deberíamos añadir que esto es así debido a que intentar cumplirlos cuando el diseño
esta avanzado es muy complicado o imposible.
Cuestión 10: Discuta sobre la madurez de la Ingeniería del Software respecto de las
ingenierías clásicas y otras profesiones.
1) Para empezar viendo las respuestas a las preguntas 7 y 8 se pone de manifiesto la
etapa de inmadurez en la que está en estos momentos la ingeniería del software en
cuanto a la etapa del diseño se refiere.
Aunque los patrones de diseño surgen precisamente para dotar de mayor madurez a la
ISW aún no se ha conseguido eliminar completamente la situación actual en cuando al
diseño se refiere, casi más cercana al arte que a otras ingenierías.
A pesar de todo poco a poco se dan los pasos necesarios para mejorar la situación.
Sin embargo en otros aspectos que caen también dentro del ámbito de la ISW los pasos
conseguidos hacia una etapa de madurez plena son más espectaculares
(Véase planificación, costes y otros aspectos estudiados en ISW3).
OK. Animo a que el resto de alumnos hicierais el esfuerzo de pensar sobre esto.
Cuestión 11: ¿Por qué se le da tanta importancia al nombre en los patrones de diseño?
¿Qué relación tiene esto con la actividad realizada en esta fase?
1) El nombre del patrón debe dar una idea primera de qué hace, qué se consigue al
aplicar el patrón.
Además, tal y como se puso de manifiesto en la primera parte de la asignatura, la
creación de un vocabulario propio y ajustado a los conceptos es vital para saber
exactamente a que nos referimos. Por ello es necesario que el nombre identifique al
patrón sin posibilidad de equivocaciones (q no haya dos patrones con el mismo nombre
que hagan cosas distintas).
2) El nombre de los patrones de diseño tiene como fin la identificación univoca y
general del mismo, con el fin de crear un vocabulario común evitando tener que
describir continuamente la idea de dicho patrón (es decir, por ejemplo la palabra
Singlenton para los diseñadores es equivalente a todos los puntos de la plantilla GOF de
este patrón (diagramas de clase, inconvenientes, patrones asociados, etc.) así al solo
decir el nombre ya nos estamos refiriendo a todo lo anterior)
Perfecto... Es decir, facilita la comunicación entre los diseñadores.
Cuestión 12: ¿Qué ventajas puede tener el Singleton cuando hay muchos
desarrolladores?
Evita que alguno de los diseñadores que no conozca bien esa parte del diseño cree
varias instancias de una clase.
Cuestión 17: Enuncie el principio de Hollywood y explique cómo se aplica esta
metáfora a los frameworks y bibliotecas
1) En una biblioteca, la forma de comunicarse con la aplicación que la utiliza consiste
en esperar a que algún método de alguna aplicación haga uso de alguno de los métodos
u objetos que ésta proporciona en alguno de sus algoritmos.
Un framework sigue el llamado principio de hollywood "nosotros te llamaremos" lo que
viene a significar que para comunicarse con la aplicación que lo usa proporciona una
interfaz con una serie de prototipos que el usuario debe implementar porque serán
invocados por el framework en alguno de sus algoritmos. Es decir, son las clases del
framework las que usaran las de la aplicación en lugar de ser al revés como en las
bibliotecas.
Perfecto
2) Bien, tengo clara lo que es la idea de biblioteca, que es un conjunto de clases para ser
reutilizados, que usamos en nuestra aplicación. Es decir, nuestra aplicación llama a los
métodos de la biblioteca. Sin embargo, el concepto de framework no lo tengo claro del
todo. Cuando lo veo en las prácticas lo entiendo, en el caso de Login. Pero en la teoría
dice que es un "Conjunto de clases parcialmente funcional (no es una aplicación) para
un dominio de aplicación" ¿Que es un dominio de aplicación? ¿Y que es lo que le falta
al framework para ser aplicación?
Tampoco tengo claro lo del principio de Hollywood en relación al framework cuando
decimos que "el framework llama a mi código".
Un framework propone un diseño para una aplicación completa (muchas clases) en la
que se dejan "huecos" para que el usuario pueda incluir sus propias clases y adaptar el
resultado a sus requerimientos. Es cierto que el framework además de un diseño
proporciona una implementación.
Lo importante de un framework es que no tenemos que cambiar ni una sola línea de
código para incluir las clases que necesitamos para nuestra aplicación gracias a que
siguen el principio de hollywood:"no me llames, yo te llamo". Esta es la razón por la
que los patrones template method y factory method son tan adecuados para los
frameworks, pues en los dos se proporciona el código donde se llama a los métodos (en
el método plantilla se llama la los métodos hook o en el método que llama al create) de
las clases que se añaden al framework.
Cuestión 18: Indique la diferencia entre idiom y patrón de diseño; discuta sobre las
situaciones en las que ambos pueden confundirse.
1) Un idiom es un patrón a bajo nivel sujeto a un lenguaje de programación concreto
mientras que los PPDD no están sujetos a ningún lenguaje de programación, estos
pueden llegar a confundirse cuando la solución de un determinado patrón esta muy
sujeta o vinculada a un lenguaje de programación.
Un idiom no tiene por que ser de bajo nivel. Iterator no lo es. Lo que realmente los
distingue es que el idiom supone “una forma especial de escribir el código”. Aun así, en
muchas ocasiones no existe una frontera clara y es cuestión de opiniones el caracterizar
algo como patrón o idiom.
2) La diferencia radica en que un idiom resuelve un determinado problema en un
lenguaje de programación concreto (copiar cadenas en c, por ejemplo), mientras que la
solución proporcionada por el patrón de diseño está alejada de la implementación en un
lenguaje concreto.
A veces puede confundirse porque los patrones de diseño a veces aparecen muy ligados
a la implementación y se incorporan como características de los lenguajes de
programación.
Bien lo que dices.
Un ejemplo de esta situación es el patrón/idiom iterator: propone un diseño
determinado, pero además supone una forma de escribir el código necesario para
recorrer una colección.
Cuestión 19: Enuncie los antipatrones que conozca junto con una breve descripción de
los mismos.
De cara al examen solo tenéis que conocer los vistos en clase. Aunque no está mal que
hagáis un poco de investigación…
*The blob: Una clase se convierte en una masa informe debido a tener un desorbitado
tamaño convirtiéndose en un problema para el mantenimiento y la compresión.
- BLob (también conocido como God Object): Una clase gigantesca que hace de todo
(una amalgama de métodos) mientras las demás apenas contienen datos, las
responsabilidades no están distribuidas uniformemente.
Son clases que intentan hacerlo todo sin ayuda de otras clases (sin acoplarse con otras
clases). Como resultado requieren gran cantidad de métodos y almacenar mucha
información.
* Poltergeists: Los objetos de una clase tiene un tiempo de vida muy corto.
- Poltergeists: Los objetos de una clase tienen una corta vida (aparecen y desaparecen
como un poltergeist) usadas usualmente para pasarle información a objetos de otra clase
(típicos nombres de estas clases son manager_xxx o controlador_xxx).
Bien esta última definición.
- Copy & Paste: típico de cuando estás aprendiendo algo nuevo y en lugar de intentar
hacerlo tú mismo te dedicas a buscar código por Internet, foros, libros o apuntes que
copias y utilizas sin llegar a entender realmente para, posteriormente, "adaptarlo" al
problema que tienes entre manos. Es normal que se produzca un palimpsesto de
distintos estilos, con código superfluo, difícil de mantener, poco eficiente...
Aunque lo usen también programadores expertos que entiendan el código a la
perfección (aun siendo suyo), es una mala técnica. El algoritmo debería ser lo
suficientemente genérico como para poder ser utilizado sin ser modificado
directamente.
Bien
- Spaghetti code: Piensa en un plato de espaguetis antes de echarle el tomate. ¿Serías
capaz de decir dónde termina un espagueti y empieza otro? Casi imposible. El
antipatrón Spaghetti code hace referencia a algoritmos cuya estructura de control es tan
complicada de seguir como la del plato. Típico de usar gotos y demás. En programación
estructurada es más complicado (pero recuerdo que con breaks, case, continues,
variables estáticas y el propio goto en c es fácil hacer algo así).
Bien
Boletín 3.2: Patrones de Asignación de responsabilidades
(GRASP)
Cuestión 1: ¿Conocidos los GRASP, qué diferencias observa entre análisis y diseño?
1) El objetivo en el análisis consiste en definir de una manera conveniente el problema
que se desea resolver. En el diseño se trata de modelar una solución asignando
responsabilidades a las clases.
Deberíamos añadir: Teniendo en cuenta además detalles de implementación y los
posibles cambios (variación/evolución) que requiera el sistema, es decir, aplicando
variaciones protegidas.
2) Pues que en el análisis la preocupación era atender a los requisitos mientras que en el
diseño se deben tener en cuenta principios como los GRASP
Demasiado incompleto.
Cuestión 2: ¿Por qué los objetos asumen responsabilidades que no existen en el mundo
real? ¿Qué problema causa esto?
1) Porque los sistemas informáticos tienen que realizar funciones que no existen en el
mundo real como la creación de un objeto, el acceso a una base de datos, etc.
Cierto, pero incompleto.
2) En el diseño ciertos objetos inanimados se ven obligados a adquirir responsabilidades
ajenas a su condición en el mundo real por la necesidad de creación de nuevos objetos
agregados o controlar ciertos valores o la ejecución de determinadas tareas que en el
mundo real haría una persona o máquina.
Estas tareas deben ser asignadas de forma que no se vean afectadas ni la eficiencia, ni el
mantenimiento, ni la reutilización y además lleve a un diseño comprensible, lo que
obliga a asignar ciertas tareas a objetos inanimados.
El mayor problema que esto supone es que la relación entre el mundo real y la
representación creada en el documento de análisis y diseño se separan.
Correcto.
Cuestión 3: ¿Por qué Larman llama patrones a los GRASP? ¿Qué nombre sería más
adecuado?
1) Larman llama patrones a los GRASP porque la palabra patrón era una buzz-word,
algo llamativo y de moda. Pues en vez de patrones hubiera sido más lógico usar el
nombre de principios.
Correcto.
2) Creo que los llama patrones siguiendo el concepto de patrón, ya que los GRASP se
aplican a un problema concurrente y aportan una especie de solución, aunque no es una
solución exactamente, sino mas bien un "consejo" que te permite obtener un buen
diseño
El nombre mas apropiado seria "principios", ya que como dijimos antes, los GRASPs
no permiten obtener una solución tal cual, sino un diseño bueno indicando una serie de
pautas para conseguirlo.
Los problemas tratados por los principios son demasiado generales para considerarlos
patrones desde el punto de vista GOF. Ver la respuesta 1.
3) Los llama Patrones porque están expresados o descritos como tales (par problema
solución y demás puntos de la plantilla), pero hubiera sido mas correcto llamarlos
principios pues en ellos se basan e intentan darle solución los demás patrones.
No son patrones, puesto que no proporcionan un esquema de solución basado en una
estructura de clases determinada. Ver respuestas anteriores.
Cuestión 4: ¿Qué ventajas tiene enunciar los GRASP si ya eran conocidos?
1) Formalizar su existencia y unificar conceptos evitando así que fuesen transmitidos de
forma independiente.
2) Primero de todo darlo a conocer "de verdad", es decir, describirlos de una manera
más rigurosa. Hay que recordar que el diseño aún se encuentra en una fase cercan al arte
por lo que a pesar de ser principios muy conocidos y aplicados, toda disciplina debe
contar con unos rigurosamente descritos y formalizados (que todo el mundo sepa de
qué se habla) para poder apoyarse en ellos. En el momento que Larman los introdujo es
cierto que eran conocidos, pero conocidos, por así decirlo, casi por ciencia infusa, de
una manera inconsciente y natural.
Las dos respuestas son correctas pero incompletas. Tendríamos que añadir:
Que también se describen para que no sean reinventados/asimilados/redescubiertos una
y otra vez. De esta forma se conocen como un todo y nadie tiene duda de que es un
principio y que no lo es. También se evita la definición del mismo principio de varias
formas distintas como ocurría por ejemplo con variaciones protegidas que era definido
de varias formas: principio abierto/cerrado, principio de sustitución de liskov, principio
de encapsulación, no hables con extraños,...
Cuestión 5: ¿Qué es un principio evaluativo? ¿Cuáles son y cómo se relacionan?
1) Un principio evaluativo es aquel que el diseñador debe aplicar cada vez que introduce
una modificación en el diseño.
Hemos visto alta cohesión y bajo acoplamiento. La relación que tienen ambos proviene
de ser principios contrapuestos. Es normal que una clase que presenta un alto
acoplamiento presente también una baja cohesión y viceversa.
Con respecto a la relación: Es correcto pero es importante tener claro que esto no es
siempre así. Es decir, una clase con alto acoplamiento puede tener muy mala
cohesión. Lo que ocurre es que por regla general (insisto en que no siempre) cuando
intentamos bajar el acoplamiento se produce un empeoramiento de la cohesión si sólo
aplicamos estos dos principios. Dado que si al intentar bajar el acoplamiento de dos
clases añadimos una tercera usando una indirección y cuidamos la cohesión, esta no
tiene que verse comprometida. Un ejemplo de esto sería la aplicación de un Simple
Factory para reducir el acoplamiento entre dos clases. De ahí que se tengan que aplicar
siempre al hacer un cambio en el diseño.
2) Son principios que son tenidos en cuenta a la hora de evaluar una decisión de diseño.
Los principios evaluativos son bajo acoplamiento y alta cohesión. Son principios
opuestos por lo que se debe intentar encontrar un equilibrio entre ambos.
Cierto, pero incompleto. Ver respuesta anterior.
Cuestión 6: ¿Es posible aplicar un GRASP de manera aislada, es decir, sin tener en
cuenta ningún otro? ¿Es habitual hacerlo?
1) Yo creo que no, ya que siempre que apliquemos un GRASP estamos tomando una
decisión de diseño por lo que debemos tener en cuenta los principios evaluativos, y al
aplicar alguno de los principios evaluativos tenemos que tener en cuenta el otro ya que
como hemos dicho anteriormente están directamente relacionados (son opuestos)
Correcto. Por ejemplo, al intentar reducir el acoplamiento sabemos que esto nos puede
empeorar la cohesión, por lo que tendremos que aplicar indirección (para mejorar el
acoplamiento) y/o fabricación pura (para mejorar la cohesión) para que el acoplamiento
y la cohesión permanezca a un buen nivel.
2) Pues yo diría que no, al ser principios de diseño deben ser tenidos todos en cuenta, no
tiene mucho sentido tener en cuenta unos principios y otros no si se desea obtener un
buen diseño, claro.
No es falso, pero es obvio. Ver comentario anterior.
3) Sí, siempre que sea un GRASP que no tenga relaciones o dependencias con otros.
¿Cuáles son estos?
No, ya que hay que tener en cuenta varios GRASPs para obtener un buen diseño.
Además, existen GRASPs que, al aplicarlos, afectan a otro GRASP, como por ejemplo,
Bajo Acoplamiento y Alta Cohesión pues al quitar responsabilidades a una clase y
delegarlas a otra, aumenta el acoplamiento. O viceversa, al eliminar clases para reducir
el acoplamiento, las responsabilidades de dichas clases van a otra de las clases con las
que estaba relacionada.
Correcto, pero siempre que no uses indirecciones/fabricaciones puras como hemos visto
antes
Cuestión 7: ¿Cuál es la tarea primordial que controlan los GRASP? ¿Por qué es tan
importante esta tarea? ¿Por qué no la hemos realizado en análisis?
1) La tarea primordial es la asignación de responsabilidades. No es posible definir estas
durante la fase de diseño puesto que durante ésta tan sólo se busca definir el problema a
resolver.
La tarea primordial es asignar responsabilidades, o lo que es lo mismo, añadir/asignar
métodos a las clases.
Con respecto al resto de preguntas: Supongo que cuando dices diseño quieres decir
análisis. Concretando un poco lo que comentas, en el mundo del análisis se hace un
modelo de conceptos (modelo conceptual) en el que existen conceptos inanimados
(facturas, productos,...) que no pueden asumir responsabilidades. Al pasar a diseño
orientado a objetos esta tarea es primordial para acercar el modelo del mundo real al de
la implementación. En análisis no se puede hacer puesto que se usan conceptos y no
clases de diseño y debido a que los conceptos inanimados no pueden asumir
responsabilidades.
2) Describen los principios fundamentales del DOO y la asignación de
responsabilidades, problemas propios de la fase de diseño.
Incompleto y casi incorrecto. Ver respuesta anterior.
Cuestión 8: ¿Cuáles son los principios más importantes a tener en cuenta?
1) Bajo acoplamiento y alta cohesión.
Variaciones protegidas también es de suma importancia, pues es el que nos guía en
decidir cuando el acoplamiento es desfavorable aun siendo no demasiado alto.
Cuestión 9: ¿Qué problemas producen los cambios en el diseño y cómo se solucionan
según los GRASP?
1) Los cambios en el diseño de un elemento suelen afectar a otros elementos por ello
GRASP propone variaciones protegidas.
Cierto, pero muy escueto.
2) Los cambios en el diseño afectan a numerosos objetos pudiendo causar inestabilidad
en el sistema si no se tiene en cuenta el principio de variaciones protegidas, que consiste
en identificar con antelación los puntos en los que el diseño podría variar (evolucionar)
y actuar de modo que sea posible protegerse de estos.
¿Qué significa protegerse? La idea es aislar esos puntos de forma que cuando se
produzca el cambio afecte lo menos posible al resto de clases del sistema.
Cuestión 10: Enuncie los problemas a los que nos lleva la aplicación desmedida de
cada GRASP (algunos de ellos son anti-patrones) y razone la respuesta. Por ejemplo:
Aplicar de manera desmedida el principio alta cohesión nos lleva al anti-patrón. . .
1)
- Aplicar de manera desmedida el principio experto en información nos lleva a tener
diseños que aumenten el acoplamiento y la duplicación de código (pensad en que cada
clase se tiene que guardarse a sí misma en una BD).
Correcto. También puede disminuir la cohesión.
- Aplicar de manera desmedida el principio alta cohesión nos lleva al anti-patrón clasesalgoritmos, lo que conlleva un aumento del acoplamiento (si mi clase hace algo
excesivamente específico necesitará otras para llevar a cabo una tarea más general).
También nos puede llevar al antipatrón poltergeist donde los objetos aparecen y
desaparecen de manera incesante.
- Aplicar de manera desmedida el principio bajo acoplamiento nos lleva al anti-patrón
Blob y además conlleva una disminución de la cohesión (la manera de bajar el
acoplamiento es que se necesiten menos clases para hacer una tarea, con lo que la
funcionalidad de esas clases será traspasada).
Correcto.
- Aplicar de manera desmedida variaciones protegidas puede llegar a hacer que el coste
de protección ante esas variaciones sea superior al de modificar un diseño.
Correcto. Esto se ilustra con la máxima: "elige tus batallas"
- Aplicar de manera desmedida el principio de indirección puede hacer que tengamos
problemas de ejecución en nuestro sistema
Más que de ejecución deberíamos decir de eficiencia. Además dificulta el entendimiento
y nos acerca al antipatrón poltergeist.
Cuestión 12: ¿Cómo se mide el acoplamiento? Ponga un ejemplo.
Acoplamiento es una medida de la fuerza con que un elemento está conectado a, tiene
conocimiento de confía en otros elementos. Usualmente se dice que una clase es muy
acoplada si tiene muchas relaciones.
Ejemplo: sea una clase A con métodos m1() y m2(), una clase B con métodos n1() y
n2(), una clase C con un método p() y una clase D. cualquier cambios en los métodos de
B o C, afectaría a la implementación de los métodos de A, por tanto, la clase A está muy
acoplada, asimismo sería muy difícil de reutilizar.
Añadir que el acoplamiento puede aparecer de muchas formas: parámetros en métodos
de una clase que son objetos de otra, atributos de una clase que son referencias a objetos
de otra, devolver objetos de otra clase en un método y crear variables locales en los
métodos de una clase de objetos que son de otra clase.
Lo importante es ver que el acoplamiento se mide entre dos clases y que éste será
desfavorable cuando exista un punto de variación o cuando el acoplamiento de una clase
con el resto sea muy fuerte: mucha utilización de objetos de otra clase y/o acoplamiento
con varias clases al mismo tiempo.
Cuestión 13: ¿Cómo se mide la cohesión? Ponga un ejemplo.
Cohesión es una medida de la fuerza con la que se relacionan y el grado de focalización
de las responsabilidades de un elemento. Un elemento con baja cohesión tiene muchas
responsabilidades.
Y estas responsabilidades además están orientadas a áreas funcionales distintas. Es
decir, muchos métodos y que además estos realizan tareas muy distintas.
Sea una clase C con métodos m1(), m2(), ..., mk(), y algunos de ellos tienen una
funcionalidad de acceder por ejemplo, a una BD, entonces se podría delegar la
responsabilidad de acceso a la BD a otra clase denominada AccesoBD.
Esto no es un ejemplo de alta cohesión o baja, es una forma de solucionar. ¿Alguien nos
manda un ejemplo de las dos situaciones que no sea el de clase?
Cuestión 16: Enuncie y razone las ventajas del principio "Controlador".
- Aumenta las posibilidades de reutilización. Al delegar las responsabilidades de
controlador a otra clase, si cambia p.e. la librería de la interfaz gráfica, no hay que
modificar el código de la clase cliente, sólo el del controlador.
- Razonamiento sobre el estado de los casos de uso. Al estar el código del controlador
separado de la aplicación, se manejan las operaciones de sistema en la lógica de la
aplicación y no en la interfaz de usuario (arquitectura de 3 capas). Esto permite un
seguimiento de los pasos en el caso de uso para verificar si es válido o no.
Faltan cosas que están detalladas en los apuntes. ¿Alguien nos las manda y nos las
explica?
Boletín 3.3.1: Façade y Template Method
Cuestiones generales
Cuestión 1: ¿Cuál es el principal objetivo del patrón Façade?
1) Crear una interfaz unificada para un conjunto de interfaces que ofrece un
determinado subsistema, haciéndolo mas fácil de usar.
2) Abstraer la funcionalidad de un sistema complejo de usar para simplificar el uso de
éste a las clases clientes que deban usarlo, actuando a modo de interfaz entre el sistema
y los clientes, pero sin hacer inaccesibles las clases del sistema.
Las palabras clave son: Simplificar pero para uno de los usos habituales del subsistema
(no para cualquier caso)
Cuestión 2: ¿Cuál es el principal objetivo del patrón Template Method?
1) Abstraer un algoritmo definiendo su esqueleto, de modo que la parte fija de éstos
aparezcan implementadas en una clase padre y las partes variables aparezcan
implementadas en las clases hijas que lo concretarán adaptándolo para la solución de un
problema concreto.
Bien.
2) Presentar una serie de plantillas de algoritmos, dichas plantillas constan de una parte
fija y una parte que deben implementar cada una de las clases cliente que quieran
utilizar las plantillas. De esta forma logramos reutilizar código y favorecemos el
mantenimiento y entendimiento de los distintos algoritmos involucrados.
No son varias plantillas, sino solo una.
Cuestión 3: ¿Qué ventajas ofrece el patrón Façade?
1) Abstrae a la clase cliente de la complejidad del subsistema que se desea utilizar,
además elimina el acoplamiento de la clase cliente con el subsistema puesto que ahora
el acoplamiento se dirige con la clase Fachada (in dirección). Por último favorece la
división en capas y no impide que las clases clientes puedan hacer un uso directo del
subsistema.
2)
- Simplifica el uso de un sistema complejo, abstrayendo la funcionalidad de éste.
- favorece la definición de distintas capas para usar el sistema.
- desacopla las clases cliente de las clases del sistema (indirección mediante la clase
fachada),
Así mejora la portabilidad y añade protección de las clases clientes ante cambios en la
implementación del sistema tras la fachada.
Correcto los dos, pero hay que tener en cuenta que al no impedir el uso directo del
subsistema, el desacoplamiento no es total y los cambios en el subsistema sí pueden
afectar.
Cuestión 4: ¿Qué ventajas ofrece el patrón Template Method?
1) Reutilización de código, no es necesario volver a implementar aquellos métodos que
son exactamente iguales en varias clases, además aquellos que varían, las partes fijas
tampoco es necesario volver a implementarlas solo aquellas partes que son distintas,
esto a su vez hace que sea mas fácil su mantenimiento, depuración y entendimiento. Por
ultimo es muy útil en la creación de bibliotecas y frameworks.
2)
- el comportamiento común de varias clases se implementa una única vez
- mejora la mantenibilidad
- es útil para la creación de bibliotecas y frameworks
Correcto los dos.
Cuestión 5: ¿Qué GRASP(s) se aplican en el patrón Façade?
1) Indirección y controlador, este ultimo ya que los controladores suelen actuar como
puntos de entradas (fachadas) de la capa lógica. Por su puesto estaría también
relacionado con los principios alta cohesión y bajo acoplamiento.
Una puntualización: La cohesión de las fachadas suele ser baja.
2)
- Indirección (introducimos la clase fachada para bajar el acoplamiento)
- Controlador (separa la lógica del sistema de la interfaz que proporciona la fachada,
que además suele ser común a todos los clientes usando el patrón Singleton)
Correcto.
Cuestión 6: ¿Con qué principio(s) está relacionado el patrón Template Method?
1) esta relacionado con el principio de hollywood, es decir "no nos llames, nosotros te
llamamos", este es el mismo principio que se aplica en los frameworks ya que al igual
que en aquellos, se dejan por definir algunos métodos (métodos hook), de manera que
después es el cliente el que debe definirlos en su aplicación concreta.
2)
- Estrategia (aunque cambia todo el algoritmo en lugar de una parte que se concreta)
- Fabricación pura (la clase fachada no representa ninguna clase del dominio del
problema, es fabricación de la mente y está creada específicamente para un fin
concreto).
Estrategia no es un principio y la fabricación pura tiene como objetivo mejorar la
cohesión, por lo que no serían ninguno de estos.
Lo correcto es variaciones protegidas y dentro de este, el principio de hollywood
¿Qué relación tiene este principio con los frameworks?
La relación proviene por la forma de llamar a los métodos hook. Puesto que el
algoritmo aparece creado en la clase padre, es ésta la que se encarga de llamar a los
métodos de las clases hijas que añaden la funcionalidad necesaria para que el algoritmo
pueda ejecutarse (según el principio de Hollywood)
3) -->> No sé si se refiere a principios de los GRASP, pero yo creo que se refiere al
Principio de Hollywood. Está relacionado con dicho principio ya que la clase padre
contiene los métodos gancho, los cuales son definidos en las clases hijas. Y es la clase
padre la que llama a dichos métodos cuando los necesita, lo q lleva al principio de
hollywood.
Correcto, es el principio de Hollywood, pues es el método plantilla el que llama a los
métodos incluidos en las clases hijas. De esta forma, la clase padre estaría dentro del
framework y las clases hijas fuera.
Cuestión 7: ¿Con qué principio(s) está relacionado el patrón Façade?
1) además de los enunciados anteriormente, estaría relacionado con la ley/principio de
Demeter, que dice "no hables con extraños", puesto que las clases cliente que hicieran
uso de la fachada usarían solo sus métodos, nunca nos encontraríamos con
encadenamientos de la forma: obj.getAtr1().getAtr2().metod().
Este principio pertenece a variaciones protegidas.
2) Además de los indicados en la respuesta 5 (indirección y controlador), yo añadiría
que también está relacionado con el patrón Bajo acoplamiento (entre las clases cliente y
el sistema) y con Variaciones protegidas (la clase cliente se protege ante variaciones del
sistema abstraído por la fachada si los clientes usan la fachada)
Correcto, pero teniendo en cuenta que la fachada no evita el uso directo del subsistema.
Por lo que el desacoplamiento no es total.
3) También el patrón Alta cohesión, pues las responsabilidades del cliente no han
cambiado, sin embargo, la fachada tiene muchas responsabilidades
La cohesión de la fachada suele ser baja al aglutinar todas las responsabilidades de un
subsistema. Nunca alta.
Cuestión 8: ¿Es posible aplicar los patrones tal y como se definen en los libros? ¿Por
qué? Ponga un ejemplo.
1) En principio si seria posible, así vemos como en la practica 4 de la asignatura se
aplicaba el patrón Singleton exactamente igual a como se describía en su plantilla, sin
embargo no es lo normal, así pues muchas veces al adaptarlos a la situación concreta ya
sea a causa de que se use junto con otros patrones, a causa de la implementación
concreta, o para que se cumplan los diversos requisitos tanto funcionales como no
funcionales.
2) El ejemplo propuesto en clases de teoría se basa en el patrón template method, que
habla de que son las clases hijas (mediante mecanismos de herencia) las que concretizan
el algoritmo y, sin embargo, en el caso de implementar la interfaz Comparable de JAVA
sólo tendrían que implementar el método compareTo sin usar mecanismos de herencia,
siendo el método plantilla el método sort de Java.util (un método estático)
Correcto. Hay numerosas ocasiones en la que no es posible aplicar el patrón como es
definido teóricamente. Un ejemplo es el sort de colecciones de JAVA. La conclusión es
que hay que manejar bien la idea y esencia de los patrones para ser capaces de
adaptarlos a la situación concreta donde tengamos que usarlo teniendo en cuenta el
diseño actual y los requisitos, tanto funcionales como no funcionales.
Cuestiones específicas
Cuestión 9: Indique las dos opciones para implementar un método gancho (hook) en la
clase base de un método plantilla.
1) No estoy seguro de que se trate de esto, pero supongo que el primer método es el
típico que se comenta de declarar en la clase padre un método abstracto que se usa en el
método plantilla, de modo que las clases hijas sean las que lo concreten e implementen.
El segundo método sería el comentado en la cuestión 8, que definiría el método
compareTo como método Hook del método plantilla sort de java.util, es decir, usaría un
método estático que sería el método plantilla definido en alguna clase, poniendo como
requisito que objetos con los métodos que concreten el algoritmo implementen una
determinada interfaz (que contendrá los métodos que se usarán de enganche).
Este segundo caso no es un template method típico. Se os enseña para que veáis que los
patrones no se pueden aplicar siempre como están definidos en los libros. La respuesta
correcta para el segundo tipo de hook es la 3) y 4).
2) Por un lado podemos declarar el método de forma abstracta de manera que fuera
después el cliente que usara el método plantilla el encargado de implementarlo. Por otro
lado podríamos darle una implementación por defecto de manera que el cliente podría
redefinir dicho método, pero al contrario que sucedía en el caso anterior, ya no seria
obligatorio, en este caso evidentemente el método hook no podría ser declarado como
abstracto.
En esta segunda forma de definir un método hook esta mi duda, en la practica 6 se
declaro un método hook de esta forma en concreto era el método getStrLog que
devolvía una cadena con la forma en la cual se había realizado el login, la duda esta en
que no se si verdaderamente podríamos llamar a este tipo de métodos, método hook
puesto que en la definición del patrón se dice que un método hook debe de ser abstracto
pues no debe de tener implementación alguien podría responder??
3) Yo tengo en mis apuntes que sí se puede. Serían las dos formas de poder definir un
método hook (método abstracto o con implementación por defecto).
Correcto, esas son las dos formas.
4) puede ser el ejemplo propuesto en la pregunta anterior, es decir por un lado
tendríamos los métodos hook definidos tal y como viene expresado en el patrón es decir
como métodos abstractos, la segunda seria darles una implementación por defecto, y
después el cliente si lo desea podría cambiar dicha implementación redefiniendo el
método, en este caso evidentemente el método hook no se podría declarar como método
abstracto.
Correcto también.
Cuestión 10: Indique que modificadores (public, protected, private, abstract, final)
deberían aplicarse a los distintos métodos implicados (el método plantilla, los métodos
hook) en el patrón template method.
1) El método plantilla debe ser final (pues nadie debe ser capaz de modificar el
algoritmo en este patrón) y público/privado/protegido dependiendo de las necesidades.
Aunque por regla general suele ser publico.
Los métodos hook deben ser protegidos (no visibles desde fuera, pero visibles por sus
hijos) y abstractos (la funcionalidad deben concretarla los hijos que los hereden).
Abstractos no siempre. Véase la pregunta anterior.
2) Sobre el o los métodos plantillas, aplicaríamos el modificador final ya que no seria
correcto que una clase hija redefiniese la parte fija del algoritmo. Por otro lado sobre los
métodos hook en primer lugar debemos de aplicar el modificador protected puesto que
este tipo de métodos solo deberían ser llamados desde las clases hijas no desde el
cliente, también habría que aplicar el modificador abstract para aquellos en los cuales no
se diera una implementación por defecto como veíamos en el apartado anterior
Perfecto
Cuestión 11: ¿Una vez aplicado el patrón Façade, cómo podemos usar las clases del
subsistema que la fachada oculta?
1) La aplicación del patrón Fachada no implica en ningún caso que se impida el acceso
a las clases del subsistema. Se puede seguir accediendo al subsistema de manera normal
(el ejemplo que se me ocurre es la relación entre JFace y el SWT para creación de
interfaces en java).
2) El patrón façade no impide de ninguna forma el uso de las clases del subsistema, este
patrón simplemente propone una interfaz para dicho subsistema con las ventajas
comentadas anteriormente. Por lo tanto podemos usar las clases y métodos del
subsistema de manera normal, es decir de la misma forma que si la fachada no existiese.
Correctas las dos respuestas.
Cuestión 12: ¿Cómo podemos enganchar una nueva funcionalidad (clase o método)
usando un método plantilla? ¿Quién es el encargado de llamar/usar esta nueva
funcionalidad?
1) Creando una nueva clase que extienda de la clase plantilla concreta, de modo que en
esta nueva clase se implementase los métodos hook con la nueva funcionalidad que se le
quieren dar, el encargado de llamar a estas clases seria el método plantilla siguiendo el
principio de hollywood
Correcto
Cuestión 13: ¿Es posible tener una clase con un método plantilla que no sea abstracta?
1) No, el método plantilla sólo define el esqueleto del algoritmo, las partes fijas sí
aparecerán especificadas, pero para completar la funcionalidad las partes variables del
algoritmo deben añadirla las clases hijas, por tanto la clase con método plantilla hará
uso de métodos abstractos (sin implementar) en el método plantilla. Automáticamente
esto convierte a esa clase en abstracta.
Incorrecto, ver respuesta 2)
2) Si, el caso visto anteriormente sobre que se de una implementación por defecto de
todos los métodos gancho.
Si damos implementación por defecto de todos los métodos gancho la clase no tiene que
ser abstracta.
Cuestión 14: ¿Cómo añade una fachada nueva funcionalidad al subsistema? ¿Es
correcto añadir nueva funcionalidad?
1) No creo que sea correcto puesto que la fachada debería abstraer la funcionalidad ya
existente en el subsistema sirviendo como "interfaz simplificada" de éste, no añadir
nueva funcionalidad.
2) La forma de que una fachada añadiese nuevas funcionalidades es tan sencilla como
crear nuevos métodos en la fachada para que implementasen dichas funcionalidades, sin
embargo esto no seria en absoluto correcto puesto que las fachadas son creadas para
facilitar el uso de un subsistema no para crear nuevas funcionalidades, es decir, todos
los cosas que pudiésemos hacer con la fachada deberíamos ser también capaces de
hacerlas utilizando directamente el subsistema.
Correctas las dos respuestas. Hay que tener en cuenta que combinar la funcionalidad
que ofrece el subsistema (varias llamadas a métodos de distintas clases) para simplificar
no podría considerarse añadir una nueva funcionalidad.
Cuestión 15: ¿Es obligatorio tener una fachada por subsistema?
1) Depende de la situación, si los subsistemas son lo suficientemente complejos puede
que sea viable pues el objetivo de este patrón es simplificar el uso del subsistema tras la
fachada al cliente.
Realmente no es obligatorio tener ni una, ni varías. Como bien dices, depende de la
situación.
2) No, por un lado podemos perfectamente no definir ninguna fachada para un
subsistema, y por otro podemos definir varias, esto ultimo es muy interesante ya que
esto permite dividir el subsistema en varias capas, de manera que cada capa
encapsularía un conjunto de funcionalidades, generalmente dichas funcionalidades
estarían relacionadas entre si (ya se sabe que por regla general se busca la alta cohesión)
Correcto, pero las fachadas casi nunca mejoran la cohesión, como se ha visto antes.
Cuestión 16: ¿Además de simplificar el uso del subsistema, qué otra ventaja
proporciona una fachada?
1) Separa el cliente del sistema que va a usar, consiguiendo así protección ante
variaciones de la implementación interna del cliente, mejora la portabilidad, baja el
acoplamiento entre los clientes y el sistema y favorece la creación de niveles en el
sistema.
2) por un lado la división del subsistema en varias capas, por otro eliminar (o reducir) el
acoplamiento entre las clases cliente y el subsistema
Bien las dos respuestas, pero reincido en que el desacoplamiento no es total.
Cuestión 17: ¿Cómo se puede implementar un paso opcional del método plantilla sin
necesidad de usar una instrucción if?
1) En el esqueleto del método plantilla usar un método abstracto que será el paso
Opcional, que deberá ser concretado en la clases hijas, pero, en éstas se implementará o
no, dependiendo de si se quiera o no usar ese paso opcional.
Incorrecto. Es mejor la segunda respuesta.
2) en el método plantilla hacer una llamada a un método, a dicho método se le dará un
cuerpo vacío en la clase plantilla, de manera que si en la clase cliente se desea utilizar el
paso opcional se le dará una implementación al método, en caso contrario se dejara tal
cual.
Correcta la segunda respuesta. De hecho esto es bastante común, pues evita que el
usuario del framework tenga que incluir métodos que no necesita con una
implementación vacía. Lo que se hace es añadirlos en la clase padre con una
implementación por defecto vacía.
Cuestión 18: Una clase que contenga un método plantilla con muchos métodos abstract
obliga a las subclases a realizar gran parte de la implementación del algoritmo. ¿Es esto
deseable? ¿En qué situaciones puede ocurrir esto? ¿Cómo podemos evitarlo?
1) Dependerá de la situación y del control que se le quiera dar a cada usuario. Por
ejemplo existe el patrón Estrategia precisamente para que el cliente cambie todo el
algoritmo en lugar de tan sólo una parte.
No es deseable, pues esto implica un mal diseño. Muy bien la idea de usar estrategia en
estas situaciones.
2) Evidentemente esto no es nada deseable, puesto puede llegar el caso que fuera
preferible que la clase no usara la plantilla y realizara una implementación del algoritmo
de una forma directa, esto sucede en caso de que la plantilla no tuviera muchas partes
fijas, por lo que la mayor parte son llamadas a métodos abstractos. Por ultimo una
posible solución seria dar una implementación por defecto a dichos métodos de manera
que no fuera necesario definirlos todos, lo cual ahorraría trabajo al cliente
La mejor solución sería usar estrategia en estos casos.
Boletín 3.3.2: Patrones Factory
Cuestiones generales
Cuestión 1: ¿Cuál es el principal objetivo del patrón Factory Method? ¿Y del idiom
Simple Factory? Deje clara la diferencia entre los dos patrones.
En los dos casos consiste en desacoplar la creación de objetos de las clases que tiene
que utilizarlos. En ambos casos esto es debido a que el conjunto de productos a crear no
es fijo y representa por tanto un punto de variación.
El objetivo de simple factory es únicamente desacoplar una clase de la creación de
objetos,
El objetivo de factory method es: Definir una interfaz para crear objetos de tipo
genérico permitiendo a las subclases decidir qué tipo de objetos concreto crear
.
Es el mismo que en simple factory sólo que se amplía para proporcionar un diseño en el
que los productos se pueden añadir sin necesidad de retocar el código existente, es decir,
desacopla la creación de objetos facilitando la creación de frameworks. Aplicando
variaciones protegidas, y dentro de este principio, el principio de hollywood.
Cuestión 2: ¿Qué tipos de acoplamiento resuelve Simple Factory?
Acoplamiento en la creación de objetos
Cuestión 3: ¿Qué relación existe entre el patrón Template Method y el patrón Factory
Method?
Son iguales, sólo que en Factory Method el método gancho se encarga de crear objetos
y es llamado create.
Cuestión 4: ¿Qué ventajas ofrece el patrón Factory Method en referencia a la
utilización/creación de frameworks?
1) Que ofrece métodos abstractos en la clase padre (actúan de métodos de enganche)
que se definen en cada una de las subclases concretas, y son invocados desde la clase
padre o interfaz (depende de la implementación que hayamos escogido), lo cual es el
principio de Hollywood.
Los métodos gancho en el caso de factory method es el create y hay que puntualizar que
no tiene que ser abstracto forzosamente, podemos proporcionar una implementación por
defecto.
Deberíamos añadir también, que al definir una interfaz común para todos los productos
a crear, también aseguramos que estos cumplan con ella y puedan añadirse al
framework sin retocar el código del mismo.
Cuestión 5: ¿Qué GRASP(s) se aplican en el idiom Simple Factory?
En primer lugar variaciones protegidas:
- Al añadir una interfaz común para el punto de variación que es representada
por el producto abstracto. Esto permite proteger al cliente de los cambios en
el uso de los productos, pero no en su creación
- También aplicamos indirección para desacoplar la clase cliente de la
creación de objetos
Cuestiones específicas
Cuestión 6: Al usar el idiom Simple Factory estamos pasando el problema de la
creación a otra clase, no lo evitamos. ¿Qué se consigue con esto?
1) Eliminar el acoplamiento entre la clase cliente y las clases concretas, a cambio de
pasar dicho acoplamiento entre la clase fábrica y las clases concretas.
Correcto. Así, si cambiamos los productos solo habrá que cambiar el código de la
fábrica y no el de todas las clases que los usen.
Cuestión 8: ¿Cuál es la ventaja del Factory Method cuando se tiene un único producto
concreto?
1) Que al existir una fábrica entre el cliente y el producto concreto, el cliente no tiene
acoplamiento con el producto concreto, no tiene que conocer su implementación y lo
protege de posibles variaciones
Correcto, pero habría que añadir que proporciona las ventajas derivadas de un
framework: nos permite añadir nuevos productos y nuevas fábricas concretas de manera
transparente (sin tener que modificar el código del framework)
Cuestión 9: ¿Qué diferencia hay entre un Simple Factory y un creador concreto de un
Factory Method?
1) Con el Factory Method podemos escoger los productos a crear en tiempo de
ejecución, Mientras que con el idiom si quisiéramos añadir nuevos productos
tendríamos que añadir código.
No es correcto. En los dos se elige el objeto a crear en tiempo de ejecución (dentro del
código del create). La diferencia primordial es que en factory method el creador
concreto hereda de la clase padre el código donde se va a utilizar ese create, mientras
que en simple factory esto no está definido y puede ser cualquier objeto el que haga uso
de la simple factory para pedirle objetos.
Además, podemos añadir varias simple factories para todos los subconjuntos de objetos
que queramos crear, igual que en factory method.
Cuestión 10: ¿Deben ser los métodos factoría siempre abstractos? ¿Y protegidos?
1) No tiene porque, ya que el método también podría dar una implementación por
defecto y luego completarla en las subclases concretas.
Correcto
2) No siempre tienen que ser abstractos, se les puede dar una implementación por
defecto y que las subclases los redefinan. Protegidos si deben de serlo para que solo
sean accesibles por las subclases que los pueden redefinir, es decir las fabricas
concretas.
Correcto a medias. Deben ser protegidos para que sólo se usen desde el método de la
clase padre que hace la llamada al create.
Cuestión 11: ¿Es obligatorio que el Factory Method o el create del Simple Factory
tomen un parámetro para decidir que tipo de objeto crear?
No pues otra opción es que decidan por ellos mismos que objetos devolver.
Boletín 3.3.3: Strategy y Adapter
Cuestiones generales
Cuestión 1: ¿Cuál es el principal objetivo del patrón Strategy? ¿Y del Adapter?
Strategy: Estructurar una familia de algoritmos de modo que sus clientes puedan
intercambiarlos en tiempo de ejecución
Adapter: Convertir la interfaz de una clase en otra interfaz esperada por los clientes.
Permite que clases con interfaces incompatibles puedan comunicarse
Cuestión 2: ¿Qué situaciones pueden motivar la utilización de un Adapter?
Que la clase cliente o la que tenemos que adaptar no puedan ser modificadas, o que sea
mas costosa la modificación de éstas que crear un adaptador.
Cuestión 3: ¿Qué ventajas se consiguen con el patrón Adapter?
Que una clase con interfaz incompatible pueda ser usada sin necesidad de modificar el
código existente. Como ventaja opcional conseguimos desacoplar el cliente y la clase
adaptada.
Cuestión 4: ¿Qué ventajas se consiguen con el patrón Strategy?
Aislar un punto de variación que consiste en distintas implementaciones del mismo
algoritmo, es decir, desacoplamos los clientes de los algoritmos de la implementación
concreta.
Centralizamos su descripción por lo que mejoramos su mantenibilidad y entendimiento.
Además, permitimos que se puedan reutilizar los algoritmos. Por último, si
Se mejora la cohesión del las clases que usan los algoritmos en aquellos casos en los
que el diseño alternativo sea incluir los algoritmos como métodos de las clases cliente.
Cuestión 5: ¿Qué relación existe entre el patrón Template Method y el patrón Strategy?
Describa sus relaciones y haga una tabla con ventajas e inconvenientes de cada patrón.
1) Los dos patrones son de tipo comportamiento, ambos permiten cambiar el código.
Mientras que el método plantilla nos permite cambiar parte del código por herencia,
tiempo de compilación. También nos permite factorizar el comportamiento común de un
algoritmo y así evita que tengamos que duplicar código, dejando que las extensiones se
encarguen las subclases.
Correcto
El estrategia nos permite cambiar todo el código por composición, en tiempo de
ejecución sin embargo tenemos que duplicar código, es posible que obliguemos a una
subclase implementar algo que no debe y además no puedo reutilizar.
La duplicación de código en el cliente no ocurrirá siempre, pues depende de que
incluyamos dentro del algoritmo de la estrategia y que no. Si aplicamos estrategia a
algoritmos que son totalmente distintos pero que solucionan el mismo problema, no
habrá repetición de código.
Con respecto a la reutilización, en estrategia se facilita la reutilización de los algoritmos,
cosa que en template method no es posible puesto que obliga a que estos sean protected.
La tabla resumiendo todo quedaría como sigue:
Patrón
Ventajas
Inconvenientes
Template
1. Es
adecuado
para
2. Es poco flexible a los cambios en
Method
implementar
frameworks
tiempo de ejecución por usar
pues obliga a definir el
herencia
contexto
(como/cuando)
3. No permite la reutilización de los
donde se usan las distintas
algoritmos (pasos en este caso) por
versiones en el método
definirlos como métodos gancho
plantilla
protected
Strategy
4. Es más flexible a los
6. No es adecuado para implementar
cambios en tiempo de
frameworks pues no indica el
ejecución gracias a la
contexto (cuando/donde) donde se
utilización de delegación
usan los algoritmos
5. Permite que cualquier objeto
reutilice los algoritmos
Cuestión 6: ¿Qué diferencias existen entre el patrón Façade y el patrón Adapter?
1) El patrón Façade se utiliza para minimizar las dependencias, reducir la complejidad,
es como un punto de entrada para los clientes. Con esto se consigue aislar al cliente de
la complejidad del sistema, minimizando el acoplamiento y haciendo que cualquier
cambio sea transparente a el.
El patrón Adapter su función es que un cliente que usa un objeto de una interfaz pueda
usar un objeto con una interfaz diferente sin tener que cambiar el código de ninguno de
los dos.
Correcto. Matizar que fachada no desacopla completamente, pues fachada se usa para
un caso de uso determinado y no para todos los usos.
Cuestiones específicas
Cuestión 7: ¿Cuántas clases puede adaptar un Adaptador?
Una o varias
¿Si es posible que adapte a varias clases, entonces qué lo diferencia de Façade?
El objetivo de Façade es simplificar, mientras que Adapter trata de cambiar la interfaz
de una clase para que pueda ser utilizada por el código existente (que ha sido
desarrollado para usar una interfaz distinta)
Cuestión 8: ¿Cómo puede conseguir que el comportamiento de una clase cambie en
tiempo de ejecución usando el patrón Strategy?
Basta con añadir un método setStrategy a la clase que usa las estrategias o añadir en esta
clase el código necesario para decidir que estrategia usar en cada momento
Boletín 3.3.4: Decorator
Cuestiones generales
Cuestión 1: ¿Cuál es el principal objetivo del patrón Decorator?
1) El cumplir el principio abierto/cerrado, es decir que una clase se pueda extender sin
que se vea afectada por las modificaciones. Poder modificar algo sin tener que añadir,
cambiar código.
Aclarar que quién no debe verse afectado por las modificaciones es el cliente de esas
clases.
Con la aclaración hecha es correcto, pero este no es el objetivo más importante. El
objetivo principal es: extender objetos de manera dinámica sin usar la herencia.
Cuestión 2: ¿Qué situaciones pueden motivar la utilización de un Decorator?
1) Cuando debido a la herencia se puede llegar a una explosión de clases, es decir
muchos tipos de clases diferentes que no son más que combinaciones de unas clases
básicas con unas clases que añaden algo nuevo y además existen puntos de variación.
Además deberíamos añadir aquellas situaciones donde en tiempo de compilación no se
conocen las extensiones que necesitará un objeto.
Cuestión 3: ¿Qué alternativas hay a la utilización de un Decorator?
1) Un Decorador consiste en la delegación, y la otra alternativa es mediante herencia.
Correcto.
Cuestión 4: ¿Cuándo es aconsejable no usar el patrón Decorator y usar la otra opción?
1) Supongo que será lo contrario a cuando usar el patrón, cuando me da igual fijar las
cosas en tiempo de compilación.
Y además no tienes explosión de herencia.
Cuestión 5: ¿Qué diferencias y similitudes observa entre el patrón Decorador y el
patrón Strategy?
1) Similitudes que fijan en tiempo de ejecución, pero no se me ocurre nada mas.
Yo diría lo mismo de otro modo: Ambos pueden cambiar el comportamiento del objeto
en tiempo de ejecución.
Aún así hay que tener claro que decorador añade/extiende el objeto, mientras que
strategy mantiene el objeto con las mismas responsabilidades solo que modifica la
forma en la que se llevan a cabo.
Cuestiones específicas
Cuestión 6: Es posible decorar un objeto varias veces e incluso decorar otro decorador
¿Que clases/relaciones permiten esto?
1) Las clases abstractas y las relaciones de herencia.
Correcto. Es posible y esto es posible gracias a que tanto los decoradores como los
objetos a decorar heredan/implementan la misma interfaz (interfaz, clase abstracta,
clase).
Cuestión 7: Todos los decoradores y objetos a decorar heredan/implementan la misma
interfaz. ¿Cómo se decide en una la implementación JAVA si ésta será una clase
abstracta o una interfaz?
1) Si podemos factorizar comportamiento común de las subclases en la superclase
utilizaremos una clase abstracta, para evitar así la duplicación de código, en cambio si
no podemos factorizar comportamiento común usaremos una interfaz.
Correcto. Es importante que notéis que al hablar de interfaz en diseño nos referimos al
conjunto de responsabilidades que ofrece un objeto y no al concepto de interface JAVA.
Cuestión 8: ¿Como puede conseguir cambiar el objeto al que se decora en tiempo de
ejecución? ¿Y el decorador?
1) Para cambiar el objeto al que se decora en tiempo de ejecución, habría que sustituir
dicho objeto con una llamada al constructor del decorador concreto. Es decir c = new
decoradorconcreto( c ); Para cambiar el decorador supongo que haría falta un decorador
para el decorador.
Más o menos bien. Otra opción para cambiar el objeto que se decora es añadir un
método setDecorado en los decoradores. Para cambiar los decoradores basta con crear el
nuevo decorador y fijarle el objeto a decorar: bien con el constructor o con el método
setDecorado.
Descargar