Noções básicas sobre modelos, classes e relações

Uma DSL (linguagem específica de domínio) é definida por seu arquivo de definição de DSL, juntamente com qualquer código de programa personalizado que você possa escrever. A maior parte do código do programa na solução DSL é gerada a partir desse arquivo.

Este tópico explica os principais recursos da definição de DSL.

A Definição de DSL

Quando você abre Dsl\DslDefinition.dsl, a janela do Visual Studio é semelhante à imagem a seguir.

dsl designer

As informações mais importantes na Definição de DSL são exibidas no diagrama de Definição de DSL. Informações adicionais, que também fazem parte do DslDefinition.dsl, são exibidas no Gerenciador de DSL, que geralmente aparece ao lado do diagrama. Você trabalha com o diagrama nas tarefas mais frequentes e com o Gerenciador de DSL em personalizações mais avançadas.

O diagrama definição de DSL mostra as classes de domínio que definem elementos de modelo e as relações que definem os links entre os elementos do modelo. Ele também mostra as formas e conectores usados para exibir os elementos do modelo para o usuário.

dsl designer with swimlane

Quando você seleciona um item na definição de DSL, tanto no diagrama quanto no Gerenciador de DSL, as informações sobre ele são exibidas no janela Propriedades. Informações adicionais podem ser exibidas na janela Detalhes da DSL.

Os modelos são instâncias dos DSLs

Um modelo é uma instância da DSL criada por um usuário. Um modelo contém elementos de modelo, que são instâncias das classes de domínio que você define e também links entre os elementos, que são instâncias das relações de domínio que você define. Um modelo também pode ter formas e conectores, que exibem os elementos do modelo e os links em um diagrama. A definição de DSL inclui as classes de forma, classes de conector e uma classe para o diagrama.

Uma definição de DSL também é conhecida como um modelo de domínio. Uma Definição de DSL ou um modelo de domínio é a representação em tempo de design da linguagem específica do domínio, enquanto o modelo é a instanciação em tempo de execução da linguagem específica do domínio.

As classes do domínio definem os elementos do modelo

As classes de domínio são usadas para criar os vários elementos no domínio, e as relações de domínio são os links entre os elementos. Eles são a representação em tempo de design dos elementos e links que serão instanciados pelos usuários da linguagem específica de design quando criarem seus modelos.

Esta ilustração mostra um modelo que foi criado pelo usuário da DSL de uma biblioteca de músicas. Os álbuns musicais são representados por caixas que contêm listas de canções. Os artistas são representados por caixas de canto redondo, e estão conectados aos álbuns com os quais contribuíram.

Instance model of generated DSL

A Definição de DSL separa dois aspectos. A aparência dos elementos do modelo no diagrama do modelo é definida usando classes de forma e classes de conector. As informações contidas no modelo são definidas usando classes de domínio e relações de domínio.

A ilustração a seguir mostra as classes e as relações de domínio na Definição de DSL da Biblioteca de Música.

Embedding and Reference relationships

A ilustração mostra quatro classes de domínio: Música, Álbum, Artista e Canção. As classes de domínio definem propriedades de domínio como Nome, Título e assim por diante. No modelo de instância, os valores de algumas dessas propriedades são exibidos no diagrama.

Entre as classes estão relações de domínio: MusicHasAlbums, MusicHasArtists, AlbumbHasSongs e ArtistAppearedOnAlbums. As relações possuem multiplicidades, como 1..1, 0..*. Por exemplo, cada Canção deve estar relacionada a exatamente um Álbum por meio da relação AlbumHasSongs. Cada Álbum pode ter qualquer número de Canções.

Reorganizando o diagrama de Definição de DSL

Observe que uma classe de domínio pode aparecer várias vezes no diagrama de Definição de DSL, como acontece com o Álbum nesta imagem. Há sempre uma exibição principal e pode haver algumas exibições de referência .

