Sei sulla pagina 1di 5

Paradigmas de Programación Parcial Paradigma Objetos – Viernes 25/06/2010

Un grupo de amigos egresados de un conocido colegio secundario han decidido juntarse


para crear su propia página web: Paradigma!,
un portal en que usuarios suben información de interés general mediante posts.

La página cuenta con un sistema de valoración de los posts que permite categorizar a los usuarios. Los posts
pueden ser comentados y puntuados: Al comentar un post se agrega un pequeño comentario textual y al
puntuarlo se le agrega una determinada cantidad de puntos al post.
El valor de un post equivale a tantos puntos como comentarios tenga, más la suma de las puntuaciones que se le
hayan hecho. Hay algunos post, llamados premium, para los cuales se considera doble el valor de las
puntuaciones recibidas. El puntaje de un usuario es la suma de todos los valores de sus posts.
Un usuario que recién ingresa es de categoría “Novato” y solo puede crear posts comunes. Cuando alcanza los
100 puntos puede ser promovido a categoría “Intermedio”, en la que sigue creando post comunes. Cuando un
usuario “Intermedio” tiene más de 1000 puntos y al menos un post con más de 500 puntos, puede ser promovido
a la última y definitiva categoría, llamada “Experto”, lo que le permite empezar a crear posts premiun. Al
cambiar de categoría los usuarios mantienen los posts anteriores.
La funcionalidad requerida es:
1. Poder crear un usuario y que esté listo para empezar a postear.
alf := ... crear: ‘Alfredo’

2. Hacer que un usuario postee un contenido dado y obtener el post.


postMaiden := alf postear: ‘Maiden vuelve a Argentina en 2011’

3. Comentar un post
postMaiden comentar: ‘Joya, ya reservo las entradas’.

4. Asignarle un puntaje
postMaiden agregarPuntaje: 15.

5. Saber el valor de un post.


postMaiden valor
"devuelve 16 (1 comentario + 15 puntos)"

6. Saber el puntaje de un usuario


alf puntaje
"devuelve 16, por tener como único post el anterior"

7. Promover a un usuario a su categoría siguiente, si es posible.


alf promover
“No hace nada. Alf sigue siendo un novato”

“Walter es de categoría intermedio, tiene 1500 puntos y su mejor post tiene 525 puntos”
walter promover
“Ahora Walter es experto”

8. Saber la cantidad de posts interesantes de un usuario. Un post común es interesante si tiene al menos 20
comentarios largos (de más de cierta cantidad determinada para todos los posts) y 50 puntos. Los posts
premium son más exigentes para ser interesantes: para considerar largo un comentario debe ser del
doble de caracteres que lo que requiere uno común.
alf cantPostsInteresantes

Se debe realizar:
 El diagrama de clases
 La codificación de los métodos necesarios
 Las siguientes justificaciones teóricas:
¿Dónde aparece el concepto de polimorfismo, cómo es usado y a qué objetos le resulta útil?
¿Fue de utilidad la herencia y la redefinición? ¿Para qué?
Paradigmas de Programación Parcial Paradigma Objetos – Viernes 25/06/2010

Solución Posible
Paradigmas de Programación Parcial Paradigma Objetos – Viernes 25/06/2010

1. Crear usuario

#Usuario>>crear: unNombre (Método de Clase)


|usuario|
usuario := self new.
usuario nombre: unNombre
usuario categoría: CategoriaNovato new.
^usuario
"nombre: y categoría: son setters"
#Usuario>>initialize
posts := Bag new
"En Pharo el mensaje initialize se manda automáticamente al instanciar"

Variantes Posibles:
 Puede haber un objeto "PaginaParadigma!" ó "SistemaPagina" que cree el usuario, y haga algo
similar a ésto, siempre que esté bien implementado.
 En Usuario, una Variable de Clase CategoríaInicial, para que sea un poco más flexible la solución
(y se asignaría una sóla vez, así que en el código de arriba la línea que asigna la categoría no
estaría).

Variantes Erróneas:
 La categoría no puede ser un String, debe ser un objeto más rico, porque más adelante se
necesitará delegarle responsabilidades.
 Los usuarios no pueden estar subclasificados en Novato, Intermedio y Experto. Ésto es porque
se debe poder cambiar de categoría, y si un objeto pertenece ya a una clase, no puede cambiar
a otra. Por otro lado, crear un nuevo objeto generaría problemas de identidad.

2 Postear

#Usuario>>postear: unTexto
|post|
post := categoria postQueTeCorresponde.
post texto: unTexto
^posts add: post.
"texto: es un setter"
#CategoriaExperto>>postQueTeCorresponde
^PostPremium new

#CategoriaIntermedio>>postQueTeCorresponde
^Post new

#Post>>initialize
comentarios := Bag new.
puntuaciones := Bag new.
"Antes de usar el sistema, alguien debería setear la variable de clase LargorDeReferencia"

Variantes Posibles:
 puntuaciones podría ser un número, en cuyo caso se inicializaría en 0

3. Comentar un post

#Post>>comentar: unTexto
comentarios add: unTexto

Variantes Posibles:
 No hace falta que los comentarios sean una clase aparte, con strings alcanza. Si se hace una
clase Comentario, ésta debe tener alguna responsabilidad interesante más allá de calcular el
largo.

4. Dar puntaje a un post

#Post>>agregarPuntaje: puntaje
puntuaciones add: puntaje
Paradigmas de Programación Parcial Paradigma Objetos – Viernes 25/06/2010

Variantes Posibles:
 puntuaciones podría ser un número, y agregarPuntaje: acumularía.

