Buscar en Gazafatonario IT

martes, mayo 20, 2008

Lectura Fundamental 12
Lectura # 12
Casos de Uso: de Extensiones y de Inclusiones
“El hombre vive fascinado por la inmensidad de la eternidad y nos preguntamos: ¿Nuestras acciones perdurarán a través de los siglos? ¿Gente que no conocemos oirá nuestros nombres mucho después de nuestra muerte? ¿Y se preguntarán quiénes éramos, cuán valientemente peleábamos, cuán ferozmente amábamos?”
Wolfgang Petersen (Troya, 2004)
Introducción
De vuelta en el tiempo, hace unas siete Lecturas Fundamentales, prometí hablar de las relaciones entre los casos de uso. Pues bien, he querido extender el tema hacía el no menos complejo asunto de modelar sistemas de información mediante casos de uso. Trataré de mantener una posición minimalista: abordaré sólo la cuestión relacionada con el diagrama de casos de uso.
Básicamente, un diagrama de casos de casos de uso está compuesto de Actores y Casos de Uso, y las relaciones entre los unos, entre los otros y entre los unos y los otros.
Para recordar qué es un Actor podemos leer la Definición 5 en [3]. Para recapitular sobre Casos de Uso, podemos leer esencialmente [4] y luego repasar [5], [6], [7] y [3]. Ya sabemos además que podemos usar UML [8] para especificar, visualizar, construir y documentar los artefactos de sistemas de software.
Generalización de Actores
Dos o más Actores se relacionan entre ellos mediante la Generalización (de actores). Esta relación significa que uno o más actores pueden heredar las características, pero mejor aún, las responsabilidades de otro actor del sistema. Un Vendedor de Licencias de Software y un Vendedor de Servicios de Ingeniería tienen al menos una responsabilidad en común, una actividad: Registrar Cliente. Si los roles se interceptan en dos o más actividades en el sistema, es posible entonces, por razones de organización del modelo, de abstracción y de simplicidad, crear un nuevo actor: Vendedor de Productos y Servicios. Este parentesco se diagrama como muestro en la figura 1.
Además, muchas veces enfrentamos el dilema en el que un caso de uso (del sistema) es ejecutado por dos o más actores. Como en un sistema de Administración de Proyectos, donde el Gerente de Proyectos puede Matricular un Proyecto, pero también lo puede hacer el Gerente de la Oficina de Proyectos. Una mala idea es expresar esta situación como lo hago aparecer en la figura 2.
Figura 1: Diagrama parcial de Actores de un Sistema CRM
En cambio, usamos la generalización, creando un actor que desde el punto de vista del negocio y del usuario es Abstracto: el Administrador de Proyectos. Entonces, el diagrama se convierte en algo como lo que sugiero en la figura 3.


Figura 2: Diagrama Incorrecto de Casos de Uso de un Sistema de Administración de Proyectos


Figura 3: Diagrama Correcto de Casos de Uso de un Sistema de Administración de Proyectos
Quizás lo que sucede en estos casos es que confundimos Actores del Negocio [3] con Actores del Sistema o, simplemente, cargos o roles de la organización para la cual se construye la aplicación con roles o responsabilidades en el sistema de las personas que ejercen esas funciones. Ese no es el camino.
Por último, tengamos en cuenta el sentido de la generalización de actores: los casos de uso ejecutados por el actor padre son en la práctica ejecutados por los hijos.
Relaciones Entre Actores y Casos de Uso
Un Actor se comunica con casos de uso, componentes y clases [9]. Esta comunicación se representa mediante la relación de Asociación (binaria). En Particular, nos interesa la relación entre el actor y el caso de uso. Esta relación muestra el actor que inicia o ejecuta el caso de uso, normalmente una persona o un grupo de personas, pero también cualquier entidad externa al sistema, como otra aplicación o maquinaria especial.
Las figuras 3, 4, 5 y 6 son muestras de relaciones de asociación típicas entre actores y casos de uso.
En estos diagramas, la constante es que la relación es en ambos sentidos, es decir, es una relación de toma y dame, el actor hace-el sistema hace. Pero también se presentan casos donde la asociación es en un solo sentido, o hacia el caso de uso o hacia el actor. Estas situaciones son comunes cuando el actor no es una persona, sino un software externo o una máquina. Como en la figura 4, donde al ejecutarse la funcionalidad de registrar un cliente que es persona natural, el sistema CRM le comunica al sistema contable que matricule un tercero.
En este diagrama, la funcionalidad que va al sistema externo se representa como un caso de uso “incluido”, una relación de la que hablaré en breve. Pero en la práctica, la comunicación puede ir directamente del caso de uso principal al sistema externo.


Figura 4: Diagrama Parcial de Casos de Uso donde interviene un sistema externo
Casos en los que un actor se relaciona con una clase o un componente se presentan cuando el actor es un sistema externo que envía o recibe datos del sistema principal o, cuando siendo persona, el actor se comunica con el sistema vía una página Web, por ejemplo, que se representa como una clase en la aplicación. Este último caso se presenta en los diagramas de Interacción, como los de Secuencia [10] o de Comunicación.
Relaciones Entre Casos de Uso
Este es la materia que genera más polémica y la que es menos entendida en la comunidad de la IT, así es que trataré de ir más despacio.
Dos o más casos de uso se pueden relacionar entre ellos para distintos propósitos: distribuir mejor el modelo, establecer condiciones de reusabilidad (de funcionalidad), de incrementos del software, y para planear las iteraciones, entre otros. Las relaciones son de tres tipos: Inclusión, Extensión y Generalización. Enfatizaré en las dos primeras.
Relación de Inclusión
Una relación de inclusión define que un caso de uso contiene el comportamiento definido en otro caso de uso [11].
Una relación de inclusión es una relación de un caso de uso base a un caso de uso incluido en la que se especifica como el comportamiento definido en el caso de uso incluido es explícitamente insertado en el comportamiento del caso de uso base [1]. Decimos entonces que el caso de uso incluido es abstracto, es decir, no es ejecutado directamente por un actor.
Esta relación se usa cuando queremos:
  • Factorizar o descomponer (en sentido matemático) el comportamiento del caso de uso base que no es necesario para entender el objetivo principal del mismo y donde solamente el resultado del caso de uso incluido es importante.
  • Distribuir en uno o más casos de uso, funcionalidad del caso de uso base que es común para dos o más casos de uso (reusabilidad).
La primera opción se usa especialmente en casos de uso largos o complejos donde algunas partes del mismo no son relevantes para el sentido primordial del caso de uso y no son necesarias, en primera instancia, para entenderlo y aprobarlo. Por ejemplo, un caso de uso para Ingresar un Cliente de Naturaleza Jurídica puede solicitar docenas o cientos de datos que se pueden agrupar de acuerdo a algunos criterios como Datos Generales, Datos del Tipo de Entidad y Naturaleza Jurídica, Datos del Gerente o Representante Legal, Datos de los Contactos, Referencias Comerciales, entre otros. Algunos de estos grupos de datos pueden incluirse en casos de uso complementarios que son ejecutados desde el caso de uso principal que podría lucir así:
Caso de Uso: Registrar Cliente Jurídico
Actor: Vendedor de Productos y Servicios
Descripción: este caso de uso permite registrar los datos de una persona de naturaleza jurídica…
Secuencia Básica:
1. El caso de uso inicia cuando el Actor decide registrar los datos de una persona jurídica
2. El sistema pide seleccionar la ciudad y oficina de vinculación
3. El actor selecciona la ciudad y oficina de vinculación
4.
12. Se ejecuta el caso de uso Registrar Datos del Tipo de Entidad y Naturaleza Jurídica
13. Se ejecuta el caso de uso Registrar Datos del Gerente o Representante Legal
14. Se ejecuta el caso de uso Registrar Datos de las Referencias Comerciales
15….
25. El caso de uso termina
Poscondiciones: N/A
Requisitos Especiales: N/A
En este ejemplo, en los pasos 12 a 14 se ejecutan distintos casos de uso de los que, en principio, interesa el resultado. La palabra clave es “en principio”. En este diagrama también muestro la segunda posibilidad de inclusión, el reuso, con el caso de uso Verificar Centrales de Riesgo, que se ejecuta desde varios casos de uso del modelo.
Algunos aspectos de los casos de uso incluidos que debemos tener en cuenta:
  • Un caso de uso incluido no contiene una funcionalidad significante para la arquitectura del sistema, especialmente para la vista funcional o de casos de uso.
  • Un caso de uso incluido se puede “prototipar” en las primeras de cambio, es decir, durante el análisis y el diseño del mismo, el diseñador se puede concentrar en el caso de uso base y omitir los detalles particulares del caso de uso incluido.


