Tarefa: Identificar Elementos de Design |
| |
|
Essa tarefa explica como identificar Subsistemas, Classes, interfaces, Eventos e Sinais. |
Disciplinas: Análise e Design |
|
Objetivo
-
Analisar interações de classes de análise para
identificar elementos de modelo de designs
|
Relacionamentos
Funções | Executor Primário:
| Executores Adicionais:
|
Entradas | Obrigatório:
| Opcional:
|
Saídas |
|
Descrição Principal
A Tarefa: Análise de Caso de Uso resulta em classes de análise,
que representam coisas conceituais que podem executar o comportamento. Em design, classes de análise
evoluem para vários tipos de elementos de design:
-
classes, para representar um conjunto refinado de responsabilidades;
-
subsistemas, para representar um conjunto não-refinado de responsabilidades, talvez composto de um outro conjunto
de subsistemas, mas, por último, um conjunto de classes;
-
classes ativas, que representam encadeamentos no sistema;
-
interfaces, para representar declarações abstratas de responsabilidades fornecidas por uma classe ou subsistema.
Além disso, no design, é necessário identificar:
-
eventos, que são especificações de ocorrências interessantes no tempo e no espaço que costumam (se forem
importantes) exigir alguma resposta do sistema; e
-
sinais, para representar mecanismos assíncronos usados para transmitir determinados tipos de eventos no sistema.
Essas distinções mais refinadas permitem examinar diferentes aspectos do design:
-
Os Eventos, e os Sinais usados para transmiti-los, permitem descrever os triggers assíncronos de comportamento aos
quais o sistema deverá responder.
-
As Classes e os Subsistemas permitem agrupar responsabilidades relacionadas em unidades que podem ser desenvolvidas
de forma relativamente independente; as classes desempenham um conjunto indivisível de responsabilidades
relacionadas, enquanto os subsistemas são blocos de construção compostos que, por sua vez, são formados de classes
ou outros subsistemas. Os subsistemas são usados para representar os produtos de trabalho de uma equipe de
desenvolvimento como uma unidade integral de funcionalidade e, sendo assim, são usados como unidades de
gerenciamento de controle e configuração, e elementos lógicos de design.
-
As classes ativas são utilizadas para representar encadeamentos de controle no sistema, permitindo a modelagem da
simultaneidade. Muitas vezes, são utilizadas na composição com outras classes que normalmente, mas não
necessariamente, são passivas. Tal composição pode então ser utilizada - da mesma maneira que uma colaboração -
para modelar comportamento complexo.
Nos sistemas em tempo real, as cápsulas são usadas no lugar das classes ativas e oferecem uma semântica mais
sólida para simplificar o design e aumentar a confiabilidade dos aplicativos simultâneos. Cápsulas compartilham
alguns aspectos de classes e subsistemas; são de fato colaborações encapsuladas de classes que juntas
representam um encadeamento de controle no sistema. Diferem de subsistemas no sentido de que uma cápsula é
responsabilidade de um único designer, enquanto um subsistema é de responsabilidade (normalmente) de uma equipe
de desenvolvedores; um subsistema pode conter cápsulas, contudo.
-
As interfaces permitem examinar e capturar as 'junções' do sistema, definindo precisamente como as suas partes
constitutivas funcionarão umas com as outras.
-
Nos sistemas em tempo real, é necessário usar Protocolos para definir precisamente as mensagens que poderão ser
enviadas e recebidas na porta de uma cápsula.
Separando assuntos e lidando com cada questão representada por esses conceitos isoladamente, é possível simplificar o
processo de design e esclarecer as soluções.
Se a rastreabilidade precisar ser mantida entre modelos de subsistemas, isso deverá ser documentado durante esta
tarefa. Para obter informações adicionais sobre como documentar a rastreabilidade entre o Modelo de Design e
outros modelos do sistema, consulte Diretriz: Modelo de
Design.
Representação da UML 1.x
De acordo com a UML 1.5, um subsistema é, efetivamente, um tipo especial de pacote que só possui interfaces como
elementos públicos. As interfaces fornecem uma camada de encapsulamento, permitindo que o design interno do subsistema
permaneça oculto dos outros elementos do modelo. O subsistema de conceito é utilizado para distingui-lo dos pacotes
"comuns", que são contêineres sem semântica de elementos de modelo; o subsistema representa uma utilização particular
de pacotes com propriedades (comportamentais) semelhantes a classe.
No RUP, Cápsulas são representadas utilizando a notação da UML 1.5. Muito disso pode ser representado em UML 2.0
utilizando o Conceito: Classe Estruturada.
Consulte Diferenças entre a UML 1.x e a UML 2.0para obter informações adicionais.
|
Etapas
Identificar Eventos e Sinais
Finalidade
|
Identificar os sinais e eventos externos e internos aos quais o sistema deve responder.
|
Eventos são ocorrências externas e internas que provocam uma ação no sistema. Os eventos e suas características
podem ajudar a conduzir a identificação dos principais elementos de design, como classes ativas.
Uma lista inicial de eventos externos pode originar-se do Modelo de Caso de Uso, das interações dos agentes com os
casos de uso. Eventos internos podem originar-se do texto nos fluxos de casos de uso ou podem ser identificados
conforme a evolução do design.
São características importantes dos eventos:
-
internos vs. externos - O evento é externo ou interno?
-
prioridade - Esse evento precisa provocar a suspensão de outros processos para ser tratado?
-
freqüência - Com que freqüência o evento ocorre?
-
distribuição da freqüência - O evento ocorre em intervalos regulares ou há picos?
-
requisitos de resposta - Qual a velocidade com que o sistema deve responder ao evento (pode precisar distinguir
entre caso médio e pior).
-
tipo- Esse é um Evento de Chamada, de Tempo, de Sinal ou de Mudança (consulte Conceito: Eventos e Sinais para obter as definições)?
As características dos eventos devem ser capturadas conforme necessário para conduzir a identificação dos elementos
de design que os tratam. A captura das características dos eventos costuma ser mais importante em sistemas reativos
(dirigidos a eventos), mas pode ser útil em outros sistemas, como naqueles com simultaneidade e/ou mensagens
assíncronas.
Eventos de comunicação assíncrona podem ser modelados como Sinais para expressar os dados que transportam ou as
relações entre os sinais, como generalização. Em alguns sistemas, particularmente em sistemas reativos, é
importante relacionar os sinais recebidos de dispositivos externos com mecanismos específicos, como interrupções ou
mensagens de polling específicas.
|
Identificar Classes, Classes Ativas e Subsistemas
Finalidade
|
Refinar as classes de análise nos elementos de modelo de design apropriados
|
Identificar Classes. Quando a classe de análise for simples e já representar uma abstração lógica individual,
poderá ser mapeada diretamente, 1:1, para uma classe de design. Em geral, as classes de entidade permanecem
relativamente intactas no Design. Como também costumam ser persistentes, decida se a classe de design deverá ser
persistente e registre a sua decisão na descrição correspondente.
Ao identificar classes, agrupe-as em Produto
de Trabalho: Pacotes de Design, para fins de gerenciamento organizacional e de configuração. Consulte Diretriz de Produto de Trabalho: Pacote de Design para obter informações adicionais
sobre como tomar decisões de empacotamento.
Identificar Classes Ativas. Considere os requisitos de simultaneidade do sistema no contexto dos objetos de
análise identificados: há necessidade de que o sistema responda aos eventos gerados externamente e, se for o caso,
quais classes de análise estarão 'ativas' quando os eventos ocorrerem? Os eventos externos no Modelo de Casos de Uso
são representados por estímulos provenientes de agentes que interagem com um caso de uso. Observe as Realizações de
Casos de Uso correspondentes para ver os objetos que interagem quando um evento ocorre. Comece agrupando os objetos em
conjuntos autônomos de objetos de colaboração - esses agrupamentos representam um recorte inicial em um grupo que pode
formar uma classe ativa composta.
Se os eventos tiverem atributos importantes que precisam ser capturados, considere a possibilidade de modelá-los como
classes, <<sinal>> estereotipadas. Nos sistemas em tempo real, é necessário agrupar os conjuntos de objetos
identificados em cápsulas, que possuem uma semântica sólida de encapsulamento.
As instâncias de classes ativas representam encadeamentos de execução 'lógicos' independentes. Esses encadeamentos de
execução 'lógicos' não devem ser confundidos com os encadeamentos de execução do sistema operacional nem ser mapeados
literalmente para eles (embora, em algum momento, eles sejam mapeados para os encadeamentos de execução do sistema
operacional). Ao contrário, eles representam encadeamentos de execução conceituais independentes no espaço de solução.
A nossa meta ao identificá-los nesta etapa do design é permitir a divisão da solução em unidades independentes com base
nas 'junções de simultaneidade' naturais do sistema. A divisão do trabalho dessa forma simplifica, do ponto de vista
conceitual, os problemas que envolvem a simultaneidade, já que é possível lidar com encadeamentos de execução
independentes separadamente, exceto no ponto em que eles compartilham classes passivas subjacentes.
Em geral, convém considerar uma classe ativa sempre que houver simultaneidade e conflitos de simultaneidade na área do
problema. Use uma classe ativa para representar um objeto simultâneo externo ou uma atividade simultânea no computador.
Com isso, é possível monitorar e controlar atividades simultâneas.
Outra opção natural é utilizar classes ativas como representativas internas de dispositivos físicos externos que
estão conectadas a um computador, já que essas entidades físicas são inerentemente simultâneas. As classes de "driver
de dispositivo"; servem não só para monitorar e controlar os dispositivos físicos correspondentes, mas também para
isolar o restante do sistema das especificações dos dispositivos. Isso significa que o restante do sistema poderá não
ser afetado mesmo se a tecnologia dos dispositivos subjacente evoluir.
As classes ativas também são usadas para representar atividades simultâneas lógicas. Uma atividade lógica representa um
";objeto" simultâneo conceitual, como por exemplo, uma transação financeira ou uma ligação telefônica. Embora elas não
sejam manifestadas diretamente como entidades físicas (apesar de ocorrerem no mundo físico), há geralmente motivos para
tratá-las como tal. Por exemplo, talvez seja necessário reter temporariamente uma transação financeira específica para
evitar um conflito de simultaneidade ou talvez seja necessário anulá-la devido a falhas no sistema. Como esses objetos
conceituais precisam ser manipulados como uma unidade, convém representá-los como objetos com interfaces próprias que
oferecem os recursos funcionais apropriados.
Um controlador de objetos ativos é um exemplo específico desse tipo de objeto conceitual. A sua finalidade é
gerenciar de forma contínua outros objetos ativos. Normalmente, isso envolve colocar cada objeto no estado operacional
desejado, mantê-lo nesse estado apesar das diversas interrupções, como falhas parciais, e sincronizar a operação
correspondente com a operação de outros objetos. Esses controladores de objetos ativos costumam evoluir dos objetos de
Controle identificados durante a Tarefa: Análise
de Caso de Uso.
Devido à sua capacidade de resolver conflitos de simultaneidade de forma simples e correta, as classes ativas também
são úteis como guardiãs de recursos compartilhados. Nesse caso, um ou mais recursos exigidos por diversas
atividades simultâneas são encapsulados na classe ativa. Devido à sua semântica de exclusão mútua interna, as guardiãs
protegem automaticamente os recursos contra conflitos de simultaneidade.
Em sistemas de tempo real, as cápsulas devem ser utilizadas no lugar das classes ativas: onde quer que você tenha
identificado a necessidade de uma classe ativa, de acordo com a heurística descrita anteriormente, uma cápsula deverá
ser substituída.
Identificar Subsistemas. Quando uma classe de análise é complexa, de maneira que pareça incorporar
comportamentos que não podem ser a responsabilidade de uma classe única agindo sozinha, a classe de análise deverá ser
mapeada para um subsistema de design. Esse subsistema é usado para encapsular colaborações de tal modo que os clientes
dele podem não ter conhecimento nenhum do seu design interno, mesmo quando usam os serviços que ele oferece.
Um subsistema é modelado como um componente da UML, que só possui interfaces como elementos públicos. As interfaces
fornecem uma camada de encapsulamento, permitindo que o design interno do subsistema permaneça oculto dos outros
elementos do modelo. O subsistema de conceitos é utilizado para distingui-lo dos pacotes, que são contêineres sem
semântica de elementos de modelo.
A decisão de criar um subsistema a partir de um conjunto de classes de análise colaboradoras se baseia, em grande
parte, no fato de que a colaboração poderá ser ou será desenvolvida de forma independente por uma equipe de design
distinta. Se for possível incluir todas as colaborações em um pacote com as classes colaboradoras, um subsistema poderá
permitir uma forma de encapsulamento mais sólida do que a permitida por um pacote simples. O conteúdo e as colaborações
de um subsistema estão isolados completamente, atrás de uma ou mais interfaces, de forma que o cliente dele dependa
apenas da interface. Dessa forma, o designer do subsistema está completamente isolado das dependências externas; o
designer (ou a equipe de design) precisa especificar como a interface é realizada, mas tem permissão total para alterar
o design interno do subsistema sem afetar as dependências externas. Em sistemas grandes, com equipes bastante
independentes, esse grau de desacoplamento, combinado com a imposição arquitetural fornecida pelas interfaces formais,
são um argumento sólido para escolher subsistemas em vez de pacotes simples. Consulte Diretriz de Produto de Trabalho: Subsistema de Design para obter informações
adicionais sobre fatores que afetem a escolha do uso de subsistemas como elementos de design.
|
Identificar Interfaces de Subsistema
Finalidade
|
Identificar os elementos de design que formalizam as junções no sistema.
|
As interfaces definem um conjunto de operações que são realizadas por um classificador. No Modelo de Design, as
interfaces são usadas principalmente para definir as interfaces de subsistemas. Isso não quer dizer que também não
podem ser usadas para classes, mas, para uma classe única, em geral basta definir operações públicas na classe que, de
fato, determinam sua 'interface'. As interfaces são importantes para subsistemas porque permitem a separação da
declaração do comportamento (a interface) da realização dele (as classes específicas no subsistema que realizam a
interface). Esse desacoplamento permite aumentar a independência das equipes de desenvolvimento que trabalham em partes
distintas do sistema e, ao mesmo tempo, reter definições precisas dos 'contratos' entre essas diferentes partes.
Para cada subsistema, identifique um conjunto de sugestões de interfaces. Usando as colaborações agrupadas
identificadas no passo anterior, identifique a responsabilidade que é 'ativada' quando a colaboração é iniciada. Para
refinar depois essa responsabilidade, determine quais informações devem ser fornecidas pelo 'cliente' e quais são
retornadas quando a colaboração é concluída; esses conjuntos de informações passam a ser os parâmetros de entrada e
saída do protótipo e retornam um valor para uma operação que o subsistema realizará. Defina um nome para essa operação,
utilizando as convenções de nomenclatura definidas no Produto de Trabalho: Diretrizes Específicas do ProjetoRepita esse
procedimento até definir todas as operações que serão realizadas pelo subsistema.
Em seguida, agrupe as operações de acordo com as responsabilidades relacionadas. Convém criar grupos pequenos em vez de
grupos grandes, já que é mais provável obter um conjunto coeso de responsabilidades comuns se há poucas operações no
grupo. Fique atento também à reutilização - procure semelhanças que possam facilitar a identificação da funcionalidade
reutilizável relacionada. No entanto, não gaste muito tempo tentando encontrar o agrupamento de responsabilidades
ideal; lembre-se de que esse é apenas um agrupamento inicial, que continuará a ser refinado de forma iterativa durante
a fase de elaboração.
Procure por similaridades entre as interfaces. No conjunto de sugestões de interfaces, procure nomes,
responsabilidades e operações semelhantes. Reajuste as interfaces que apresentam as mesmas operações, extraindo as
operações comuns para uma nova interface. Não se esqueça de verificar também as interfaces existentes, reutilizando-as
sempre que possível. A meta é manter a coesão das interfaces e, ao mesmo tempo, remover operações redundantes entre
elas. Isso facilitará a compreensão e o desenvolvimento das interfaces ao longo do tempo.
Defina dependências de interface. Os parâmetros e o valor de retorno de cada operação da interface têm um tipo
específico: eles devem realizar uma determinada interface ou devem ser instâncias de um tipo de dados simples. Nos
casos em que os parâmetros são objetos que realizam uma interface específica, defina relacionamentos de dependência
entre a interface e as interfaces das quais ela depende. A definição de dependências entre interfaces fornece
informações de acoplamento úteis ao arquiteto de software, já que essas dependências definem as principais dependências
entre elementos no modelo de design.
Mapeie as interfaces para subsistemas. Uma vez identificadas as interfaces, crie associações de
realização entre o subsistema e as interfaces realizadas por ele. Uma realização do subsistema para uma
interface indica que existem um ou mais elementos no subsistema que realizam as operações da interface. Posteriormente,
quando o subsistema for projetado, as realizações entre ele e a interface serão refinadas, e o designer do subsistema
definirá os elementos específicos dele que realizam as operações da interface. Essas realizações refinadas podem ser
visualizadas apenas pelo designer do subsistema; para o cliente do subsistema, apenas a realização entre o subsistema e
a interface está visível.
Defina o comportamento especificado pelas interfaces. As interfaces em geral definem uma máquina de estado
implícita para os elementos que realizam a interface. Se for necessário disparar as operações da interface em uma ordem
específica (por exemplo, é necessário ativar a conexão com o banco de dados antes de usá-lo), será preciso definir uma
máquina de estados com os estados visíveis (ou inferidos) publicamente que deverão ser suportados pelos elementos de
design que realizam a interface. Essa máquina de estados ajudará o usuário da interface a compreendê-la melhor e
ajudará o designer dos elementos que realizam a interface a especificar o comportamento adequado deles.
Empacote as interfaces. As interfaces são de propriedade do arquiteto de software; mudanças nas interfaces são
sempre arquiteturalmente significativas. Para gerenciar essas mudanças, é necessário agrupar as interfaces em um ou
mais pacotes pertencentes ao arquiteto de software. Se cada interface for realizada por um único subsistema, será
possível colocá-las no mesmo pacote com o subsistema. Se forem realizadas por mais de um subsistema, deverão ser
colocadas em um outro pacote pertencente ao arquiteto de software. Com isso, é possível gerenciar e controlar as
interfaces independentemente dos próprios subsistemas.
Finalidade
|
Identificar os elementos de design que formalizam as junções no sistema (design RT apenas).
|
Protocolos são semelhantes a interfaces em sistemas dirigidos a eventos: eles identificam o 'contrato' entre cápsulas
definindo um conjunto combinado de sinais, utilizados para a comunicação entre encadeamentos de controle independentes.
Enquanto as interfaces são usadas principalmente para definir um serviço de mensagens síncrono através de um modelo de
chamada de funções, os protocolos são usados principalmente para definir a comunicação assíncrona através de um serviço
de mensagens baseado em sinais. Os protocolos permitem a separação da declaração do comportamento (o conjunto de
sinais) da realização dele (os elementos no subsistema que realizam a interface). Esse desacoplamento permite aumentar
a independência das equipes de desenvolvimento que trabalham em partes distintas do sistema e, ao mesmo tempo, reter
definições precisas dos 'contratos' entre essas diferentes partes.
Para cada cápsula, identifique um conjunto de sinais de entrada e de saída. Usando as colaborações agrupadas
identificadas nos passos anteriores, identifique a responsabilidade que é 'ativada' quando a colaboração é iniciada.
Para refinar depois essa responsabilidade, determine quais informações devem ser fornecidas pelo 'cliente' e quais são
retornadas quando a colaboração é concluída; esses conjuntos de informações passam a ser os parâmetros de entrada do
protótipo para um sinal que a cápsula realizará através de uma de suas portas. Defina um nome para esse sinal,
utilizando as convenções de nomenclatura definidas no Produto de Trabalho: Diretrizes Específicas do Projeto. Repita esse
procedimento até definir todos os sinais que serão realizados pelo subsistema.
Em seguida, agrupe os sinais de acordo com as responsabilidades relacionadas. Convém criar grupos pequenos em vez de
grupos grandes, já que é mais provável obter um conjunto coeso de responsabilidades comuns se há poucos sinais no
grupo. Fique atento também à reutilização - procure semelhanças que possam facilitar a identificação da funcionalidade
reutilizável relacionada. No entanto, não gaste muito tempo tentando encontrar o agrupamento de responsabilidades
ideal; lembre-se de que esse é apenas um agrupamento inicial, que continuará a ser refinado de forma iterativa durante
a fase de elaboração. Atribua ao protocolo um nome significativo que descreva a função que ele desempenha nas
colaborações de cápsula.
Procure por similaridades entre os protocolos. No conjunto de sugestões de protocolos, procure nomes,
responsabilidades e sinais semelhantes. Reajuste os protocolos que apresentam os mesmos sinais, extraindo os sinais
comuns para uma nova interface. Não se esqueça de verificar também os protocolos existentes, reutilizando-os sempre que
possível. A meta é manter a coesão dos protocolos e, ao mesmo tempo, remover sinais redundantes entre eles. Isso
facilitará a compreensão e o desenvolvimento dos protocolos ao longo do tempo.
Mapeie os protocolos para cápsulas. Uma vez identificados os protocolos, crie portas nas cápsulas que os
realizam. As portas da cápsula definem suas 'interfaces', o comportamento que pode ser solicitado dela. Posteriormente,
quando ela for projetada, o comportamento especificado pelas portas será descrito pela máquina de estados da cápsula.
Defina o comportamento especificado pelos protocolosOs protocolos em geral definem uma máquina de estado
implícita para os elementos que realizam a interface. Se for necessário receber os sinais de entrada na interface em
uma ordem específica (p. ex., é necessário receber um sinal 'o sistema está pronto' antes de receber um sinal de erro
específico), será preciso definir uma máquina de estados com os estados visíveis (ou inferidos) publicamente que
deverão ser suportados pelos elementos de design que realizam o protocolo. Essa máquina de estados ajudará o usuário
das cápsulas que realizam o protocolo a entender melhor o comportamento delas e ajudará o designer das cápsulas a
apresentar o comportamento adequado para os elementos correspondentes.
Empacote os protocolos. Os protocolos são de propriedade do arquiteto de software; alterações nos protocolos são
sempre arquiteturalmente significativas. Para gerenciar essas mudanças, é necessário agrupá-los em um ou mais pacotes
pertencentes ao arquiteto de software. Com isso, é possível gerenciar e controlar os protocolos independentemente das
cápsulas que os realizam.
|
|
Informações Adicionais
Listas de Verificação |
|
Conceitos |
|
Diretrizes |
|
Mentores de Ferramentas |
|
© Copyright IBM Corp. 1987, 2006. Todos os Direitos Reservados.
|
|