Para reorganizar o diagrama de definição de DSL, você pode:

  • Trocar as exibições principal e de referência usando os comandos Trazer Árvore Aqui e Dividir Árvore. Clique com o botão direito do mouse em uma única classe de domínio para ver esses comandos.

  • Ordene novamente as classes de domínio e as classes de forma pressionando Ctrl+Seta para cima e Ctrl+Seta para baixo.

  • Recolha ou expanda as classes usando o ícone no canto superior direito de cada forma.

  • Recolha partes da árvore clicando no sinal de subtração (-) na parte inferior de uma classe de domínio.

Herança

As classes de domínio podem ser definidas usando herança. Para criar uma derivação de herança, clique na ferramenta Herança, clique na classe derivada e depois clique na classe base. Um elemento de modelo possui todas as propriedades definidas em sua própria classe de domínio, juntamente com todas as propriedades herdadas da classe base. Ele também herda suas funções nas relações.

A herança também pode ser usada entre Relações, Formas e Conectores. A herança deve ser mantida dentro do mesmo grupo. Uma forma não pode herdar de uma classe de domínio.

Relacionamentos de Domínio

Os elementos do modelo podem ser vinculados por relações. Os links são sempre binários; eles vinculam exatamente dois elementos. No entanto, qualquer elemento pode ter muitos links para outros objetos e pode até mesmo haver mais de um link entre o mesmo par de elementos.

Assim como você pode definir diferentes classes de elementos, você pode definir diferentes classes de links. A classe de um link é chamada de relação de domínio. Uma relação de domínio especifica a quais classes do elemento suas instâncias podem se conectar. Cada extremidade de uma relação é chamada de função e a relação de domínio define nomes para as duas funções, bem como para a própria relação.

Há dois tipos de relações de domínio: relações de incorporação e relações de referência. No diagrama de Definição de DSL, as relações de incorporação possuem linhas sólidas em cada função e as relações de referência possuem linhas tracejadas.

Relações de incorporação

Cada elemento em um modelo, com exceção de sua raiz, é o destino de um link de incorporação. Portanto, todo o modelo forma uma única árvore de links de incorporação. A relação de incorporação representa contenção ou propriedade. Dois elementos de modelo relacionados dessa maneira também são conhecidos como pai e filho. Dizemos que a criança está incorporada no pai.

Os links de incorporação geralmente não são mostrados explicitamente como conectores em um diagrama. Em vez disso, eles geralmente são representados pela contenção. A raiz do modelo é representada pelo diagrama e os elementos incorporados nele são exibidos como formas no diagrama.

No exemplo, a classe raiz Música possui uma relação de incorporação MusicHasAlbums para Álbum, que possui uma incorporação AlbumHasSongs para Canção. As canções são exibidas como itens em uma lista dentro de cada Álbum. A Música também possuir uma incorporação de MusicHasArtists na classe Artista, cujas instâncias também aparecem como formas no diagrama.

Por padrão, os elementos incorporados são excluídos automaticamente quando seus pais são excluídos.

Quando um modelo é salvo no arquivo em formato XML, os elementos incorporados são aninhados dentro de seus pais, a menos que você tenha personalizado a serialização.

Observação

Incorporação não é o mesmo que herança. Os filhos em uma relação de incorporação não herdam as propriedades do pai. Uma incorporação é um tipo de vínculo entre elementos de modelo. A herança é uma relação entre classes e não cria vínculos entre os elementos do modelo.

Regras de incorporação

Cada elemento do modelo de uma instância deve ser o destino de exatamente um link de incorporação, exceto para a raiz do modelo.

Portanto, cada classe de domínio não abstrata, exceto a classe raiz, deve ser o destino de pelo menos uma relação de incorporação, ou ela deve herdar de uma classe base. Uma classe pode ser o destino de duas ou mais incorporações, mas os elementos de seu modelo de instância só podem ter um pai por vez. A multiplicidade de destino para a origem deve ser 0..1 ou 1..1.

O Gerenciador exibe a Árvore de incorporação

Sua definição de DSL também cria um gerenciador, que os usuários veem junto com o diagrama de seu modelo.

Generated explorer of DSL

O gerenciador mostra todos os elementos do modelo, mesmo aqueles para os quais você não definiu nenhuma forma. Ele mostra elementos e relações de incorporação, mas não relações de referência.

