Buscar en Gazafatonario IT

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…)

martes, octubre 23, 2007

Lecturas Fundamentales 10

Lectura Fundamental Anterior: “RUP: Fase de Concepción Parte 2”

Lectura # 10: Realización de Casos de Uso: De los Objetos y sus Interacciones

Presentación

¿Es familiar para alguno de ustedes esta imagen?

Figura 1: Meta-Modelo de un proceso de desarrollo de software mal-ejecutado

Este meta-modelo muestra un paradigma muy común en los equipos de desarrollo de software en el que la substancia de los emisores (los Analistas) no se coordina con la idiosincrasia de los receptores (los Programadores y los Probadores). Lo que está sucediendo es que el formato en el que se emite y el formato en el que se recibe (para usar términos reconocibles por nosotros) no son compatibles en el sentido en que unos y otros ven las cosas de distinta forma: mientras los Analistas observamos el universo del problema desde una perspectiva de usuario final, los Programadores lo hacemos con una visión técnica y tecnológica de las cosas. Mientras el Analista habla (escribe) en términos de necesidades, causas raíz, características, requisitos y solicitudes, el Programador espera recibir expresiones orientadas al método (orientado-a-objetos, orientado-a-aspectos o a algún otro similar): clases, tablas, objetos, controles visuales, entre otros.

Esta cacofonía por antonomasia, esta genuina desproporción de los formatos de emisión y recepción que nacen (durante la Concepción del sistema) y evolucionan (a lo largo de la Elaboración y Construcción) de manera asimétrica por la simple causa de que una se apoya en lo biológico (las necesidades y los requisitos vienen de seres humanos) mientras que la otra se soporta en la mecánica y en la electrónica (las tablas, los índices y los objetos necesitan de una máquina para vivir), esta situación en la que la comunicación (entre Analistas y Programadores) se torna en un procedimiento irregular y embrollado, esta disyuntiva es la que me empieza a ocupar a partir de esta lectura fundamental.

Ahora bien, puesto que el análisis y diseño orientado a objetos es ciertamente un proceso dinámico, debo elegir desde que ángulo presentarlo. Como con el mismo proceso de desarrollo de software, mostrar un estado “final” muchas veces da al lector falsas expectativas de estar en lo correcto desde el primer intento, mientras que con un primer acercamiento se puede exhibir un sistema incompleto o peor aún, erróneamente entendido. En este artículo elegí compartir mi trabajo a partir de un enfoque temprano, corriendo el riesgo de darle al lector inexperto algunas falsas concepciones acerca de lo que son el análisis y el diseño orientados a objeto. Es un buen reto, sobre todo porque me da la oportunidad de reducir ese riesgo al mínimo, al punto de hacerlo desaparecer a lo largo de la explicación que tengo planeada en esta exposición; al final de la misma, espero, el Diseñador orientado a objetos habrá entendido las cuestiones básicas y algunas no tan básicas de la realización de casos de uso desde una perspectiva sistémica. Si eso sucede, al menos para un pequeño grupo de lectores, entonces habré cumplido mi misión.

Aquí vamos otra vez.

Sobre el Lenguaje de Modelado Unificado

Definición 19: “El Lenguaje de Modelado Unificado es un lenguaje visual para especificar, construir y documentar los artefactos de los sistemas. UML es un lenguaje de modelado de propósito general que puede ser usado con todos los métodos orientados a objetos y a componentes y puede ser aplicado a todos los dominios de aplicación (por ejemplo, salud, financiero, telecomunicaciones, aeroespacial) y a distintas plataformas de implementación (por ejemplo, J2EE y .NET).” 1

En este contexto, Especificar significa enumerar y construir modelos que son precisos, no ambiguos y completos. UML dirige la especificación de todas las decisiones importantes de análisis, diseño e implementación2. Mientras tanto, Construir quiere decir crear o modificar diagramas y modelos, usualmente basado en la existencia y estado de otros símbolos base o de otros diagramas. Los modelos que se construyen con UML están relacionados con los lenguajes de programación orientados a objetos. UML se usa para hacer Ingeniería Hacía Adelante, esto es, un mapeo directo de un modelo UML con código fuente. UML también se usa para hacer Ingeniería en Reversa, o sea, una reconstrucción de un modelo UML desde una implementación específica, normalmente en un lenguaje OO3. UML además se usa para Documentar la arquitectura de los sistemas, los requisitos, las pruebas y actividades como planeación del proyecto y manejo de la entrega del producto4.

Como cualquier lenguaje, UML tiene una sintaxis y una semántica. La sintaxis de UML está compuesta por un conjunto de construcciones gráficas útiles para especificar diagramas y modelos de sistemas5. Cada uno de estos símbolos tiene un significado de manera independiente, como lo tienen las palabras reservadas Begin, End y While en Pascal o los términos private, void y string en C# (léase C Sharp)6.

La semántica de UML es la que nos dice, por ejemplo, que un Actor solo se puede “comunicar” con el sistema a través de los casos de uso mediante una relación de Asociación, o que un paquete puede estar compuesto de Clases, Casos de Uso, Componentes u otros Paquetes y que existen distintos tipos de diagramas, a manera de modelos, que pueden ser construidos a partir de uno o más símbolos de UML7. De esta manera, podemos construir “instrucciones válidas” en UML como las que ilustro en la figura 2, que resulta ser un Diagrama de Casos de Uso, un espécimen del que hablaré en alguna oportunidad.

