POO Lección 4: Relaciones entre objetos

Relaciones entre Objetos

Adicionalmente a la extensión e implementación que hemos visto, existen otros tipos de relaciones entre objetos que todavía no hemos hablado.

Dependencia

Dependencia es la más basica y debil relacion que existe entre clases. Hay una dependencia entre dos clases si algún cambio en la definición de una clase podría resultar en modificaciones de la otra clase. La dependencia tipicamente sucede cuando utilizas nombres de clases concretos en el código. Por ejemplo, cuando especificamos tipos en las firmas de un método metodo, cuando instanciamos objetos vía constructor, o dentro de un método, etc. Apesar que exista dependencia puedes hacer que esta dependencia sea debil si haces depender tu codigo de interfaces o clases abstractas en lugar de clases concretas, para que sea más apto a cambios nuestro codigo fuente.

final class Client
{
    public function __construct()
    {
        $messageBag = new MessageBag();
    }
}

Asociación

Asociación es una relación donde un objeto usa o interactua con otro. En los diagramas UML, la relación de asociación es vista como una fecha simple desde un objeto y señalando al objeto con el que interactua. De todas maneras, tener una asociación bidireccional es algo complemente normal. En este caso la flecha esta al final de ambos lados. La asociación puede ser vista como un tipo especializado de dependencia, donde un objeto siempre tiene acceso a los objetos con los que interactua, sin embargo una dependencia simple no establece una relación permanente entre objetos.

En general, usamos una asociación para representar algo como un campo en una clase. El vínculo esta siempre ahí, donde tu puedes siempre preguntar sobre la orden de un cliente. Pero no siempre tiene que ser una propiedad o campo. Si estas modelando tus clases desde una perspectiva de interfaces, esto solo puede indicar la presencia de un metodo que va a retornar la orden de un cliente.

En el caso de este modelado el "Cliente" posee una lista de "Ordenes" asociada o relacionada a la cuál podemos acceder.

final class Client
{
    public function getName(): string
    {
        return $this->name;
    }

    public function getOrders(): OrderableInterface[]
    {
        return $this->orders;
    }
}

Agregación

Agregación es un tipo especializado de asociación que representa relaciones de “uno a muchos”, “muchos a muchos” o “todo-parte” entre múltiples objetos, mientras que una asociación simple describe las relaciones entre un par de objetos. Por lo general, bajo agregación, un objeto “tiene” un conjunto de otros objetos y sirve como un contenedor o colección. El componente (Profesores) puede existir sin el contenedor (Departamentos) y se puede vincular a varios contenedores al mismo tiempo. En UML la relación de agregación se muestra mediante una línea con un diamante vacío en el extremo del contenedor y una flecha en el final apuntando hacia el componente.


Mientras hablamos de las relaciones entre los objetos, tenga en cuenta que UML representa las relaciones entre clases. Eso significa que un objeto `Universidad` podría consistir en múltiples `Departamentos` a pesar de que solo ve un "bloque" para cada entidad en el diagrama (Imagen debajo). La notación UML puede representar cantidades en ambos lados de las relaciones, pero está bien omítalos si las cantidades son claras dentro del contexto.


Composición

Composición es un tipo especifico de agregación, donde un objeto esta compuesto por una o más instancias de otros. La diferencia entre esta relación y otras es que el componente solo puede existir como una parte de el contenedor. En UML la agregación se dibuja parecida a la composición, pero esta tiene el diamante lleno en la base de la fecha.


Notemos que mucha gente a menudo usa el termino "composición" cuando realmente significa agregación. El ejemplo mas notorio para esto es el famoso principio "elegir la composición sobre la herencia". Esto no es porque la gente sea ignorante sobre la diferencia, pero es porque la palabra "composición" (ejemplo: "composición de un objeto") suena mas natural en el lenguaje inglés.


Resumen en una imagen

Ahora que conocemos todos los tipos de relaciones entre objetos vamos a ver como estan todos conectados. Con suerte, esto te guiara para responder las preguntas como “¿Cual es la diferencia entre agregación y composición?” o “¿Es la herencia un tipo de dependencia?”

    ⚜️ Dependencia: Una clase A puede ser afectada por cambios de una clase B, es decir, la clase A depende de la clase B.

    ⚜️ Asociación: Un objeto A conoce acerca de un objeto B.

    ⚜️ Agregación: Un objeto A conoce acerca de un objeto B, y se compone de B.

    ⚜️ Composición: Un objeto A conoce acerca de un objeto B, se compone de B, y maneja el ciclo de vida de B.

⚠️ En cualquiera de estos 3 últimos tipos de relación: La clase A siempre depende de la clase B.

Luego tenemos los otros dos tipos de relaciones que mencionabamos en posts anteriores:

    ⚜️ Implementación: Una clase A define (implementa “cómo”) metodos declarados en una interfaz B (definición “qué”). Los objetos A pueden ser tratados como B.

    ⚜️ Herencia: Una clase A hereda la interfaz y la implementación por defecto de B pero además puede extenderla (cambiando su implementación base). Los objetos A pueden ser tratados como B.

⚠️ En ambos casos nuevamente: La clase A depende también de la clase B.


Podemos hacer una representación gráfica de todo lo anteriormente dicho en la siguiente imagen:

Ahora ya conocemos las relaciones que existen, son las más utilizadas y nombradas en el ambiente de POO, además sabemos su correcta implementación en diagramas de UML (no siempre son tan malos como muchas veces parecen), espero que les haya sido de utilidad y nos vemos en los próximos capítulos.

Written on March 7, 2020