Atividade:
| ||||||||||||||||
Finalidade
|
|
Passos
|
|
| Artefatos Informados: | Artefatos Resultantes: |
| Papel: Designer | |
| Mentor de Ferramentas: | |
| Detalhamentos do Fluxo de Trabalho: |
As classes são o motor propulsor do esforço de design elas executam o trabalho real do sistema. Os outros elementos de design subsistemas, pacotes e colaborações apenas descrevem como as classes são agrupadas e como elas operam entre si.
As cápsulas também são classes estereotipadas, usadas para representar threads de execução simultânea em sistemas de tempo real. Nesses casos, outras classes de design são classes 'passivas', usadas no contexto de execução fornecido pelas cápsulas 'ativas'. Mesmo quando o arquiteto e o designer de software não usam uma abordagem baseada em cápsulas, é possível modelar comportamentos concorrentes com as classes 'ativas'.
As classes ativas são classes de design que coordenam e orientam o comportamento das classes passivas - uma classe ativa é aquela cujas instâncias são os objetos ativos que possuem seu próprio thread de controle.
Comece criando uma ou várias classes de design (iniciais) para a classe de análise usada como informação para essa atividade e atribua as dependências de rastreamento. As classes de design criadas nesse passo serão refinadas, ajustadas, divididas e/ou mescladas nos passos subseqüentes quando forem atribuídas várias propriedades de "design", como operações, métodos e uma máquina de estado, que descrevem como a classe de análise foi projetada.
Dependendo do tipo da classe de análise (fronteira, entidade ou controle) que será criada, há estratégias específicas que podem ser usadas para criar as classes de design iniciais.
Como regra geral de análise, haverá uma classe de fronteira para cada janela ou para cada formulário na interface do usuário. Como conseqüência, as classes de fronteira podem ter responsabilidades de um nível bem alto e, por isso, precisam ser refinadas e detalhadas nesse passo.
O design das classes de fronteira depende das ferramentas de desenvolvimento de interface do usuário (GUI) disponíveis para o projeto. Usando a tecnologia atual, é bastante comum que a construção visual da interface do usuário seja feita diretamente na ferramenta de desenvolvimento, o que, por conseqüência, cria automaticamente as classes de interface do usuário que precisam estar relacionadas ao design das classes de controle e/ou entidade. Se o ambiente de desenvolvimento da interface gráfica do usuário criar as classes de suporte automaticamente, será necessário implementar a interface do usuário, mas não será preciso considerar essas classes no design - projete apenas o que o ambiente de desenvolvimento não criar para você.
Os esboços são fontes adicionais de informações para esse trabalho, assim como as capturas de tela de um protótipo de interface do usuário, que podem ser criadas para especificar melhor os requisitos estabelecidos nas classes de fronteira.
As classes de fronteira que representam as interfaces nos sistemas existentes são, em geral, modeladas como subsistemas, pois normalmente têm um comportamento interno complexo. Se o comportamento da interface for simples (talvez atuando apenas como um mecanismo de acesso para a API existente do sistema externo), é possível representar a interface com uma ou mais classes de design. Se este for o caminho escolhido, use uma única classe de design por protocolo, interface ou API, e observe os requisitos especiais da classe sobre os padrões usados e outros itens.
Durante o processo de análise, as classes de entidade representam unidades manipuladas de informações. Geralmente, os objetos da entidade são passivos e persistentes. Durante a análise, essas classes de entidade podem ser identificadas e associadas com o mecanismo de análise para garantir a persistência. O detalhamento de um mecanismo de persistência com base no banco de dados está definido em Atividade: Design de Banco de Dados. As considerações sobre desempenho podem impor a refatoração das classes persistentes, provocando mudanças no Modelo de Design, que serão abordadas em conjunto em Papel: Designer de Banco de Dados e Papel: Designer.
Uma abordagem mais ampla das questões de design para as classes persistentes será apresentada a seguir em Identificar Classes Persistentes.
Um objeto de controle é responsável pelo gerenciamento do fluxo de um caso de uso e, portanto, coordena a maioria de suas ações. Os objetos de controle encapsulam a lógica que não está particularmente relacionada às questões da interface do usuário (objetos de fronteira) ou da engenharia de dados (objetos de entidade). Muitas vezes, essa lógica denomina-se lógica de aplicativo ou lógica de negócios.
Sendo assim, pelo menos as questões abaixo precisam ser consideradas durante o design das classes de controle:
- O comportamento de coordenação dos casos de uso incorpora-se à interface do usuário, dificultando a realização de mudanças no sistema.
- A mesma interface do usuário não pode ser usada em realizações de casos de uso distintas sem dificuldades.
- A interface do usuário fica sobrecarregada com funcionalidades adicionais, o que prejudica seu desempenho.
- Os objetos de entidade podem ficar sobrecarregados com o comportamento específico dos casos de uso, o que reduz sua generalidade.
Para evitar esses problemas, as classes de controle foram introduzidas para fornecer o comportamento relacionado à coordenação dos fluxos de eventos
Lembre-se de que nos últimos dois casos, se a classe de controle representar um thread de controle separado, será melhor usar uma classe ativa para modelar o thread de controle.
Em um sistema de tempo real, o uso de Artefato: Cápsulas é a abordagem de modelagem preferencial nessas circunstâncias.
As classes que precisam armazenar seu estado em uma mídia permanente são denominadas 'persistentes'. A necessidade de armazenar seu estado pode ser para registrar permanentemente as informações de classe, para fins de backup em casos de falhas do sistema ou para intercâmbio de informações. Uma classe persistente pode ter instâncias persistentes ou transientes. Denominar uma classe como 'persistente' significa que algumas instâncias da classe talvez precisem ser persistentes.
A identificação das classes persistentes serve para notificar o Papel: Designer de Banco de Dados de que a classe precisa de atenção especial às suas características de armazenamento físico. Notifica também o Papel: Arquiteto de Software de que a classe precisa ser persistente, e o Papel: Designer, responsável pelo mecanismo de persistência, de que as instâncias da classe precisam ser persistentes.
Devido à necessidade de uma estratégia persistente coordenada, o Papel: Designer de Banco de Dados é responsável por mapear classes persistentes no banco de dados usando um framework de persistência. Se o projeto estiver desenvolvendo um framework de persistência, o desenvolvedor do framework também será responsável por conhecer os requisitos de persistência das classes de design. Para oferecer a essas pessoas as informações necessárias, basta indicar que a classe ou, mais precisamente, as instâncias da classe, são persistentes. Incorpore também os mecanismos de design que correspondem aos mecanismos de persistência encontrados durante a análise.
Exemplo
O mecanismo de análise para a verificação de persistência pode ser executado por um dos seguintes mecanismos de design:
- Armazenamento em memória
- Placa Flash
- Arquivo binário
- Sistema de Gerenciamento de Banco de Dados (DBMS)
- Depende do que for exigido pela classe.
Lembre-se de que os objetos persistentes podem não ser os únicos derivados das classes de entidade. Os objetos persistentes também podem ser necessários para tratar requisitos não-funcionais em geral. Exemplos são os objetos persistentes necessários para manter as informações relevantes ao controle do processo ou as informações de estado entre as transações.
Para cada classe, determine a visibilidade que ela terá no pacote em que reside. Uma classe 'pública' pode ser referenciada fora do pacote que a contém. Uma classe 'privada' (ou uma cuja visibilidade seja 'implementação') pode ser referenciada apenas pelas classes contidas no mesmo pacote.
Para identificar Operações em classes de design:
As operações devem oferecer suporte às mensagens que aparecem em diagramas de seqüência, porque os scripts e as mensagens (especificações de mensagens temporárias) que ainda não foram atribuídos às operações descrevem o comportamento esperado da classe. Este é um exemplo de diagrama de seqüência:

As mensagens são a base de identificação das operações.
As realizações de casos de uso fornecem informações suficientes para identificar todas as operações. Para encontrar as outras operações, considere o seguinte:
Não defina operações que apenas obtêm e definem os valores de atributos públicos (consulte Definir Atributos e Associações). Geralmente, eles são gerados por recursos de criação de código e não precisam ser definidos explicitamente.
As convenções de nomes da linguagem de implementação devem ser usadas para nomear operações, tipos e parâmetros de retorno. Elas estão descritas em Artefato: Guia de Design.
Para cada operação, você deve definir:
Depois de definir as operações, complete os diagramas de seqüência com as informações sobre as operações disparadas por cada mensagem.
Consulte a seção "Operações de Classe", em Diretrizes: Visão de Design, para obter mais informações. Consulte também a seção "Definição de Operações", em Diretrizes: Design de Classes em Visual Basic, para obter informações sobre o Visual Basic®.
Para cada operação, identifique a visibilidade de exportação da operação. Estas são as opções possíveis:
Escolha a visibilidade que, embora seja a mais restrita, possa atender aos objetivos da operação. Para fazer isso, verifique os diagramas de seqüência e, para cada mensagem, determine se ela é originária de uma classe externa ao pacote do receptor (requer visibilidade pública), de uma classe interna ao pacote (requer visibilidade de implementação), de uma subclasse (requer visibilidade protegida), da própria classe ou de um amigo (requer visibilidade privada).
Em geral, as operações são operações de 'instância', ou seja, elas são executadas em instâncias da classe. Em alguns casos, no entanto, uma operação se aplica a todas as instâncias da classe e, portanto, ela é uma operação executada no escopo de classe. O receptor da operação de 'classe' é, na verdade, uma instância de uma metaclasse, a descrição da própria classe, e não uma instância específica da classe. Entre os exemplos das operações de classe estão as mensagens que criam novas instâncias e que retornam todas as instâncias de uma classe e assim por diante.
Para indicar uma operação no escopo de classe, a seqüência de caracteres da operação deve ser sublinhada.
Um método especifica a implementação de uma operação. Em muitos casos, os métodos são implementados diretamente na linguagem de programação. Isso ocorre quando o comportamento exigido pela operação é suficientemente definido pelo nome, pela descrição e pelos parâmetros da operação. Quando a implementação requer o uso de um algoritmo específico ou requer mais informações do que as apresentadas na descrição da operação, é necessário usar uma descrição de método separada. O método descreve como a operação funciona, e não apenas o que ela faz.
Se for descrito, o método deverá abordar:
Naturalmente, os requisitos variam entre um caso e outro. Contudo, as especificações do método para uma classe devem sempre informar:
Requisitos mais específicos podem incluir:
Os diagramas de seqüência são uma importante fonte para esse tipo de informação. A partir daí, ficará claro quais serão as operações usadas em outros objetos quando uma operação for executada. É necessária uma especificação de quais operações serão usadas em outros objetos para permitir a implementação completa da operação. A produção de uma especificação de método completa requer que você identifique as operações para os objetos envolvidos e que você verifique os respectivos diagramas de seqüência.
Consulte a seção "Definição de Métodos (UML) ", em Diretrizes: Design de Classes em Visual Basic, para obter informações sobre o Visual Basic®.
Em algumas operações, o comportamento depende do estado do objeto receptor. Uma máquina de estado é uma ferramenta para descrever os estados em que o objeto pode estar e os eventos que fazem o objeto passar de um estado para outro. Consulte Diretrizes: Diagrama de Estados. As máquinas de estado são bastante úteis para descrever as classes ativas.
A utilização de máquinas de estado é particularmente importante para definir o comportamento de Artefato: Cápsulas.
Este é um exemplo de máquina de estado simples:

Um diagrama de estados para uma Bomba de Combustível
Cada evento de transição de estado pode ser associado a uma operação. Dependendo do estado do objeto, a operação pode apresentar um comportamento diferente. Os eventos de transição descrevem como isso ocorre.
A descrição do método para a operação associada deve ser atualizada com as informações específicas de estados, indicando, para cada estado relevante, o que a operação deve fazer. Em geral, os estados são representados com o uso de atributos. Os diagramas de estados funcionam como fonte de informações para a identificação do atributo.
Para obter mais informações, consulte Diretrizes: Diagrama de Estados.
Consulte a seção "Definição de Estados ", em Diretrizes: Design de Classes em Visual Basic, para obter informações sobre o Visual Basic®.
Durante a definição de métodos e a identificação de estados, os atributos requisitados pela classe para executar suas operações são identificados. Os atributos permitem o armazenamento de informações para a instância da classe e, geralmente, são usados para representar o estado da instância da classe. As classes usam atributos quando mantêm suas próprias informações. Para cada atributo, defina:
Verifique se todos os atributos são necessários. Os atributos devem ser justificados - é fácil incluir atributos no início do processo e mantê-los, mesmo quando não são mais necessários, por falta de perspectiva. Os atributos extras, multiplicados por milhares ou milhões de instâncias, podem causar um forte efeito sobre os requisitos de desempenho e armazenamento do sistema.
Consulte a seção "Atributos", em Diretrizes: Classe de Design, para obter mais informações sobre atributos.
Para os casos nos quais é necessária a comunicação entre os objetos, levante as seguintes questões:
Lembre-se de que os vínculos modelados dessa maneira são transientes, existem apenas por um período limitado, no contexto específico da colaboração. Nesse sentido, eles são instâncias do papel de associação na colaboração. Contudo, o relacionamento em um modelo de classe (isto é, independente do contexto) deve ser, como descrito acima, uma dependência. Como definido em [RUM98], em transient link (vínculo transitório): "É possível modelar esses vínculos como associações, mas as condições nas associações devem ser definidas muito amplamente, pois perdem muito de sua precisão ao limitarem as combinações de objetos ". Nessa situação, a modelagem de uma dependência é menos importante do que a modelagem do relacionamento na colaboração, porque a dependência não descreve o relacionamento completamente, somente indica que ele existe.
As associações proporcionam o mecanismo para os objetos se comunicarem entre si. Elas oferecem aos objetos um "conduto" ao longo do qual as mensagens podem fluir. Elas também documentam as dependências entre as classes, destacando que as mudanças efetuadas em uma classe poderão se refletir em muitas outras classes.
Examine as descrições de método para cada operação a fim de entender como as instâncias da classe se comunicam e colaboram com outros objetos. Para enviar uma mensagem para outro objeto, o objeto deve fazer uma referência ao receptor da mensagem. Um diagrama de colaboração (uma representação alternativa de um diagrama de seqüência) mostrará a comunicação do objeto em termos de vínculos, como indicado abaixo:

As mensagens restantes usarão uma associação ou uma agregação para especificar o relacionamento entre as instâncias de duas classes que se comunicam. Consulte Diretrizes: Associação e Diretrizes: Agregação para obter informações sobre como escolher a representação apropriada. Para essas duas associações, defina a visibilidade do vínculo como 'campo' nos diagramas de colaboração. Outros tarefas:
As associações e agregações são melhor definidas em um diagrama de classes que ilustre as classes associadas. O diagrama de classes deve estar incluído no pacote que contém as classes associadas. Este é um exemplo de diagrama de classes, indicando as associações e agregações existentes:

Exemplo de Diagrama de Classe, com as Associações, Agregações e Generalizações entre as Classes.
As associações de assinatura entre as classes de análise são usadas para identificar dependências de eventos entre as classes. No Modelo de Design, devemos tratar explicitamente dessas dependências de eventos, usando os frameworks para tratar eventos disponíveis ou por meio do design e da criação do nosso próprio framework para esse fim. Em algumas linguagens de programação, como Visual Basic, esse é um procedimento direto executado com a declaração, ocorrência e tratamento dos eventos correspondentes. Em outras linguagens, talvez seja necessário usar alguma biblioteca adicional de funções reutilizáveis para tratar assinaturas e eventos. Se não for possível adquirir a funcionalidade, ela terá que ser projetada e criada. Consulte também Diretrizes: Associação de Assinatura.
As classes podem ser organizadas em uma hierarquia de generalização para refletir um comportamento e uma estrutura comuns. Uma superclasse comum pode ser definida para que suas subclasses possam herdar tanto o comportamento quanto a estrutura. A generalização é uma comodidade notacional, que permite definir uma estrutura e um comportamento comuns em um único local para serem reutilizados em outros locais, onde a mesma estrutura e o mesmo comportamento serão encontrados. Consulte Diretrizes: Generalização, para obter mais informações sobre os relacionamentos de generalização.
Em caso de generalização, crie uma superclasse comum para conter os atributos, as associações, as agregações e as operações comuns. Remova o comportamento comum das classes que passarão a ser subclasses da superclasse. Defina um relacionamento de generalização da subclasse com a superclasse.
Finalidade
|
| Conceitos: Simultaneidade |
Uma das dificuldades em utilizar um caso de uso após o outro no processo de design é o fato de dois casos de uso ou mais poderem disparar simultaneamente operações nos objetos de design, possivelmente de maneiras conflitantes. Nesses casos, os conflitos de simultaneidade devem ser identificados e resolvidos explicitamente.
Se o serviço de mensagens síncronas for usado, a execução de uma operação bloqueará as chamadas subseqüentes feitas para os objetos, até a conclusão da operação. O serviço de mensagens síncronas implica uma ordem na qual o primeiro a chegar é o primeiro a ser atendido para o processamento das mensagens. Esse procedimento pode resolver o conflito de simultaneidade nos casos em que todas as mensagens têm a mesma prioridade ou quando elas são executadas no mesmo thread. Nos casos em que um objeto pode ser acessado por diversos threads de execução (representados por classes ativas), devem ser usados mecanismos explícitos para impedir ou resolver o conflito de simultaneidade.
Em sistemas de tempo real, nos quais os threads são representados por Artefato: Cápsulas, esse problema ainda precisa ser solucionado para o acesso simultâneo a objetos passivos. Por outro lado, as cápsulas proporcionam um mecanismo de enfileiramento e impõem uma semântica de execução-conclusão para tratar o acesso simultâneo. Uma solução recomendada é inserir os objetos passivos em cápsulas. Dessa forma, não há problema de acesso simultâneo, por causa da semântica da própria cápsula.
É possível que diversas operações executadas no mesmo objeto sejam disparadas simultaneamente por threads de execução distintos sem ocorrer conflito de simultaneidade. O nome e o endereço de um cliente podem ser modificados ao mesmo tempo sem que haja conflito. O conflito só ocorre quando dois threads de execução distintos tentam modificar a mesma propriedade do objeto.
Para cada objeto que pode ser acessado simultaneamente por diversos threads de execução, identifique as seções do código que precisam ser protegidas de acesso simultâneo. No início da fase de Elaboração, é impossível identificar os segmentos de código específicos. As operações que devem ser protegidas são suficientes. Em seguida, selecione ou projete os mecanismos de controle de acesso apropriados para evitar o conflito devido ao acesso simultâneo. Exemplos desses mecanismos são o enfileiramento de mensagens para serializar o acesso, o uso de semáforos (ou 'tokens') para permitir o acesso a apenas um thread por vez ou outras variantes de mecanismos de bloqueio. A escolha do mecanismo depende bastante da implementação e, em geral, varia de acordo com a linguagem de programação e o ambiente operacional. Consulte o Artefato: Guia de Design específico ao projeto, para obter informações sobre como selecionar os mecanismos de simultaneidade.
As Classes de Design devem ser refinadas para tratar de requisitos não-funcionais gerais, como descrito no Guia de Design específico do projeto. Uma informação importante para esse passo são os requisitos não-funcionais para uma classe de análise, que já podem estar descritos em seus requisitos especiais e responsabilidades. Esses requisitos são, muitas vezes, especificados em termos dos mecanismos arquiteturais (análise) necessários para a realização da classe. Nesse passo, a classe é refinada para incorporar os mecanismos de design correspondentes a esses mecanismos de análise.
Os mecanismos de design disponíveis são identificados e caracterizados pelo arquiteto de software em Artefato: Guia de Design. Para cada mecanismo de design necessário, qualifique quantas características puder, informando grupos quando possível. Consulte Atividade: Identificar Mecanismos de Design, Conceitos: Mecanismos de Análise e Conceitos: Mecanismos de Design e Implementação para obter mais informações sobre os mecanismos de design.
Pode haver vários mecanismos e guias gerais de design a serem considerados quando as classes são projetadas:
Consulte a seção "Gerenciamento de Requisitos Não-funcionais em Geral" em Diretrizes: Design de Classes em Visual Basic, para obter informações sobre o Visual Basic®.
Nesse ponto, analise o modelo de design para verificar se o seu trabalho está indo na direção correta. Não há necessidade de revisar o modelo detalhadamente, mas é importante considerar os seguintes pontos de verificação:
|
Rational Unified Process
|