Figura 5: Diagrama parcial del caso de uso Registrar Cliente Jurídico
  • Un caso de uso incluido no debe usarse como excusa para hacer descomposición funcional [4], es decir, tener uno o más casos de uso incluidos que especifiquen aspectos CLAB (creación, lectura, actualización o borrado –CRUD en inglés) o que estén vinculados a usuarios concretos específicos, o completamente ligados a un componente del sistema o a un componente arquitectónico específico, o vinculados a una pantalla o función de usuario determinada, o en algún paso de su secuencia ejecutan otros casos de uso incluidos (asunto este que debería evitarse tanto como se pueda). Para saber más de casos de uso funcionalmente descompuestos ver Definición 3 en [4].
  • Un caso de uso incluido está incompleto por naturaleza, es decir, por sí solo no arroja un resultado observable para el actor, o es un resultado parcial, o sus escenarios dependen de lo que ha pasado antes en el caso de uso principal.
  • Un caso de uso incluido no es ejecutado por un actor distinto al actor del caso de uso base. Sin embargo, un caso de uso incluido puede tener asociado un actor pasivo o secundario, normalmente cuando este actor recibe o entrega información al caso de uso incluido, como anotaba en la figura 4.
  • Un caso de uso incluido no se usa para especificar procesos automáticos o semi-automáticos que el sistema realiza en su totalidad sin interacción con el usuario.
  • Un caso de uso incluido siempre se implementa con el caso de uso base o antes, si se trata de un caso de uso que expone funcionalidad común. En otras palabras, el caso de uso incluido se implementa durante la misma iteración en que se implementa el primero caso de uso principal que lo incluya.
  • Un caso de uso incluido no es condicional, es decir, si el ejecutar el caso de uso base se alcanza el paso donde se ejecuta el caso de uso incluido, éste se ejecuta. Por supuesto, la ejecución de la funcionalidad incluida puede depender de si se cumple una condición o no en el caso de uso base, pero esta condición debe especificarse explícitamente en el caso de uso principal, como apunto en el paso 12 del ejemplo siguiente:
Caso de Uso: Registrar Cliente Natural
Actor: Vendedor de Productos y Servicios
Descripción: este caso de uso permite registrar los datos de una persona natural.
Secuencia Básica:
5. El caso de uso inicia cuando el Actor decide registrar los datos de una persona natural
6. El sistema pide seleccionar la ciudad y oficina de vinculación
7. El actor selecciona la ciudad y oficina de vinculación
8. El sistema solicita el nombre de la persona
9. El actor ingresa el nombre de la persona
10. El sistema pide seleccionar la profesión de la persona
11. El actor selecciona la profesión de la persona
12. Si la profesión es “Congresista” se ejecuta el caso de uso Verificar Lista Clinton.
13. …
14. Se ejecuta el caso de uso Registrar Datos de las Referencias Comerciales
15….
25. El caso de uso termina
Poscondiciones: N/A
Requisitos Especiales: N/A
  • Un caso de uso incluido debería incluir, en su documentación, una sección que describa explícitamente los casos de uso base desde los cuales es incluido. Este simple ejercicio hace al documento tan auto-suficiente o auto-contenido como sea posible, es decir, los interesados en el artefacto no tendrán que navegar por ningún otro lado para conocer todo el detalle del caso de uso.
  • En un caso de uso incluido, las precondiciones siempre se han cumplido en el caso de uso base que lo incluye. Entre tanto, las poscondiciones del caso de uso incluido afectan el comportamiento del resto del caso de uso base.
  • Finalmente, un caso de uso incluido no debería tener relaciones de extensión con otros casos de uso. Simplemente no tiene sentido.
Pasemos precisamente a la trama de las extensiones.
Relación de Extensión
La Extensión es una relación de un caso de uso de extensión a un caso de uso extendido que especifica como y cuando el comportamiento definido en el caso de uso de extensión puede ser insertado en el comportamiento definido en el caso de uso extendido [12].
Esta relación se usa:
  • Para establecer que un fragmento de la funcionalidad del caso de uso es opcional, o potencialmente opcional. A diferencia de lo que ocurre con la inclusión que es una relación que implica obligatoriedad en la ejecución, por decirlo de cierta manera.
  • Para señalar una parte del comportamiento que es ejecutado sólo bajo ciertas circunstancias, a veces excepcionales, tales como el envío de un mensaje a un usuario cuando se produce un hecho determinado. Por ejemplo, cuando un cliente VIP solicita el aumento de un cupo de crédito y la cantidad solicitada sobrepasa la política de crédito que puede soportar al Analista de Crédito, entonces el proceso pasa a una instancia mayor, como un Gerente de Oficina o algo así. Decimos entonces que ha ocurrido una interrupción en el caso de uso. A este dilema nos enfrentamos continuamente y la primera intención de un Ingeniero de Requisitos inexperto es crear un único caso de uso con dos actores. Ahora ya sabemos que realmente son dos parejas actor-caso de uso.
  • Para mostrar que puede haber un conjunto de segmentos de comportamiento de los cuales uno o varios de estos pueden ser insertados en un punto de extensión en un caso de uso base o extendido. Estas secciones insertadas (y el orden en el cual son insertadas) dependerán de la interacción con los actores durante la ejecución del caso de uso base.
La extensión es condicional, lo que significa que su ejecución depende de lo que ha pasado mientras se ejecuta el caso de uso base. Éste no controla las condiciones para la ejecución de la extensión –las condiciones son descritas dentro la relación de extensión. El caso de uso de extensión puede acceder y modificar los atributos del caso de uso base. Éste, sin embargo, no puede ver las extensiones y no puede acceder a sus atributos.
Una diferencia fundamental con la inclusión es que, en la extensión, el caso de uso base está completo por sí mismo, es decir, que debería entenderse y tener significado completo sin ninguna referencia a sus extensiones. Sin embargo, el caso de uso base no es independiente de las extensiones, puesto que no puede ser ejecutado sin la posibilidad de seguir las extensiones [2]. También pasa que el caso de uso de extensión puede acceder y modificar los atributos del caso de uso base, pero éste no puede ver las extensiones y no puede acceder a sus atributos. Y más, el caso de uso base se modifica implícitamente por las extensiones. En otras palabras, el caso de uso extendido (base) es ciego a sus extensiones específicas, pero no al contrario.
Un poco truculento, pero así es. La figura 6 es una muestra típica de extensión de casos de uso.
Otra gran diferencia entre la inclusión y la extensión es que el caso de uso de extensión puede ser ejecutado por un actor distinto al caso de uso base, como observamos en el diagrama. Observamos también la condición que activa la extensión en cada caso: en una de ellas se trata de un crédito de mayor cuantía, donde la mayor cuantía es un atributo que puede y debería ser configurable; mientras que en el segundo caso se trata de un cliente del sector gubernamental o bien podría ser algún otro tipo de cliente con tratamiento especial.


Figura 6: Diagrama parcial del caso de uso Aprobar Solicitud de Crédito
Y más de la cuestión semántica, las extensiones de un caso de uso son suplementarias, lo que quiere decir, que el caso de uso extendido está completo, es un todo. En el ejemplo de la figura 6, Aprobar Solicitud de Crédito es un caso de uso terminado por sí mismo y bien podría ser implementado en una iteración distinta (previa) y hasta en un proyecto diferente a la iteración o proyecto donde se implementan los otros casos de uso. Esta es otra de las razones por las que se usa la extensión.
Y estos son algunos aspectos de los casos de uso extendidos y de extensión que debemos tener en cuenta a la hora de modelar sistemas de información:
  • Un caso de uso extendido y sus casos de uso de extensión sí entregan un resultado de valor observable para el actor que los ejecuta, ya sea a través de ellos mismos o transfiriéndolo de la extensión al extendido y de allí al actor.
  • Un caso de uso de extensión no es una especialización del caso de uso extendido, es decir, la extensión no es una relación de herencia o de generalización, dependiendo desde el ángulo del cual miremos. Hago énfasis en este aspecto porque tengo la ligera impresión de que, no sólo los analistas noveles, sino también los diseñadores y los programadores estamos entrenamos para ver la extensión como una especialización, cuando en realidad no es así.
  • Quizás es por eso que la OMG tomó la decisión de cambiar la definición formal de la extensión para que sea una relación de dependencia. Aunque quiero aprovechar este punto para decir también que esta situación se desprende de la estructura formal de UML, la así llamada Especificación de Infraestructura de UML [13], algo que nos ha complicado la vida de muchas formas, sin embargo, esta definición formal muchas veces es irrelevante en la vida real, quiero decir, no es práctica en la mayoría de los modelos que construimos.
  • Un caso de uso se puede usar para documentar nuevas versiones del caso de uso original. Este es un gran beneficio de la extensión, porque deja intacto el caso de uso original que posiblemente ya está implementado y hasta en producción y permite que el analista de requisitos se concentre con los usuarios en las nuevas características del caso de uso extendido.