5. Calcular puntaje de un post

#Post>>valor
^self cantidadComentarios + self puntajeOtorgado.

#Post>>cantidadComentarios
^comentarios size.

#Post>>puntajeOtorgado
^puntuaciones inject: 0 into: [:acum :puntos| acum + puntos]

#PostPremium>>puntajeOtorgado
^super puntajeOtorgado * 2

Variantes Posibles:
 puntuaciones podría ser un número, y puntajeOtorgado directamente devolvería el valor
acumulado previamente.

6. Puntaje de un usuario.

#Usuario>>puntaje
posts inject: 0 into: [:unPost | acum + unPost valor]

7. Promover a un usuario, si es posible.

#Usuario>>promover
(categoria puedePromover: self)
ifTrue: [ categoria:= categoría categoriaSiguiente]

#CategoriaIntermedio>>categoriaSiguiente
^ CategoriaExperto new
"También podría tener un atributo con la categoría siguiente, oportunamente instanciado."

#CategoriaNovato>>categoriaSiguiente
^ CategoriaIntermedio new

#CategoriaExperto>>puedePromover: usuario
^false

#CategoriaIntermedio>>puedePromover: usuario
^(usuario tenesMasDe: 1000) and:[ usuario tenesAlgunPostConMasDe: 500]

#CategoriaNovato>>puedePromover: usuario
^ usuario tenesMasDe: 100

#Usuario>>tenesMasDe: puntos
^ self puntaje > puntos.

#Usuario>>tenesAlgunPostConMasDe: puntos
^ posts anySatisfy: [:unPost | unPost valor > puntos]

Variantes Posibles:
 Podría delegar más en categoría: la categoría sería la responsable de devolverme la categoría
siguiente si corresponde, ó ella misma si no cambia la categoría.
#Usuario>>promover
categoria := categoria tuSiguientePara: self

8. Cantidad de posts interesantes de un usuario.

#Usuario>>cantPostsInteresantes
^ (posts select: [:unPost | unPost esInteresante]) size
Paradigmas de Programación Parcial Paradigma Objetos – Viernes 25/06/2010

#Post>>esInteresante
^self cantComentariosLargos > 20 and: [self valor > 50]

#Post>>cantComentariosLargos
^ (comentarios select: [:unComentario | self esLargo: unComentario]) size

#Post>>esLargo: unComentario
^unComentario size > self largorDeReferencia

#Post>>largorDeReferencia.
^LargorDeReferencia

#PostPremium>>largorDeReferencia.
^super largorDeReferencia * 2

Justificaciones

Polimorfismo:
 Hay polimorfismo entre las instancias de Post y PostPremium, por el mensaje puntajeOtorgado, y
le sirve a cualquier post, para poder calcular el valor de cada post sin importar cómo se calcula
ese puntajeOtorgado. La manera de calcular valor de un post es una sola, y haber encontrado
ésta abstracción fue posible gracias a tratar polimórficamente ambos post.
 Hay polimorfismo entre las categorías por el mensaje postQueTeCorresponde y le sirve al usuario
para poder crear un post sin que le importe de qué clase es, ya que la categoría le creará el post
que le corresponda. De ésta manera, el usuario usa el nuevo post (poniéndole el texto que le
corresponde y guardándoselo en la colección) sin importar qué tipo de post es.
 Hay polimorfismo entre las categorías por el mensaje puedoPromover: y le sirve al usuario para no
preocuparse por cuáles son las diferentes condiciones para pasar de categoría. Entonces, sólo
delega en la categoría, que puede ser cualquiera de las tres, pero al usuario le es transparente.

Herencia:
 La herencia fue útil porque permitió agrupar el comportamiento común de todos los Post en la
clase Post, y definir el comportamiento distinto dentro de PostPremium, en los mensajes
puntajeOtorgado y largorDeReferencia.
 También resulta útil la herencia entre categoríaIntermedio y CategoríaNovato para reutilizar el
comportamiento de postQueTeCorresponde (para ambas categorías es el mismo). Una variante a
esto podría haber sido hacer una clase abstracta Categoría, que tuviera postQueTeCorresponde
como "^Post new", y redefinir "^PostPremium new" en CategoríaExperto. También sería válido no
usar herencia, ya que el código repetido no sería tan importante (es un "^Post new").

Redefinición:
 Hay redefinición en CategoríaNovato. Los métodos puedePromover: y categoríaSiguiente deben
hacer cosas distintas a los métodos de la superclase (se promueve distinto un novato, y la
categoría siguiente es distinta). Entonces redefino esos métodos para que no hagan lo mismo que
la superclase.
 También hay redefinición en el PostPremium, de los métodos puntajeOtorgado y
largorDeReferencia. Es útil porque es distinto el comportamiento de los PostPremium con respecto
a éstos mensajes. Además, en éste caso en particular, para ambos métodos resulta útil redefinir
porque mediante super reutilizo el comportamiento de la superclase, multiplicando por dos el
cálculo dentro de ambos métodos.

Errores comunes:
 Sólo puedo asignar sobre variables. Ó sea, sobre un atributo propio ó sobre una variable local.
Nada más. Esta mal hacer ésto:
#CategoriaNovato>>promoverA: unUsuario
unUsuario categoria := CategoriaIntermedio new.
"¡Mal mal mal!"
 No se puede tratar de acceder a variables de instancia desde un método de clase:
#Usuario>>crear: unNombre (Método de Clase)
self new.
nombre := unNombre
categoría := CategoriaNovato new.
"¡Mal mal mal!"

Potrebbero piacerti anche