Diagramas de Sequência e
Padrões GRASP adicionais
Projeto de Sistemas
Diagrama de Sequência
• É um diagrama de interações que enfatiza a ordem temporal das mensagens.
• Uma linha de vida é uma linha tracejada
vertical que representa o tempo de vida de um objeto.
• Um foco de controle é um retângulo fino
vertical sobreposto à linha de vida que mostra o período durante o qual um objeto está
Diagrama de Sequência
: Ticket Agent c: Client «create» setItinerary(i) calculateRoute() route• Mostra, baseado em um cenário:
– Objetos e classes envolvidos;
– A seqüência de mensagens (simbolizadas por setas) trocadas pelos objetos, necessárias para desenvolver a funcionalidade do cenário.
• Consiste em um número de objetos mostrado em linhas verticais;
• O decorrer do tempo é visualizado observando-se o diagrama no sentido vertical de cima para baixo.
• Os objetos participantes da interação são organizados na horizontal.
• Abaixo de cada objeto existe uma linha, chamada de linha de vida.
• Um retângulo na linha da vida representa o seu foco de controle que indica a duração da ação realizada pelo objeto.
• O topo do retângulo indica o início da execução da operação solicitada pela mensagem recebida e a base inferior do retângulo marca o fim da
execução da operação.
• As mensagens entre objetos são representadas com linhas horizontais rotuladas partindo da
linha de vida do objeto remetente e chegando a linha de vida do objeto receptor.
• A posição vertical das mensagens permite deduzir a ordem na qual elas são enviadas. • Ordem de envio de mensagens em um
diagrama de seqüência pode ser deduzida a partir das expressões de seqüência.
• Criação e destruição de objetos podem ser representadas.
O diagrama de seqüência exibe uma visão dinâmica do sistema.
Exemplo: Criar Cliente
Fluxo Principal
1. O usuário solicita o cadastro de cliente.
2. O sistema apresenta o formulário para preenchimento.
3. O usuário entra com as informações necessárias do cliente no sistema e submete. 4. O sistema valida o cadastro do cliente. (FE01) (FE02)
5. O sistema armazena os dados do cliente.
6. O sistema cria uma conta em nome do cliente
7. O sistema notifica o usuário sobre o cadastro e o caso de uso termina.
Fluxos de Exceção
FE01 - Usuário cadastrado
1. Se o cliente já estiver cadastrado, uma mensagem será exibida e o caso de uso termina. FE02 - Dados incompletos
1. Se os dados estiverem incompletos, o sistema exibe uma mensagem para que o usuário forneça as informações completas e o caso de uso retorna ao passo 3 do fluxo principal.
Pure Fabrication
Problema:
Como não violar High Cohesion e Low Coupling? Solução:
Atribuir um conjunto altamente coeso de
responsabilidades a uma classe artificial que não representa nada no domínio do problema, de
modo a prover alta coesão, baixo acoplamento e reuso.
Pure Fabrication: Benefícios
• Alta coesão é fortalecida porque algumas responsabilidades são fatoradas em uma classe que focaliza apenas em um conjunto muito específico de tarefas relacionadas.
• O potencial de reuso pode ser aumentado por conta da presença de classes de granularidade fina do tipo Pure Fabrication.
Pure Fabrication: Exemplo
Suponha, no exemplo do ponto de vendas, que é necessário suporte para salvar instâncias de Venda em um banco de dados relacional. Por Expert, há alguma justificativa em em atribuir esta responsabilidade à classe Venda.
Entretanto:
• A tarefa requer um número relativamente grande de operações orientadas a bancos de dados, o que torna a classe Venda não coesa. • A classe Venda tem de ser acoplada a um banco de dados relacional,
aumentando o seu acoplamento.
• Salvar objetos em um banco de dados relacional é uma tarefa bastante geral, que será necessária para várias classes. Colocar estas responsabilidades na classe Venda sugere baixo nível de reuso e muita duplicação em outras classes que farão a mesma coisa.
Pure Fabrication: Exemplo
PersistentStorageBroker
save() Por Pure Fabrication
•A classe Venda permanece bem projetada, com alta coesão e baixo acoplamento
•A classe PersistentStorageBroker é, ela própria, relativamente coesa
•A classe PersistentStorageBroker é um objeto bastante genérico e reutilizável
Pure Fabrication
• Preserva baixo acoplamento e alta coesão das classes
Indirection
Problema:
Como evitar acoplamento direto?
Como desacoplar objetos de modo que Low Coupling tenha suporte e o potencial de reuso permaneça alto? Solução:
Atribuir as responsabilidades a um objeto
intermediário que medie a comunicação com outros componentes ou serviços, de modo que eles não
Exemplo : PersistentStorageBroker
O exemplo Pure fabrication para desacoplar a Venda dos serviços de bancos de dados relacionais através da introdução de um PersistentStorageBroker
também é um exemplo de atribuir responsabilidades para dar suporte à Indirection. O
PersistentStorageBroker atua com um intermediário
Indirection : Exemplo
Modem dial( ) receive( ) send( ) By Indirection Modem::dial(phoneNum) { ::OS_OpenPort(1); ::OS_Dial(phoneNUM) } CreditAuthorizationService 1:dial(phoneNum) Modem
Indirection
• Preserva o baixo acoplamento entre os objetos
Law of Demeter
Problema:
Como evitar conhecer a estrutura de objetos indiretos?
Solução:
Se duas classes não têm outra razão para se
conhecerem, então as duas classes não devem interagir diretamente.
Law of Demeter
A lei de Demeter afirma que, dentro de um método, mensagens devem ser enviadas apenas para os seguintes objetos:
• O objeto this (ou self)
• Um parâmetro do método • Um atributo de self
• Um elemento de uma coleção que é atributo de self • Um objeto criado dentro do método
Law of Demeter : Exemplo
POST paymentAmount () : Float endSale () enteritem () makePayment () 1 1 Sale date : Date isComplete : Boolean time : Time becomeComplete () makeLineitem () makepayment () payment () : Payment total () : Float 1 1 Payment amountTendered amountTendered () : Float 1 11 1 Captures Paid-byViola a Law of Demeter : Exemplo
:Sale 1:prnt:=payment() : payment :POST prnt:Payment 1.1:amt:=amountTendered():Float amt:=paymentAmount():Float POST::PaymentAmount() { prnt:= m_sale->Payment() //Violates Law of DM return prnt->amountTendered(); } Violates Law of DM prnt is a 'Stranger' to POSTDá suporte à Law of Demeter
1:prnt:=payment() : payment
1.1:amt:=amountTendered():Float amt:=paymentAmount():Float
Supports the Law of Demeter :POST prnt:Payment :Sale POST:: PaymentAmount() {
return m_sale -> Payment();
Sale date : Date isComplete : Boolean time : Time becomeComplete( ) makeLineitem( ) makePayment( ) payment( ) paymentAmount( ) total( )
Law of Demeter
• Mantém baixo o acoplamento entre classes e torna o design mais robusto
• Adiciona um pequeno overhead na norma de chamadas de método indiretas
Law of Demeter:
O exemplo de totalização de horas
Employee – Instâncias da classe Employee representam um empregado. PayrollRules – As regras de pagamento de um empregado podem variar
de acordo com o local onde o empregado trabalha. Instâncias da classe PayrollRules class encapsulam as regras de pagamento que se aplicam a um empregado.
PayPeriod – Instâncias da classe PayPeriod representam uma faixa de dias para os quais um empregado é pago no mesmo contracheque. Shift – Instâncias da classe Shift (Turno) representam faixas de tempo
que o empregado trabalhou.
TimeTotaller – A classe TimeTotaller é uma classe usada pela classe PayPeriod para quebrar o total de horas trabalhadas durante um período de pagamento em minutos normais e minutos extra.
Interação no exemplo de totalização de horas
• O período de pagamento (PayPeriod) deve se associar com uma instância de TimeTotaller apropriada para o empregado quando o
objeto PayPeriod é criado.
• O objeto TimeTotaller deve ser capaz de examinar cada turno no período de
pagamento para aprender o número de minutos trabalhados em cada turno.
Colaboração ruim para totalização de horas
A classe PayPeriod não tem razão alguma para conhecer qualquer coisa sobre a classe PayrollRules
TimeTotaller ter acesso direto à coleção de turnos que ela precisa, implica em violar o encapsulamento da classe
Colaboração boa para totalização de horas
• Para preservar o nível de coesão e
acoplamento, uma interação menos direta pode ser utilizada.
• Isto é feito pelo seguinte diagrama de colaboração e pela criação de métodos adicionais.