Aquí nos enfrentamos a la disyuntiva de extender o no extender un caso de uso. Me refiero a que si el cambio es pequeño, posiblemente sea más útil y práctico especificar una secuencia alterna en el caso de uso base; si la modificación es substancial, a juicio del analista, éste tomará la sabia decisión de crear un nuevo caso de uso.
Ahora bien, un caso de uso extendido luce más o menos así:
Caso de Uso: Aprobar Solicitud de Crédito
Actor: Analista de Crédito
Descripción: este caso de uso permite aprobar una solicitud de crédito realizada por un cliente…
Secuencia Básica:
1. El caso de uso inicia cuando el Actor decide aprobar una solicitud de crédito
2. El sistema solicita el radicado y la fecha de de la solicitud
3. El actor ingresa el radicado y la fecha de de la solicitud
4. El sistema valida que el radicado exista para la fecha establecida y muestra los datos de la solicitud: nombre o razón social del cliente, número de identificación y tipo de la misma, dirección, ciudad, …, sector del cliente, cantidad solicitada, …
5. El sistema pide seleccionar el tipo de desembolso (Cheque, Consignación, Efectivo)
6. El actor selecciona el tipo de desembolso
7. El sistema solicita el número de aprobación de la solicitud
8.
25. El caso de uso termina
Poscondiciones: N/A
Puntos de Extensión
5A. La cantidad solicitada es de Mayor Cuantía
7A. El cliente es del sector Gobierno
Requisitos Especiales: N/A
Lo único distinto son los puntos de extensión. Observen que la secuencia básica del caso de uso, ni ninguna otra secuencia, hace alusión a uno o más casos de uso de extensión. Es lo que había dicho: el caso de uso base no conoce los atributos ni las características del caso de uso de extensión.
Por su parte un caso de uso de extensión, se diferencia de un caso de uso normal en que debe tener especificado el evento que lo activa (llamado comúnmente trigger). Por ejemplo, en la figura 7, Asignar Revisión de Arquitectura es considerada una actividad especial por el sistema de Administración de Proyectos:


Figura 7: Diagrama parcial de casos de usos de un Sistema de Administración de Proyectos
Este caso de uso, que extiende a Asignar Actividad, podría lucir más o menos así:
Caso de Uso: Asignar Revisión de Arquitectura
Actor: Gerente de Oficina de Proyectos
Descripción: este caso de uso permite al PMO asignar la revisión de una arquitectura de software…
Evento de Activación: la actividad es una actividad especial: Revisión de Arquitectura
Secuencia Básica:
1. El caso de uso inicia cuando el Actor decide asignar una revisión de arquitectura
2. El sistema pide seleccionar el revisor técnico
3. El actor selecciona el revisor técnico
4. El sistema verifica que el revisor técnico tenga el perfil requerido para la actividad
5. El actor …
6.
12. El caso de uso termina
Poscondiciones: N/A
Requisitos Especiales: N/A
La figura 7 también dilucida sobre otro aspecto de las relaciones entre casos de uso: un caso de uso base puede estar asociado con uno o más casos de uso incluidos y con uno o más casos de uso extendidos.
Otro aspecto importante de las relaciones de extensión es que el diagrama es bastante explicativo. En la figura 8, por ejemplo, está claro que un vuelo cualquiera puede ser reservado por un pasajero cualquiera, pero que si el pasajero está registrado como frecuente, la reserva tiene algunas características especiales (estas particularidades no se pueden observar en un diagrama de casos de uso como este).
El diagrama 8 también muestra otro aspecto de las relaciones de extensión y es que un caso de uso de extensión puede ser a su vez extendido por uno o más casos de uso de extensión. Y este hecho profundiza más en el proceso del negocio que resuelve este modelo: si el vuelo es internacional, y el pasajero frecuente además está registrado como pasajero VIP, tiene la opción de establecer o seleccionar el menú que consumirá durante el vuelo.


Figura 8: Diagrama parcial de casos de usos de un Sistema de Reservación de Vuelos
Del diagrama no se pude extraer información sobre las distintas clases de vuelo que proporciona la aerolínea. Sin embargo, este es precisamente el objeto del siguiente apartado: la clasificación de casos de uso, en el sentido de generalización, llamada también herencia de casos de uso.
Generalización Entre Casos de Uso
Una generalización es una relación taxonómica entre un clasificador más general y un clasificador más específico. Cada instancia del clasificador específico también es una instancia indirecta del clasificador general. Así, el clasificador específico hereda las características del clasificador más general [14].
Esta relación es ampliamente usada en el modelado orientado a objetos, sin embargo, no solo se da entre clases y objetos, sino entre cualquier elemento de UML que actúe como clasificador, como los casos de uso.
La generalización de casos de uso se usa cuando dos o más casos de uso comparten comportamiento, estructura y propósito. Es decir, si dos casos de uso ejecutan un conjunto amplio de actividades similares y sólo algunas diferentes, es posible tomar todas las tareas comunes y especificarlas en un nuevo caso de uso que generaliza a los dos anteriores y en estos dos sólo se especifican las tareas disímiles. Esa es la primera premisa para usar la relación de generalización entre casos de uso, como en la figura 9, donde es posible que Reservar Vuelo Doméstico y Reservar Vuelo Internacional sólo difieran en que para este último caso el actor pueda seleccionar la ruta y especificar algunas condiciones especiales de vuelo.


Figura 9: Diagrama parcial de casos de usos de un Sistema de Reservación de Vuelos
El caso de uso Reservar Vuelo Doméstico puede especificarse de la siguiente manera:
Caso de Uso: Reservar Vuelo Doméstico
Actor: Pasajero
Descripción: este caso de uso permite a un pasajero reservar un vuelo entre dos ciudades nacionales…
Secuencia Básica:
1. El caso de uso inicia cuando el Actor decide reservar un vuelo doméstico
2. El sistema pide seleccionar las ciudades origen y destino del vuelo
3. El actor selecciona las ciudades origen y destino del vuelo
4. El sistema solicita las fechas de ida y de regreso del vuelo
5. El sistema valida la existencia de vuelos con las condiciones establecidas y pide seleccionar la tarifa
6. El actor selecciona la tarifa
7. El sistema genera y muestra un código de reserva y el caso de uso termina
Poscondiciones: N/A
Entre tanto, el caso de uso Reservar Vuelo Internacional puede ir así:
Caso de Uso: Reservar Vuelo Internacional
Actor: Pasajero
Descripción: este caso de uso permite a un pasajero reservar un vuelo cuya ciudad destino es de otro país…
Secuencia Básica:
1. El caso de uso inicia cuando el Actor decide reservar un vuelo internacional
2. El sistema pide seleccionar las ciudades origen y destino del vuelo
3. El actor selecciona las ciudades origen y destino del vuelo
4. El sistema solicita las fechas de ida y de regreso del vuelo
5. El sistema valida la existencia de vuelos con las condiciones establecidas, muestra las rutas disponibles (escalas intermedias) y pide seleccionar la ruta y tarifa de preferencia
6. El actor selecciona la ruta y la tarifa de su preferencia
7. El sistema pide seleccionar las condiciones especiales del vuelo
8. El sistema genera y muestra un código de reserva y el caso de uso termina
Poscondiciones: N/A
Requisitos Especiales: N/A
La diferencia entre uno y otro se nota en los pasos 5, 6 y 7. En este caso, el caso de uso padre, Reservar Vuelo puede contener exactamente la misma funcionalidad que Reservar Vuelo Doméstico y dejar sólo los pasos distintos en Reservar Vuelo Internacional. De esta manera se simplifica la especificación y el modelado del sistema.
También puede ocurrir que sea necesario agrupar dos o más casos de uso cuya funcionalidad, estructura y objetivo sean compartidos en un caso de uso puramente abstracto, también para efectos de simplificación del modelo. Como en la figura 10.


