Predicados de visão
As visões não são estáticas: elas são geradas a partir do modelo. Qualquer alteração no modelo é aplicada imediatamente e atualiza as visões. Dois tipos de predicados definem o que fica visível: predicados de elementos e de relacionamentos.
Predicados de elementos
Seção intitulada “Predicados de elementos”Predicados de elementos definem explicitamente quais elementos ficam visíveis. Cada elemento incluído traz seus relacionamentos com os elementos que já estão visíveis.
view { // Only backend is visible include backend
// Add frontend to the view // and its relationships with backend include frontend
// Add authService to the view // and its relationships with visible (backend and frontend) include authService
// Add children of messageBroker, // and their relationships among themselves and visible (backend, frontend and authService) include messageBroker.*
// Add all descendants of messageBroker, // and their relationships among themselves and visible (backend, frontend and authService) include messageBroker.**
// Exclude emailsQueue and its relationships exclude messageBroker.emailsQueue}Combinando
Seção intitulada “Combinando”Predicados podem ser combinados. O exemplo abaixo é equivalente ao anterior:
view { include backend, frontend, authService, messageBroker.**
exclude messageBroker.emailsQueue}Curinga
Seção intitulada “Curinga”Predicados curinga podem ser usados para referenciar “tudo” (mas o comportamento difere entre visões com e sem escopo).
Considere o seguinte modelo:
model { actor customer { -> webApp 'uses in browser via HTTPS' } system cloud { container backend { component api } container ui { component webApp { -> api 'requests data' } } }}views {
// Unscoped view - wildcard refers to top-level elements view { include * // Visible top-level elements: customer, cloud // and derived relationship customer -> cloud }
// Scoped view - wildcard refers to element and its children view of cloud.ui { include * // Visible: // - cloud.ui // - cloud.ui.webApp // - customer // - relationship customer -> cloud.ui.webApp // - cloud.backend // - cloud.ui.webApp -> cloud.backend, derived from cloud.ui.webApp -> cloud.backend.api }}Com sobrescritas
Seção intitulada “Com sobrescritas”Você pode modificar propriedades de um elemento especificamente para a visão:
// Include the element and override its propertiesinclude cloud.backend with { title 'Backend components' description '...' technology 'Java, Spring' icon tech:java color amber shape browser multiple true}// Include all nested elements, change color and textSizeinclude cloud.* with { color amber textSize small}with pode ser usado apenas dentro de include.
Com navegação personalizada
Seção intitulada “Com navegação personalizada”Você pode definir navegação e links personalizados entre visões:
view view2 { include * include cloud.backend with { // navigate to 'view3' on click navigateTo view3 }}
view view3 { include * include cloud.backend with { // navigate back to 'view2' navigateTo view2 }}Por tipo ou tag do elemento
Seção intitulada “Por tipo ou tag do elemento”// elements by kindinclude element.kind != systemexclude element.kind = container
// elements by taginclude element.tag != #V2exclude element.tag = #nextSeletores de elementos
Seção intitulada “Seletores de elementos”Filhos .*
Seção intitulada “Filhos .*”O seletor de filhos inclui os filhos do elemento e seus relacionamentos com os elementos visíveis.
include cloud.*
// Same asinclude cloud.backendinclude cloud.uiDescendentes .**
Seção intitulada “Descendentes .**”O seletor de descendentes inclui os descendentes do elemento SE eles tiverem um relacionamento com elementos visíveis.
include cloud.**
// Same asinclude cloud.backendinclude cloud.uiinclude cloud.ui.webAppExpandir ._
Seção intitulada “Expandir ._”O seletor de expansão inclui os filhos do elemento SE eles tiverem um relacionamento com elementos visíveis. Todos os outros filhos são omitidos.
include cloud._
// Same asinclude cloudinclude -> cloud.* ->Predicados de relacionamentos
Seção intitulada “Predicados de relacionamentos”Predicados de relacionamentos incluem elementos apenas quando eles possuem relacionamentos que atendem às condições especificadas pelo predicado.
Relacionamentos direcionados
Seção intitulada “Relacionamentos direcionados”Inclua elementos quando eles tiverem relacionamentos direcionados (ou quando seus elementos aninhados tiverem):
// Include customer and cloud:include customer -> cloud
// Include customer and nested elements of cloud (that have relationships):include customer -> cloud.*Qualquer relacionamento
Seção intitulada “Qualquer relacionamento”Inclua elementos quando eles tiverem qualquer relacionamento:
include customer <-> cloudEntrada
Seção intitulada “Entrada”Inclua elementos quando eles tiverem relacionamentos de entrada vindos de elementos já visíveis.
Veja um exemplo baseado no modelo do exemplo com curinga:
view { // visible element include customer
// include nothing, customer has no relation to backend include -> backend
// add ui, // because customer has a relationship with nested ui.webApp include -> ui
// add backend, because visible ui has a relationship to backend // derived from ui.webApp -> backend.api include -> backend}
// This view includes customer and uiview { include customer, -> cloud.*}Inclua elementos somente quando eles tiverem relacionamentos de saída para elementos já visíveis:
include customer ->include cloud.* ->Entrada/saída
Seção intitulada “Entrada/saída”Inclua elementos aninhados de cloud que tenham qualquer relacionamento com elementos visíveis:
include -> cloud.* ->Personalização de relacionamentos
Seção intitulada “Personalização de relacionamentos”Relacionamentos podem ser personalizados dentro da visão:
include // Make lines red and solid cloud.* <-> amazon.* with { color red line solid }, // or only directed customer -> cloud.* with { // Override label title 'Customer uses cloud' navigateTo dynamicview1 },Navegação de relacionamentos
Seção intitulada “Navegação de relacionamentos”Para personalizar a navegação a partir de um relacionamento:
include webApp -> backend.api with { navigateTo dashboardRequestFlow }O operador where restringe os resultados aplicando condições adicionais:
// include only microservices from nestedinclude cloud.* where kind is microservice
// only microservices and not deprecatedinclude cloud.* where kind == microservice and // possible to use 'is' or '==' tag != #deprecated // possible to use 'is not' or '!='
// Use logical operatorsinclude cloud.* where not (kind is microservice or kind is webapp) and tag is not #legacy and (tag is #v1 or tag is #v2)Predicados de relacionamentos
Quando where é usado com predicados de elementos, ele é aplicado aos elementos.
Quando é usado com predicados de relacionamentos, ele é aplicado aos relacionamentos.
include // only relationships with tag #messaging cloud.* <-> amazon.* where tag is #messaging,
// only incoming http-requests -> backend where kind is http-request -[http-request]-> backend .http-request backendTambém é possível filtrar relacionamentos pela tag ou pelo tipo de seus endpoints.
include // only relationships outgoing from elements with with tag #next cloud.* -> amazon.* where source.tag is #next,
// only incoming relations of elements with kind microservice -> * where target.kind is microserviceJunto com with
É possível usar where junto com with, mas where deve ser definido primeiro:
include * where kind is microservice with { color amber }Filtro de metadados
Seção intitulada “Filtro de metadados”where também pode filtrar por valores de metadados de elementos ou relacionamentos:
// include only elements with environment="production"include cloud.* where metadata.environment is "production"
// exclude elements without a version metadata keyexclude * where not metadata.version
// combine with other filtersinclude cloud.* where metadata.environment is "production" and kind is not databaseValores booleanos de metadados podem ser comparados diretamente com true ou false (sem aspas):
// matches elements where critical is trueinclude * where metadata.critical is trueQuando um valor de metadado é um array (por exemplo, regions ['us-east-1', 'eu-west-1']), is verifica se o array contém o valor:
// matches if "us-east-1" is one of the regionsinclude * where metadata.regions is "us-east-1"Para predicados de relacionamentos, filtre pelos próprios metadados do relacionamento ou pelos metadados de seus endpoints:
include // only relationships with protocol="grpc" cloud.* -> amazon.* where metadata.protocol is "grpc",
// only relations from elements with env="production" cloud.* -> * where source.metadata.environment is "production",
// only relations to staging targets * -> * where target.metadata.environment is "staging"Os mesmos filtros de metadados funcionam com predicados exclude:
// remove relationships with protocol="http"exclude * -> * where metadata.protocol is "http"
// remove relationships targeting staging elementsexclude * -> * where target.metadata.environment is "staging"Em visões de deployment, source.metadata.* e target.metadata.* seguem as regras de metadados de deployment.
Os metadados definidos em uma instância implantada substituem os metadados do elemento correspondente no modelo.
Grupos globais de predicados
Seção intitulada “Grupos globais de predicados”Se você perceber que está repetindo os mesmos predicados em várias visões, pode defini-los como um grupo global:
global { predicateGroup microservices { include cloud.* where kind is microservice exclude * where tag is #deprecated }}
views { view of newServices { include cloud.new.* global predicate microservices }
view of newBackendServices { // Keep in mind that order is significant global predicate microservices include cloud.backend.* }}É possível agrupar elementos, e isso é renderizado como um limite ao redor deles:
view {
group { include backend }
// with title group 'Frontend' { include frontend.* }
// with style group 'Service Bus' { color amber opacity 20% border solid
include messageBroker.* }}Grupos podem ser aninhados:
view { group 'Third-parties' { group 'Integrations' { group 'Analytics' {} group 'Marketing' {} } group 'Monitoring' {} }}Grupos também podem referenciar grupos globais de predicados, permitindo reutilizar um conjunto de predicados e manter os elementos correspondentes dentro do grupo:
global { predicateGroup microservices { include cloud.* where kind is microservice }}
views { view of newServices { include cloud.new.*
group 'Microservices' { global predicate microservices } }}Predicados de estilo
Seção intitulada “Predicados de estilo”Predicados de estilo definem como os elementos são renderizados e são aplicados na ordem em que foram definidos, combinando-se com os anteriores:
view apiApp of internetBankingSystem.apiApplication {
include *
// apply to all elements style * { color muted opacity 10% }
// apply only to these elements style singlePageApplication, mobileApp { color secondary size xlarge }
// apply only to nested of apiApplication style apiApplication.* { color primary multiple true } // apply to apiApplication and nested style apiApplication._ { color primary }
// apply only to elements with specific tag style element.tag = #deprecated { color muted }
// apply to elements not tagged style element.tag != #deprecated { opacity 20% }}Estilos locais compartilhados
Seção intitulada “Estilos locais compartilhados”Estilos podem ser compartilhados dentro de um bloco views (“estilos locais”):
views { // apply to all views in this block style * { color muted opacity 10% }
view of apiApp { include * style cloud.web.* { color green } }
view of mobileApp { include * style cloud.ui.* { color amber } }}
views { // Styles from previous block are not applied here // ...}Estilos globais compartilhados
Seção intitulada “Estilos globais compartilhados”Estilos podem ser compartilhados globalmente.
Estilos globais devem ter um nome e ser definidos no bloco global:
global { // Format: // style <name> <targets> { ... } style mute_all * { color muted opacity 10% }
style applications singlePageApplication._, mobileApp._ { color secondary }
style mute_deprecated element.tag = #deprecated { color muted }}
views { view of singlePageApplication { // Styles are applied in the order they are defined // 1. Apply global style global style mute_all
// 2. Then this style cloud.* { color green }
// 3. and 4. global style applications global style mute_deprecated }}Grupos de estilos compartilhados
Seção intitulada “Grupos de estilos compartilhados”Estilos globais podem ser agrupados:
global { // Define style group styleGroup common_styles { style singlePageApplication, mobileApp { color secondary } style element.tag = #deprecated { color muted } }}
views { view mobileApp of mobileApp { include *
// Apply styles from group global style common_styles
// Override style mobileApp { color primary } }}Layout automático
Seção intitulada “Layout automático”view { include * autoLayout LeftRight 120 110}Os parâmetros são:
- direção: os valores possíveis são
TopBottom(padrão),BottomTop,LeftRight,RightLeft. - distância entre ranks: opcional, deve ser um número positivo
- distância entre nós: opcional, deve ser um número positivo
Estender visões
Seção intitulada “Estender visões”Visões podem ser estendidas para evitar duplicação, criar uma “baseline” ou, por exemplo, “slides” para uma apresentação:
views {
view view1 { include * }
view view2 extends view1 { title 'Same as View1, but with more details'
style * { color muted }
include some.backend }
// cascade inheritance view view3 extends view2 { title 'Same as View2, but with more details'
include * -> some.backend }
}Os predicados e as regras de estilo das visões estendidas são aplicados depois dos definidos nas visões ancestrais.
Uma visão estendida também herda o escopo:
views {
view view1 of cloud.backend { title 'Backend components' }
view view2 extends view1 { include api // ✅ This is OK, references 'cloud.backend.api' }
}Restrições de rank
Seção intitulada “Restrições de rank”Você pode manter elementos específicos no mesmo nível horizontal/vertical (ou empurrá-los para o início/fim do layout)
adicionando um bloco rank explícito à visão.
Essas restrições de rank são encaminhadas ao mecanismo de layout Graphviz para produzir os efeitos de layout desejados.
view checkoutFlow { include *
// keep the API nodes aligned rank same { cloud.backend.api, cloud.backend.billingApi, }
// make customers appear at the beginning of the diagram, exclusive of the elements rank source { customer }
// render reporting systems at the end, exclusive of the elements rank sink { analytics, dataWarehouse }}- Valores de rank permitidos:
same,min,max,source,sink. Se omitido,sameé assumido. - Os alvos são
FqnRefs comuns, portanto você pode referenciar elementos aninhados como em outras regras. Alvos inexistentes ou duplicados são ignorados. - A restrição afeta apenas os elementos que realmente permanecem na visão calculada. Se um predicado remover posteriormente um elemento, ele também deixa de participar do bloco
rank. - Regras de rank também participam do tiling manual de nós compostos, permitindo que restrições definidas pelo autor sejam combinadas com o layout automático em vez de entrar em conflito com ele.
Use restrições de rank com moderação — elas são mais úteis para ancorar colunas/linhas críticas (por exemplo, nós de entrada versus saída ou agrupamentos semânticos no lugar de containers) e obter um layout melhor.