É incrível quanta confusão existe sobre a distinção entre a parte-todo - agregação de conceitos de associação e composição . O principal problema é o mal-entendido generalizado (mesmo entre desenvolvedores de software especializados e entre os autores da UML) de que o conceito de composição implica uma dependência do ciclo de vida entre o todo e suas partes, de forma que as partes não podem existir sem o todo. Mas essa visão ignora o fato de que também há casos de associações parte-todo com partes não compartilháveis, em que as partes podem ser destacadas e sobreviver à destruição do todo.
No documento de especificação UML, a definição do termo "composição" sempre implicou em partes não compartilháveis, mas não ficou claro qual é a característica definidora de "composição" e o que é meramente uma característica opcional. Mesmo na nova versão (a partir de 2015), UML 2.5, após uma tentativa de melhorar a definição do termo "composição", ela permanece ambígua e não fornece qualquer orientação sobre como modelar associações parte-todo com não partes compartilháveis em que as partes podem ser destacadas e sobrevivem à destruição do todo, em oposição ao caso em que as partes não podem ser destacadas e são destruídas juntamente com o todo. Eles dizem
Se um objeto de composição for excluído, todas as suas instâncias de parte que são objetos são excluídas com ele.
Mas ao mesmo tempo eles também dizem
Um objeto de parte pode ser removido de um objeto de composição antes que o objeto de composição seja excluído e, portanto, não pode ser excluído como parte do objeto de composição.
Essa confusão aponta para uma incompletude da definição UML, que não leva em conta as dependências do ciclo de vida entre componentes e compostos. Portanto, é importante compreender como a definição UML pode ser aprimorada pela introdução de um estereótipo UML para composições << inseparáveis >> onde os componentes não podem ser separados de seu composto e, portanto, devem ser destruídos sempre que seu composto for destruído.
1) Composição
Como Martin Fowler explicou , o principal problema para caracterizar a composição é que "um objeto só pode ser parte de uma relação de composição". Isso também é explicado na excelente postagem do blog UML Composition vs Aggregation vs Association de Geert Bellekens. Além dessa característica definidora de uma composição (ter partes exclusivas ou não compartilháveis ), uma composição também pode vir com uma dependência de ciclo de vida entre o composto e seus componentes. Na verdade, existem dois tipos de dependências:
- Sempre que um componente deve sempre ser anexado a um composto, ou, em outras palavras, quando ele tem um composto obrigatório , conforme expresso pela multiplicidade "exatamente um" no lado composto da linha de composição, então ele deve ser reutilizado em (ou reconectado a) outro composto, ou destruído, quando seu composto atual é destruído. Isso é exemplificado pela composição entre
Person
e Heart
, mostrada no diagrama abaixo. Um coração é destruído ou transplantado para outra pessoa, quando seu dono morre.
- Sempre que um componente não puder ser separado de seu composto, ou seja, quando for inseparável , então, e somente então, o componente deverá ser destruído, quando seu composto for destruído. Um exemplo de tal composição com partes inseparáveis é a composição entre
Person
e Brain
.
Em resumo, as dependências do ciclo de vida só se aplicam a casos específicos de composição, mas não em geral; portanto, não são uma característica definidora.
A especificação UML afirma: "Uma parte pode ser removida de uma instância composta antes que a instância composta seja excluída e, portanto, não pode ser excluída como parte da instância composta." No exemplo de uma composição Car
- Engine
, conforme mostrado no diagrama a seguir, é claro que o motor pode ser retirado do carro antes que o carro seja destruído, caso em que o motor não é destruído e pode ser reutilizado. Isso está implícito no zero ou uma multiplicidade no lado composto da linha de composição.
A multiplicidade da extremidade de associação de uma composição no lado do composto é 1 ou 0..1, dependendo do fato de os componentes terem um composto obrigatório (devem ser anexados a um composto) ou não. Se os componentes forem inseparáveis , isso significa que eles têm um composto obrigatório.
2) Agregação
Uma agregação é outra forma especial de associação com o significado pretendido de um relacionamento parte-todo, onde as partes de um todo podem ser compartilhadas com outros todos. Por exemplo, podemos modelar uma agregação entre as classes DegreeProgram
e Course
, conforme mostrado no diagrama a seguir, uma vez que um curso faz parte de um programa de graduação e um curso pode ser compartilhado entre dois ou mais programas de graduação (por exemplo, um diploma de engenharia pode compartilhar um C curso de programação com graduação em ciência da computação).
No entanto, o conceito de uma agregação com partes compartilháveis não significa muito, realmente, por isso não tem implicações na implementação e muitos desenvolvedores, portanto, preferem não usar o diamante branco em seus diagramas de classe, mas apenas modelar uma associação simples em vez de. A especificação UML diz: "A semântica precisa da agregação compartilhada varia por área de aplicativo e modelador".
A multiplicidade da extremidade da associação de uma agregação no lado inteiro pode ser qualquer número (*) porque uma parte pode pertencer a, ou ser compartilhada entre, qualquer número de todos.