Figura 10: Diagrama parcial de casos de usos de un Sistema de Administración de Proyectos
Aquí, el caso de uso abstracto no contiene ninguna especificación funcional y se usa como “comodín”, quizás para relacionar los casos de uso hijos con uno o más casos de uso incluidos o de extensión. También para hacer el análisis y diseño de todos ellos al mismo tiempo (hacer una única realización de casos de uso, por ejemplo).
Aunque no está especificado, los casos de uso hijos pueden ser ejecutados por actores diferentes. También, si el caso de uso padre es abstracto, podría no tener actor relacionado. En esta última instancia, los hijos deberían tener asociado el actor que los ejecuta, necesariamente.
Mi recomendación final es que usemos la generalización de casos de uso como detallo en esta última alternativa. Para la primera forma, siempre podemos usar inclusión y hasta extensión.
Conclusiones
Un modelo es una abstracción de la realidad, una representación simplificada de algunos fenómenos del mundo real. En materia de sistemas de software, esos fenómenos se refieren a requisitos del software y la representación de los mismos se hace mediante actores, casos de uso y las relaciones entre aquellos y estos y entre cada uno de ellos.
La asociación, la generalización, la inclusión y la extensión son los cuatro tipos de relaciones entre estos elementos de los sistemas de información. Algunas de ellas se quedan en un plano estrictamente teórico o conceptual, en el sentido de que no tienen aplicación práctica, al menos, no una de valor para el modelador. Me refiero a la generalización que en lo que a casos de uso se refiere no tiene el sentido de provecho que tiene, por ejemplo, en un diagrama de clases o uno de objetos.
La asociación, por su parte, es la relación natural entre actores y casos de uso, su significado es directo y simple: este actor ejecuta o inicia este caso de uso. También, este actor entrega o recibe información de (interactúa con) este caso de uso. Más allá, la inclusión y la extensión constituyen un par de relaciones que despiertan emociones encontradas en la comunidad de analistas, ya sea porque tendemos a confundir su uso o porque nuestros paradigmas mentales (específicamente los de la orientación a objetos) no nos permiten verlas y usarlas con claridad expedita.
Estos son los temas que he tratado de dilucidar en este artículo. Son aspectos en los que todos debemos mejorar en aras de incrementar la calidad de los productos que desarrollamos.
¿Quiere Saber Más?
Para conocer más sobre especificación de casos de uso, podemos consultar [15] que sigue siendo, sino el mejor, uno de los muy buenos libros sobre el espinoso asunto de escribir casos de uso.
Para conocer más de modelado de casos de uso, relaciones de inclusión, extensión y generalización, podemos consultar [16], [17] y [18] cuyos autores concentran sus esfuerzos en explicar los distintos patrones que podemos encontrar al momento de modelar requisitos de software con casos de uso.
Como siempre, está el que considero el mejor libro sobre UML, patrones, análisis y diseño orientado a objetos y el proceso de desarrollo de software, todo en uno. Se trata del libro de Larman [19].
También está el libro origen de todo, el de los three amigos [20].
Fin.
Referencias
[1] IBM. The Rational Unified Process V7.1.
[2] IBM. The Rational Unified Process version V7.1.
[3] Luis Antonio Salazar Caraballo, “Casos de Uso: Origen, Especificación y Evolución”, Gazafatonario IT, http://gazafatonarioit.blogspot.com/2006/11/lecturas-fundamentales-2.html, 17 nov. 2006.
[4] Luis Antonio Salazar Caraballo, “Casos de Uso: De Vuelta a lo Fundamental”, Gazafatonario IT, http://gazafatonarioit.blogspot.com/2006/11/lecturas-fundamentales.html, 09 nov. 2006.
[5] Luis Antonio Salazar Caraballo, “Casos de Uso: Del Todo y de Sus Partes”, Gazafatonario IT, http://gazafatonarioit.blogspot.com/2006/11/lecturas-fundamentales-3.html, 23 nov. 2006.
[6] Luis Antonio Salazar Caraballo, “Casos de Uso: ¿Cuándo Están Terminados?... ¿Y qué hacer con ellos a continuación?”, Gazafatonario IT, http://gazafatonarioit.blogspot.com/2006/12/lecturas-fundamentales-4-1-de-2.html, 07 dic. 2006.
[7] Luis Antonio Salazar Caraballo, “Casos de Uso: ¿Cuándo Están Terminados?... ¿Y qué hacer con ellos a continuación? Parte 2 de 2”, Gazafatonario IT, http://gazafatonarioit.blogspot.com/2006/12/lecturas-fundamentales-5-2-de-2.html, 22 dic. 2006.
[8] Luis Antonio Salazar Caraballo, “Prolegómenos Sobre el Lenguaje de Modelado Unificado”, Gazafatonario IT, http://gazafatonarioit.blogspot.com/2005/06/prolegmenos-sobre-el-lenguaje-de.html, 01 jun. 2006.
[9] Object Management Group, “OMG Unified Modeling Language (OMG UML), Superstructure, V2.1.2”, http://www.omg.org/technology/documents/modeling_spec_catalog.htm#UML, 2 nov. 2007. Pp. 587.
[10] Luis Antonio Salazar Caraballo, “Realización de Casos de Uso: de los Objetos y sus Interacciones”, Gazafatonario IT, http://gazafatonarioit.blogspot.com/2007/10/lecturas-fundamentales-10-lectura_3046.html, 23 oct. 2006.
[11] Object Management Group, “OMG Unified Modeling Language (OMG UML), Superstructure, V2.1.2”, http://www.omg.org/technology/documents/modeling_spec_catalog.htm#UML, 2 nov. 2007. Pp. 592.
[12] Object Management Group, “OMG Unified Modeling Language (OMG UML), Superstructure, V2.1.2”, http://www.omg.org/technology/documents/modeling_spec_catalog.htm#UML, 2 nov. 2007. Pp. 589.
[13] Object Management Group, “OMG Unified Modeling Language (OMG UML), Infrastructure, V2.1.2”, http://www.omg.org/technology/documents/modeling_spec_catalog.htm#UML, 4 nov. 2007.
[14] Object Management Group, “OMG Unified Modeling Language (OMG UML), Superstructure, V2.1.2”, http://www.omg.org/technology/documents/modeling_spec_catalog.htm#UML, 2 nov. 2007. Pp. 71.
[15] Alistair Cockburn, “Writing Effective Use Cases”, Addison-Wesley, 21 feb. 2000.
[16] Mike O’Docherty, Object-Oriented Analysis & design, Understanding System Development With UML.” John Wiley & Sons. 2005.
[17] Steve Adolph, Paul Bramble, Alistair Cockburn, Andy Pols. Patterns for Effective Use Cases. Addison Wesley. August 23, 2002.
[18] Kim Hamilton, Russell Miles. Learning UML 2.0. O'Reilly. April 2006.
[19] Graig Larman. applying-uml-and-patterns-an-introduction-to-object-oriented-analysis-and-design-and-the-unified-process-2nd-edition. 13 jul. 2001.
[20] Grady Booch, James Rumbaugh, Ivar Jacobson. The Unified Modeling Language User Guide. 2nd-edition. May 29, 2005.
Lectura Fundamental Siguiente: Casos de Abuso

viernes, noviembre 23, 2007

Lectura Fundamental 11

Lectura Fundamental Anterior: “Realización de Casos de Uso: De los Objetos y sus Interacciones”

Lectura # 11

Orientación a Objetos: Un Enfoque Teórico Moderno (Actualizado)

“Cuando la Generación-Net alcance la mayoría de edad, el mundo será más pequeño e infinitamente más complejo. No tenemos idea de cuáles problemas afrontarán estos jóvenes, cuáles serán sus sueños, ni qué nuevas y audaces soluciones idearán. Pero una cosa es segura: la democracia tal como la conocemos se acabará. Quizás debamos adoptar una actitud seria desde ahora y replantear nuestra noción sobre el gobierno y el significado de la libertad.”

Don Tapscott (Creciendo en un Entorno Digital)

Introducción

En Ingeniería del Software, la clase es la unidad esencial que forma a todo sistema de software. Es además la estructura sistémica y funcional fundamental del software en actividad, capaz de ejecutarse independientemente como entidad mono-funcional (como un servicio), o bien, hacer parte de una formación mayor, como instrumento multi-funcional. La clase presenta dos modelos básicos: abstracto y concreto. Su organización general comprende: identificador de la clase o nombre, atributos o propiedades y operaciones o métodos.

La teoría de la orientación a objetos o simplemente orientada-a-objetos es la base sobre la que se sustenta gran parte de la Ingeniería del Software. Todos los elementos utilitarios que forman los productos de software moderno están formados por clases.

El concepto de clase como unidad orgánica (en el sentido de estructural) y funcional de los sistemas de software surgió hará apenas unos cuarenta años, cuando el término “orientado-a-objetos” fue usado por primera vez.

“En Utah, en algún momento después de Noviembre del 66 cuando, influenciado por Sketchpad, Simula, el diseño para la ARPAnet2, el Burroughs B5000 y mi conocimiento en Biología y Matemáticas, empecé a pensar en una arquitectura para la programación. Y fue probablemente en 1967 cuando alguien me preguntó qué estaba haciendo y le respondí: “Es programación orientada-a-objetos”.”3

Posteriormente, en los años setenta, el Grupo de Investigación en Aprendizaje (Learning Research Group) de XPARC (Xerox Palo Alto Research Center) con el Dr. Alan Kay a la cabeza, desarrolló SmallTalk, el primer lenguaje de programación orientado-a-objetos nativo que fue liberado a principios de los ochenta a toda la comunidad de desarrolladores. Algunas leyes4 o primitivas subyacen el desarrollo del lenguaje:

1. Cualquier cosa es un objeto

2. Los objetos se comunican enviando y recibiendo mensajes (en términos de objetos)

3. Los objetos tienen su propia memoria (en términos de objetos)

4. Cada objeto es una instancia de una clase (la cual puede ser un objeto)

5. La clase contiene el comportamiento compartido para sus instancias (en la forma de objetos en un programa)

6. Para evaluar un programa, el control se pasa al primer objeto y el resto es tratado como su mensaje.

Hoy, todos los lenguajes de programación implementan esas leyes y como programadores deberíamos tenerlas siempre presente a la hora de escribir un programa.

Más tarde se crearon lenguajes como C++, Eiffel y Oberon. En los noventas, Java y hace apenas unos años, ya en este milenio, C# (C Sharp), alrededor de los cuales se han establecido los postulados de la teoría orientada-a-objetos, que afirma, entre otras cosas, que la clase (el objeto) es una unidad morfológica (desde el punto de vista sistémico) de todo sistema de software.

Biología Informática