Pueden encontrar más de UML en mis Prolegómenos Sobre el Lenguaje de Modelado Unificado (http://gazafatonarioit.blogspot.com/2005/06/prolegmenos-sobre-el-lenguaje-de.html).

El Caso de Estudio (aka, el Ejemplo)

Consideremos el siguiente caso de uso típico ingreso al sistema de reserva de vuelos:

Caso de Uso: Ingresar al Sistema

Actor: Pasajero

Descripción: Este caso de uso permite al Pasajero ingresar al sistema Web de Reservas usando su número de pasajero frecuente y la clave actual. A solicitud del usuario, el caso de uso además muestra los datos detallados del pasajero registrado.

Objetivo: Suministrar al usuario Web del sistema de Reservas una interfaz amigable que le permita acceder rápidamente a las principales opciones del sistema.

Precondiciones

Ninguna

Secuencia Básica:

1. El caso de uso inicia cuando el pasajero decide ingresar al sistema

2. El sistema solicita el código (número) de pasajero frecuente y su respectiva clave

3. El pasajero ingresa su número y clave

4. El sistema busca los datos del pasajero, valida que el número y la clave del mismo coincidan con los registrados previamente.

5. El sistema solicita confirmación para mostrar los datos completos del pasajero

6. El pasajero confirma que quiere ver sus datos

7. El sistema muestra los datos detallados del pasajero

8. El caso de uso termina

Secuencia Alternativa 1

4A. El número de pasajero o la clave no coinciden.

4A1. el sistema muestra el mensaje: “Los datos proporcionados del pasajero no coinciden con los registrados en el sistema. Verifique.”

4A2. El caso de uso continúa en el paso 2.

Poscondiciones

El pasajero puede realizar diversas transacciones en el sistema como Reservar Vuelos, Cancelar Reservas, Cambiar su Clave, Modificar su Perfil, Pagar una Reserva o Cambiar los datos de una reserva.

Requisitos Especiales

Por razones de seguridad, el sistema sólo muestra los cuatro últimos dígitos de la tarjeta de crédito del pasajero.

Por razones de seguridad, el sistema no indica cual de los datos (número o clave) está erróneo.

Advertencia: aunque éste es un caso de uso terminado, es de una situación simulada. Si lo usa en algún proyecto es bajo su propia responsabilidad. Todos los nombres y lugares han sido cambiados para proteger la identidad de los culpables.

Puesto que se trata de un enfoque holista, no puedo continuar sin poner en perspectiva este caso de uso. Hablo de ubicarlo dentro de un sistema, en este caso, de un sistema de reserva de vuelos en el que además se pueda cancelar una reserva, pagar por el vuelo (con tarjeta de crédito, por ejemplo), cambiar la reserva (algunos de sus datos, como la fecha de regreso, por ejemplo), confirmar una reserva, hacer apertura y cierre de vuelos por parte de las aerolíneas y mantener información de los aeropuertos, entre otras funcionalidades. Las cosas así, el diagrama de casos de uso de la figura 2 nos muestra una vista funcional del sistema.

Figura 2: Algunos casos de uso del Sistema de Reserva de Vuelos

Con este conato de modelo en mente, volvamos a nuestro caso de uso.

Interacciones

Las Interacciones son usadas en diversas situaciones: para tener un mejor control de una situación de interacción por parte de un diseñador individual o por un grupo de personas que necesita lograr una interpretación común de la situación. Las interacciones también son usadas durante la fase de diseño más detallada donde la precisa comunicación entre procesos debe ser establecida de acuerdo a protocolos formales. Cuando se ejecutan las pruebas, las secuencias de ocurrencias de eventos del sistema pueden ser descritas como interacciones y comparadas con las de las fases anteriores.8

En UML 2.x hay tres clases de diagramas de Interacción: Diagrama de Secuencia, Diagrama de Comunicación (anteriormente diagrama de Colaboración) y Diagrama de Revisión de Interacciones (nuevo a partir de la versión 2.0 de UML).

Los Diagramas de Comunicación muestran las interacciones a través de una vista arquitectónica de las líneas de vida de los objetos en donde la secuencia de Mensajes es dada vía un esquema de numeración secuencial. Mientras tanto, los Diagramas de Revisión de Interacciones definen Interacciones a través de una variante de los Diagramas de Actividad promoviendo la revisión del flujo de eventos. En estos diagramas de Revisión se omiten las Líneas de Vida y los Mensajes entre ellas.

En lo que sigue, me concentraré en los Diagramas de Secuencia, que se enfocan en el intercambio de mensajes entre las Líneas de Vida de los objetos.

Diagramas de Secuencia, Paso a Paso

Un Diagrama de Secuencia muestra una vista de las entrañas del sistema, cómo se van a suceder las funciones (expuestas normalmente en un caso de uso o en un conjunto de casos de uso) a partir de la activación de un Actor (una persona). En general, un diagrama de secuencia se usa para modelar la lógica del sistema (de uno o más casos de uso del sistema al tiempo, o de parte de un caso de uso). Este tipo de diagrama muestra precisamente el orden temporal en el que ocurren las acciones en un sistema. Estas acciones son especificadas en términos de Mensajes entre los objetos que interactúan en el modelo. Además, son modelados a nivel de objetos en vez de a nivel de clases para permitir escenarios que usan más de una instancia de la misma clase y para trabajar a nivel de hechos (reales), datos de prueba y ejemplos. Y más aún, el diagrama de secuencia muestra una vista dinámica del sistema (o de parte de él), en contraposición a lo que hace por ejemplo el diagrama de clases, que presenta un panorama estático del mismo sistema.

De acuerdo a Ivar Jacobson, la parte más importante del así llamado análisis dinámico es la realización del caso de uso, nombrada así puesto que con ellos hacemos real(idad) el caso uso mediante la demostración de cómo puede ser implementado a través de la colaboración entre objetos. La realización de casos de uso tiene tres pasos esenciales:

1. Ir a través de (caminar por) los casos de uso del sistema simulando los mensajes enviados entre objetos y almacenando los resultados en diagramas de interacción.

2. Agregar operaciones a los objetos que reciben los mensajes.

3. Adicionar clases para representar límites (interfaces del sistema) y controladores (un receptáculo para procesos del negocio complejos o para la creación y recuperación de objetos), cuando sea necesario.

En nuestro ejemplo, el caso de uso inicia cuando el Pasajero decide Ingresar al Sistema. Este es el punto de partida, la activación del proceso. La primera pregunta que tratamos de responder es: ¿mediante qué mecanismo (de interacción) el pasajero le indica al sistema que quiere autenticarse? Esta es una pregunta simple que tiene una respuesta simple: mediante un formulario llamado, coincidentemente, Ingresar al Sistema. Si asumimos que estamos desarrollando una aplicación para Internet, este formulario se encuentra en una página Web (no entraré en el detalle de la plataforma de implementación, del lenguaje de programación o de la base de datos a usar para la producción de este sistema). En este escenario, entonces, el actor le envía un mensaje (interactúa) con un formulario llamado Ingresar al Sistema (que no es más que una instancia –un objeto – de una página Web.

Anotación: estoy usando una definición amplia e indistinta de los términos Instancia, Objeto y Clase. En una futura Lectura Fundamental abordaré el tema específico de la programación orientada a objetos y especificaré los detalles de tales conceptos.

La figura 3 muestra entonces la interacción inicial entre el actor (el pasajero) y el sistema (la página Ingresar al Sistema). El diagrama de la figura muestra dos Líneas de Vida.

Definición 20: Una Línea de Vida representa un participante individual en la Interacción. Cada Línea de Vida se conoce como una entidad interactuante9. Simplificando, una Línea de Vida es una instancia de una clase (si nos encontramos a la altura del análisis del sistema, ésta es realmente una instancia potencial) que muestra su propio ciclo de vida, desde la creación (que puede ser implícita o explícita), pasando por diferentes estados, hasta su destrucción (que también puede ser implícita o explícita).

Definición 21: Un Mensaje define una comunicación específica entre las Líneas de Vida de una Interacción. La comunicación puede ser de diversos tipos: el envío de una señal, la invocación de una operación, la creación o destrucción de una instancia10, entre otras. Con el Mensaje se pueden identificar tanto el Emisor (el objeto que envía el mensaje) como el Receptor (el objeto que recibe el mensaje). Este último es el que finalmente implementará la funcionalidad (las operaciones) que se requiere para que el sistema procese el Mensaje.

En el diagrama, el mensaje es “Ingresar”. El mensaje tiene dos argumentos: Número y Clave del Pasajero.

Por ahora, esta interacción nos resuelve los pasos 1 a 3 del caso, en los que el sistema solicita el número y clave del pasajero y este los ingresa. Lo que sigue es que el sistema busca y valida los datos de ese pasajero en particular.

Puesto que normalmente estaríamos en una fase en la que ya se conoce al menos una arquitectura preliminar o candidata del sistema, como diseñadores seguimos los patrones o las restricciones impuestas por esa arquitectura. En este caso, asumamos que nos enfrentamos a un diseño de varias capas en el que la interfaz de usuario no se comunica por ningún motivo con la base de datos. En este caso, la página Ingresar al Sistema debe transferir la solicitud de acceso a otro elemento del modelo que bien podría ser un objeto, una instancia de un Controlador de Pasajeros, como lo muestra la figura 4.

Figura 3: Diagrama de Secuencia Inicial del Caso de Uso Ingresar al Sistema

Figura 4: Transferencia de la Solicitud de Ingreso al Sistema

Quiero detenerme unos instantes en este asunto de las restricciones impuestas por la arquitectura del software. Resulta que durante parte del proceso de desarrollo, los analistas, diseñadores, programadores y demás miembros del equipo nos encontramos en un proceso creativo, un proceso de descubrimiento constante, desde los objetos del dominio (del negocio) durante el modelado del negocio, pasando por los requisitos (en términos de casos de uso) y las clases y las tablas del sistema, hasta muchas de las líneas de código que escribimos. Eso es lo que hace que nuestra profesión siga siendo un “arte”, poco precisa y hasta llena de dilemas y ambigüedades. Pues bien, resulta que la Arquitectura es uno de esos “artilugios” que tenemos para guiar ese proceso de hallazgo al que nos enfrentamos. La arquitectura define o establece un conjunto de elementos estructurales que se nutren de decisiones de diseño, reglas o patrones que restringen ese diseño y la construcción misma del software.

Ahora bien, si nos ceñimos a las reglas arquitecturales (o arquitectónicas), el número de salidas que encontremos para un caso de uso o para un conjunto de ellos puede ser grande. La solución que estoy exponiendo es la de una transacción “tipo”, un patrón determinístico que se puede usar en la gran mayoría de los escenarios que nos ocupan día a día.

Volvamos al ejemplo. Este recién llegado Controlador de Pasajeros es quien puede comunicarse con algo así como una Relación de Pasajeros, un inventario que conozca los datos de todos los pasajeros registrados en el sistema. Este repertorio, bien podríamos llamarlo Catálogo de Pasajeros y dependiendo del momento por el que atravesemos en el proceso de desarrollo, este elemento bien podría permanecer en la abstracción conceptual de lo que ordinariamente conocemos como catálogo (durante el análisis) o bien podría ser una instancia de una Clase (realmente una Colección) de Pasajeros (más tarde en el diseño), hasta llegar a ser una Tabla de la base de datos (durante la implementación de la solución). Por ahora, sólo será el Catálogo de Pasajeros, simple.

Y es a este catálogo al que el Controlador de Pasajeros le puede indagar por los datos del pasajero que acaba de suscribir la solicitud de acceso, como lo dibujo en la figura 5.

Figura 5: Buscar Pasajero por Número

Sabemos que hay dos alternativas posibles: que el pasajero se encuentre registrado en el catálogo o que no se encuentre registrado. En este diagrama sólo ilustraré la primera. Una vez los datos del pasajero han sido localizados, el Catálogo de Pasajeros puede hacer dos cosas: informar a Control de Pasajeros y crear un nuevo objeto, finalmente, el Pasajero. Este nuevo objeto tiene todos los datos del pasajero y conoce todas las funciones que un pasajero (una persona) puede desempeñar en el sistema. ¡Es un Humanoide Virtual!

En la figura 6 podemos observar el instante preciso en el que se crea la instancia del Pasajero, justo después de que el Control de Pasajeros recibe la notificación de que el pasajero en proceso existe.

Figura 6: Crear la Entidad Pasajero

En esta versión del diagrama de secuencia aparecen dos nuevos tipos de mensaje: el mensaje 4: Existe Pasajero devuelve una confirmación del registro de pasajero al Controlador de Pasajeros; mientras tanto, el mensaje 5: Crear Pasajero crea un nuevo objeto del sistema, Pasajero. Aquí, el título del mensaje, nemotécnico por demás, no es el que advierte de la creación del objeto, es más bien el lugar en el diagrama donde aparece la instancia recién-creada, mucho más abajo de donde inician las demás líneas de vida de esta realización.

Bueno, al parecer ya tenemos las identidades de todos los seres interactuantes que nos permitirán terminar de implementar el caso de uso Ingresar al Sistema o, al menos, uno de sus escenarios. El paso 4 del caso de uso: El sistema busca los datos del pasajero, valida que el número y la clave del mismo coincidan con los registrados previamente, se puede implementar como lo muestra la figura 7.

Figura 7: Diagrama de Secuencia del Caso de Uso Ingresar al Sistema (versión 1 – Beta)

La imagen también muestra los demás pasos de la secuencia básica del caso de uso. Observamos que la Entidad Pasajero se convierte en una fuente de información para el resto de elementos del modelo ya que representa, como establecí antes, un pasajero real.

En esta versión del diagrama también aparece un nuevo tipo de mensaje (8: Validar Clave). Este es un mensaje Reflexivo (o Auto-Mensaje), en el que el origen y el destino del mensaje son el mismo objeto. No confundir con mensaje recursivo, que es un mensaje reflexivo que se ejecuta recursivamente (se llama a sí mismo durante su ejecución).

De otro lado, los mensajes 11 y 12 comunican directamente la interfaz de usuario con la entidad Pasajero. Si volvemos a los patrones arquitectónicos quizás deberíamos evitar este tipo de interacción y pasar siempre a través del Controlador de Pasajeros. Esta es apenas una primerísima versión, bien podrían existir algunas otras antes de lograr una que sea definitoria para el sistema.

De Estereotipos y Otros Menesteres

Un estereotipo es el mecanismo que proporciona UML para que podamos extender las construcciones útiles de diseño. Un estereotipo puede ser visto como un clasificador (o tipificador) de clases o de otros elementos del lenguaje, es decir, adicionan un nuevo nivel al árbol de jerarquías en un modelo. Los estereotipos también sirven para representar objetos (físicos o virtuales) de una manera más cercana a la realidad de los mismos. De esta forma, Página Web (o Página HTML o Página ASP), Formulario Windows, Controlador, Entidad del Dominio, Colección, Tabla y Procedimiento Almacenado son estereotipos válidos que aplican al elemento base Clase de UML, mientras que Reporte, Proceso por Lotes, Ingreso de Datos y Transacción bien podrían ser estereotipos aplicables al elemento base Caso de Uso de UML.

La sintaxis de estos clasificadores es: <<Nombre del Estereotipo>>, como en <<Colección>>.

Figura 8: Diagrama de Secuencia del Caso de Uso Ingresar al Sistema con Estereotipos

Algunos de estos estereotipos (usados en el ejemplo), cuyo uso se ha difundido ampliamente en la comunidad de desarrollo, ya tienen su propia sintaxis, como revelo en la figura 8. Ingresar al Sistema tiene un estereotipo boundary (límite), Control de Pasajeros y Catálogo de Pasajeros tienen un estereotipo control, mientras que Pasajero tiene un estereotipo entity. Cada uno de estos clasificadores tiene también su propia semántica: las clases límite (llamadas así porque tienen el estereotipo boundary) representan interfaces con los usuarios o con otros sistemas; las clases controladoras son las responsables de manejar el flujo o la lógica de un caso de uso y coordina la mayoría de sus acciones; por su parte, las clases entidad simbolizan las unidades de información operadas en el sistema, normalmente son elementos pasivos y persistentes en cuanto muchas veces la información que encapsulan en almacenada en algún tipo de repositorio de datos.

En esta figura, también aparece una Nota de UML, que es el equivalente de un comentario en un lenguaje de programación como C++ o Java. Las notas se pueden asociar a una línea de vida, a un mensaje, a un argumento del mensaje o a cualquier otro elemento sustancial del modelo.

Comentarios Finales

Los diagramas de secuencia pueden ser usados en distintas etapas del ciclo de vida, desde el análisis primitivo de los casos de uso, empleando abstracciones clave del sistema, hasta el diseño detallado, explotando muchos de los recursos del lenguaje de modelado unificado. De esta manera, constituyen un conducto natural entre la especificación de requisitos funcionales (casos de uso) y no funcionales por parte de los Analistas y Arquitectos del software y la implementación y prueba de los mismos por parte de los Programadores y Probadores del sistema.

Que cuántos diagramas son necesarios por caso de uso es una cuestión que dejo a las condiciones particulares de cada proyecto y dentro de este, a cada caso de uso. Primero es importante reconocer que no todos los casos de uso necesitan de un diagrama de secuencia para ser implementados (y en este subconjunto quizás entre el propio caso de uso que usé de ejemplo y que quizás solo sirve para ilustrar los principales conceptos de la realización de casos de uso). El paso a seguir es entonces decidir cuáles son los casos de uso que definen la arquitectura del sistema, es decir, los más complejos o riesgosos desde el punto de vista arquitectónico; de estos, los escenarios que abarquen más elementos del modelo (extensión) y que incluyan muchos mensajes entre ellos o mensajes que impliquen procesos delicados o laboriosos (profundidad), son los mejores candidatos, los más útiles, para diseñar con ellos el sistema a través de diagramas de secuencia. Habitualmente, estos casos de uso son los que se desarrollan durante la fase de Elaboración del proyecto y a menudo requieren de información suplementaria para su diseño: requisitos especiales, arquitectura, restricciones de diseño, longitud y tipos de datos y al final del diseño, restricciones de la plataforma de implementación. Los demás casos de uso, aquellos que son más fáciles o directos de implementar encontrarán, si hicimos bien el trabajo, un camino de ida hacía los elementos (clases, objetos, controles, tablas) que se usaron para realizar los primeros.

Los diagramas de secuencia constituyen así un medio de comunicación efectivo que cura esa fisura, a veces insondable, a veces abierta, que supone el paso de la especificación de requisitos a la programación de los sistemas de cómputo. Ahora bien, lograr comunicar un diagrama, y por extensión un modelo, demanda discernimiento y práctica, pues el diseño (orientado a objetos) de software es por ley un proceso formal y para ejecutarlo debemos adquirir los fundamentos (que rayan en lo estrictamente teórico) para que luego la práctica habitual nos permita perfeccionar la técnica y desarrollar mejores productos en cada nuevo intento.

¡Funciona para mí!

Referencias

1 Object Management Group –OMG. UML Infrastructure Specification, v2.1.1. Page 9.

2,3,4,5,6,7 Salazar Caraballo, Luis A. Prolegómenos Sobre el Lenguaje de Modelado Unificado

8 Object Management Group –OMG. UML Superstructure Specification, v2.1.1. Page 457.

9 Object Management Group –OMG. UML Superstructure Specification, v2.1.1. Page 489.

10 Object Management Group –OMG. UML Superstructure Specification, v2.1.1. Page 491.

Lectura Fundamental Siguiente: “Orientación a Objetos: Un Enfoque Teórico Moderno (Actualizado)”

lunes, junio 25, 2007

Lecturas Fundamentales 9

Lectura Fundamental Anterior: “RUP: Fase de Concepción”

Lectura # 9
RUP: Fase de Concepción, Parte 2


“¿De dónde viene esto? Esta búsqueda, esta necesidad de solventar los misterios de la vida..., cuando las más simples preguntas nunca han sido contestadas.
¿Por qué estamos aquí? ¿Qué es el alma? ¿Por qué soñamos? Puede que sea mucho mejor si dejáramos de buscarlas. Sin investigar, sin anhelar. Esa no es la naturaleza humana. No está en el corazón humano.
¡Ése no es el motivo por el que estamos aquí!”
Héroes (Capítulo 1, “Génesis”)

Según las creencias de algunas tribus primitivas de la India, la Tierra era una enorme bandeja de té que descansaba sobre tres enormes elefantes, los que a su vez estaban sobre la caparazón de una tortuga corpulenta. En otra geografía, los antiguos egipcios mitificaron el cielo como una versión etérea del rio Nilo, a través del cual el dios Ra (el Sol) navegaba de Oriente a Occidente cada día, regresando a su sitio de partida por los abismos subterráneos donde residen los muertos; para ellos, los eclipses eran inducidos por ataques de una serpiente a la embarcación de Ra.

Así comienzan los proyectos de software: con usa serie de afirmaciones que a veces distan mucho de la realidad. Hacer que la Tierra efectivamente sea redonda, que el cielo sea un reflejo fantástico de las cosas en el cerebro humano y que los eclipses realmente se provoquen a medida que la luz procedente de un cuerpo celeste es bloqueada por otro, es una tarea ardua que requiere de tiempo, de foco, de actitud. Es la faena del Analista del Software.

En términos simples, en la Concepción buscamos un acuerdo con los usuarios sobre lo que hará el sistema. Durante esta fase atendemos cuidadosamente cada palabra de los usuarios, indagamos por el problema y el problema detrás del problema, nos movemos precisamente en el espacio del problema y desde ningún punto de vista pensamos en la solución. Bueno, hasta cierto grado. Una vez que hayamos entendido y acordado esa cuestión, resumida con diligencia en el documento de Visión y Alcance y tengamos claridad sobre el impacto, sobre los afectados y sobre lo que podrían ser los beneficios de una posible solución, entonces nos movemos al espacio de ésta, donde consideramos las características mayores del software a producir.
Estas características están en el nivel intermedio entre las necesidades de los usuarios y los requisitos detallados de la solución, de tal manera que constituyen un puente estructural entre las unas y los otros y definen la organización del sistema.

Hacer la transición entre lo que es y lo que será, enfrentarse a la ambiciosa tarea de prever el futuro cercano (¡a veces incierto!) de un proyecto de tecnología informática, con la profundidad y el rigor necesarios para calcar en palabras e imágenes las ideas y los sueños de docenas, quizás de cientos de usuarios, es algo que sólo la perspicacia y la sabiduría del Analista del Sistema es capaz de lograr.

El Analista de Requisitos

Gran parte de la responsabilidad del éxito de la fase de Concepción de un proyecto depende del Ingeniero de Requisitos, Analista del Software o Analista de Requisitos.

Analizar el problema de los usuarios comienza con la búsqueda y concertación de un vocabulario común, un glosario que sirva de referencia para todos los interesados en el proyecto, desde los mismos usuarios, los administradores del proyecto, los diseñadores y arquitectos, los programadores, los probadores y cualquier otra persona que requiera información sobre el proyecto y el producto a construir. En paralelo, el Analista busca actores y casos de uso (el mecanismo último para elicitar, especificar y administrar los requisitos del software), es decir, quién hará qué en el sistema (no puedo pasar por aquí sin permitirme remitirlos a mis cinco primeras Lecturas Fundamentales, donde abordé ampliamente este asunto de los casos de uso). Aquí el orden altera el resultado, por eso resalto que primero debemos conocer a los actores que jugarán un papel en el sistema y que luego ubiquemos sus necesidades como organismos primarios de funcionalidad en el software por desarrollar. Uno de los grandes motivos de fracaso en proyectos de software es que al final se encuentran en ellos funciones o módulos completos que nadie solicitó, que nadie necesitaba; también, funcionalidad equivocada. Eso se debe a que no anticipamos con quien o quienes iba a interactuar nuestro sistema.

El espiral de actividades del Analista se complementa con el desarrollo de la Visión del proyecto, condición sine qua non para terminar la fase de Concepción. Pero durante ese desarrollo, los Analistas nos enfrentamos a demasiadas posibilidades y muchas de nuestras aseveraciones (a manera de especificaciones) pueden vacilar porque reflejan puntos de vista coartados y hasta extravagantes de una sola persona o de muchas personas que no se ponen de acuerdo entre ellas. Es labor nuestra encontrar a los individuos adecuados, a los representantes apropiados de los usuarios, ojalá con distintos puntos de vista, conocimiento y experiencia, y entrevistarlos para así poder delinear un marco conceptual y temporal en el que esa Visión se lleve a cabo antes de terminar con el presupuesto del proyecto.

Los Analistas pasamos (o deberíamos pasar) de transeúntes pasivos en materia del conocimiento del negocio que nos ocupa a ser coreógrafos activos del proceso previamente expuesto por los usuarios. En un sentido limitado esto quiere decir que primero debemos escuchar. Un Analista que hable mucho en las primeras de cambio con los usuarios corre el riesgo de caer en el conductivismo, o sea, llevar al usuario por donde cree que debería ir, cuando en realidad debe ser él (o ella) quien conduzca su propio destino. Si ya tenemos experiencia en el negocio debemos incluso estar más atentos porque entonces caemos en el síndrome de la copa medio llena, cuando en realidad está medio vacía; esto es, el conocimiento previo evita que escuchemos como ávidos observadores las recién descubiertas necesidades de nuestro interlocutor.

Después, cuando haya suficientes exposiciones de los usuarios, finalmente empezaremos a descodificar sus palabras, sus ideas, sus verdades, mediante un proceso de ingeniería que las convierta en expresiones que se puedan ejecutar en un computador, que sean factibles de automatizar. Eso significa entonces que nos hemos convertido en conocedores de ese negocio (o de esa parte específica del negocio), con lo que bien podríamos contribuir al mejoramiento del mismo poniendo de manifiesto las tareas repetitivas, las posibles ambigüedades, las actividades imposibles y las faltantes en el proceso de la organización para la cual desarrollamos el sistema. Eso simboliza ser “coreógrafos activos.”

Al definir la visión, es fundamental comprender el marco temporal que tenemos para hacerla realidad. Nos enfrentaremos a diferentes tecnologías, condiciones y personas. Es importante que quede claro qué hará el producto de software, qué no hará y con qué se hará, lo mismo que los riesgos preexistentes.

En la parte final de la Concepción, aceleramos el proceso y disponemos las estrategias y las herramientas para la próxima fase: Elaboración. Nuestro trabajo tendrá grandes repercusiones sobre el resto del proyecto y de las personas involucradas en el. Entrarán el Arquitecto y el Diseñador, lo mismo que el Programador y el Probador, se crearán las clases y los componentes, se integrarán las partes y finalmente se ensamblará un producto que se pondrá a disposición del usuario que lo concibió.

Pero todo comienza aquí, en la Concepción; en consecuencia, el futuro del proyecto está fijado por la mayor disposición, el mayor y mejor esfuerzo y de la calidad del tiempo y del proceso que usemos en esta fase los Analistas del Software.

De Artefactos y Otros Menesteres Durante la Concepción

El resultado del proceso siempre debe documentarse para que quede una prueba fehaciente y toda la fundamentación de lo que será. RUP proporciona algunas herramientas a manera de plantillas, agrupadas en Dominios de Productos de Trabajo, relacionadas unos con otros sobre la base de recursos, temporalidad o interrelación entre ellos, para que podamos concluir nuestro trabajo. En el caso del subdominio de los Requisitos, encontramos:

La Visión y el Alcance. Este artefacto define la vista de los interesados sobre el producto a ser desarrollado, especificado en términos de las necesidades clave de esos interesados y de las características del software. Contiene un perfil o resumen de los requisitos centrales visionados (el corazón o núcleo del sistema) y de esta forma suministra la base contractual para los requisitos técnicos más detallados. En breve, el documento de Visión captura la esencia de la solución imaginada en forma de requisitos de alto nivel y restricciones de diseño que dan al lector una visión del sistema a ser desarrollado desde una perspectiva de requisitos comportacionales. Además, facilita una entrada al proceso de aprobación del proyecto y está, de esta forma, íntimamente relacionado con el Caso del Negocio (del que hablaré en otra oportunidad). El documento de Visión comunica también el “por qué y qué” fundamental del proyecto y es un indicador contra el cual todas las decisiones futuras deberían ser validadas. Otro nombre usado para este artefacto es el Documento de Requisitos del Producto.

En general, este documento está escrito usando un léxico del dominio de los usuarios líderes y finales del sistema y son ellos quienes en última instancia establecen la completitud y la exactitud del artefacto.

El responsable directo, el hacedor de este documento es el Analista del Software.

La Especificación de Requisitos del Software. Por su parte, este artefacto captura los requisitos del software para todo el sistema o para una porción de el. Se enfoca en la recolección y organización de todos los requisitos alrededor del proyecto, tanto funcionales (lo que hace el sistema) como los no funcionales (aquellos aspectos de usabilidad, confiabilidad, desempeño, escalabilidad y restricciones de diseño, implementación y despliegue del software que afectan el producto). Cuando no se usa la técnica de los casos de uso, es en este documento donde consignamos el semblante funcional del sistema tal cual será implementado posteriormente. Si usamos casos de uso, en cambio, dejamos aquí el detalle de aquellos requisitos transversales y reusables del software, aquellos que se usan en distintos ámbitos del producto. En cualquier caso, los requisitos no funcionales encuentran aquí su repositorio absoluto, aunque en ocasiones estos requisitos son expuestos en un Documento de Especificaciones Suplementarias, que también puede incluir requisitos legales y regulatorios, lo mismo que el uso estándares de distinto tipo.

Como antes, el garante inmediato, el productor de este documento es el Analista del Software.

Sin embargo, muchas personas en el equipo del proyecto usan la Especificación de Requisitos del Software:

  • Los diseñadores lo usan como referencia al definir responsabilidades, operaciones y atributos en las clases y cuando ajustan las clases al entorno de implementación.
  • Los programadores referencian el documento buscando insumos para la implementación de clases.
  • El gerente del proyecto lo usa para planear las iteraciones.
  • Los probadores lo usan para definir las pruebas que serán requeridas.
La Especificación del Caso de Uso. No me extenderé en este apartado. Las cinco Lecturas Fundamentales iníciales describen ampliamente esto del Caso de Uso. Habrá más, pronto.

Algunos otros artefactos importantes durante la Concepción y el resto del proyecto, que bien podrían hacer parte de uno de los anteriores o simplemente poseer su propio repositorio, son:
El Glosario, que define términos importantes usados en el proyecto; constituye el carácter léxico-gráfico del proyecto y del producto. Los Atributos de los Requisitos, que describe los atributos de y dependencias (trazabilidad) entre los requisitos, importantes a la hora de administrar los cambios desde la perspectiva de los requisitos. El Plan de Manejo de Requisitos, que describe los artefactos de requisitos usados en el proyecto, los tipos de requisitos y sus atributos respectivos, especificando la información a recolectar y los mecanismos de control a ser usados para medir, reportar y controlar los cambios a los requisitos del producto.

Por último, pero no menos importante, está el Modelo de Casos de Uso, que sirve como un medio de comunicación y como un contrato entre el usuario líder, los usuarios finales y los desarrolladores (y estoy usando el término desarrolladores en un sentido amplio con el que denoto realmente a todos los miembros del equipo del proyecto) sobre la funcionalidad del sistema. El modelo de casos de uso permite que los usuarios validen que el sistema será lo que ellos esperan y que los desarrolladores construyan lo que se espera del producto. Este modelo está compuesto de casos de uso y de actores y de las relaciones entre ellos. Por supuesto, va más allá de un simple diagrama.

Y ya desde la Lectura Fundamental 7 he mencionado artefactos como la Lista de Riesgos, el Plan de Desarrollo de Software (que incluye como mínimo el Plan Maestro de Iteraciones y la Agenda del proyecto) y el Plan de Pruebas cuya responsabilidad recae más sobre el Gerente del Proyecto u otros integrantes del equipo de desarrollo.

Quiero aclarar que el hecho de que no haga el mismo énfasis en estos últimos artefactos que en los primeros no quiere decir que estos sean menos relevantes que aquellos. Es una mera cuestión de espacio y de tiempo. Quizás en otra ocasión, en otra Lectura, aborde con más detalle algunos de estos documentos. Lo que sí es importante tener en cuenta es que la elaboración de uno o más de estos documentos (de todos los que he expuesto) depende del tipo de proyecto: si el proyecto es grande, requiere de más rigor documental y de más contratos y puesto que más personas estarán interesadas, la necesidad de usar cada artefacto por separado es mayor. En proyectos pequeños, de menos carácter ceremonial, varios de estos artefactos se pueden combinar en uno solo pero a la postre el resultado será el mismo.

Sobre la Arquitectura Preliminar

Ninguna disertación sobre el Inicio de un proyecto estará completa sin hablar de la Arquitectura Candidata. Por allá en la segunda mitad de la fase, el Arquitecto del Software recibe del Analista los insumos necesarios para abordar la Solución. Esta se expresa en términos de vistas o perspectivas, empezando por la vista funcional, arquitectura funcional o vista de casos de uso; ésta es un compendio de los casos de uso que precisamente “definen” la arquitectura, o son los más complejos arquitectónicamente (y la complejidad es un asunto espinoso sobre el que únicamente el arquitecto tiene potestad). El arquitecto incluso puede desviar la atención del analista hacia un grupo distinto de casos de uso y solicitar el detalle de estos para validar efectivamente dicha complejidad. También puede requerir el diseño e implementación de una o más pruebas de concepto arquitectónicas con el ánimo de comprobar la factibilidad técnico-científica de implementar una parte del software que se prevé problemática o en la que no se tiene experiencia anterior.

En un mundo ideal, es deseable que el arquitecto proponga más de una arquitectura candidata y que sea un comité (de arquitectos o de varios miembros del equipo desarrollador) el que decida más adelante (durante la Elaboración) cuál es la mejor alternativa para las necesidades actuales.

En el Final

Cuando un proyecto de Tecnología Informática comienza no damos cuenta del abismo colosal de realidad inexplorada que se expande ante nuestras mentes. La búsqueda inicia aquí y es nuestro compromiso revelar esas ambiciones y estrechar las contingencias de los usuarios, concebir la solución, pasar de observadores pasivos de una organización a ser coreógrafos activos de su proceso o, al menos, de parte de el. A medida que nuestro conocimiento de ese proceso aumenta, se abre la posibilidad de construir mejores artilugios de cómputo para los usuarios. Y salvo que se produzca una catástrofe natural (que en este contexto quiere decir que se desborden los sueños de los usuarios, o que dejemos que esa visión rebase la capacidad técnica y presupuestal del proyecto), o un colapso ocasionado por factores que van más allá de lo técnico y caen en lo legal o regulatorio, estamos en camino de alcanzar, en un marco de tiempo más o menos previsible (¡estimable!), la implantación de un producto de software de alta calidad que satisfaga o resuelva las necesidades elementales de nuestros usuarios.

Y lo que hará que esto sea posible es la configuración y el seguimiento de un proceso de Ingeniería maduro para las características específicas de ese proyecto en particular. En última instancia, haremos que sea permisible plasmar nuestra meta si disponemos de las herramientas y técnicas más o menos como lo he expuesto en estas Lecturas Fundamentales. El aprovechamiento de ellas (de las herramientas y de las Lecturas) es el primer paso para convertirnos en mejores profesionales de la Ingeniería del Software.

Referencias

Algunas de las características y conceptos expuestos aquí se basan en la documentación de IBM Rational Unified Process.

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

lucho.salazar@gmail.com

jueves, marzo 08, 2007

Lecturas Fundamentales 8

Lectura Fundamental Anterior: “RUP o Todo lo que quisiste saber alguna vez de RUP y no te atreviste a preguntar…”

Lectura # 8
RUP: Fase de Concepción

“No hay nada más difícil de emprender, ni más dudoso de hacer triunfar, ni más peligroso de manejar, que el introducir nuevas leyes.”
Nicolás Maquiavelo (El Príncipe, 1513)


“In principio creavit…”
Génesis 1 {1:1}

Inicio o Concepción es la primera fase de RUP. El nombre no es importante, solo la meta es importante. Lo realmente trascendental es el objetivo que buscamos durante este período de gestación del proyecto: complementando lo que dije en la lectura fundamental # 7, la finalidad cardinal de esta fase es establecer la visión y el alcance del proyecto y del sistema, lo que se hará y no se hará dentro del proyecto y más aún, lo que hará y lo que no hará el producto a construir.

Para ello, RUP nos proporciona herramientas, a manera de mecanismos y maniobras, que bien usadas nos llevan de la mano hacia la consecución del objeto primario que nos ocupa: obtener un acuerdo con todos los involucrados sobre los objetivos del ciclo de vida para el proyecto.

Pero antes de abordar detalladamente la fase de Concepción como la explica RUP, quiero referirme al significado de las características del proceso durante la misma.

RUP es Dirigido por Casos de Uso y es Centrado en la Arquitectura

Esto significa que los casos de uso son la base para el resto del proceso de desarrollo. Durante la fase de Inicio, cuantificamos y cualificamos los requisitos funcionales del sistema en términos de casos de uso. Estos se convierten en el insumo para:
  • Crear y validar el modelo de diseño de la solución
  • Diseñar la arquitectura del sistema
  • Definir los casos y procedimientos de prueba en el modelo de pruebas
  • Planear las iteraciones
  • Elaborar la documentación de usuario
  • Hacer el despliegue del sistema
  • Sincronizar el contenido de los diferentes modelos que forman el sistema

Los casos de uso también son usados para modelar el negocio, actividad que pocas veces es tenida en cuenta a la hora de entender el comportamiento sistemático de una organización.

Cualificar los casos de uso quiere decir en el contexto del proceso que el Arquitecto del software debe hacer una priorización de los mismos desde el punto de vista arquitectónico. Es decir, establecer cuales son los casos de uso que definen la arquitectura o que tienen un impacto mayor en la misma. Para ello, los Arquitectos ponemos de manifiesto nuestra experiencia en proyectos anteriores y similares, si es posible, para reconocer los casos de uso arquitecturales: El ciclo de vida del caso de uso, el número y la calidad de los elementos estructurales (tanto de arquitectura como de diseño como de implementación) que se requieren para implementar el comportamiento del caso de uso en el sistema, requisitos de desempeño, confiabilidad, soportabilidad, concurrencia y restriccio-nes de diseño, la complejidad algorítmica asociada al caso de uso, el número de escenarios del caso de uso, el ranking del caso de uso desde el punto de vista de su criticidad (esto es, si el caso de uso es requerido u obligatorio, o importante, o adicional –normalmente los casos de uso arquitectónicos se cuentan entre los dos primeros), el grado de novedad de la tecnología y las estrategias disponibles para implementar el caso de uso o, en otras palabras, la experiencia del equipo de desarrollo en el uso de tal o cual tecnología o conjunto de técnicas para resolver un problema dado, son todas variables relevantes a la hora de catalogar o evaluar los casos de uso desde una perspectiva de arquitectura.

La fase de inicio es exploratoria, los casos de uso, todavía en estado primitivo, corren por un río de aguas diáfanas que se precipitan desde la mente de los usuarios como huevos prehistóricos. Encontrarlos, darles un lugar en el sistema, clasificarlos, esbozarlos, modelarlos y finalmente presentarlos, es lo que hacemos como analistas durante este período del proyecto. Una vez aprobado el modelo, los casos de uso rigen los designios a veces insondables a veces meta-humanos de todo el proyecto. A los casos de uso no se les puede poner limitantes técnicas y el equipo de desarrollo debe mantenerlos como un libro abierto de referencia para decidir siempre el siguiente paso. Eso significa “dirigido por casos de uso.”

La arquitectura del software, por su parte, asoma tímida durante la concepción, a manera de arquitectura candidata o preliminar y debería contemplar más de una posible solución, un conjunto pequeño de alternativas de cómo se va a implementar el software y la estrategia que usaremos para abordar el tratamiento de los requisitos suplementarios o no funcionales: la vista de casos de uso o funcional, subconjunto propio del modelo de casos de uso, una vista lógica de alto nivel y quizás una perspectiva del despliegue de la aplicación, surgen de la mente creativa del arquitecto, cual visión futurista de lo que será, de cómo lucirán las entrañas del sistema una vez esté construido. Y sea cual fuere la decisión, la elección que tomemos en la siguiente fase del proyecto, la arquitectura es desde todo punto de vista restrictiva, circunscribe el diseño y, consecuentemente, la implementación y el despliegue de la solución software que se conciba. Pero a partir de ella se abordan y mitigan los riesgos técnicos del proyecto, durante las primeras iteraciones del mismo; también se construyen las bases o cimientos del sistema, unas en las que todos los requisitos conocidos y algunos de los no conocidos tengan cabida; por supuesto, la arquitectura es el eje medular alrededor del cual se construye la solución, se planea y se controla el proyecto y también, en torno al cual se asegura la calidad del producto. Eso significa “centrado en la arquitectura.”

Para el Gazafatonario IT

A manera de inventario, y puesto que esto no es más que un Gazafatonario, la palabra Conceptualización[1], aunque aparece en algún diccionario de la lengua española definida simplemente como: “f. Elaboración detallada y organizada de un concepto a partir de datos concretos o reales” no es aceptada por la Real Academia de la Lengua Española. Así que seguiremos usando Inicio o Concepción para referirnos a la primera fase del ciclo de vida de acuerdo a RUP.

Roles y Responsabilidades Durante Concepción

Un Ingeniero de Procesos, un Gerente de Proyectos, al menos un Analista de Requisitos, un Analista del Negocio y un Administrador de la Configuración y el Versionamiento son los responsables de iniciar el proyecto. Con ellos, los usuarios, clasificados en Usuarios Líderes, Usuarios Finales y otros Involucrados (stakeholders es el término que nos llega del inglés) son los encargados de dictar el problema (y el problema detrás del problema, la causa raíz), sus necesidades, y hasta sus ambiciones, sus sueños y sus esperanzas. Más adelante, un Especificador de Requisitos (realmente un escritor técnico de casos de uso que bien podría ser el mismo analista de requisitos –de hecho casi siempre lo es) y un Arquitecto del Software, se unen a los anteriores para establecer las características (de alto nivel) del software, los primeros requisitos funcionales (a manera de casos de uso) detallados, los requisitos no funcionales y la misma solución de software expresada en términos arquitectónicos y de diseño.

Vamos por partes.

El Ingeniero de Procesos

Sí, RUP es un proceso configurable y adaptable a cada proyecto. Es así como lo leen, a cada proyecto. La primera conclusión que viene a mi mente, aunque reiterativa, tiene que ver con la forma de abordar el proceso. Recordemos que el proceso expone prácticas que han funcionado alguna vez, pero que no deberíamos seguir al pie de la letra, cual ensayo de laboratorio.

Un proyecto tiene condiciones muy particulares: el tipo de organización, más exactamente, el contexto del negocio, el tamaño del esfuerzo de desarrollo del software, el grado de novedad, el tipo de aplicación, el proceso actual de desarrollo, los problemas actuales y sus causas primarias, los factores organizacionales, las actitudes y la complejidad técnica y de gestión son algunos discriminantes que el así llamado Ingeniero de Procesos debe tener en cuenta al momento de decidir el mejor de los caminos posibles del proceso para ese proyecto.

Previo a ello, debemos tener claridad sobre las influencias del proceso de desarrollo: factores del dominio, por ejemplo, entre los que se cuentan factores del dominio de la aplicación, del proceso de negocio a soportar, de la comunidad de usuarios y de las ofertas disponibles de los competidores; factores del ciclo de vida como el tiempo de salida al mercado, la vida esperada del software y las versiones futuras planeadas son igualmente importantes; factores técnicos, ni más faltaba, como los lenguajes de programación a usar, las herramientas de desarrollo, las bases de datos, los frameworks de componentes y los sistemas de software existentes, constituyen influjos de peso que actúan sobre el proceso de desarrollo, junto con otros factores organizacionales cuyo nombramiento, al menos, se escapa del alcance de esta lectura fundamental.

Sobre el tamaño del esfuerzo del proceso de desarrollo, tenemos en cuenta aspectos medibles como el número de líneas de código entregadas, el número de casos de uso, el número de personas por mes o por alguna otra unidad de tiempo, el número de clases y de componentes, el número de tablas y de procedimientos almacenados en la base de datos, entre otros, para cuantificar la influencia en el desarrollo: a mayor tamaño de proyecto, mayor tamaño de equipo de desarrollo, el contexto del negocio pierde importancia en favor de más formalidad y más visibilidad en los requisitos, en las interfaces y en los indicadores de progreso del proyecto. Adicionalmente, para equipos geográfi-camente dispersos, incluso transoceánicos, tenemos en cuenta aspectos cruciales de comunicación y el cambio del huso horario.

El grado de novedad es otra condición influyente que tengo en cuenta como ingeniero de procesos. Este grado de novedad es relativo al equipo de desarrollo y a la organización que lo envuelve: factores como la madurez de la organización y del proceso de desarrollo (medido vía CMMi o algún otro modelo similar), los activos del proceso, las habilidades actuales del personal, la composición y el entrenamiento del equipo y la adquisición de herramientas y otros recursos para el proyecto, son definitivos a la hora de configurar el proceso: si se trata de un sistema nuevo, establezco fases de concepción y de elaboración más largas y más iteraciones en esta última; también hago más énfasis en la captura y administración de requisitos, el modelo de casos de uso, la arquitectura y en la mitigación de riesgos. Entre tanto, para un sistema en evolución, enfatizo en la gestión de cambios y en la incorporación o no de código legado.
En breve, durante la concepción, el ingeniero de procesos además elabora el caso de desarrollo, prepara las plantillas y las guías para el proyecto y, con un especialista en herramientas, selecciona las herramientas más adecuadas para el proyecto. Son materias que tienen tanto extensión como profundidad y abordarlas bien podría ser objeto de futuras Lecturas Fundamentales.

Lo que sí tengo que decir antes de cerrar esta puerta es que el ingeniero de procesos es al proceso lo que el arquitecto es al sistema y recuerden: la calidad de un producto está determinada en gran medida por la calidad del proceso que se usa para desarrollarlo y mantenerlo[2].

El Analista de Procesos del Negocio

Hablo de procesos distintos. En el apartado anterior me refería al proceso de desarrollo de software, mientras que en este me refiero al conjunto de procesos mediante los cuales una compañía organiza su actividad para conseguir sus objetivos. Cada proceso del negocio se identifica por un repertorio de datos que son elaborados y operados mediante un conjunto de quehaceres, en los que ciertos agentes (trabajadores, proveedores, departamentos, entre otros) interactúan de acuerdo a un flujo de trabajo determinado. Además, estos procesos dependen de un conjunto de reglas de negocio que fijan las políticas y la arquitectura de la información de la empresa.

El analista de procesos del negocio o simplemente analista del negocio es el responsable de definir la arquitectura del negocio y los actores y casos de uso del negocio, lo mismo que la interacción entre ellos. El modelo producido por este analista delimita la organización desde el punto de vista del sistema a desarrollar.

Entender la organización es un aspecto clave en todo desarrollo de software: enterarse de los procesos de negocio, quienes intervienen en su ejecución, sus entradas y sus resultados, como se manejan las excepciones, como se mantiene la integridad de la información y la consistencia entre procesos; también, conocer hacía donde va la organización, las expectativas de los usuarios, la visión que ellos tienen sobre lo que será y no será el negocio en el futuro, al menos, durante el ciclo de vida esperado del sistema.

Ahora bien, idealmente, la construcción de sistemas de software es uno de esos buenos momentos para cambiar procesos de negocio, no porque el negocio tenga que adaptarse al nuevo sistema, sino porque el esfuerzo de revisión de tales procesos puede llegar a ser tan significativo, tan profundo, que se encuentren oportunidades de mejora. Esto, por supuesto, es completa responsabilidad de la organización para la cual se construye el sistema y el área de TI, como buena conocedora de estos procesos, debe apoyar el diseño y la implantación del nuevo modelo y de paso quedar con el nuevo conocimiento para futuros ejercicios de esta índole.

Por supuesto, este trabajo implica un tiempo y recursos adicionales considerables que casi nunca son estimados a la hora de emprender un proyecto de tecnología informática, de tal forma que la cautela y el tratamiento efectivo de las expectativas de nuestros clientes son recomendables.

El Gerente de Proyectos

Planea, maneja y asigna recursos, determina prioridades, coordina las interaccio-nes con los usuarios y mantiene el foco del equipo del proyecto. También establece un conjunto de prácticas para asegurar la integridad y la calidad de los entregables del proyecto. Es un orquestador, articula y coordina los movimientos que se den en el proyecto.

Es el gerente quien precisamente concibe el proyecto mediante la transformación de una idea inicial a un estado en el que, soportado en razones de peso, pueda tomar una decisión sobre continuarlo o abandonarlo. Para lo que nos ocupa la mayor parte del tiempo, este “abandonarlo” más bien se convierte en un “ajustar” algunas condiciones críticas del proyecto, como el tiempo, el talento humano necesario para llevarlo a cabo y, por consiguiente, el presupuesto y la estrategia para alcanzar el éxito.

Durante la concepción, el gerente del proyecto identifica y evalúa los riesgos, elabora un caso de negocio e inicia el proyecto. Más adelante, en la misma concepción, planea el proyecto, teniendo en cuenta las métricas, los riesgos, los criterios de aceptación del producto, las tácticas para la resolución de problemas, el proceso de aseguramiento de la calidad, la organización del equipo de desarrollo, los modos de monitoreo y control del proyecto y las fases e iteraciones del mismo. Para ello se alimenta de toda la materia prima que los demás responsables de la concepción le transmitan. Es el gerente quien también decide si se han alcanzado los objetivos de la fase de concepción y si es viable empezar la fase de Elaboración.

Tanto en Concepción, como en el resto del proyecto, el gerente tiene una perspectiva de mediana profundidad para poder izar los hilos del proyecto con mayor propiedad y asegurar, casi como un dogma, que se pueda hacer una entrega, que se pueda avanzar o, si por el contrario, que se deba replantear la técnica y reorientar el enfoque (corregir el rumbo). Y el final de la fase de concepción es buen momento para asegurarnos de la idoneidad (en cuanto talento, competitividad, aptitud) del equipo de desarrollo, de indagar si los miembros del equipo tienen las habilidades y destrezas suficientes, comparten todos la misma visión de lo que vendrá, soportarán la presión, están dispuestos a dar ese “delta de t” (y otros deltas) necesarios para triunfar en todo proyecto. Desde este punto de vista, el destino del proyecto, incierto hasta este punto, depende enteramente de su gerente.

Bueno, esto no lo dice ningún proceso, no está escrito en ningún lado, simplemente es y con eso basta.

Continuará…

Hace poco uno de mis revisores de cabecera me dijo que estas lecturas fundamentales estaban quedando muy largas. Yo les reenvío la inquietud, ¿ustedes qué piensan? En cualquier caso, les he dado suficiente tiempo, creo, para que hagan la mejor de las lecturas. Estoy atento, los escucho.

De todas formas, es evidente que esta lectura amerita otra parte, donde concluiremos con los aspectos más importantes de la fase de concepción. Hasta la próxima entonces.

Referencias

Algunas de las características y conceptos expuestos aquí se basan en la documentación de IBM Rational Unified Process.

1. Diccionario de la lengua española © 2005 Espasa-Calpe S.A., Madrid:
Conceptualización
f. Elaboración detallada y organizada de un concepto a partir de datos concretos o reales.

2. Basado en principios de Administración Total de la Calidad enseñados por Shewhart, Juran, Deming y Humphrey.

Lectura Fundamental Siguiente: “RUP: Fase de Concepción. Parte 2.”

lucho.salazar@gmail.com