Para ver os valores das propriedades de domínio de um elemento, o usuário seleciona um elemento, seja no diagrama do modelo ou no gerenciador de modelos, e abre o janela Propriedades. Ela exibe todas as propriedades do domínio, incluindo aquelas que não são exibidas no diagrama. No exemplo, cada Canção possuir um Título e um Gênero, mas apenas o valor do Título é mostrado no diagrama.

Relações de referência

Uma relação de referência representa qualquer tipo de relação que não esteja incorporada.

As relações de referência são geralmente exibidas em um diagrama como conectores entre as formas.

Na representação XML do modelo, o link de referência entre os dois elementos é representado usando monikers. Em outras palavras, os monikers são nomes que identificam cada elemento no modelo de modo exclusivo. O nó XML para cada elemento do modelo contém um nó que especifica o nome da relação e o moniker do outro elemento.

Funções

Cada relação de domínio possui duas funções, uma função de origem e uma função de destino.

Na imagem a seguir, a linha entre a classe de domínio Editora e a relação de domínio PublisherCatalog é a função de origem. A linha entre a relação de domínio e a classe de domínio Álbum é a função de destino.

Roles and properties.

Os nomes associados a uma relação são especialmente importantes quando você escreve o código do programa que atravessa o modelo. Por exemplo, quando você cria a solução DSL, a classe gerada Editora possui uma propriedade Catálogo que é uma coleção de Álbuns. A classe Álbum possui uma propriedade Editora que é uma única instância da classe Editora.

Quando você cria uma relação em uma Definição de DSL, os nomes de propriedade e relação recebem valores padrão. No entanto, é possível alterá-los.

Multiplicidades

As multiplicidades especificam quantos elementos podem ter a mesma função em uma relação de domínio. No exemplo, a configuração de multiplicidade de zero para muitos (0..*) na função Catálogo especifica que qualquer instância da classe de domínio Editora pode ter quantos links de relação PublisherCatalog quiser fornecer a ela.

Configure a multiplicidade de uma função digitando no diagrama ou modificando a Multiplicity propriedade na janela Propriedades. A tabela a seguir descreve as configurações dessa propriedade.

Tipo de multiplicidade Descrição
0..* (Zero a muitos) Cada instância da classe de domínio pode ter várias instâncias da relação ou nenhuma instância da relação.
0..1 (Zero a um) Cada instância da classe de domínio pode ter no máximo uma instância da relação ou nenhuma instância da relação.
1..1 (Um) Cada instância da classe de domínio pode ter uma instância da relação. Você não pode criar mais de uma instância dessa relação a partir de qualquer instância da classe de função. Se a validação estiver habilitada, um erro de validação será exibido quando qualquer instância da classe de função não tiver nenhuma instância da relação.
1..* (Uma para muitas) Cada instância da classe na função que tem essa multiplicidade pode ter várias instâncias da relação, e cada instância deve ter pelo menos uma instância da relação. Se a validação estiver habilitada, um erro de validação será exibido quando qualquer instância da classe de função não tiver nenhuma instância da relação.

Relações de domínio como classes

Um link é representado na Store como uma instância da LinkElement, a qual é uma classe derivada da ModelElement. Você pode definir essas propriedades no diagrama do modelo do domínio nas relações de domínio.

Você também pode tornar uma relação a origem ou destino de outras relações. No diagrama do modelo do domínio, clique com o botão direito do mouse na relação de domínio e depois clique em Mostrar como Classe. Uma caixa de classe adicional será exibida. A partir desse ponto você pode conectar relações a ele.

Você pode definir uma relação parcialmente por herança, da mesma forma que com as classes de domínio. Selecione a relação derivada e defina a Relação base na janela Propriedades.

Uma relação derivada é especializada em sua relação base. As classes de domínio que ela vincula devem ser derivadas ou iguais às classes vinculadas pela relação base. Quando um link da relação derivada é criado em um modelo, ele é uma instância tanto das relações derivadas quanto das relações base. No código do programa, você pode navegar até a extremidade oposta do link usando as propriedades geradas pela classe base ou pela classe derivada.