Criar Realizações de Casos de Uso
O Produto de Trabalho:Projetar Realização de Casos de Uso fornece uma
maneira de rastrear o comportamento do Modelo de Design no Modelo de Casos de Uso e organiza as colaborações no Modelo
de Design com base no conceito de Caso de Uso.
Crie uma Realização de Casos de Uso de Design no Modelo de Design para cada Caso de Uso a ser projetado. O nome da
Realização de Casos de Uso de Design deve ser o mesmo do Caso de Uso associado e uma relação de "realizações" deve ser
estabelecida, da realização de casos de uso para seu caso de uso associado.
|
Descrever Interações entre Objetos de Design
Para cada realização de casos de uso, ilustre as interações entre seus objetos de design participantes, criando um ou
mais diagramas de seqüência. As versões anteriores desses diagramas podem ter sido criadas durante a Tarefa: Análise de Casos de Uso. Tais "versões de análise" das
realizações de casos de uso descrevem interações entre as classes
de análise. Elas devem ser desenvolvidas para descrever interações entre elementos de design.
A atualização dos diagramas de seqüência envolve os seguintes passos:
-
Identificar cada objeto que participa do fluxo do caso de uso. Isso é feito ao instanciar classes e subsistemas de
design identificados na Tarefa: Identificar Elementos de Design. Em sistemas de tempo
real, você também identificará as instâncias de cápsula que participam do fluxo do caso de uso.
-
Represente cada objeto participante em um diagrama de seqüência. Faça uma linha de vida para cada objeto
participante no diagrama de seqüência. Para representar os subsistemas de design, existem algumas opções:
-
É possível mostrar as instâncias do subsistema no diagrama de seqüências.
-
É possível utilizar as interfaces realizadas pelo subsistema. Essa é a forma preferencial nos casos em que
se deseja mostrar que qualquer elemento de modelo que realiza a mesma interface pode ser utilizado no lugar
da interface. Se optar por mostrar as interfaces no diagrama de seqüência, certifique-se de que nenhuma
mensagem seja enviada da interface para outros objetos. O motivo disso é que as interfaces encapsulam
completamente a realização interna de suas operações. Portanto, não se pode ter certeza de que todos os
elementos de modelo que realizam a interface serão projetados de fato da mesma maneira. Portanto, nos
diagramas de seqüência, nenhuma mensagem deve ser mostrada sendo enviada das interfaces.
-
É possível utilizar o componente para representar o subsistema nos diagramas de seqüência. Utilize o
componente nos casos em que deseja mostrar que um subsistema específico responde a uma mensagem. Nesse
caso, é possível mostrar as mensagens que estão sendo enviadas do componente para outros objetos.
Observe que esses são os diagramas de seqüência no nível do sistema que mostram como interagem as instâncias
dos elementos de design de nível superior (normalmente, subsistemas e interfaces de subsistemas). Diagramas de
seqüência mostrando o design interno de subsistemas são produzidos separadamente, como parte da Tarefa: Design de Subsistema.
-
Observe que as interações de um objeto ativo são normalmente descritas usando colaborações de especificação e
máquinas de estado. Elas seriam utilizadas aqui para mostrar como as mensagens podem ser enviadas para ativar
objetos por outros elementos do sistema em uma realização de caso de uso maior. No uso típico, os objetos
ativos são encapsulados dentro de subsistemas, para a finalidade desta tarefa, de modo que a realização de
casos de uso consista em um conjunto de subsistemas em interação. As interações definem as responsabilidades e
interfaces dos subsistemas. Dentro dos subsistemas, os objetos ativos representam encadeamentos simultâneos de
execução. Os subsistemas permitem que o trabalho seja dividido entre as equipes de desenvolvimento, com as
interfaces servindo como contratos formais entre as equipes. Para sistemas de tempo real, você utilizará o Produto de Trabalho: Cápsulas, para representar os objetos
ativos.
Uma nota secundária sobre a exibição das mensagens provenientes dos subsistemas: a restrição de mensagens
somente a interfaces reduz o acoplamento entre elementos de modelo e aprimora a resiliência do design. Sempre
que possível, tente fazer isso e, quando houver mensagens dos subsistemas para elementos do modelo que não
sejam da interface, procure oportunidades para alterá-las para mensagens para interfaces a fim de melhorar o
desacoplamento no modelo.
-
Represente a interação que ocorre com agentes. Represente cada instância de agente e objeto externo com os quais os
objetos participantes interagem por uma linha de vida no diagrama de seqüência.
-
Ilustre a mensagem enviada entre os objetos participantes. O fluxo de eventos inicia no topo do diagrama e continua
na ordem descendente, indicando um eixo cronológico vertical. Ilustre a mensagem enviada entre os objetos, criando
mensagens (setas) entre as linhas de vida. O nome de uma mensagem deve ser o nome da operação disparada pela
mensagem. Nos estágios iniciais do design, poucas operações serão designadas aos objetos, por isso talvez você
tenha de deixar de fora essas informações e dar à mensagem um nome temporário; tais mensagens são chamadas de "não
designadas." Posteriormente, quando tiver descoberto mais a respeito das operações dos objetos participantes,
atualize o diagrama de seqüências, "designando" as mensagens com essas operações.
-
Descreva a ação de um objeto ao receber uma mensagem. Isso é feito anexando um script à mensagem correspondente.
Coloque esses scripts na margem do diagrama. Use um texto estruturado ou um pseudocódigo. Se você usar um
pseudocódigo, certifique-se de que tenha usado construções na linguagem de implementação para facilitar a
implementação das operações correspondentes. Quando a pessoa responsável pela classe de um objeto atribuir e
definir suas operações, os scripts do objeto fornecerão uma base para esse trabalho.
Documentação do comportamento de caso de uso executado pelos objetos em um diagrama de seqüência.
Quando tiver distribuído o comportamento entre os objetos, considere como o fluxo será controlado. Você localizou os
objetos presumindo que eles interagiriam de uma certa maneira na realização de casos de uso e teriam uma determinada
função. Ao distribuir o comportamento, você pode começar a testar essas suposições. Em algumas partes do fluxo, pode
ser preferível utilizar uma estrutura descentralizada; em outras, prefira uma estrutura centralizada. Para obter as
definições dessas variantes e as recomendações sobre quando utilizar os dois tipos de estrutura, consulte Técnica: Diagramas de Seqüência.
Você poderá precisar de novos objetos nesse ponto, por exemplo, se estiver utilizando uma estrutura centralizada e
precisar de um novo objeto para controlar o fluxo. Lembre-se de que qualquer objeto adicionado ao modelo de design deve
atender aos requisitos feitos em relação do modelo de objeto.
Durante a Tarefa: Análise Arquitetural, mecanismos de análise foram
identificados. Durante a Tarefa:
Identificar Mecanismos de Design, mecanismos de análise são refinados em mecanismos de design, o mapeamento dos
mecanismos de análise para os mecanismos de design são capturados no Documento de Arquitetura de Software e os mecanismos de design são
documentados nas Diretrizes Específicas do Projeto.
Durante essa tarefa, Design de Caso de Uso, todos os mecanismos de design aplicáveis são incorporados nas realizações
de casos de uso. O designer pesquisa os mecanismos de design disponíveis e determina aqueles que se aplicam à
realização de casos de uso que está sendo desenvolvida, trabalhando dentro das recomendações e diretrizes documentadas
no Documento de Arquitetura de Software e nas Diretrizes de Design.
Nota: O mecanismo de design aplicável pode ter sido identificado na Tarefa: Análise
de Casos de Uso, durante a qual as classes de análise podem ter sido "marcadas" com um mecanismo de análise
específico, indicando que uma determinada parte da funcionalidade precisou ser manipulada no design. Em tal
caso, os mecanismos de design aplicáveis são aqueles associados aos mecanismos de análise com os quais foram marcadas
as classes de análise que participam da realização de casos de uso
O Designer incorpora os mecanismos de design aplicáveis nas realizações de casos de uso, incluindo nas realizações de
casos de uso os elementos de design necessários e as interações de elementos de design, conforme as regras de uso
documentadas nas Diretrizes de Design.
Descreva cada variante de fluxo em um diagrama de seqüência separado. Diagramas de seqüência geralmente são preferíveis
ao diagrama de comunicação, visto que sua leitura tende a ser mais fácil quando o diagrama precisa conter o nível de
detalhe que normalmente se deseja obter ao projetar o sistema.
Comece descrevendo o fluxo básico, que é o mais comum ou o fluxo de eventos mais importante. Em seguida, descreva as
variantes, como os fluxos excepcionais. Você não precisará descrever todos os fluxos de eventos, desde que empregue e
exemplifique todas as operações dos objetos participantes. Desse modo, fluxos muito triviais poderão ser omitidos, como
aqueles que só se concentram em um objeto.
Estude o caso de uso para verificar se há outras variantes de fluxo além das já descritas na captura e na análise de
requisitos, por exemplo, aquelas que dependem de implementação. À medida que for identificando novos fluxos, descreva
cada um deles em um diagrama de seqüência. Veja a seguir alguns exemplos de fluxos excepcionais.
-
Manipulação de erros. Se uma interface relatar que um erro ocorreu em sua comunicação com algum sistema
externo, por exemplo, o caso de uso deverá lidar com isso. Uma possível solução é abrir uma nova rota de
comunicação.
-
Manipulação de tempo limite. Se o usuário não responder dentro de um certo período, o caso de uso deverá
tomar algumas medidas especiais.
-
Manipulação de entrada incorreta nos objetos que participam do caso de uso. Erros como este podem se
originar de uma entrada incorreta do usuário.
Você pode descrever um caminho alternativo de um fluxo como um fluxo opcional em vez de como uma variante. A lista a
seguir inclui dois exemplos de fluxos opcionais.
-
Ao enviar um sinal, o agente decide, a partir de várias opções, a ação a ser executada em seguida pelo caso de uso.
O caso de uso solicitou que o agente responda sim ou não a uma pergunta, por exemplo ou forneceu ao agente uma
variedade de funções que o sistema pode executar no estado atual do caso de uso.
-
O caminho de fluxo varia dependendo do valor dos relacionamentos ou dos atributos armazenados. O fluxo de eventos
subseqüente depende do tipo de dado a ser processado.
Se desejar que um fluxo opcional ou qualquer subfluxo complexo fique especialmente destacado, use um diagrama de
seqüência separado. Cada diagrama de seqüência separado deve ser referido no diagrama de seqüência do fluxo principal
de eventos através de scripts, texto ou anotações nas margens para indicar onde o comportamento do subfluxo ou o
comportamento opcional ocorre.
Quando o comportamento de fluxo opcional ou excepcional puder ocorrer em qualquer parte, por exemplo, o comportamento
executado quando um determinado evento ocorre, o diagrama de seqüência do fluxo principal de eventos deverá ser anotado
para indicar que quando o evento ocorrer, o comportamento descrito no diagrama de seqüência opcional/excepcional será
executado. Você também pode, no caso de um comportamento significativo controlado por eventos, utilizar diagramas de
estados para descrever o comportamento do sistema. obter informações adicionais, consulte Diretriz: Diagrama de Estados.
|
Simplificar Diagramas de Seqüência Utilizando Subsistemas (Opcional)
Quando um caso de uso é realizado, o fluxo de eventos é geralmente descrito em termos dos objetos de execução , ou
seja, como uma interação entre os objetos de design. Para simplificar os diagramas para identificar o comportamento
reutilizável, talvez seja necessário encapsular um subfluxo de eventos dentro de um subsistema. Nesse caso, grandes
subseções do diagrama de seqüência serão substituídas por uma única mensagem para o subsistema. No sistema, um diagrama
de seqüências separado pode ilustrar as interações internas do subsistema que fornecem o comportamento exigido (para
obter informações adicionais, consulte Tarefa: Design de
Subsistema).
As subseqüências de mensagens dentro dos diagramas de seqüência deverão ser encapsuladas dentro de uma subsistema
quando:
-
A subseqüência ocorrer repetidamente em diferentes realizações de casos de uso; isto é, as mesmas mensagens (ou
semelhantes) são enviadas para os mesmos objetos (ou semelhantes), fornecendo o mesmo resultado final. A frase
'semelhante' é utilizada porque um trabalho de design poderá precisar tornar o comportamento reutilizável.
-
A subseqüência ocorre em apenas uma realização de casos de uso, mas espera-se que seja executada repetidamente em
futuras iterações ou em sistemas semelhantes no futuro. O comportamento poderá criar um componente reutilizável
adequado.
-
A subseqüência ocorre em apenas uma realização de casos de uso, é complexa apesar de ser facilmente encapsulada,
precisa ter a responsabilidade de uma pessoa ou equipe e fornece um resultado bem definido. Nesses tipos de
situações, o comportamento complexo geralmente exige um conhecimento técnico ou um conhecimento de domínio
especial, e, conseqüentemente, é bem adequado para ser encapsulado dentro de um subsistema.
-
A subseqüência é determinada para ser encapsulada em um componente substituível (consulte Conceito: Componente). Nesse caso, um subsistema é a representação apropriada
para o componente dentro do modelo de design.
Uma realização de casos de uso pode ser descrita, se necessário, em vários níveis na hierarquia do subsistema. As
linhas de vida no diagrama do meio representam subsistemas; as interações nos círculos representam a interação interna
dos membros do subsistema em resposta à mensagem.
Vantagens dessa abordagem:
-
As realizações de casos de uso tornam-se menos desordenadas, especialmente se o design interno de alguns
subsistemas for complexo.
-
As realizações de casos de uso podem ser criadas antes que os designs internos do subsistema sejam criados; isso é
útil, por exemplo, em ambientes de desenvolvimento paralelos (consulte "Como Trabalhar em Paralelo").
-
As realizações de casos de uso tornam-se mais genéricas e fáceis de serem alteradas, especialmente se um subsistema
precisar ser substituído por outro.
Exemplo:
Considere o seguinte diagrama de seqüência, que faz parte de uma realização do caso de uso Chamada Local:
Nesse diagrama, as classes exibidas em cinza pertencem ao subsistema Administração de Rede; as outras classes pertencem
ao subsistema Administração de Assinantes. Isso implica em um diagrama de seqüência de vários subsistemas , ou seja, em
um diagrama no qual todos os objetos que participam do fluxo de eventos foram incluídos, independentemente de suas
classes estarem ou não em diferentes subsistemas.
Como alternativa, podemos mostrar a chamada de comportamento no subsistema Administração de Rede e o exercício de uma
interface específica nesse subsistema. Vamos considerar que o subsistema Administração de Rede forneça uma interface
ICoordinator, usada pelo subsistema Administração de Assinantes:
Essa interface é realizada pela classe Coordenador dentro de Administração de Rede. Nesse caso, podemos usar o próprio
subsistema Administração de Rede e sua interface ICoordinator no diagrama de seqüência, em vez das instâncias de
classes dentro de Administração de Rede:
Observe que as instâncias de classe Coordenador, Informações sobre Dígitos e Rede são substituídas pelo subsistema que
as contêm. Todas as chamadas para o subsistema são feitas através da interface ICoordinator.
Exibição de Interfaces nas Linhas de Vida
Para haver uma capacidade de substituição dos subsistemas que realizam a mesma interface, apenas as interfaces desses
subsistemas devem estar visíveis nas interações (e nos diagramas em geral); caso contrário, as interações (ou os
diagramas) precisarão ser alteradas quando um subsistema for substituído pelo outro.
Exemplo:
Podemos incluir apenas a interface ICoordinator, mas não seu subsistema provedor, em um diagrama de seqüência:
Enviar uma mensagem para uma linha de vida de interface significa que qualquer subsistema que realize a interface
poderá ser substituído pela interface do diagrama. Observe que a linha de vida da interface ICoordinator não possui
mensagens de saída, visto que diferentes subsistemas que realizam a interface poderão enviar mensagens diferentes. No
entanto, se você desejar descrever os tipos de mensagens a serem enviadas (ou com permissão para serem enviadas) de
qualquer subsistema que esteja realizando a interface, essas mensagens poderão partir da linha de vida da interface.
Em alguns casos, pode ser apropriado desenvolver um subsistema de forma mais ou menos independente e em paralelo com o
desenvolvimento de outros subsistemas. Para isso, é necessário primeiro encontrar dependências de subsistema,
identificando as interfaces entre eles.
O trabalho pode ser realizado da seguinte maneira:
-
Concentre-se nos requisitos que afetam as interfaces entre os subsistemas.
-
Faça esquemas das interfaces necessárias, mostrando as mensagens que passarão pelas bordas do subsistema.
-
Desenhe diagramas de seqüência em termos dos subsistemas para cada caso de uso.
-
Refine as interfaces necessárias para fornecer mensagens.
-
Desenvolva cada subsistema em paralelo e use as interfaces como instrumentos de sincronização entre as equipes de
desenvolvimento.
Você também pode escolher se deseja ordenar os diagramas de seqüência em termos dos subsistemas ou em termos apenas de
suas interfaces. Em alguns projetos, pode até ser necessário implementar as classes, fornecendo as interfaces antes de
você continuar com o resto da modelagem.
|
Descrever Comportamento Relacionado a Persistência
Toda a meta do paradigma orientado a objetos é encapsular os detalhes de implementação. Por isso, com relação à
persistência, é preferível ter um objeto persistente que se pareça exatamente um objeto transiente. Não
precisamos estar cientes de que o objeto é persistente ou tratá-lo de forma diferente do que trataríamos qualquer outro
objeto. Essa pelo menos é a meta.
Na prática, talvez haja ocasiões em que o aplicativo precise controlar vários aspectos da persistência:
-
quando objetos persistentes forem lidos e gravados
-
quando objetos persistentes forem excluídos
-
como as transações são administradas
-
como o controle de bloqueio e simultaneidade é atingido
Existem dois casos a serem considerados: o tempo inicial no qual o objeto é gravado no armazenamento de objetos
persistentes e as horas subseqüentes em que o aplicativo deseja atualizar o armazenamento de objetos persistentes com
uma alteração no objeto.
Em qualquer um desses dois casos, o mecanismo específico depende das operações suportadas pelo framework de
persistência. Em geral, o mecanismo usado consiste no envio de uma mensagem para o framework de persistência para criar
o objeto persistente. Uma vez que um objeto seja persistente, o framework de persistência é inteligente o suficiente
para detectar mudanças subseqüentes no objeto persistente e gravá-las no armazenamento de objetos persistentes quando
necessário (em geral, quando uma transação for comprometida).
Um exemplo de objeto persistente sendo criado é mostrado abaixo:
O objeto PersistenceMgr é uma instância de VBOS, um framework de persistência. O OrderCoordinator cria um Pedido
persistente, enviando-o como argumento de uma mensagem 'createPersistentObject' para o PersistenceMgr.
Em geral, não é necessário modelar explicitamente isso, a menos que seja importante saber que o objeto está
sendo armazenado explicitamente em um momento específico de uma seqüência de eventos. Se as operações subseqüentes
precisarem consultar o objeto, ele deverá existir no banco de dados e, portanto, será importante saber que o objeto
existirá lá.
A recuperação de objetos do armazenamento de objetos persistentes é necessária antes que o aplicativo envie mensagens
para esse objeto. Lembre-se de que o trabalho em um sistema orientado a objetos é executado através do envio de
mensagens para objetos. Mas se o objeto para o qual você deseja enviar uma mensagem estiver no banco de dados mas não
na memória ainda, haverá um problema: você não conseguirá enviar uma mensagem para algo que ainda não existe!
Em resumo, você precisa enviar uma mensagem para um objeto que saiba como consultar o banco de dados, recuperar o
objeto correto e instanciá-lo. Somente depois disso você poderá enviar a mensagem original que pretendia enviar. O
objeto que instancia um objeto persistente às vezes é chamado de depósito de informações. Um objeto depósito
de informações é responsável por criar instâncias de objetos, incluindo objetos persistentes. Com base em uma
consulta, o depósito de informações poderia ser designado para retornar um conjunto de um ou mais objetos que
correspondessem à consulta.
Em geral, os objetos estão tão bem conectados uns aos outros através de suas associações que é comum ser necessário
recuperar apenas o objeto raiz em um gráfico de objetos; o restante é "extraído" do banco de dados de forma
essencialmente transparente, de acordo com suas respectivas associações com o objeto raiz. (Um mecanismo de
persistência adequado é sensível a isso: ele só recupera objetos quando eles são necessários; caso contrário,
acabaríamos tentando instanciar um grande número de objetos sem necessidade. A recuperação de objetos antes que sejam
necessários é um dos principais problemas de desempenho causados por mecanismos de persistência simplistas.)
O exemplo a seguir mostra como a recuperação de um objeto do armazenamento de objetos persistentes pode ser modelada.
Em um diagrama de seqüências real, o DBMS não seria mostrado, visto que deveria ser encapsulado no objeto depósito
de informações.
O problema com objetos persistentes é que eles persistem! Ao contrário dos objetos transientes que simplesmente
desaparecem quando o processo que os criou é eliminado, os objetos persistentes existem até serem excluídos
explicitamente. Por isso, é importante excluir o objeto quando ele não estiver mais sendo utilizado.
O problema é que isso é difícil de ser determinado. Só porque um aplicativo terminou de usar o objeto não significa que
todos os aplicativos, atuais e futuros, também terminaram de usá-lo. E como os objetos não só podem como de fato
possuem associações sobre as quais nem mesmo sabem, nem sempre é fácil descobrir se é correto excluir um objeto.
Em design, isso pode ser representado semanticamente, utilizando gráficos de estado: quando o objeto atinge o
estado final, pode-se dizer que ele está liberado. Os desenvolvedores responsáveis pela implementação das
classes persistentes poderão usar, então, as informações do diagrama de estados para disparar o comportamento
apropriado do mecanismo de persistência a fim de liberar o objeto. A responsabilidade do Designer da realização de
casos de uso é chamar as operações apropriadas para fazer com que o objeto atinja seu estado final quando é
adequado excluí-lo.
Se um objeto estiver muito bem conectado a outros objetos, poderá ser difícil determinar se ele pode ser excluído.
Visto que um objeto depósito de informações conhece a estrutura do objeto e também dos demais aos quais ele está
conectado, muitas vezes é útil carregar o objeto depósito de informações com uma classe cuja responsabilidade seja
determinar se uma instância específica pode ser excluída. A estrutura de persistência também pode fornecer suporte para
esse recurso.
As transações definem um conjunto de chamadas de operação que são indivisíveis, isto é ou são todas executadas
ou nenhuma delas é executada. No contexto da persistência, uma transação define um conjunto de mudanças para um
conjunto de objetos que são todas executadas ou nenhuma é executada. As transações oferecem consistência, assegurando
que conjuntos de objetos passem de um estado consistente para outro.
Há várias opções que mostram transações em Realizações de Casos de Uso:
-
Textualmente. Usando scripts na margem do diagrama de seqüência, é possível documentar as fronteiras de
transação conforme mostrado abaixo. Este método é simples e permite o uso de qualquer número de mecanismos para
implementar a transação.
Representação das fronteiras de transação usando anotações textuais.
-
Utilizando Mensagens Explícitas. Se o mecanismo de gerenciamento de transação usado empregar mensagens
explícitas para iniciar e encerrar transações, essas mensagens poderão ser mostradas explicitamente no diagrama de
seqüência, conforme mostrado abaixo:
Diagrama de seqüência mostrando mensagens explícitas para iniciar e encerrar transações.
Manipulando Condições de Erro
Se não for possível executar todas as operações de uma transação (geralmente, por causa de um erro ocorrido), a
transação será interrompida e todas as mudanças feitas durante a transação serão revertidas. Condições de erro
antecipadas muitas vezes representam fluxos de eventos excepcionais em casos de uso. Em outros casos, as condições de
erro ocorrem devido a alguma falha no sistema. As condições de erro também devem ser documentadas em interações.
Exceções e erros simples podem ser mostrados na interação onde ocorreram; exceções e erros complexos podem exigir suas
próprias interações.
Os modos de falha de objetos específicos podem ser mostrados em diagramas de estados. O fluxo condicional do tratamento
de controle desses modos de falha pode ser mostrado na interação em que o erro ou a exceção ocorreu.
A simultaneidade descreve o controle de acesso a recursos críticos do sistema durante uma transação. Para manter o
sistema em um estado consistente, uma transação pode exigir que ele tenha acesso exclusivo a determinados
recursos-chave do sistema. A exclusividade pode incluir a capacidade de leitura de um conjunto de objetos, a gravação
de um conjunto de objetos ou a leitura e a gravação de um conjunto de objetos.
Vamos examinar um exemplo simples do motivo pelo qual poderemos precisar restringir o acesso a um conjunto de objetos.
Digamos que esteja em execução um sistema simples de entrada de pedidos. As pessoas ligam para fazer pedidos e nós
processamos e enviamos os pedidos. Podemos considerar o pedido como um tipo de transação.
Para ilustrar a necessidade de controle de simultaneidade, vamos supor que eu ligue solicitando um novo par de botas
para caminhada. Quando a entrada do pedido é feita no sistema, ele verifica se as botas que desejo, no tamanho correto,
existem no estoque. Se existirem, é feita a reserva desse par para que ninguém mais possa comprá-las antes do
envio do pedido. Quando o pedido é enviado, as botas são retiradas do estoque.
Durante o período entre o pedido ser feito e enviado, as botas ficam em um estado especialelas estão no
estoque, mas estão "comprometidas" com meu pedido. Se o meu pedido for cancelado por algum motivo (se eu mudar de idéia
ou o meu cartão de crédito tiver expirado), as botas voltarão para o estoque. Quando o pedido for enviado, vamos
considerar que nossa pequena empresa não deseje manter um registro dessas botas.
A meta da simultaneidade, como nas transações, é assegurar que o sistema passe de um estado consistente para outro.
Além disso, a simultaneidade procura assegurar que uma transação tenha todos os recursos de que precisa para concluir
seu trabalho. O controle da simultaneidade pode ser implementado de várias maneiras diferentes, incluindo bloqueio de
recursos, semáforos, travas de memória compartilhadas e espaços de trabalho privados.
Em um sistema orientado a objetos, é difícil saber apenas pelos padrões de mensagem se uma mensagem específica pode
causar uma mudança de estado em um objeto. Além disso, diferentes implementações podem prevenir para a necessidade de
restringir o acesso a determinados tipos de recursos; por exemplo, algumas implementações fornecem a cada transação sua
própria visão do estado do sistema no início da transação. Nesse caso, outros processos podem alterar o estado de um
objeto sem afetar a 'visualização' de qualquer outra transação em execução.
Para evitar restrição da implementação, no design desejamos simplesmente indicar os recursos aos quais a transação deve
ter acesso exclusivo. Usando o exemplo anterior, desejamos indicar que precisamos de acesso exclusivo às botas que
foram pedidas. Uma alternativa simples é anotar a descrição da mensagem que está sendo enviada, indicando que o
aplicativo precisa de acesso exclusivo ao objeto. O Implementador poderá, então, usar essa informação para determinar a
melhor maneira de implementar o requisito de simultaneidade. Um exemplo de diagrama de seqüência mostrando a anotação
das mensagens que exigem acesso exclusivo é mostrado abaixo. A suposição é que todos os bloqueios sejam liberados
quando a transação for concluída.
Exemplo mostrando o controle de acesso anotado em um diagrama de seqüência.
O motivo para a não restrição do acesso a todos os objetos necessários em uma transação é que muitas vezes apenas
alguns objetos devem ter restrições de acesso; restringir o acesso a todos os objetos que participam de uma transação
desperdiça recursos valiosos e poderia criar, em vez de evitar, gargalos de desempenho.
|
Refinar a Descrição do Fluxo de Eventos
No fluxo de eventos da realização de casos de uso, você talvez precise acrescentar uma descrição aos diagramas de
seqüência, nos casos em que o fluxo de eventos não fica totalmente claro apenas com o exame das mensagens enviadas
entre os objetos participantes. Alguns exemplos incluem casos onde são necessárias anotações de tempo, observações
sobre comportamento condicional ou algum esclarecimento sobre o comportamento da operação para facilitar a leitura dos
diagramas por observadores externos.
O fluxo de eventos é delineado inicialmente na Tarefa: Análise
de Caso de Uso. Nesse passo, você refina o fluxo de eventos conforme necessário para esclarecer os diagramas de
seqüência.
Muitas vezes, o nome da operação não é suficiente para entender por que a operação está sendo executada. Anotações de
texto ou scripts na margem do diagrama podem ser necessários para esclarecer o diagrama de seqüência. Eles também podem
ser necessários para representar o fluxo de controle, como passos de decisão, looping e ramificação. Além disso, marcas
de texto talvez sejam necessárias para correlacionar os pontos de extensão no caso de uso com locais específicos nos
diagramas de seqüência.
Exemplos anteriores dentro dessa tarefa já ilustraram várias maneiras diferentes de anotar diagramas de seqüência.
|
Unificar Classes e Subsistemas de Design
Conforme os casos de uso são realizados, é necessário unificar as classes e subsistemas de design identificados para
assegurar a homogeneidade e consistência do Modelo de
Design.
Pontos a serem considerados:
-
Os nomes dos elementos do modelo devem descrever sua função.
-
Evite nomes semelhantes e sinônimos porque eles dificultam a distinção dos elementos do modelo.
-
Mescle elementos do modelo que definam um comportamento semelhante ou que representem o mesmo fenômeno.
-
Mescle classes de entidades que representam o mesmo conceito ou que possuem os mesmos atributos, mesmo que seu
comportamento definido seja diferente.
-
Use a herança para abstrair elementos do modelo, o que tende a tornar o modelo mais robusto.
-
Ao atualizar um elemento do modelo, atualize também a descrição do fluxo de eventos correspondente das realizações
de casos de uso.
|
Avaliar Seus Resultados
|