Diretrizes:
|
Nome | Uma seqüência de caracteres textuais que distingue o estado de outros estados; um estado também pode ser anônimo, ou seja, não ter nenhum nome. |
---|---|
Ações de entrada/saída | As ações executadas ao entrar no estado ou sair dele. |
Transições internas | As transições que são manipuladas sem causar mudança de estado. |
Subestados | A estrutura aninhada de um estado, envolvendo subestados separados (ativos seqüencialmente) ou simultâneos (ativos concomitantemente). |
Eventos adiados | Uma lista de eventos que não são manipulados no estado, mas são adiados e enfileirados para serem manipulados pelo objeto em outro estado. |
Como mostra a Figura 1, existem dois estados especiais que podem ser definidos para a máquina de estado de um objeto. O estado inicial indica o local inicial padrão para a máquina de estado ou o subestado. Um estado inicial é representado como um círculo de preenchimento preto. O estado final indica o término da execução da máquina de estado ou que o estado confinado foi concluído. Um estado final é representado como um círculo de preenchimento preto dentro de um círculo sem preenchimento. Os estados final e inicial são, na verdade, pseudo-estados. Nenhum dos dois pode ter as partes usuais de um estado normal, exceto o nome. Uma transição de um estado inicial para um estado final pode ter o complemento completo de características, incluindo uma condição de guarda e uma ação, mas não pode ter um evento trigger.
Uma transição é um relacionamento entre dois estados indicando que um objeto no primeiro estado executará certas ações, e entrará em um segundo estado quando ocorrer um evento especificado e determinadas condições forem satisfeitas. Nessa mudança de estado, diz-se que a transição foi 'acionada'. Até que a transição seja acionada, diz-se que o objeto está no estado 'de origem'; após o seu acionamento, diz-se que o objeto está no estado 'de destino'. Uma transição tem várias propriedades:
Estado de origem | O estado afetado pela transição. Se um objeto estiver no estado de origem, uma transição de saída poderá ser acionada quando o objeto receber um evento trigger da transição e quando a condição de guarda, se houver, for satisfeita. |
---|---|
Acionador de eventos | O evento que torna a transição passível de ser acionada (contanto que sua condição de guarda seja cumprida) quando recebido pelo objeto no estado de origem. |
Condição de guarda | Uma expressão booleana que é avaliada quando a transição é disparada pela recepção do disparador de evento. Se o valor da expressão for Verdadeiro, a transição poderá ser acionada; se a expressão for Falso, a transição não será acionada. Se não houver outra transição que possa ser disparada pelo mesmo evento, o evento será perdido. |
Ação | Um cálculo indivisível executável que pode agir diretamente sobre o objeto que possui a máquina de estado e indiretamente em outros objetos visíveis ao objeto. |
Estado de destino | O estado que é ativado após a conclusão da transição. |
Uma transição pode ter várias origens (nesse caso, ela representa uma junção de vários estados simultâneos) e vários alvos (nesse caso, ela representa uma forquilha para vários estados simultâneos).
No contexto da máquina de estado, um evento é uma ocorrência de um estímulo que pode disparar uma transição de estado. Os eventos podem incluir eventos de sinais, eventos de chamada, a passagem do tempo ou uma mudança de estado. Um sinal ou uma chamada pode ter parâmetros cujos valores estão disponíveis para a transição, incluindo expressões para as condições de guarda e a ação. Também é possível haver uma transição sem disparador, representada por uma transição sem trigger de evento algum. Essas transições, também denominadas transições de conclusão, são disparadas implicitamente quando o seu estado de origem concluiu sua atividade.
Uma condição de guarda é avaliada após o evento trigger acionar a transição. É possível que haja várias transições do mesmo estado de origem e com o mesmo trigger de evento, contanto que as condições de guarda não se sobreponham. Uma condição de guarda é avaliada apenas uma vez para a transição no momento em que o evento ocorre. A expressão booleana pode fazer referência ao estado do objeto.
Uma ação é um cálculo indivisível executável, ou seja, ela não pode ser interrompida por um evento e, portanto, é executada até a sua conclusão. Isso contrasta com uma atividade, que pode ser interrompida por outros eventos. As ações podem incluir chamadas de operação (para o proprietário da máquina de estado, bem como para outros objetos visíveis), a criação ou a destruição de outro objeto, ou o envio de um sinal para outro objeto. No caso de envio de um sinal, o nome do sinal recebe como prefixo a palavra-chave 'send'.
As ações de entrada e de saída permitem que uma mesma ação seja enviada sempre que um estado entra ou sai, respectivamente. As ações de entrada e de saída permitem que isso seja feito adequadamente, sem precisar colocar ações explícitas em todas as transições de entrada e de saída. As ações de entrada e de saída não devem ter argumentos ou condições de guarda. As ações de entrada no nível mais alto da máquina de estado para um elemento de modelo podem ter parâmetros que representam os argumentos que a máquina receberá quando o elemento for criado.
As transições internas permitem que eventos sejam manipulados dentro do estado, evitando, com isso, disparar ações de entrada ou de saída. As transições internas podem ter eventos com parâmetros e condições de guarda e representam, essencialmente, manipuladores de interrupção.
Os eventos adiados são aqueles cuja manipulação é adiada até que um estado em que o evento não seja adiado se torne ativo. Quando esse estado se torna ativo, a ocorrência do evento é disparada e pode causar transições como se ele tivesse acabado de ocorrer. A implementação de eventos adiados requer a presença de uma fila interna de eventos. Quando um evento ocorre mas está listado como adiado, ele é enfileirado. Os eventos sairão da fila tão logo o objeto entre em um estado que não adie esses eventos.
Um estado simples é aquele que não possui subestrutura. Um estado que possui subestados (estados aninhados) é denominado estado composto. Os subestados podem ser aninhados em qualquer nível. Uma máquina de estados aninhados deve ter no máximo um estado inicial e um estado final. Os subestados são usados para simplificar máquinas complexas de estados simples mostrando que alguns estados são possíveis apenas dentro de um determinado contexto (o estado confinado).
Figura 3. Subestados.
A partir de uma origem externa ao estado composto confinado, uma transição pode ter como objetivo um estado composto ou um subestado. Se o seu alvo for o estado composto, a máquina de estados aninhados deverá conter um estado inicial, para o qual o controle passará após entrar no estado composto e após enviar sua ação de entrada (se houver alguma). Se o seu alvo for o estado aninhado, o controle passará para o estado aninhado após enviar a ação de entrada do estado composto (se houver alguma) e, em seguida, a ação de entrada do estado aninhado (se houver alguma).
Uma transição orientada para fora de um estado composto pode ter como sua origem o estado composto ou um subestado. Nos dois casos, o controle sai primeiro do estado aninhado (e sua ação de saída, se houver, é enviada) e, em seguida, sai do estado composto (e sua ação de saída, se houver, é enviada). Uma transição, cuja origem é o estado composto intrinsecamente, interrompe a atividade da máquina de estados aninhados.
A menos que seja especificado de outra forma, quando uma transição entra em um estado composto, a ação da máquina de estado aninhado reinicia novamente o estado inicial (a não ser que o alvo da transição seja um subestado direto). Os estados de histórico permitem que a máquina de estado entre novamente no último subestado que estava ativo antes de sair do estado composto. Um exemplo de uso de estado de histórico é apresentado na Figura 4.
Figura 4. Estado de Histórico.
Geralmente, as máquinas de estado são usadas para modelar o comportamento de um objeto ao longo de sua vida útil. Elas são especialmente necessárias quando os objetos têm comportamento dependente do estado. Os objetos que podem ter máquinas de estado são classes, subsistemas, casos de uso e interfaces (para declarar estados que devem ser satisfeitos por um objeto que realize a interface).
Nem todo objeto exige máquinas de estado. Se o comportamento de um objeto for simples, de forma que ele apenas armazene ou recupere dados, o comportamento do objeto não varia de estado e sua máquina de estado é de pouco interesse.
A modelagem da vida útil de um objeto envolve três itens: a especificação dos eventos aos quais o objeto pode responder, a resposta a esses eventos e o impacto do comportamento passado no atual. A modelagem da vida útil de um objeto também envolve definição da ordem em que o objeto pode responder coerentemente a eventos, iniciando no momento da criação do objeto e continuando até sua destruição.
Para modelar a vida útil de um objeto:
Uma máquina de estado abstrato é uma máquina de estado na qual é necessário incluir mais detalhes para que possa ser utilizada para finalidades práticas. As máquinas de estado abstrato podem ser utilizadas para definir comportamento genérico e reutilizável que será mais refinado nos elementos de modelo subseqüentes.
Figura 5. Uma máquina de estado abstrato.
Considere a máquina de estado abstrato na Figura 5. A máquina de estado simples retratada representa o nível mais abstrato de comportamento (o autômato de "controle") de diferentes tipos de elementos em sistemas direcionados a eventos. Embora eles compartilhem essa forma de alto nível, os diferentes tipos de elementos podem ter comportamentos bem diversos no estado Execução dependendo das suas finalidades. Portanto, essa máquina de estado seria melhor definida em alguma classe abstrata que servisse como a classe original para as diversas classes ativas especializadas.
Vamos, então, definir dois refinamentos diferentes dessa máquina de estado abstrato, usando herança. Esses dois refinamentos, R1 e R2, são mostrados na Figura 6. Para maior clareza, desenhamos os elementos herdados da classe pai usando uma caneta cinza.
Figura 6. Dois refinamentos da máquina de estado na Figura 5.
Os dois refinamentos diferem claramente no modo como decompõem o estado Em Execução e em como estendem a transição "inicial" original. Essas opções só podem ser feitas quando o refinamento for conhecido e, portanto, não poderiam ter sido feitas com uma única transição de extremidade-a-extremidade na classe abstrata.
A capacidade de "continuar" tanto as transições de entrada como as de saída é fundamental para o tipo de refinamento descrito acima. Pode parecer que os pontos de entrada e os estados finais, combinados com as transições de continuação, sejam suficientes para fornecer essa semântica. Mas isso não será suficiente quando houver várias transições diferentes que precisam ser estendidas.
O que é necessário para o padrão de comportamento abstrato é um modo de encadear dois ou mais segmentos de transição que sejam executados no escopo de uma única etapa indivisível. Isso significa que as transições que entram no estado hierárquico são divididas na parte de entrada que realmente encerra na fronteira do estado e na extensão que continua dentro do estado. Da mesma forma, as transições de saída que procedem de um estado hierarquicamente aninhado são segmentadas em uma parte que encerra na fronteira do estado confinado e outra parte que prossegue da fronteira do estado para o estado de destino. Esse efeito pode ser conseguido em UML com a introdução do conceito de estado em cadeia. Isso é modelado por um estereótipo (<<chainState>>) do conceito de Estado da UML. Trata-se de um estado cuja única finalidade é "encadear" mais transições automáticas (sem acionadores) em uma transição de entrada. Um estado em cadeia não possui estrutura interna - nenhuma ação de entrada, nenhuma atividade interna, nenhuma ação de saída. Também não possui transições disparadas por eventos. Ele pode ter inúmeras transições de entrada. Ele pode ter uma transição de saída sem um evento trigger; essa transição é acionada quando uma transição de entrada ativa o estado. A finalidade do estado é encadear uma transição de entrada a uma transição de saída separada. Entre as transições de entrada e a transição de saída encadeada, uma se conecta a outro estado dentro do estado armazenador e a outra de conecta a outro estado fora do estado armazenador. A finalidade de introduzir um estado em cadeia é separar a especificação interna do estado armazenador do seu ambiente externo. É uma questão de encapsulamento.
Na verdade, um estado em cadeia representa um estado de "passagem" que serve para encadear uma transição a uma transição específica de continuação. Se nenhuma transição de continuação for definida, a transição encerrará no estado em cadeia, e alguma transição em um estado confinado deverá, por fim, acionar a movimentação.
O exemplo de segmento de máquina de estado na Figura 7 ilustra estados em cadeia e suas notações. Os estados em cadeia são representados em um diagrama de máquina de estado por pequenos círculos brancos localizados dentro do estado hierárquico apropriado (essa notação é semelhante aos estados inicial e final, com os quais se parece). Os círculos são ícones do estereótipo do estado em cadeia e, em geral, são desenhados próximos à fronteira por conveniência. (Na verdade, uma variação de notação seria desenhá-los na borda do estado confinado.)
Figura 7. Estados em cadeia e transições encadeadas.
A transição encadeada neste exemplo consiste em três segmentos de transição encadeada e1/a11-/a12-/a13. Quando o sinal e1 é recebido, ocorre a transição rotulada e1/a11, sua ação a11 é executada, e o estado em cadeia c1 é alcançado. Em seguida, ocorre a transição de continuação entre c1 e c2 e, por fim, como c2 também é um estado em cadeia, ocorre a transição de c2 para S21. Se todos os estados ao longo desses caminhos tiverem ações de entrada e de saída, a seqüência real de ações executadas é seguida da seguinte forma:
Tudo isso é executado no escopo de um único passo indivisível.
Isso deve ser comparado com a semântica de execução de ação da transição direta e2/a2, que é:
Rational Unified Process
|