La célula es la unidad fundamental de los organismos vivos, generalmente de tamaño microscópico, capaz de reproducción independiente y formada por un citoplasma y un núcleo rodeados por una membrana.1

Una célula está compuesta por un Núcleo, el organillo más ilustre en la mayoría de células animales y vegetales. En el núcleo, las moléculas de ADN y proteínas están estructuradas en cromosomas normalmente dispuestos en pares iguales. El ADN del interior de cada cromosoma es una molécula indivisible larga y arrollada que contiene cadenas lineales de genes. Éstos encierran a su vez instrucciones codificadas para la construcción de las moléculas de proteínas y ARN necesarias para producir una copia funcional de la célula, ¡el mismísimo milagro de la vida!

Los otros componentes de la célula son el Citoplasma y el Citosol. El primero comprende todo el volumen de la célula, salvo el núcleo. Engloba numerosas estructuras especializadas y orgánulos. El otro es la solución acuosa concentrada en la que están suspendidos los orgánulos.

Les estoy contando todo esto precisamente porque una analogía muy útil para una célula (biológica) es un objeto (informático). Los objetos tienen instrucciones codificadas dentro de ellos llamadas métodos (o procedimientos o funciones). Los programas en los objetos son análogos a la programación genética en el DNA dentro de las células. El DNA se subdivide en unidades funcionales llamadas genes; estas unidades corresponden a los atributos (o variables) en el objeto. Un objeto también tiene un metabolismo: consume memoria de acceso aleatorio (léase RAM) o hasta de sólo lectura (ROM).

Tanto los programas en las células como los métodos en los objetos pueden ser 1) copiados y 2) ejecutados. Algunas de las proteínas creadas cuando un programa genético se ejecuta corresponden a los resultados o salidas de los procedimientos y funciones del objeto. Pero otras proteínas son más análogas a los componentes de la clase o a las interfaces de la misma con el entorno. Por supuesto, los objetos no crean sus propios métodos o sus interfaces, lo hacen los programadores; la analogía no es perfecta.

De hecho, nada en los objetos es análogo a la reproducción de una célula. Una célula puede crear una copia completa de sí misma; esta célula contiene las instrucciones completas (programas) y la maquinaria celular (hardware) necesarias para reproducirse por sí misma. Un objeto no puede crear una copia de sí mismo… ¡hasta ahora! Le hacen falta los mecanismos necesarios (pero puede ser capaz de reproducir su conjunto de instrucciones respondiendo a un mensaje de su entorno, por ejemplo.) Un objeto que pueda reproducirse por sí mismo sería mejor descrito como un robot-software auto-reproductor. Tal cosa es concebible, pero no existe hoy.

Una criatura multiceldada es como un diagrama de clases. Se requiere de una arquitectura orientada a objetos, paralela, a gran escala para operar criaturas multiceldadas tales como mamíferos con billones o trillones de celdas, todas trabajando en armonía, cada una haciendo su tarea. El sistema nervioso y el sistema hormonal son dos importantes sistemas en red usados por los mamíferos.

Cambiar la forma en que un objeto trabaja requiere de novedosos y más avanzados algoritmos. Algunas veces un programador puede simplemente codificar un conjunto nuevo de órdenes de Inteligencia Artificial: el objeto reconoce el nuevo método o procedimiento, acepta su nuevo código y lo usa. Otras veces, reprogramar un objeto es más traumático. Las nuevas funciones pueden tener “errores”; puede no ser compatible desde el punto de vista de la lógica con el comportamiento existente en el objeto; se pueden llegar a necesitar parches adicionales; se puede introducir un virus de computador; o puede causar que el todo el objeto, y con ello el sistema del que hace parte, colapse sin explicación.

La evolución biológica sucede cuando las células son reprogramadas. De una forma u otra, los nuevos programas genéticos son instalados y activados. ¿Cómo se consigue instalar y activar nuevo software genético? ¿Y de dónde viene? Estas son algunas de las preguntas que la Cósmica Ancestral22 intenta responder.

Mientras encontramos estas y otras respuestas fundamentales, volvamos a nuestro hemisferio.

Conceptos Fundamentales

Una suite de conceptos, unos básicos o fundamentales, otros más avanzados, desde el punto de vista de la semántica, son necesarios para entender la teoría de la orientación a objetos.

Definición 22: Clase. Una descripción de un conjunto de objetos que comparten los mismos atributos, operaciones, métodos, relaciones y semántica. Una clase puede usar un conjunto de interfaces para especificar colecciones de operaciones que ella proporciona a su entorno.5

Una clase puede ser vista como una plantilla o molde, un prototipo funcional, a partir del cual se pueden crear o instanciar un conjunto de elementos con las mismas características y comportamientos llamados Objetos. La clase es la unidad básica, el equivalente de la célula en el ser humano, que forma todo sistema de software. Una clase representa un grupo de datos y la manipulación de estos datos. Como piezas de datos, las clases pueden ser manipuladas. Sin embargo, como procedimientos, las clases también describen la manipulación. La información se manipula enviando un mensaje a la clase que representa la información.

Tiene sentido: puesto que un sistema de software es una herramienta para manipular información, las clases son esos diminutos corpúsculos, invisibles, que forman un sistema de software. Para los propósitos de este artículo, estoy usando una definición muy amplia de información.

Definición 23: Información. Una representación o descripción de algo.6 Hay muchos tipos de información que describen diferentes cosas en formas diversas. Uno de los grandes sucesos en la computación fue el hecho de que la información podía, entre otras cosas, describir la manipulación de la información. Este tipo de información es llamada software.

En el mundo real, los seres humanos no concebimos una estructura (una cosa) sin pensar al mismo tiempo en el comportamiento que presenta o puede presentar esa estructura (esa cosa). Esta fue la premisa que alimentó la investigación del LRG en XPARC. Y debería ser el punto de partida en el desarrollo de cualquier producto de software. Es el orden natural de las cosas: las clases, al menos las primeras que aparecen de la mano de los usuarios, provienen precisamente del mundo real que, en términos del ciclo de vida o del proceso de desarrollo, constituyen lo que se llama el modelo de dominio. Alrededor de estas clases aparecen otras, durante el análisis y el diseño del software, que apoyan la operación “automatizada” de las primeras.

Ejemplos de clases típicas son: Proveedor, Cliente, Factura, Producto, Contrato, Pago (vemos una clase puede representar Personas, Cosas o Artefactos y Operaciones transaccionales). Cada una de estas clases tiene un conjunto de atributos o valores o características y un conjunto de métodos o procedimientos. En el caso de Contrato, por ejemplo, los atributos clave serían Número del Contrato, Fecha de Contrato, Valor del Contrato, Objeto del Contrato, Contratante, Contratista, Modalidad del Contrato, entre otros; algunas operaciones que se pueden hacer con el contrato son: Abrir Contrato, Cancelar Contrato, Suspender Contrato, Cerrar Contrato, Extender Contrato, Pagar Contrato. Son operaciones inherentes al negocio, del dominio dentro del cual una empresa rige su negocio.

Definición 24: Modelo de Dominio. Un modelo de dominio es un modelo del dominio dentro del cual una Empresa conduce su negocio. El Modelo de Dominio para una Empresa debería ser el mismo que para cualquier otra Empresa que conduzca el negocio en el mismo dominio. Cuando bajamos a niveles más detallados, personas distintas tienen diferentes ideas acerca de lo que constituye un Modelo de Dominio.

Un modelo de dominio puede verse como un modelo conceptual de un sistema el cual describe las distintas entidades involucradas en ese sistema y sus relaciones. El modelo de dominio es creado para documentar los conceptos clave y el vocabulario del sistema. El modelo muestra las relaciones entre las entidades principales dentro del sistema y usualmente identifica sus métodos y atributos importantes. Esto significa que el modelo proporciona una vista estructural del sistema el cual es complementado por las vistas dinámicas en el modelo de casos de uso. Un beneficio importante de un modelo de dominio es describir y restringir el alcance del sistema.

El modelo de dominio puede ser usado a bajo nivel en el ciclo de vida del desarrollo del software desde que la semántica del mismo puede ser usada en el código fuente. Las entidades se convierten en clases, mientras que los métodos y atributos pueden llevarse directamente al código fuente; los mismos nombres típicamente aparecen en el código fuente.

El modelo de dominio es uno de los artefactos centrales en las más importantes metodologías o procesos de desarrollo de software existentes. En UML, un diagrama de clases se usa para representar el modelo de dominio.

Todas las clases mencionadas en el apartado anterior son clases típicas que conforman un modelo de dominio. Para entender mejor, citemos algunas clases que no harían parte de ningún modelo de dominio: la Clase de Acceso a Datos, El Manejador de Errores (llamado también Controlador de Errores), la clase Usuario (en un contexto de seguridad), El Controlador de Transacciones, la clase de Auditoria, entre muchas otras que hacen parte del diseño de la solución y están fuera del dominio del problema.

Definición 25: Objeto. Una entidad con un límite bien definido e identidad que encapsula un estado y un comportamiento. El estado se representa por los atributos y las relaciones, mientras que el comportamiento es representado por las operaciones, métodos y las máquinas de estado. Un objeto es una instancia de una clase. 7

