Mostrando las entradas con la etiqueta Asociación. Mostrar todas las entradas
Mostrando las entradas con la etiqueta Asociación. Mostrar todas las entradas

28 de marzo de 2019

Composición, Agregación y Asociación.

   Desde mi perspectiva, resulta no trivial el explicar la sutil diferencia que existe entre los conceptos de Composición, Agregación y Asociación. En mi experiencia, existe una tendencia muy común hacia utilizarlos de manera indistinta, sobre todo los dos primeros; por otro lado, el tratar de mostrar uno u otro tipo de relación con ejemplos aislados, en donde sólo me muestre la Composición pero no las otras dos y así con las otras combinaciones representa, al menos para mí, una tarea no muy sencilla.

   El siguiente diagrama de clases UML presenta los cuatro tipos de relaciones más comunes que se dan entre clases:
  1. Herencia (entre las clases Persona y Científico, estudiada en la entrada Herencia / Generalización).
  2. Composición (entre la clase Persona y las clases Pierna, Cabeza y Tórax entre otras tantas posibles).
  3. Agregación (entre las clases Persona y Ropa).
  4. Asociación (entre las clases Persona y Tarjeta de Crédito).
Diagrama de Clases UML para mostrar tres tipos de relaciones: Composición, Agregación y Asociación.

    Probablemente he abusado de la simplicidad para el ejemplo, pero he tratado de utilizar elementos conocidos y asequibles en lo general para evitar lo rebuscado o complejo que puede llegar a ser el modelado de un sistema más "real", en el que con toda seguridad aparecerán, de manera natural, este tipo de relaciones. Ahora bien, la generación de esta clase de diagramas se obtiene como resultado del análisis, la experiencia, y la previa comprensión de las diferencias (muchas veces sutiles e incluso subjetivas) que pretendo clarificar.

   La principal diferencia entre las relaciones radica fundamentalmente en dos cosas:

  1. En el tiempo de vida de los objetos que se deriven de las clases.
  2. El grado de dependencia o cohesión entre los objetos.
Herencia.
   Quizá la relación más simple y más común de las mostradas en el diagrama de clases anterior, sea la de la herencia: un Científico es una Persona, un Científico posee todas las características de una Persona (modeladas por sus atributos) más algunas características particulares a un Científico. Lo mismo sucede con sus responsabilidades y comportamiento. Para ampliar un poco más los detalles, puede el lector revisar la entrada Herencia / Generalización.

Composición.
   La Composición es un tipo de relación de alto grado de dependencia entre la clase contenedora (Persona) y las clases que la componen (Cabeza, Tórax, Pierna, etc.), es decir, cuando se crea una instancia de la clase contenedora, deben crearse, como parte de su conformación, instancias de los objetos que la componen, ya que no tendría sentido, desde el punto de vista de la instancia de Persona, conformar una persona sin cabeza o sin un tórax; por otro lado, durante toda la vida del objeto de la clase Persona debe existir el objeto de la clase Cabeza por la misma razón que antes. En este mismo sentido, tampoco tendría congruencia el tener una instancia de la clase Cabeza que nunca haya estado relacionada con una Persona.

   Algún lector inconforme podría argumentar que sí es posible que un objeto de la clase Persona deje de contener a uno de la clase Pierna por ejemplo, sin afectar la existencia de primero, y en efecto: es posible. Bastaría entonces con analizar si conviene más que la clase Pierna se modele mejor como Agregación, pero finalmente esto es sólo un ejemplo y la idea principal considero que ha sido plasmada, lo último sería más cuestión de análisis y de la conveniencia dada para un sistema determinado tal y como sucede en la vida real.

   Mi perspectiva y determinación personal sería: que se quedara como Composición.

