El análisis y diseño orientado a objetos es mucho más
complejo que el estructurado ya que no busca algo cerrado sino más bien algo más
genérico y abierto.
Un Diseño orientado a Objetos
Una de las metodologías existentes para la
construcción de software OO es la de R.Wirfs con un diseño orientado a las
responsabilidades.
Se divide en dos fases:
FASE EXPLORATORIA Clases
Se mapean los objetos lógicos del espacio del
problema a objetos del sistema. Esta metodología identifica los objetos a través
de los sustantivos de la especificación de requerimientos. Se descartan
los que obviamente no son clases y se forma una lista de clases
candidatas.
Luego se analiza esta lista bajo la siguiente
guía:
Con esta lista refinada se analizan los grupos de
clases para agruparlas en relaciones jerárquicas con eventuales clases
abstractas y de describe el propósito de cada clase y el rol que juegan cada una
de ellas en el sistema. Responsabilidades
Asignar las responsabilidades a las clases. Se decide
que conocen y que hacen las instancias de cada clase. Las responsabilidades de
un objeto son:
Las responsabilidades de un objeto son los
servicios que provee. Cuando un objeto cumple una petición realizada por
otro objeto juega el rol de servidor. Un contrato entre dos clases
representa una lista de servicios que una instancia solicita a otra de otra
clase. Como identificar responsabilidades
A través de la especificación se listan los
verbos y se determina si representan acciones que algún objeto debe
ejecutar.
A partir de las clases encontradas y sus nombres, lo
cual sugiere una responsabilidad al menos y esta deriva en otras y así
sucesivamente.
También pueden analizarse las relaciones
"es_tipo_de", "es_análoga_a" y "es_parte_de" para identificar superclases y/o
subclases que determinen responsabilidades. Colaboraciones
Un objeto cumple una responsabilidad o solo requiere
asistencia de otros objetos:
Con esto se identifica para cada contrato cuales son
las clases que juegan el rol de cliente y cuales las de servidor. Analizando
colaboraciones se pueden detectar responsabilidades mal asignadas en la etapa
previa.
Para determinar las colaboraciones se examina cada
responsabilidad de cada clase preguntando:
Similarmente para cada clase:
Ahora se tienen tarjetas descriptoras de las clases
donde figuran sus subclases y responsabilidades. Y además para cada
responsabilidades se registra las clases servidoras para cumplimentarla, lo que
especifica las colaboraciones. FASE ANALITICA Herencia
1- Construir grafos de jerarquía.
2- Identificar las clases abstractas y clases
concretas.
3- Dibujar diagramas de Venn representando las
responsabilidades compartidas entre las clases. Esto es útil para descubrir
superclases abstractas y para analizar si eran correctas las jerarquías
existentes.
4- Construir jerarquías de clases usando las
siguientes guías:
5- Construir los contratos definidos por cada clase
para deducir los servicios provistos por cada una:
Subsistemas
Se pueden encontrar piezas que tiene integridad
lógica y que pueden descomponerse en partes más pequeñas. Un subsistema es un
conjunto de clases (y posiblemente de otros subsistemas) colaborando con el fin
de cumplir un conjunto de responsabilidades.
Se trata de simplificar el diseño de la comunicación
entre objetos. Existen dos herramientas que ayudan a este propósito:
Entonces:
- Las clases en un subsistema deben colaborar para
soportar un pequeño número de responsabilidades fuertemente unido.
- Las clases en un subsistema deben ser
independientes.
Simplificar las colaboraciones entre y dentro de los
subsistemas. Minimizando las colaboraciones de una clase, los cambios en el
sistema tienen menos probabilidad de afectarla.
Un subsistema bien diseñado tiene pocas clases o
subsistemas que soportan sus contratos. Protocolos
Errores Comunes en el diseño
Por otro lado es buena práctica en un diseño
considerar los siguientes puntos:
Son una violación a la encapsulación. Produce ligaduras
ocultas innecesarias. Mal diseño.
No cumplen papel
importante en nuestra aplicación. Por simplicidad pueden eliminarse.
Como resultado de diseñar las clases sin analizar las relaciones con
las demás.
Mal diseño al no
usar adecuadamente la relación "es un".
Se duplica el código
innecesariamente. Condensar en una superclase común.
anObject class =
thisClass ifTrue: [ anObject foo]
"thatClass" ifFalse:[ anObject
fee[.
Este tipo de código va encontra del polimorfismo. Evitarlo!:
thisClass ---thatClass
answer -----answer
^self foo ----^self
fee
y el método anterior sería:
anObject answer.
(media docena ya
es demasiado)
No tiene sentido una
clase padre de 20 subclases, por ejemplo.
Ya que con esto se está "abriendo" al propio objeto.
Si deseas terminar esta exposición con buen humor, un poco fuerte para
algunas personas, simplemente acepta, si no, pues no entres y ya