Un objeto es una entidad individual que satisface la descripción de una clase o tipo.

Definición 26: Instancia. Es una manifestación concreta de una abstracción a la cual un conjunto de operaciones puede aplicarse y que tiene un estado que almacena los efectos de las operaciones.8 Instancia y Objeto son básicamente sinónimos.

Una clase puede derivar muchas instancias. Dicho de otra manera, en un momento determinado se pueden crear una o más instancias u objetos de una clase. El número de instancias creadas a partir de una clase está limitado únicamente por la cantidad de memoria disponible en el computador donde se esté ejecutando la aplicación que usa la clase.

Cada objeto se diferencia del otro por los valores de sus atributos. Este conjunto de valores forman el Estado del Objeto, único para cada instancia. Y observen que estoy usando los términos Instancia y Objeto indistintamente para referirme a lo mismo.

Definición 27: Operación. Un servicio que puede ser requerido desde un objeto para afectar su comportamiento. Una operación tiene una firma, que puede restringir los parámetros reales que son posibles. En otras palabras, una operación es una abstracción de algo que se puede hacer a un objeto que es compartido por todas las instancias de la clase.9

Una clase puede tener cualquier número de operaciones o ninguna operación. Por ejemplo, en una librería de ventanas como la que se encuentra en el paquete awt de Java, todos los objetos de la clase Rectangle pueden moverse, cambiar de tamaño o ser consultados sobre el valor de sus propiedades.

Muchas veces (pero no siempre), invocar una operación sobre un objeto cambia los datos o estado del objeto. En la Orientación a Objetos, una operación recibe comúnmente el nombre de método y en los lenguajes de programación se pueden clasificar en procedimientos y funciones.

En general las clases incluyen algunas operaciones comunes para Crear (create o new) o Destruir (Destroy o Release o Dispose) una instancia.

Además, las operaciones pueden ser públicas, es decir, visibles desde el exterior de la clase, o privadas, las que están disponibles solamente para los objetos de la clase.

Un término bastante relacionado con Operación es Mensaje.

Definición 28: Mensaje. Una especificación de una comunicación entre objetos que transmite información con la expectativa de iniciar una actividad; el recibo (la recepción) de una instancia de un mensaje es considerada normalmente una instancia de un evento. 10

Los mensajes se establecen vía el conjunto de operaciones públicas de una clase.

Definición 29: Protocolo. El conjunto de mensajes a los que un objeto puede responder. 11

Como programadores, lo primero que debemos preguntarnos es cuál será el protocolo de la clase a programar y cuál es el protocolo de la(s) clase(s) relacionadas. Son estos protocolos los que permiten poner en movimiento un proceso (automático), los que permiten el flujo de información y mantener en ejecución por tiempo indefinido un sistema de software.

Definición 30: Interfaz. Una colección de operaciones que son usadas para especificar un servicio de una clase o de un componente.12

La Interfaz es el mecanismo que usan los lenguajes de programación para implementar un Protocolo.

Definición 31: Atributo. Un atributo definido por una clase representa una propiedad nombrada de la clase o sus objetos. Un atributo tiene un tipo que define el tipo de sus instancias. 13

El conjunto de atributos de una clase constituye su Estructura y los valores de esos atributos en un instante dado representan el Estado del objeto.

Normalmente los atributos o propiedades de una clase están ocultos al mundo exterior, es decir, al resto de clases o de entidades que forman un sistema. Solamente se puede acceder a los valores de tales propiedades a través de métodos de la clase dispuestos para tal fin. Algunos de estos métodos son especializados y únicamente son capaces de asignar o “recordar” (leer) el valor de una propiedad, otros lo hacen mediante operaciones o transacciones más o menos complejas. Hay atributos que sólo pueden ser vistos por las operaciones de la clase, otros pueden ser vistos además por las clases “hijas” en una jerarquía de clases (ver Herencia).

Sin embargo, la mayoría de los lenguajes de programación implementan mecanismos para que desde el exterior de un objeto, o sea, desde otros objetos se pueda acceder directamente a los valores de las propiedades de una clase. Esto se hace para mejorar el desempeño de las aplicaciones en varios sentidos, sin embargo, deberíamos evitar el uso de estos mecanismos tanto como sea posible.

Definición 32: Relación. Es una conexión semántica entre elementos de un modelo. Ejemplos de relaciones incluyen asociaciones y generalizaciones.14

Las relaciones son los elementos encargados de darle vida a un modelo. Por sí solos, los demás componentes de un modelo como las clases no son capaces de hacer mucho (tal como muchos organismos unicelulares que actúan simplemente como parásitos) y es a través de relaciones como la Asociación, la Composición, la Agregación y la Generalización que se pone un modelo en ejecución.

Como regla general, todas las clases del dominio deberían estar relacionadas entre sí, sin embargo, el número de relaciones entre una clase y otras del modelo debería mantenerse al mínimo, lo que permitirá a su vez una baja dependencia entre el subsistema a los que pertenece una clase y los subsistemas a los que pertenecen las clases relacionadas. Esto se llama el Principio o Patrón de Bajo Acoplamiento.

Definición 33: Asociación. Una asociación es una relación estructural que especifica que objetos de una cosa están conectados con objetos de otra. Dada una asociación que conecta dos clases, podemos relacionar objetos de una clase con objetos de la otra clase. Es legal tener ambos extremos de una asociación sobre la misma clase, de manera circular. Esto significa que, dado un objeto de la clase, podemos enlazar a otros objetos de la misma clase. Una asociación que conecta exactamente dos clases se llama una asociación binaria. Aunque no es común, podemos tener asociaciones que conectan más de dos clases; éstas son llamadas asociaciones n-arias. Usamos asociaciones cuando queremos mostrar relaciones estructurales.15

En principio, durante las etapas de Análisis, todas las clases del dominio deberían estar “asociadas” entre sí. Más adelante, hacia el final del análisis y en el diseño, algunas asociaciones se pueden convertir en otro tipo de relaciones y las que permanecen como asociaciones se deben cualificar.

La cualificación de una relación como la asociación se logra mediante la cardinalización de ambos extremos de la relación, lo mismo que con el nombramiento, en ambos sentidos, de la misma. Por ejemplo, en un sistema típico tanto la entidad Cliente (de una Compañía) como la entidad Proveedor (de la misma Compañía) tienen alguna forma de relación (de asociación) con la entidad Producto. Pero a todas luces se evidencia la diferencia existente en la relación entre Proveedor y Producto que entre Cliente y Producto.

El Proveedor “vende” o “provee” de productos a la compañía, mientras que el Cliente “compra” o es “surtido” de productos por la compañía. En este contexto, “proveer”, “vender”, “comprar” y “surtir” son nombres representativos de asociaciones.

A su vez, es probable que un Proveedor suministre uno o más productos a la compañía (y hasta puede suceder, por políticas de la compañía –regla del negocio-, que quizás haya un máximo número de productos que un proveedor pueda suministrar, por ejemplo, 5). También puede ocurrir que para ser considerado como tal, un Cliente de la compañía deba comprar o adquirir mínimo 2 productos y máximo 12. Estos rangos (uno o más productos, 1 a 5, 2 a 12) hacen parte de la cardinalidad de las asociaciones.

Definición 34: Generalización. Es una relación entre un tipo general de una cosa (llamada la superclase o padre) y un tipo más específico de cosa (llamada la subclase o hija). Algunas veces, la generalización es llamada una relación “es-un-tipo-de”: una cosa (como la clase Baywindow) es-un-tipo-de una cosa más general (por ejemplo, la clase Ventana). Un objeto de la clase hija puede ser usado para una variable o parámetro tipado por el padre, pero no a la inversa. En otras palabras, la generalización significa que la hija es sustituible para una declaración del padre. Una hija hereda las propiedades de sus padres, especialmente sus atributos y operaciones. Muchas veces pero no siempre la hija tiene atributos y operaciones en adición a los encontrados en sus padres. Una implementación de una operación en una hija anula una implementación de la misma operación del padre; esto se conoce como polimorfismo. Para ser la misma, dos operaciones deben tener la misma firma (mismo nombre y parámetros). Use generalizaciones cuando quiera mostrar las relaciones padre/hija.16

La generalización es una relación taxonómica entre un elemento más general y un elemento más específico. El elemento más específico es completamente con el elemento más general y contiene información adicional. Una instancia del elemento más específico puede usarse donde el elemento más general es permitido.

Definición 35: Herencia. Es el mecanismo que hace posible la generalización; un mecanismo para crear descripciones completas de clases a partir de segmentos de clases individuales.17

En Orientación-a-Objetos, dada una clase, con unas características y un comportamiento bien definidos, se puede crear una jerarquía de clases, en donde cada clase de la jerarquía “hereda” los atributos y las operaciones de todos sus ancestros. El elemento hereditario además puede tener características y comportamiento propios o adicionales a los de los demás miembros de la estructura taxonómica a la que pertenece.