Agregación.
   La Agregación, por otro lado, es un tipo de relación con un bajo grado de dependencia. Así por ejemplo, una instancia de la clase Persona, puede tener o no, durante su tiempo de vida (pero no es preciso que lo tenga desde su creación), un atributo de la clase Ropa sin que ello afecte su propia existencia; al mismo tiempo que un objeto de la clase Ropa podría existir independientemente de si es agregado a una Persona o a un Maniquí (clase que no aparece en el diagrama), por ejemplo.

   En este tipo de relación, la existencia de los objetos involucrados es independiente, lo mismo que su tiempo de vida: un objeto de la clase Ropa podría seguir existiendo más allá del tiempo de vida del de una Persona y viceversa, sin que ninguno de los dos se vea afectado.

Asociación.
   Una Asociación es aún menos dependiente en relación y tiempo. Espero que el lector coincida conmigo en que si bien la ropa no es imprescindible para la existencia de una persona, sí es necesaria; mientras que una tarjeta de crédito podría ser útil, en el mejor de los casos necesaria, pero en definitiva prescindible, es decir, una Persona podría pasar toda su vida sin tener la necesidad de ninguna Tarjeta de Crédito, mientras que otras podría tener muchas de ellas.

   Finalmente la relación de Asociación presentada en el diagrama, muestra que una Tarjeta de Crédito está asociada a una Persona, y que una Persona tiene ninguna (0) o varias (*) Tarjetas de Crédito.

    Finalmente, se recomienda revisar también la información expuesta en la entrada Consideraciones adicionales, en donde se presentan y contrastan ejemplos relacionados con lo aquí expuesto.

6 de abril de 2017

Consideraciones adicionales (pilas).

   La pila es una estructura de datos sumamente importante y ampliamente utilizada en distintas áreas no sólo de la computación. Su definición y funcionalidad es clara y simple, por lo que no es casual que haya sido la primera estructura de datos estudiada y presentada en el blog.

   Por otro lado, los conceptos expuestos en el blog respecto a los genéricos en Java y C++ resultarán fundamentales para los siguientes temas, ya que todas las estructuras de datos siguientes se basan en ellos, por lo que se invita nuevamente al lector a realizar un repaso de los conceptos relacionados con los genéricos así como a tener presente la importancia de los mismos a lo largo de las estructuras de datos subsecuentes.

   Adicionalmente, una vez que se han presentado los conceptos de pila (definición y operaciones) y una propuesta de implementación, resulta fundamental el conocer el esquema de relación que existe entre las clases más importantes involucradas en la implementación de la pila genérica estudiada. Los siguientes diagramas de clases UML presentan dicha relación respecto a las dos implementaciones realizadas:

Diagrama de clases UML para la pila genérica (Java).
 
    Insto amablemente al lector a que se tome el tiempo que considere necesario para comparar el diagrama de clases de la figura anterior con las clases en Java que implementan la pila genérica (Ejemplo Pila), el nodo genérico (Ejemplo NodoG), y la excepción de estructura de datos vacía (Ejemplo ExcepcionEDVacia).
 
Diagrama de clases UML para la pila genérica (C++).
 
    De manera similar a lo dicho en el párrafo anterior para el Ejemplo pila_genérica de C++.

   Los detalles de UML quedan fuera de los alcances del blog; sin embargo, los diagramas de clases UML de las figuras anteriores muestran una relación de composición entre la clase Pila y la clase NodoG (Nodo) de cero a muchos (0 .. *), lo cual quiere decir que una pila puede tener ninguno, uno, o muchos nodos. Por otro lado, también se muestra la relación de asociación uno a uno existente entre la clase Pila y la clases de excepción correspondientes a cada diagrama (observe también que los diagramas de clases muestran así mismo la relación de herencia que existe para las excepciones).

   Asegúrese de comprender el diagrama UML que sea de su interés respecto al lenguaje que esté utilizando así como su relación con los ejemplos citados, ya que en las entradas siguientes se utilizarán este tipo de diagramas de clases UML en complemento con la definición del ADT, para definir la implementación de la estructura de datos correspondiente.