Pular para o conteúdo

Fluxos: uma sequência

Um fluxo conta um caso de uso como uma sequência de mensagens, no estilo de um diagrama de sequência. Ele é a resposta do cfourdev à visão dynamic do C4.

Um fluxo não inventa caixa nenhuma: ele percorre as que já existem. E cada passo deveria corresponder a uma seta que o modelo já declara — quando não corresponde, o desenho marca o passo, porque o fluxo acabou de encontrar um buraco na estrutura.

model/reservas/fluxo-reservar.yaml
kind: flow
id: reservar
title: Reservar uma sala
scope: reservas
level: container
order: 10
main:
name: Sala livre
outcome: success
participants:
- colaborador
- painel
- api
steps:
- from: colaborador
to: painel
label: Escolhe sala e horario
- to: api
label: Pede a reserva
# Da API para o componente que faz o trabalho: nao ha seta declarada entre os
# dois, e nem precisa haver — um deles esta DENTRO do outro.
- to: servico-de-reserva
label: Confirma a reserva
- id: conflito
to: repositorio-de-reservas
label: Procura conflito no horario
reply: Nenhum conflito
- from: servico-de-reserva
to: publicador
label: Pede a publicacao
- to: fila-de-sincronizacao
kind: async
label: Enfileira a reserva confirmada
- from: api
to: painel
label: Reserva confirmada
- to: colaborador
label: Mostra a confirmacao
paths:
- id: ocupada
name: Sala ocupada
outcome: failure
from: conflito
steps:
- to: servico-de-reserva
label: Ja existe reserva nesse horario
- from: api
to: painel
label: Recusa com o motivo
- to: colaborador
label: Sugere outro horario
CampoObrigatórioO que faz
idnãoo identificador. Sem ele, o nome do arquivo
titlenãoo título exibido
scopenãoonde o caso de uso acontece. Dá a trilha e o lugar na árvore — não escolhe os participantes
levelnãoo nível em que o fluxo abre. Sem ele, o nível mais fino que os passos citam
ordernãoa posição na barra lateral
mainnãoname e outcome do caminho principal
participantsnãofixa quem são as colunas e a ordem delas
stepssimas mensagens do caminho principal
pathsnãoos caminhos alternativos
tags, metanãoetiquetas e metadados
steps:
- from: colaborador
to: painel
label: Escolhe sala e horario
- to: api
label: Pede a reserva
CampoObrigatórioO que faz
tosimquem recebe
fromnãoquem envia. Omitido, herda o to do passo anterior
labelnãoo texto ao lado da linha. Sem ele, o rótulo da seta declarada
kindnãoo tipo da seta. Sem ele, o da seta declarada
replynãouma resposta curta, tracejada, na própria linha
descriptionnãoo texto longo, revelado ao passar o mouse
idnãoum identificador local, necessário só para ser ponto de desvio

O from implícito é o que torna a maioria dos fluxos curta: quase toda sequência é uma corrente, e escrever from em todo passo seria repetir o passo anterior. No primeiro passo não há o que herdar, e omiti-lo é erro.

Os três casos em que um passo não precisa de seta declarada

Seção intitulada “Os três casos em que um passo não precisa de seta declarada”

Um passo cuja conversa não existe no modelo recebe um aviso e é desenhado marcado. Três situações são exceção, e não geram aviso nenhum:

Contenção. Um passo da API para um componente dentro dela é sustentado pelo modelo tanto quanto uma seta seria — a contenção é a relação entre os dois. Pedir uma seta ali seria pedir para escrever algo que o vocabulário do C4 não tem.

Chamada interna. Um passo de uma caixa para ela mesma é uma ação interna, e não uma integração.

A resposta. Um passo no sentido contrário ao de uma seta declarada é sustentado por ela — a resposta volta pelo mesmo caminho da pergunta. O rótulo não é herdado, porque o rótulo declarado descreve a chamada, e não a resposta.

- id: conflito
to: repositorio-de-reservas
label: Procura conflito no horario
reply: Nenhum conflito

Desenha uma linha tracejada de volta, logo abaixo. É para a resposta que não merece um passo próprio. Uma resposta que muda o rumo da história merece um passo.

paths:
- id: ocupada
name: Sala ocupada
outcome: failure
from: conflito
steps:
- to: servico-de-reserva
label: Ja existe reserva nesse horario
CampoObrigatórioO que faz
idsimo identificador do caminho dentro do fluxo
namenãoo nome no seletor. Sem ele, o próprio id
outcomenãocomo ele termina. Padrão: alternate
fromnãoo id do passo de onde ele desvia, inclusive
stepssimos passos deste caminho

from: conflito significa: os passos do caminho principal até conflito, incluindo-o, são reproduzidos esmaecidos como contexto, e daí em diante vale o que está escrito aqui. Você escreve só o que difere.

Um caminho sem from começa do zero.

O primeiro passo de um caminho que desvia herda o to do passo de desvio, do mesmo jeito que dentro de uma sequência.

outcomeRótuloCor
successSucessoverde
failureFalhavermelho
alternateAlternativoâmbar

A cor fica no seletor que escolhe o caminho, e nunca nas mensagens — um final infeliz é uma leitura do fluxo, e não uma propriedade de uma seta. O vocabulário é aberto: flowOutcomes em workspace.yaml aceita os seus.

participants:
- colaborador
- painel
- api

Fixa quem são as primeiras colunas e em que ordem. Quem não está na lista entra na ordem em que aparece pela primeira vez. Listar a espinha do caso de uso costuma bastar.

Um participante que não aparece em passo nenhum recebe aviso.

Um fluxo escrito no nível mais fino que o modelo tem pode ser lido mais acima: o seletor de nível do leitor sobe as pontas de cada mensagem. Quando as duas pontas caem na mesma caixa, aquela mensagem desaparece — ela aconteceu dentro de uma caixa só.

É por isso que vale escrever o fluxo fino: a leitura grosseira é derivada, e a fina não seria.

Diagramas guardam a posição das caixas em .layout/. Fluxos não guardam nada: toda coordenada vem da ordem das colunas e da ordem das mensagens. A única decisão de apresentação é a ordem de participants, e ela é escrita.

Projetos — como dividir um modelo grande.