Os subsistemas podem ser utilizados de várias maneiras
complementares para particionar o sistema em unidades que
-
possam ser ordenadas, configuradas ou liberadas independentemente
-
possam ser desenvolvidas independentemente, contanto que as interfaces permaneçam inalteradas
-
possam ser implementadas independentemente em um conjunto de nós computacionais distribuídos
-
possam ser alteradas independentemente sem danificar outras partes dos sistemas
Portanto, os subsistemas são ideais para modelar componentes - as unidades substituíveis da montagem no desenvolvimento
com base em componentes - maiores que uma única classe de design.
Além disso, os subsistemas podem
-
dividir o sistema em unidades que possam fornecer segurança restrita para os principais recursos
-
representar produtos existentes ou sistemas externos no design
Uma classe de análise complexa será mapeada para um subsistema de design se ele mostrar que está incorporando um
comportamento que não pode ser responsabilidade de uma única classe de design que atua sozinha. Uma classe de design
complexa também pode tornar-se um subsistema, se estiver provavelmente para ser implementada como um conjunto de
classes de colaboração.
Os subsistemas também são um bom meio de identificar partes do sistema que serão desenvolvidas independentemente por
uma equipe separada. Se for possível incluir completamente os elementos de design de colaboração em um pacote com suas
colaborações, um subsistema poderá oferecer uma forma de encapsulamento mais sólida do que a oferecida 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.
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. Se as classes/subsistemas de participação de uma
colaboração interagirem apenas entre si para produzir um conjunto bem definido de resultados, a colaboração e seus
elementos de design de colaboração deverão ser encapsulados em um subsistema.
Essa regra também se aplica a subconjuntos de colaborações. Em qualquer lugar, toda a colaboração ou parte dela poderá
ser encapsulada e simplificada. Isso facilitará a compreensão do design.
Dicas
Dica
|
Detalhes
|
Procure possibilidade de opção
|
Se uma determinada colaboração (ou subcolaboração) representar um comportamento opcional, inclua-a em
um subsistema. As funcionalidades que possam ser removidas, atualizadas ou substituídas por outras
deverão ser consideradas independentes.
|
Observe a interface do usuário do sistema
|
Se a interface com o usuário for relativamente independente das classes de entidade do sistema (ou
seja, elas podem e serão alteradas independentemente), crie subsistemas que sejam integrados
horizontalmente: agrupe as classes de limite da interface com o usuário relacionadas em um subsistema e
agrupe as classes de entidade relacionadas em um outro subsistema.
|
Se a interface com o usuário e as classes de entidade exibidas por ela estiverem intrinsecamente
acopladas (ou seja, se uma alteração em uma disparar uma alteração na outra), crie subsistemas que
sejam integrados verticalmente: inclua as classes de limite e de entidade relacionadas no subsistema
comum.
|
Observe os Agentes
|
Separe a funcionalidade usada por dois atores diferentes, já que cada agente pode alterar
independentemente seus requisitos no sistema.
|
Crie subsistemas para encapsular o acesso a um sistema ou subsistema externo.
|
Procure o acoplamento e a coesão entre os elementos de design
|
Classes/subsistemas com um elevado grau de acoplamento ou coesão colaboram para fornecer um conjunto de
serviços. Organize os elementos altamente acoplados em subsistemas e separe-os em linhas de menor grau
de acoplamento. Em alguns casos, o menor grau de acoplamento pode ser eliminado inteiramente, dividindo
as classes em classes menores com responsabilidades mais coesas ou reparticionando os subsistemas
apropriadamente.
|
Examine a substituição
|
Se houver vários níveis de serviço especificados para um recurso específico (exemplo: disponibilidade
alta, média e baixa), represente cada nível de serviço como um subsistema separado, cada qual
realizando o mesmo conjunto de interfaces. Com isso, os subsistemas serão substituídos uns pelos
outros.
|
Examine a distribuição
|
Embora
possa haver diversas instâncias de um subsistema específico, cada uma executada em diferentes nós, em
muitas arquiteturas não é possível que uma única instância de um componente seja dividida em nós. Nos
casos em que o comportamento do subsistema deve ser dividido em nós, é recomendável decompor o
subsistema em subsistemas menores (cada qual representando um único componente) com uma funcionalidade
mais restrita.
Determine a funcionalidade que deve residir em cada nó e crie um novo subsistema para 'possuir' essa
funcionalidade, distribuindo as responsabilidades e os elementos relacionados do subsistema original de
modo apropriado.
Os novos subsistemas são internos ao subsistema original.
|
Depois que o design tiver sido organizado em subsistemas, atualize as realizações de casos de uso apropriadamente.
Os subsistemas de design são modelados utilizando componentes da UML. Essa construção fornece os recursos de modelagem
a seguir:
-
é possível agrupar classes para definir uma parte maior de granularidade de um sistema
-
é possível separar as interfaces visíveis da implementação interna
-
que podem ser executadas no tempo de execução
Outras considerações são:
-
Cada Subsistema de Design deve receber um nome e uma descrição resumida.
-
As responsabilidades da classe de análise original deverão ser transferidas para o subsistema recém-criado,
utilizando-se a descrição do subsistema para documentar as responsabilidades.
Nota: a UML 2.0 também define um estereótipo para o componente nomeado <<subsistema>>, indicando que ele
pode ser utilizado, por exemplo, para representar estruturas em larga escala. Um Subsistema de Design RUP pode ou não
ser uma estrutura em larga escala; ambos são Subsistemas de Design da perspectiva RUP. Esta é uma questão a ser
decidida pelo arquiteto de software (se escolherá, por exemplo, etiquetar componentes que sejam compostos de
componentes como <<subsistema>>).
Quando um produto existente é um produto que exporta interfaces, ou seja, operações (e talvez recepções), mas, em contrapartida, mantém todos os detalhes de implementação
ocultos, ele pode ser modelado como um subsistema na visualização lógica. Exemplos de produtos utilizados pelo
sistema que podem ser representados por um subsistema incluem:
-
Software de comunicação (middleware).
-
Suporte de acesso a banco de dados (suporte de mapeamento RDBMS).
-
Produtos para aplicações específicas.
Alguns produtos existentes, como coleções de tipos e estruturas de dados (por exemplo, pilhas, listas, filas), podem
ser melhor representados como pacotes, já que revelam mais do que simplesmente um comportamento. Além disso, é o
conteúdo específico do pacote que é importante e útil, e não o pacote propriamente dito, que é simplesmente um
contêiner.
Utilitários comuns, como bibliotecas de matemática, podem ser representados como subsistemas, caso simplesmente
exportem interfaces, mas se isso é necessário ou faz sentido depende do julgamento do designer sobre a natureza do que
é modelado. Os subsistemas são constructos orientados a objetos (uma vez que são componentes modelados): um
subsistema pode ter instâncias (se assim indicado pelo designer). A UML fornece uma outra forma de modelar grupos de
variáveis e procedimentos globais no utilitário,
que é um estereótipo de classe - o utilitário não possui instâncias.
Ao definir o subsistema para representar o produto, defina também uma ou mais interfaces para representar as interfaces
do produto.
Os Subsistemas de Design (modelados como componentes da UML) diferem dos pacotes em relação à semântica: um subsistema
fornece o comportamento por meio de uma ou mais interfaces que ele realiza. Os pacotes não apresentam nenhum
comportamento; são simplesmente contêiners de elementos que apresentam comportamento.
A razão para utilizar um subsistema em vez de um pacote é que os subsistemas encapsulam seu conteúdo, fornecendo o
comportamento somente por meio de suas interfaces. A vantagem disso é que, ao contrário do que ocorre no pacote, o
conteúdo e os comportamentos internos de um subsistema podem ser alterados com total liberdade, contanto que as
interfaces do subsistema permaneçam constantes. Os subsistemas também fornecem um elemento de 'design substituível':
dois componentes <<realização>> que realizam as mesmas interfaces (ou componente
<<especificação>>) são intercambiáveis.
Para assegurar que os subsistemas sejam elementos substituíveis no modelo, algumas regras precisam ser aplicadas:
-
Um subsistema deve minimizar a exposição de seu conteúdo. O ideal é que nenhum elemento contido em um subsistema
tenha visibilidade 'pública' e, portanto, nenhum elemento fora do subsistema dependa da existência de um elemento
específico contido no subsistema. Algumas exceções são as seguintes:
-
Em algumas tecnologias, as aparências externas de um subsistema não podem ser modeladas como uma interface
UML. Por exemplo, uma interface Java é modelada como uma classe estereotipada.
-
O design do subsistema pode exigir a exposição de classes em vez de interfaces UML. Por exemplo, uma classe
"delegar" ou "acessar" pode ser utilizada para ocultar uma colaboração complexa de outras classes. Embora
seja possível utilizar um pacote comum no lugar, pode-se utilizar um subsistema para enfatizar a intenção
de encapsular o comportamento e ocultar os detalhes internos.
-
Quando as aparências externas de um subsistema não são interfaces UML, geralmente é útil ter um diagrama (por
exemplo, nomeado "Visualização Externa") que mostre os elementos visíveis do subsistema.
-
Um subsistema deve definir suas dependências em interfaces do subsistema (e elementos publicamente visíveis do
subsistema nos casos excepcionais descritos anteriormente). Além disso, vários subsistemas podem compartilhar um
conjunto de interfaces ou definições de classes em comum. Neste caso, esses subsistemas 'importam' o conteúdo dos
pacotes que contêm os elementos comuns. Isso é mais comum com pacotes em camadas inferiores da arquitetura, para
assegurar que definições comuns de classes que devam ser transmitidas entre os subsistemas sejam definidas de
maneira consistente.
Veja a seguir um exemplo das dependências de Subsistema e de Pacote:
Dependências de Subsistema e de Pacote no Modelo de Design
A UML ([UML04]) declara:
Existem vários estereótipos padrão da UML que aplicam-se ao componente, por exemplo, <<especificação>>
e <<realização>> para modelar componentes com definições distintas de especificação e realização, em
que uma especificação pode ter várias realizações.
Um Componente estereotipado por <<especificação>> especifica um domínio de objetos sem definir a
implementação física desses objetos. Ele terá apenas interfaces fornecidas e requeridas e não deverá ter classes e
subcomponentes de realização como parte de sua definição.
Um Componente estereotipado por <<realização>> especifica um domínio de objetos e também define a
implementação física desses objetos. Por exemplo, um Componente estereotipado por <<realização>> terá
apenas classes e subcomponentes de realização que implementam o comportamento especificado por um Componente
<<especificação>> separado.
A separação de especificação e realização permite essencialmente duas descrições separadas do subsistema. A
especificação serve como um contrato que define tudo que um cliente precisa saber para utilizar o subsistema. A
realização é um design interno detalhado destinado a orientar o implementador. Se você desejar suportar várias
realizações, crie subsistemas de "realização" separados e represente uma realização de cada subsistema de realização
para o subsistema de especificação.
Se o estado e o comportamento internos do subsistema forem relativamente simples, poderá ser suficiente especificar o
subsistema por suas interfaces expostas, diagramas de estado para descrever o comportamento e texto descritivo.
Para estado e comportamento internos mais complexos, é possível utilizar classes de análise para especificar o
subsistema em um alto nível de abstração. Para sistemas em larga escala, a especificação de um subsistema também pode
incluir casos de uso. Consulte Desenvolvendo Sistemas de Grande Escala com o Rational Unified Process.
O fornecimento de uma especificação detalhada separada da realização tende a ser mais útil nas situações a seguir:
-
o estado ou comportamento interno da realização do subsistema é complexo - e a especificação precisa ser expressa
no modo mais simples possível para que os clientes a utilizem de modo efetivo;
-
o subsistema é um "componente de montagem" destinado à montagem em vários sistemas (consulte Conceito: Componente);
-
as aparências internas do subsistema devem ser desenvolvidas por uma organização separada;
-
várias implementações do subsistema precisam ser criadas;
-
o subsistema deve ser substituído por uma outra versão que tenha mudanças internas significativas, sem mudanças no
comportamento externamente visível.
No entanto, manter uma especificação separada exige esforço - uma vez que deve-se assegurar que a realização do
subsistema esteja em conformidade com a especificação. Os critérios de quando, e se deve, criar classes e colaborações
separadas de especificação e realização devem ser definidos em Produto de Trabalho: Diretrizes Específicas do Projeto.
Uma especificação deverá definir suas dependências. Estas são as interfaces e os elementos visíveis de outros
subsistemas e pacotes que devem estar disponíveis em todas as realizações de conformidade do subsistema.
Uma realização pode ter dependências adicionais, inseridas pelo designer ou implementador. Por exemplo, pode haver uma
oportunidade para utilizar um componente de utilitário para simplificar a implementação - mas o uso desse componente de
utilitário é um detalhe que não precisa ser exposto aos clientes. Essas dependências adicionais deverão ser capturadas
em um diagrama separado como parte da realização.
Uma especificação totalmente detalhada define tudo o que um cliente precisa para utilizar um subsistema. Isso significa
refinar as interfaces expostas e quaisquer elementos publicamente visíveis, de modo que fiquem um-a-um com o código. As
classes de análise inseridas para especificar o comportamento do subsistema devem permanecer como abstrações de alto
nível uma vez que elas devem ser independentes de quaisquer realizações de subsistemas.
Os elementos de realização de um subsistema devem ser alinhados juntamente com o código.
Consulte Técnica: Mapeando de Design para Código para discussão adicional sobre este tópico.
Modelagem
Os subsistemas de design podem ser modelados como componentes da UML 2.0 ou subsistemas da UML 1.5. Essas construções
fornecem recursos de modelagem quase equivalentes, como modularidade, encapsulamento e instâncias capazes de serem
executados no tempo de execução.
Algumas considerações adicionais sobre essas opções de modelagem são:
-
Os subsistemas da UML 1.5 incluíam explicitamente a noção de "especificação" e "realização" (definidas acima na
seção intitulada Especificação e Realização do
Subsistema). Os componentes da UML 2.0 suportam a noção de especificação (na forma de uma ou mais interfaces
fornecidas e requeridas) e realização (implementação interna que consiste em uma ou mais classes e subcomponentes
que realizam seu comportamento).
-
Os subsistemas da UML 1.5 também eram pacotes. Os componentes da UML 2.0 possuem recursos de empacotamento, o que
significa que eles podem ter e importar um conjunto potencialmente grande de elementos do modelo.
No entanto, de um modo geral, essas notações podem ser utilizadas de modo intercambiável. A decisão de representar os
Subsistemas de Design como subsistemas da UML 1.5 ou componentes da UML 2.0 deverá ser documentada nas Diretrizes Específicas do Projeto adaptadas ao projeto.
Se a sua ferramenta de modelagem visual suportar pacotes da UML 1.5, mas não subsistemas da UML 1.5, um pacote
estereotipado como <<subsistema>> poderá ser utilizado para indicar um subsistema.
Restrições de Dependência de Subsistema
As mesmas restrições e discussões de dependência mencionadas na seção intitulada Restrições de Dependência de Subsistema também se aplicam a
subsistemas de design que estejam sendo modelados como subsistemas da UML 1.5.
Um exemplo de dependências de Subsistema e de Pacote na UML 1.5 é mostrado a seguir:
Dependências de Subsistema e de Pacote no Modelo de Design
Especificação e Realização de Subsistema
A UML 1.5 determina:
O conteúdo de um subsistema é dividido em dois subconjuntos: 1) elementos de especificação e 2) elementos de
realização. Os elementos de especificação, juntamente com as operações e recepções do subsistema, são utilizados
para fornecer uma especificação abstrata do comportamento oferecido pelos elementos de realização. A coleta de
elementos de realização modelam o interior da unidade comportamental do sistema físico.
A separação de especificação e realização permite essencialmente duas descrições separadas do subsistema. A
especificação serve como um contrato que define tudo que um cliente precisa saber para utilizar o subsistema. A
realização é um design interno detalhado destinado a orientar o implementador.
Uma opção para modelar especificações e realizações, se não suportadas diretamente pelo ambiente de modelagem, é
colocar dois pacotes, especificação e realização, dentro de cada subsistema.
Uma motivação para as especificações é suportar várias realizações. Isso não era diretamente suportado na UML 1.x. Se
você desejar suportar várias realizações utilizando subsistemas da UML 1.5, crie subsistemas de "realização" separados
e represente uma realização de cada subsistema de realização para o subsistema de especificação.
Basicamente, as mesmas considerações para Especificação e Realização que são aplicáveis à UML 2.0 também aplicam-se
aqui (consulte Quando e Como Utilizar, Dependências e Relacionamento com
Implementação para obter uma explicação).
Informações Adicionais
Consulte Diferenças entre a UML 1.x e a UML 2.0para obter informações adicionais.
|