Diretriz: Subsistema de Design
Um Subsistema de Design implementa o conceito de Componente de Software. Esta diretriz explica como identificar e especificar Subsistemas de Design.
Relacionamentos
Descrição Principal

Uso do Subsistema

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

Identificando Subsistemas

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.

Modelando Subsistemas

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>>).

Subsistemas que Representam os Produtos Existentes Para o início da página

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.

Restrições de Dependência de Subsistema Para o início da página

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:

Diagrama descrito no texto associado.

Dependências de Subsistema e de Pacote no Modelo de Design

Especificação e Realização de SubsistemaPara o início da página

DefiniçãoPara o início da página

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.

Quando e Como Utilizar

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.

Dependências

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.

Relacionamento com Implementaçã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.

Representação da UML 1.x

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:



Diagrama descrito no texto associado.

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.