La herencia aparece cuando tipificamos o clasificamos elementos de un modelo, cuando decimos que este elemento “es-una-clase-de” o “es-un-tipo-de”. Por ejemplo un (Animal) Mamífero es una clase de Animal, un Automóvil es un tipo de Transporte Terrestre, un Vendedor es una clase de Persona.

Definición 36: Agregación. Una asociación plana entre dos clases representa una relación estructural entre pares, lo que significa que ambas clases están conceptualmente al mismo nivel, ninguna es más importante que la otra. Algunas veces queremos modelar una relación “todo/parte” en la que una clase representa una cosa más grande (el “todo”), que consiste de cosas más pequeñas (las “partes”). Este tipo de relación se llama agregación, que representa una relación “tiene-un” que significa que un objeto del todo tiene objetos de la parte. La agregación es realmente una clase especial de asociación.18 Una de las grandes diferencias de la Agregación con la Asociación es que las instancias no pueden tener relaciones de agregación cíclicas, es decir, una parte no puede contener al todo.

La agregación se convierte en un concepto simple con alguna semántica moderadamente profunda. La agregación simple es enteramente conceptual y no hace nada más que distinguir un “todo” de una “parte”. La agregación simple no cambia el significado de la navegación a través de la asociación entre el todo y sus partes, ni enlace los ciclos de vida del todo y sus partes.

La multiplicidad de la parte agregada no puede ser mayor a 1, esto quiere decir que no es compartida.

Definición 37: Composición. Hay una variación de la agregación simple, la composición, que adiciona cierta semántica importante. La composición es una forma de agregación con propiedad fuerte y ciclos de vida coincidentes como parte del todo. Partes con multiplicidad no fija pueden ser creadas después del compuesto mismo, pero una vez creadas viven o mueren con ella. Tales partes también pueden ser explícitamente removidas antes de la muerte del compuesto.19 A la Composición también se le conoce como Agregación Compuesta.

Esto significa que, en una agregación compuesta, un objeto puede ser una parte de sólo un compuesto a la vez. Por ejemplo, en un sistema de Ventanas, un Marco pertenece a exactamente una Ventana. Esto contrasta con una agregación simple en la que una parte puede ser compartida por varias partes. Por ejemplo, en el modelo de una casa, una Pared puede ser una parte de uno o más objetos Cuarto.

Además, en una agregación compuesta el todo es responsable por la disposición de sus partes, lo que significa que el compuesto debe manejar la creación y destrucción de sus partes. Por ejemplo, cuando creamos un Marco en un sistema de ventanas, debemos adicionarlo a una Ventana. Similarmente, cuando destruimos una Ventana, el objeto Ventana debe a su vez destruir sus partes Marco.

El control que mantiene el “todo” con la “parte” puede ser directo o transitivo, o sea, el “todo” puede tener la responsabilidad directa de crear o destruir la “parte” o puede aceptar una parte previamente creada y más tarde pasarla a algún otro “todo” que asuma la responsabilidad por esa “parte”.

Un objeto puede ser parte de solamente un compuesto a la vez. Si el compuesto es destruido, este debe destruir todas sus partes o pasar la responsabilidad de ellos a algún otro objeto. Un objeto compuesto puede ser diseñado con el conocimiento de que ningún otro objeto podrá destruir sus partes.

Un ejemplo típico de una composición es el del Automóvil: las puertas, la carrocería, las llantas y el motor, por sí solos pueden no tener ninguna utilidad (funcionalidad), pero compuestos, bien podríamos tener un (objeto) buen automóvil que nos presta una mayor utilidad (funcionalidad), seguramente mayor que la suma de sus partes.

Definición 38: Polimorfismo. Generalmente, la habilidad aparece en muchas formas. En programación orientada-a-objetos, el polimorfismo se refiere a la habilidad de un lenguaje de programación de procesar objetos de manera diferente dependiendo de su tipo de dato o clase. Más específicamente, es la habilidad de redefinir métodos para clases derivadas.20 Por ejemplo, dada una clase base Figura_Geometrica, el polimorfismo habilita al programador para definir métodos CalcularArea diferentes para cualquier número de clases derivadas, tales como círculos, rectángulos y triángulos. Sin importar de qué forma es un objeto, aplicarle el método CalcularArea retornará los resultados correctos. El polimorfismo es considerado un requisito de cualquier lenguaje de programación orientado-a-objetos (OOPL).

En otras palabras, dada una jerarquía de objetos, cada objeto implementa su(s) comportamiento(s) de acuerdo a sus características. La operación para calcular el área de un triángulo (Base X Altura / 2) es diferente de la operación para calcular el área de un círculo (π X Radio2) porque evidentemente tienen atributos distintos como bien sabemos.

Definición 39: Abstracción. Es un mecanismo y práctica para reducir y factorizar los detalles de tal manera que podamos enfocarnos en unos pocos conceptos al tiempo.21

El concepto se da por analogía con la abstracción matemática. La técnica matemática de abstracción comienza con definiciones matemáticas; esto tiene el efecto afortunado de afinar algunos de los aspectos filosóficos molestos de abstracción. Por ejemplo, tanto en computación como en matemáticas, los números son conceptos en los lenguajes de programación, tal como se encuentran en las matemáticas. Los detalles de implementación dependen del hardware y del software, pero esto no es una restricción porque el concepto computacional de número todavía está basado en el concepto matemático.

La abstracción puede aplicarse tanto al control del proceso como a los datos manipulados por el proceso. La abstracción de control es la abstracción de acciones mientras que la abstracción de datos aplica a las estructuras. Por ejemplo, la abstracción de control en programación orientada a objetos tiene que ver con el uso de métodos, interfaces y clases genéricas. La abstracción de datos permite el manejo de datos de maneras significativas. Por ejemplo, es la motivación básica detrás de los tipos de datos. Finalmente, la Programación orientada-a-objetos puede verse como un intento de abstraer tanto el dato como el código.

De Dónde Surgen los Objetos

Parece justo, al menos para mí, terminar esta disertación sobre orientación a objetos con un aspecto del que tengo algún conocimiento: la Gramática, en particular, y el lenguaje, en general. Por supuesto no hablo de C#, Java o C++, algunos de los lenguajes de programación más ampliamente usados hoy, estoy hablando del idioma Español.

Luego de tener un manifiesto con los requisitos del sistema (y por sistema también quiero decir un módulo, un subsistema, un proceso, un modelo), expuestos en distintos artefactos como un documento de visión, un glosario, una descripción detallada de esos requisitos, un conjunto finito de casos de uso (hoy se llaman casos de uso, Jacobson 1994, ayer se llamaban escenarios, Rumbaugh 1991), entonces procedemos a realizar un análisis sintáctico, pero no de esos que hacen los compiladores, no. Estoy hablando de una exploración minuciosa de todas y cada una de las frases del manifiesto y hacer una tabla con los sustantivos, los verbos, los adjetivos, los adverbios. Si de pronto hemos olvidado lo que es un Predicado o lo que es un Adverbio de Lugar, entonces hay que volver a sacar el libro Español y Literatura de nuestra queridísima maestra Lucila González de Chávez y repasar algunos detalles sobre el tema.

Los sustantivos son clases o atributos potenciales (en este período mesozoico del proceso todavía no somos capaces de acertar en el primer intento sobre que elemento de nuestras fuentes documentarias es que elemento de nuestro modelo objetual). Entre tanto, los verbos son métodos potenciales (incluso, podrán llegar a ser procedimientos almacenados o triggers).

¿Y los adjetivos y los adverbios dónde se quedan? Bueno, dice mi Gazafatonario y doña Lucila González que un adjetivo califica al sustantivo (hay muchas clases de adjetivos), le da un valor, esa es la clave: si finalmente nuestro sustantivo es una propiedad, el adjetivo posiblemente sea su valor predeterminado, mientras que si es una clase, el calificativo será una instancia. Por su parte, el adverbio califica al verbo (¿recuerdan? Adverbios de modo, de lugar, de tiempo, demostrativos, relativos, interrogativos, de cantidad e intensidad), una teoría lingüística interesante y profunda que si la conocemos bien nos ayudará a encontrar cuál es el desempeño que se quiere para el método (adverbio de modo), dónde se ejecuta el método (adverbio de lugar) –quizás nos diga de qué clase es, en qué capa de la arquitectura va, si puede ser un trigger o no y cuándo se ejecuta (adverbio de tiempo), algunos criterios funcionales (adverbios demostrativos, relativos, interrogativos), cuál es la frecuencia de ejecución (adverbios de cantidad e intensidad), y hasta pueden llegar a ser argumentos del método en cuestión.

El tema tiene tanto de ancho como de profundidad y no quiero extender más esta lectura, así que los invito a que revisen la extensa literatura que existe sobre ello.

El Siguiente Paso en la Evolución

Fue por allá a mediados de los años 80 cuando escuché y leí por primera vez sobre la orientación a objetos. El término realmente me pareció interesante pero extraño. En contraste, algunos otros compañeros que todavía no habían tenido su primera vez con computadores encontraron la idea de los sistemas orientados a objeto como algo natural. No es que los programadores novatos puedan crear sistemas complejos en un ambiente orientado a objetos más fácilmente de lo que pueden los programadores experimentados. Ciertamente, crear sistemas complejos envuelve muchas técnicas más familiares al programador experto que al principiante, sin tener en cuenta si se usa o no un entorno orientado a objetos. Pero la idea básica acerca de cómo crear un sistema de software en un estilo orientado a objetos llega de una forma más natural a quienes no tienen una preconceptualización acerca de la naturaleza de sistemas de software. Entender los conceptos que he expuesto fue la clave que condujo mi carrera profesional durante mucho tiempo y que me permitió escribir algunos cientos de miles de líneas de código en diversos lenguajes de programación.

Muchos años después, con el advenimiento de la Internet, me di a la tarea de buscar y conocer en qué andaba el célebre equipo de XPARC que creó la técnica tan acertadamente. Los encontré en www.parc.com y el mundo de la programación no volvió a ser igual para mí.

Los amigos de PARC habían encontrado muchos problemas de programación para los que ni las técnicas de programación procedimental ni orientadas a objeto parecían suficientes para capturar claramente algunas de las decisiones importantes que un programa debía implementar. Ellos observaron que esos problemas forzaban la implementación de muchas decisiones de diseño en el código de una manera dispersa y heterogénea, dando como resultado un código fuente “enmarañado” que es difícil de desarrollar y mantener. Así es que presentaron a la comunidad un análisis del porqué ciertas decisiones de diseño eran difíciles de capturar apropiadamente en el código actual y llamaron a las propiedades a las que esas decisiones apuntaban aspectos. También mostraron que la razón de su captura compleja era que estas decisiones eran transversales a la funcionalidad básica de todo sistema. Con esto en mente, presentaron las bases para una nueva técnica de programación que llamaron programación orientada a aspectos o simplemente aspectos. Esta técnica hace posible escribir programas con precisión que involucren tales aspectos, incluyendo aislamiento apropiado (más allá de la encapsulación de objetos), composición y reusabilidad de código “aspectual”.

En breve, los Aspectos son propiedades para las cuales la implementación no puede ser encapsulada en un procedimiento generalizado. Los Aspectos y los componentes transversales se cruzan entre sí en la implementación de un sistema. Esta técnica soporta una abstracción completa y la composición tanto de componentes como de aspectos. La diferencia clave entre AOP y la OOP (y por extensión con PPO) es que la AOP proporciona lenguajes de componentes y aspectos con diferentes mecanismos de abstracción y composición.23

Los Aspectos son a los Objetos lo que estos fueron a los Procedimientos. Hoy ya existen lenguajes orientados a aspectos como AspectJ (la primera implementación de un lenguaje AOP basado en Java), AspectC++, Aspicere2 y otros basados en C/C++; también existen LOOM.NET, AspectDNG, Compose, Aspect.NET, DotAspect y otros basados en C#/VB.NET y muchas otras docenas de estos lenguajes emergentes, incluyendo WEAVR de Motorola para UML 2.0, una herramienta de desarrollo de software Orientado a Aspectos de naturaleza industrial que soporta weaving de los modelos comportacionales de UML 2.0 como los diagramas de interacción y de actividad. Y es tiempo de un último aserto.

Definición 40: Weaving es el proceso de aplicar Aspectos a los Objetos Destinatarios para crear los nuevos Objetos Resultantes en los especificados Puntos de Cruce. Este proceso puede ocurrir a lo largo del ciclo de vida del Objeto Destinatario:

· Aspectos en Tiempo de Compilación, que necesita un compilador especial.

· Aspectos en Tiempo de Carga, los Aspectos se implementan cuando el Objeto Destinatario es cargado en la máquina virtual.

· Aspectos en Tiempo de Ejecución.

Está ocurriendo tal cual ha ocurrido durante millones de años en la naturaleza, las insuficiencias existentes, los entornos recién descubiertos, recién creados, sólo dan paso a los más fuertes y sólo los más arriesgados sobreviven, así es la biología celular. Así mismo pasa en la TI, las nuevas necesidades exigen nuevas soluciones y estas a su vez requieren de nuevas tecnologías y nuevas técnicas.

En el futuro lejano, luego de la fusión de tres revoluciones científicas que todavía no ocurren, la teoría cuántica nos proveerá de transistores cuánticos microscópicos más pequeños que una neurona, la revolución informática nos facilitaría redes neuronales tan poderosas como las que hoy residen en el cerebro humano, y la revolución biomolecular nos permitiría la capacidad de reemplazar las redes neuronales de nuestro cerebro por tejidos sintetizados, garantizándonos así cierta condición de renovación, seríamos inmortales.

Pero no nos apresuremos, un paso a la vez, “así se ha hecho durante millones de años” 24, así que todo esto será motivo de otra de mis lecturas.

Conclusión

He abordado sucintamente los conceptos que subyacen la técnica de la programación orientada a objetos. Es lo que existió antes del lenguaje de programación, antes del Java y el C#, aún antes del BASIC y el C. Entender estos conceptos nos da una visión que permite reducir la complejidad de grandes sistemas sin poner complicaciones adicionales en la construcción de sistemas pequeños. Ciertamente, como lo pensaron los investigadores en XPARC durante 20 años de estudios, la técnica se acerca a la forma cómo pensamos los seres humanos; sin embargo, todavía el hardware disponible hoy, otros 30 años después, es incapaz de aceptar tales principios. Quizás en el futuro próximo, ayudados por lo que he dado en llamar Biología Informática, podamos tener máquinas casi tan hábiles como nosotros, máquinas que entretejan (como los Aspectos), millones de chips neuronales que se crucen ad-infinitum y sean capaces de pensar y adaptarse a nuevos entornos.

Mientras tanto, la programación orientada a objetos, y con ésta, el análisis y diseño orientados a objeto, la programación orientada a aspectos, la herencia y el polimorfismo, las asociaciones binarias y las abstracciones lógicas, serán las técnicas que reinen en el mundo de las tecnologías informáticas.

Cierre y fin de la emisión.

Referencias

1. Diccionario de la Real Academia de la Lengua Española Edición En Línea. http://buscon.rae.es/draeI/SrvltConsulta?TIPO_BUS=3&LEMA=célula

2. ARPANet fue el nombre original de Internet. ARPA son las siglas en inglés de Advanced Research Projects Agency, que inicialmente conectó cuatro grandes computadores en universidades en el suroeste de los Estados Unidos (UCLA, Stanford Research Institute, UCSB y la Universidad de Utah) por allá en 1.969.

3. Dr. Alan Kay. On The Meaning of “Object-Oriented Programming” (http://www.purl.org/stefan_ram/pub/doc_kay_oop_en)

4. Dr. Alan Kay. The Early History of Smalltalk. http://gagne.homedns.org/~tgagne/contrib/EarlyHistoryST.html

5. IBM. The Rational Unified Process Glossary.

6. Luis Antonio Salazar Caraballo. Sistemas de Software Orientado a Objetos. 2000.

7. IBM. The Rational Unified Process Glossary.

8. IBM. The Rational Unified Process. UML.

9. IBM. The Rational Unified Process Glossary.

10. IBM. The Rational Unified Process. UML.

11. Luis Antonio Salazar Caraballo. Sistemas de Software Orientado a Objetos. 2000.

12. IBM. The Rational Unified Process. UML.

13. IBM. The Rational Unified Process. UML.

14. IBM. The Rational Unified Process. UML.

15. IBM. The Rational Unified Process. UML.

16. IBM. The Rational Unified Process. UML.

17. IBM. The Rational Unified Process. UML.

18. IBM. The Rational Unified Process. UML.

19. IBM. The Rational Unified Process. UML.

20. IBM. The Rational Unified Process. UML.

21. Wikipedia contributors, 'Abstraction (computer science)', Wikipedia, The Free Encyclopedia, 7 November 2007, 04:20 UTC, <http://en.wikipedia.org/w/index.php?title=Abstraction_%28computer_science%29&oldid=169781888> [accessed 21 November 2007].

22. Wikipedia contributors, 'Cosmic ancestry', Wikipedia, The Free Encyclopedia, 26 April 2007, 23:28 UTC, <http://en.wikipedia.org/w/index.php?title=Cosmic_ancestry&oldid=126264933> [accessed 21 November 2007]

23. Kiczales, Lamping, Mendhekar, Maeda, Videira Lopes, Loingtier & Irwin. Aspect-Oriented Programming. 1997.

24. Así le dice Ted a Ellie en Contacto, de Carl Sagan.

Ted: Este ha sido un primer paso. Con el tiempo, daréis otro.

Ellie: Pero otros necesitan ver lo que he visto yo.

Ted: Así se ha hecho durante millones de años. Poco a poco, Ellie. Poco a poco.

(Le besa la frente. Ambos miran al cielo. Cientos de rayos, como cometas, se

aproximan a la nebulosa rojiza. Al chocar con ella, hay como una explosión

blanca. Volvemos a la realidad, con la cápsula cayendo bruscamente al agua…)