Diagramas de Colaboração e
Projeto e Desenvolvimento de Sistemas de Informação
UNIVERSIDADE ESTADUAL PAULISTAINSTITUTO DE BIOCIÊNCIAS, LETRAS E CIÊNCIAS EXATASDEPARTAMENTO DE CIÊNCIAS DE COMPUTAÇÃO E ESTATÍSTICA
Diagramas de Colaboração e Padrões GRASP
O que vimos até agora
� Diagramas de Caso de Uso� Casos de uso resumido e completo� Modelo Conceitual� Diagramas de Sequência do Sistema� Diagramas de Sequência do Sistema� Contratos de Operações� Notação dos Diagramas de
Comunicação
Atendente
nome
Leitor
nometipo : char
0..n1..1 0..n1..1
registra
Empréstimo/Devolução
data do empréstimosituação : Char0..n1..1 0..n1..1
faz
1..11..1 possui
Reserva
períodosituacao : char0..n
1..1
0..n
1..1
^
faz
0..1
0..1
0..1
0..1
corresponde a
0..10..1 corresponde a0..n0..n
LinhaDoEmpréstimo
data_prevista_devoluçãodata_entrega_real
1..n1..n
Bibliotecaria
nome
0..10..1
CopiaDoLivro
nro sequencialsituacao : charliberadoParaEmprestimo : char
1..1
0..n
1..1
0..n
< refere-se a
Livro
titulo : String[30]autor : String[30]ano : intISBN : string[20]editora : inttipo : char
0..n1..1 0..n1..1
registra
1..11..1refere-se a >
0..n
1..1
0..n
1..1possui
Objetivo ao final da fase de projeto
Mais a especificação
das interfaces
1
Leitornometipo
calcularDataDevolucao( )
0..*
1
Emprestimodata_do_emprestimosituacao : char
adicionarCopia( )devolverCopia( )
1 0..*
faz
1possui
das interfaces
(métodos)1..*
1
CopiaDoLivronro_sequencialsituacao : charliberadoParaEmprestimo : char
mudarSituacao( )codCopia( )sinalizarDevolucao( )
0..*
LinhaDoEmprestimodata_prevista_devoluçãodata_entrega_real
codCopia( )atualizarDataDev( )
1..*
10..*
refere-se a
Como projetar as responsabilidades de cada objeto
� Sabemos que os objetos precisam se comunicar para completar as operações.
� Os Diagramas de comunicação � Os Diagramas de comunicação mostram escolhas de atribuições de responsabilidades a objetos.
� Mas quem é o melhor candidato para realizar cada uma das operações ou métodos do sistema?
Como projetar as responsabilidades de cada objeto
� Responsabilidade:� Um contrato ou obrigação de um tipo ou uma classe(Booch
e Rumbaugh)� Responsabilidades estão relacionadas às obrigações de um
objeto em termos de seu comportamento.� Dois tipos de responsabilidades básicas:� Dois tipos de responsabilidades básicas:
� Fazer� Fazer algo (criar um objeto, executar uma operação, ...)� Iniciar ações em outros objetos(delegação).� Controlar e coordenar atividades em outros objetos.
� Conhecer� Conhecer dados privados encapsulados.� Conhecer objetos relacionados.� Conhecer dados/atributos que podem ser derivados ou calculados.
Responsabilidades e Diagramas de Interação
� Diagramas de interação mostram escolhas de atribuição de responsabilidade a objetos.
� Exemplo: atribuir aos objetos do tipo � Exemplo: atribuir aos objetos do tipo Venda a responsabilidade de imprimirem a si próprios.
:Vendaimprimir()
Responsabilidade de
imprimir a si própria
Exemplo: Motivação para aplicação de Padrões
� Implementação inchada ou concentradora
Diagrama de Comunicação para a operação
EmprestarFita(fcodigo)
� Implementação inchada ou concentradoraX
� Implementação leve, distribuída
Cod Cópia fita
Emprestar
:Atendente
:CWindowCamada de Interface
açãoExecutada(eventoDaAção)
Sistema Videolocadora
:CWindow
:????
Camada de Interface
Camada do Domínio
emprestarFita(fcodigo)
Comunicação entre os objetos
emprestarFita(fCodigo)----> :Videolocadora clienteCorrente: Cliente
2: emprestimoCorrente := getEmprestimoCorrente
3: criar()
Qual é o problema desta solução?
emprestimoCorrente: Emprestimo
fitas: Fita item: ItemDeEmprestimo
5: associarItem(item)1: fita:=get(fCodigo)
4: associarFita(fita)
Pseudo-código Concentrador VideoLocadora
Classe VideoLocadorafitas: Conjunto;clienteCorrente: Cliente
Método emprestarFita(fCodigo: String)fita:Fita;emprestimoCorrente: Emprestimo;emprestimoCorrente: Emprestimo;item: ItemDeEmprestimo;
fita := fitas.get(fCodigo);emprestimoCorrente := clienteCorrente.getEmprestimoCorrente();item := itemDeEmprestimo.new();Item.associarFita(fita);EmprestimoCorrente.associarItem(item);
Fim Método;FIM Classe;
Comunicação entre objetos (concentrador)
emprestarFita(fCodigo)----> :Videolocadora clienteCorrente: Cliente
5: associarItem(item)
2: emprestimoCorrente := getEmprestimoCorrente
1: fita:=get(fCodigo)
3: criar()
4: associarFita(fita)
emprestimoCorrente: Emprestimo
fitas: Fita item: ItemDeEmprestimo
5: associarItem(item) 4: associarFita(fita)
Diagrama de Comunicação não Concentrador
emprestarFita(fCodigo)----> :Videolocadora
emprestimoCorrente: Emprestimo
5: associarItem()
2: emprestar(fita)1: fita:=get(fCodigo)
clienteCorrente: Cliente
fitas: Fita
item: ItemDeEmprestimo
3: adicionar(fita)
4: criar()
6: associarFita(fita)
2: emprestar(fita)
Código com Responsabilidade Distribuída
Classe VideoLocadorafitas: Conjunto;clienteCorrente: Cliente;
Metodo emprestarFita(fCodigo:string)
fita:Fita;fita:=fitas.get(tCodigo);
Classe Emprestimo
Itens:Conjunto;
Metodo adicionar(fita:Fita);item: ItemDeEmprestimo;
fita:=fitas.get(tCodigo);clienteCorrente.empresta(fita)
Fim Metodo;Fim Classe;
Classe ClienteemprestimoCorrente: Empretimo;
Método emprestar(fita:Fita);emprestimoCorrente.adiciona(fita);
Fim Método;Fim Classe;
item := ItemDeEmprestimo.new();self.associaItem(item);item.associaFita(fita);
Fim Metodo;Fim Classe;
Discussão
� Qual dos códigos é mais fácil de entender e manter?
� Em qual dos códigos as responsabilidades das classes parecem mais intuitivas?
� Para desenvolver um bom projeto, precisamos de princípios para nos guiar na atribuição de responsabilidades -> padrões de projeto OO.
Responsabilidade
� Responsabilidade não é a mesma coisa que um método.� Métodos são implementados para
satisfazer as responsabilidades
� Responsabilidades são implementadas � Responsabilidades são implementadas usando métodos que agem sozinhos ou colaboram com outros métodos e objetos.
� Padrões de projeto são princípios para guiar a atribuição de responsabilidades aos objetos.
Padrões� Desenvolvedores experientes em OO criaram
um repertório de princípios gerais e boas soluções para guiar a construção de software.
� Essas soluções foram descritas em um formato padronizado (nome, problema, solução) e podem ser usadas em outros solução) e podem ser usadas em outros contextos(outros projetos).
� Surgiram com base no trabalho do arquiteto Christopher Alexander, 1977. (Padrões Arquitetônicos).
� Ganharam impulso após a publicação do livro sobre Padrões de Projeto (Design Patterns –Gamma e outros – GoF- 1994)
Padrões
� Padrões usualmente não contem novas idéias � Organizam conhecimentos e princípios existentes,
testados e consagrados.
� Padrão é uma descrição nomeada de um � Padrão é uma descrição nomeada de um problema e uma solução, que pode ser aplicado em novos contextos.
� Nomear padrões melhora a comunicação (cria-se um vocabulário, ou idioma)
Padrões GRASP� GRASP = General Responsability
Assignment Software Patterns.� Descrevem princípios fundamentais de
atribuição de responsabilidades a objetos.� A compreensão dos padrões de projeto � A compreensão dos padrões de projeto
durante a criação de diagramas de comunicação é importante, pois:� São princípios de bons projetos Orientado a
Objetos.� Levam a projetos OO de qualidade.
Padrões GRASP
� Alguns padrões GRASP principais:� Especialista (Expert)� Criador (Creator)� Coesão alta (High Cohesion)� Coesão alta (High Cohesion)� Acoplamento fraco (Low Coupling)� Controlador (Controller)
� Esses padrões abordam questões básicas comuns e tópicos fundamentais de desenvolvimento.
O padrão Especialista (Expert)
� Problema: qual é o princípio mais básico para atribuir responsabilidades em projeto orientado a objetos?em projeto orientado a objetos?
� Solução: Atribuir responsabilidade ao especialista da informação – a classe que tem a informação necessária para satisfazer a responsabilidade.
Exemplo
� No sistema biblioteca, quem seria o responsável por calcular a data de devolução de um livro?devolução de um livro?
Modelo Conceitual Biblioteca
Atendente
nome
Leitor
nometipo : char
0..n1 0..n1
registra
Empréstimo/Devolução
data do empréstimosituação : Char0..n1 0..n1
faz
11 possui
Reserva
períodosituacao : char0..n
1
0..n
1
^
faz
0..1
0..1
0..1
0..1
corresponde a
0..10..1 corresponde a
Livro
0..n
LinhaDoEmpréstimo
data_prevista_devoluçãodata_entrega_real
1..n1..n
Bibliotecaria
nome
0..10..1
CopiaDoLivro
nro sequencialsituacao : charliberadoParaEmprestimo : char
1
0..n
1
0..n
< refere-se a
Livro
titulo : String[30]autor : String[30]ano : intISBN : string[20]editora : inttipo : char
0..n1 0..n1
registra
11refere-se a >
0..n
1
0..n
1possui
Especialista
� A data de devolução ficará armazenada no atributo data_prevista_devolução do objeto LinhaDoEmprestimoobjeto LinhaDoEmprestimo
� Mas quem possui conhecimento necessário para calculá-la?
Modelo Conceitual Biblioteca
Atendente
nome
Leitor
nometipo : char
0..n1 0..n1
registra
Empréstimo/Devolução
data do empréstimosituação : Char0..n1 0..n1
faz
11 possui
Reserva
períodosituacao : char0..n
1
0..n
1
^
faz
0..1
0..1
0..1
0..1
corresponde a
0..10..1 corresponde a
Livro
0..n
LinhaDoEmpréstimo
data_prevista_devoluçãodata_entrega_real
1..n1..n
Bibliotecaria
nome
0..10..1
CopiaDoLivro
nro sequencialsituacao : charliberadoParaEmprestimo : char
1
0..n
1
0..n
< refere-se a
Livro
titulo : String[30]autor : String[30]ano : intISBN : string[20]editora : inttipo : char
0..n1 0..n1
registra
11refere-se a >
0..n
1
0..n
1possui
Especialista
� Pelo padrão especialista, Leitor deve receber essa atribuição, pois conhece o tipo de Leitor (por exemplo, aluno de tipo de Leitor (por exemplo, aluno de graduação, aluno de pós-graduação, professor, etc), que é utilizado para calcular a data em que o livro deve ser devolvido.
Especialista
: Emprestimo
2: criar(d, copiaLivro)
adicionarCopia(copiaLivro)--->
1: d:=calcularDataDevolução()
linh: LinhaDoEmprestimo:Leitor Uso do padrão
Especialista
Especialista: alternativa mais detalhada
: EmprestimoadicionarCopia(copiaLivro)---> copiaLivro: CopiaDoLivro
2: criar(d)
1: d:=calcularDataDevolução()
4: associarLinha(linh)adicionarCopia(CopiaLivro)�
Uso do padrão
Especialista
linh: LinhaDoEmprestimo
:Leitor3: associarCopia(copiaLivro)
1: d:=calcularDataDevolução()
Especialista
� Onde procurar pela classe especialista?� Começar pelas classes já estabelecidas durante o
projeto.� Se não encontrar, utilizar o Modelo Conceitual.
� Lembrar que existem especialistas parciais � Lembrar que existem especialistas parciais que colaboram numa tarefa� Informação espalhada -> comunicação via
mensagens
� Existe uma analogia no mundo real.
� Discussão� É o padrão mais utilizado� Tem uma analogia no mundo real� Coad: “Fazê-lo eu mesmo”� Lembrar que existem especialistas parciais
� Benefícios:� Mantém encapsulamento -> favorece o acoplamento fraco.� O Comportamento fica distribuído entre as classes que tem
a informação necessária (classes “leves”) -> favorece alta
Especialista
a informação necessária (classes “leves”) -> favorece alta coesão.
� Favorece o reuso.� Contra-indicações
� contra indicado quando aumenta acoplamento e reduz coesão
� Ex: quem é responsável por salvar um Empréstimo no banco de dados?
Padrão Criador (Creator)
� Problema: Quem deveria ser responsável pela criação de uma nova instância de alguma classe?
� Solução: atribua à classe B a responsabilidade de criar uma nova instância da classe A se uma das seguintes condições for verdadeira:� B agrega objetos de A� B contém objetos de A� B registra instâncias de objetos de A� B usa objetos de A� B tem os valores iniciais que serão passados para
objetos de A, quando de sua criação
Criador� No sistema da Biblioteca, quem é responsável
pela criação de uma linhaDoEmprestimo
: EmprestimoadicionarCopia(copiaLivro)--->
linh: LinhaDoEmprestimo
2: criar(d, copiaLivro)
:Leitor
1: d:=calcularDataDevolução()
Uso do padrão Criador: Emprestimo contém várias linhas de emprestimo
Empréstimo/Devolução
data do empréstimosituação : Char
CriarLinhaEmprest()
Criador
� Discussão� O padrão guia a atribuição de responsabilidades
relacionadas com a criação de objetos.� Escolha adequada favorece acoplamento fraco
� Objetos agregados, contêineres e registradores � Objetos agregados, contêineres e registradores são bons candidatos à responsabilidade de criar outros objetos
� Algumas vezes o candidato a criador é o objeto que conhece os dados iniciais do objeto a ser criado.
Acoplamento
� Acoplamento: dependência entre elementos (classes, subsistemas, ...). Normalmente resultante de colaboração para atender a uma responsabilidade.
� O acoplamento mede o quanto um objeto está conectado a, tem conhecimento de ou está conectado a, tem conhecimento de ou depende de outros objetos� Acoplamento fraco (ou baixo) – um objeto não
depende de muitos outros.� Acoplamento forte (ou alto) – um objeto depende
de muitos outros.
Acoplamento
� Problemas do acoplamento alto:� Mudanças em classes interdependentes
forçam mudanças locais.� Dificulta a compreensão do objetivo de
cada classe.cada classe.� Dificulta a reutilização.
� Acoplamento fraco é o desejável
Padrão Acoplamento Fraco
� Problema: como apoiar a baixa dependência entre classes e aumentar a reutilização ?
� Solução: Atribuir responsabilidade de � Solução: Atribuir responsabilidade de maneira que o acoplamento permaneça baixo.
Padrão Acoplamento Fraco
� Exemplo: No sistema de biblioteca, suponha que queremos realizar a devolução da cópia do livro. Qual classe deve ser responsável por essa tarefa?
� Alternativas:� Alternativas:� A classe Leitor
� A classe Livro
� A classe Empréstimo
Modelo Conceitual Biblioteca
Atendente
nome
Leitor
nometipo : char
0..n1 0..n1
registra
Empréstimo/Devolução
data do empréstimosituação : Char0..n1 0..n1
faz
11 possui
Reserva
períodosituacao : char0..n
1
0..n
1
^
faz
0..1
0..1
0..1
0..1
corresponde a
0..10..1 corresponde a
Livro
0..n
LinhaDoEmpréstimo
data_prevista_devoluçãodata_entrega_real
1..n1..n
Bibliotecaria
nome
0..10..1
CopiaDoLivro
nro sequencialsituacao : charliberadoParaEmprestimo : char
1
0..n
1
0..n
< refere-se a
Livro
titulo : String[30]autor : String[30]ano : intISBN : string[20]editora : inttipo : char
0..n1 0..n1
registra
11refere-se a >
0..n
1
0..n
1possui
Projeto 1: responsabilidade atribuída ao Leitor
devolveCopia(codCopia)--> leit: Leitor4: atualizarSituacao('devolvida')
cop:=busca(codCopia)devolver(dataDeHoje)
Leitor conhece copias do livro?
copias: CopiaDoLivrolinh: LinhaDoEmprestimo
1: cop:=busca(codCopia)
cop: CopiaDoLivro2: devolver(dataDeHoje)
3: atualizarDataDev(dataDeHoje)
Copia conhece linha do
empréstimo?
Projeto 2: responsabilidade atribuída ao Livro
devolveCopia(codCopia)-->
cop: CopiaDoLivro
3: atualizarSituacao('devolvida')liv: Livro
1: cop:=busca(codCopia)
2: devolver(dataDeHoje)
linh: LinhaDoEmprestimo
copias: CopiaDoLivro 4: atualizarDataDev(dataDeHoje)
Eficiente?
Cópia conhece a linha de
empréstimo?
devolverCopia(codCopia)---> : Emprestimo :LinhaDoEmprestimo
1: *[enquanto encontrou=false] linh:==proximo()
4: [encontrou] atualizaDataDev(dataDeHoje)
2: * [enquanto encontrou = false] cc:=obterCodigoCopia()
3: cc :=CodigoCopia()
6: mudarSituacao('devolvida')
Projeto 3: responsabilidade atribuída ao Empréstimo
linh: LinhaDoEmprestimo cop: CopiaDeLivro
5: sinalizaDevolucao()encontrou := falseenquanto encontrou == false
linh := proxima linha do emprestimo cc:=linh.obterCódigoCópia()encontrou:=(cc==codCopia)
fim-enquantose encontrou
linh.atualizaDataDevolucao(dataDeHoje)fim-se
Qual projeto é melhor?
� Qual dos projetos anteriores favorece o acoplamento fraco?� Projeto 1 e 2 – acoplamento aumenta
(entre cópia do livro e linha do empréstimo, (entre cópia do livro e linha do empréstimo, entre leitor e cópia do livro)
� Projeto 3 – não aumenta acoplamento
PREFERÍVEL
Formas de Acoplamentos
� Um objeto tem um atributo que referencia um objeto de outra classe.
� Um objeto tem um método que referencia um objeto de outra classe.� Parâmetro, variável local ou retorno� Parâmetro, variável local ou retorno
� Um objeto invoca os serviços de um objeto de outra classe.
� Uma classe é subclasse de outra, direta ou indiretamente.
Acoplamento Fraco
� Discussão:� Acoplamento fraco -> classes mais independentes.
� Reduz impacto de mudanças.� Favorece reuso de classes.
� Considerado em conjunto com outros padrões� Considerado em conjunto com outros padrões� Extremo de acoplamento fraco não é desejável
� Fere princípios da tecnologia de objetos – comunicação por mensagens
� Projeto pobre: objetos inchados e complexos, responsáveis por muito trabalho -> baixa coesão
Acoplamento Fraco
� Discussão:� Dica: concentre-se em reduzir o acoplamento em
pontos de evolução ou de alta instabilidade do sistema.
� Benefícios:� Benefícios:� Classes são pouco afetadas por mudanças em
outras partes.� Classes são simples de entender isoladamente.� Conveniente para reutilização.
Coesão� Mede o quanto as responsabilidade de um elemento
(classe, objeto, subsistema,...) são fortemente focalizadas e relacionadas. (coesão funcional)
� Objeto com Coesão Alta -> objetos cujas responsabilidades são altamente relacionadas e que não executa um volume muito grande de trabalho. não executa um volume muito grande de trabalho.
� Objeto com Coesão Baixa -> objeto que faz muitas coisas não relacionadas ou executa muitas tarefas.� Difícil de compreender, reutilizar e manter.� constantemente afetado por mudanças.
Coesão Alta
� Problema: Como manter a complexidade sob controle?
� Solução: Atribuir responsabilidade de tal forma que a coesão permaneça alta.tal forma que a coesão permaneça alta.
Coesão Alta
� Exemplo 1: ( o mesmo para o acoplamento fraco): No sistema de biblioteca, suponha que queremos realizar a devolução da cópia do livro. Qual classe deve ser responsável por essa tarefa?por essa tarefa?� Leitor� Livro� Empréstimo
Projeto 1: responsabilidade atribuída ao Leitor
devolveCopia(codCopia)--> leit: Leitor4: atualizarSituacao('devolvida')
cop:=busca(codCopia)devolver(dataDeHoje)
O Leitor fica parcialmente encarregado da devolução da cópia do livro. Neste exemplo, isso seria aceitável, mas o que aconteceria se houvesse 50 mensagens de outro tipo recebidas por Leitor?
copias: CopiaDoLivrolinh: LinhaDoEmprestimo
1: cop:=busca(codCopia)
cop: CopiaDoLivro2: devolver(dataDeHoje)
3: atualizarDataDev(dataDeHoje)
Projeto 2: responsabilidade atribuída ao Livro
devolveCopia(codCopia)-->
cop: CopiaDoLivro
3: atualizarSituacao('devolvida')liv: Livro
1: cop:=busca(codCopia)
2: devolver(dataDeHoje)
linh: LinhaDoEmprestimo
copias: CopiaDoLivro 4: atualizarDataDev(dataDeHoje)
cop:=busca(codCopia)devolver(dataDeHoje) Parece uma solução melhor. Mas se
houver inúmeras operações a serem feitas com o livro, ocorre o mesmo problema de Leitor.
Projeto 3: responsabilidade atribuída ao Empréstimo
devolverCopia(codCopia)---> : Emprestimo :LinhaDoEmprestimo
1: *[enquanto encontrou=false] linh:==proximo()
4: [encontrou] atualizaDataDev(dataDeHoje)
2: cc:=codigoCopia()
3: cc := codigoCopia()
6: mudarSituacao('devolvida')
Esta é a melhor solução. O objeto empréstimo representa eventos bem definidos no sistema de biblioteca (empréstimo e devolução), por isso é mais intuitivo que ele assuma esta responsabilidade.
linh: LinhaDoEmprestimo cop: CopiaDeLivro
5: sinalizaDevolucao()encontrou := falseenquanto encontrou == false
linh := proxima linha do emprestimo cc:= linh.obter o código da cópia()encontrou:=(cc==codCopia)
fim-enquantose encontrou
linh.atualizaDataDev(dataDeHoje)fim-se
Coesão Alta
� Discussão:� Coesão alta, assim como Acoplamento Fraco, são
princípios que devem ser considerados para a avaliação de projetos de objetos� Má coesão traz acoplamento e vice-versa� Má coesão traz acoplamento e vice-versa
� Regra prática: classe com coesão alta tem um número relativamente pequeno de métodos, com funcionalidades relacionadas, e não executa muito trabalho.
� Analogia com mundo real� Pessoas que assume muitas responsabilidades não
associadas podem tornar-se (e normalmente tornam-se) ineficientes.
Coesão Alta
� Benefícios:� Mais clareza e facilidade de compreensão
do projeto.� Simplificação de manutenção e de � Simplificação de manutenção e de
acréscimo de funcionalidade/melhorias.� Favorecimento do acoplamento fraco.� Aumento no potencial de reutilização
� Classe altamente coesa pode ser usada para uma finalidade bastante específica.
Será que a solução dada para o evento de devolução da cópia é ideal?
� Ainda temos um problema: quando ocorre o evento de devolução da cópia, o objeto empréstimo ao qual a cópia emprestada se refere ainda não é conhecido .refere ainda não é conhecido .
� Portanto, é preciso eleger alguma classe, que conheça os empréstimos, para receber a mensagem devolverCopia.
� Essa classe terá que identificar o objeto empréstimo cujo código de cópia seja igual ao parâmetro fornecido.
A pergunta anterior não está respondida nos slides a seguir. Voltaremos a ela no fim
deste assunto.deste assunto.
Controlador
� É um objeto de interface (entre sistema e mundo externo) responsável por tratar um evento externo (evento de sistema).
� Define (implementa) o método para a operação de sistema. operação de sistema.
Sistema
entrarItem()
terminarVenda()
efetuarPagamento()
Operações de sistema associadas aos eventos de sistema:
Sistema
iniciarDevo(idLei)
devolver(codCop)
FinalizarDevol()
Padrão Controlador
� Problema: Quem deve ser responsável por tratar um evento do sistema (gerado por um ator externo) ?
� Solução: A responsabilidade de receber ou tratar as mensagens de eventos do sistema (operações) pode ser atribuída uma classe que:� Representa o sistema todo, representa o negócio ou � Representa o sistema todo, representa o negócio ou
organização, um dispositivo ou um subsistema (chamado de controlador fachada)
� Representa algo no mundo real que é ativo (chamado de controlador do papel)
� Representa um tratador artificial de todos os eventos de sistema de um caso de uso (Controlador do caso de uso)� TratadorDe<NomeDoCasoDeUso>� ControladorDe<NomeDoCasoDeUso>
Padrão Controlador� Exemplo: Quem vai tratar os eventos do
sistema de biblioteca?
:Atendente:Atendente SistemaSistema
1: iniciarEmpréstimo(id_Leitor)
2: nome e situação do leitor
5: encerrarEmpréstimo()
3: emprestarLivro(id_Livro)
2: nome e situação do leitor
4: dataDeDevolução
* mais livros a emprestar
Cod Cópia Livro
Emprestar
:Atendente
:CWindowCamada de Interface
açãoExecutada(eventoDaAção)
:CWindow
:????
Camada de Interface
Camada do Domínio
emprestarLivro(codCopia)
Objeto de Interface
Exemplo1: Opções de Controlador
� todo o sistema (controlador fachada): Biblioteca
:BibliotecainiciarEmprestimo(…) :ControladorDe
� um tratador artificial do caso de uso: ControladorDeEmprestarLivro
iniciarEmprestimo(…)
61
:Biblioteca:ControladorDe
EmprestarLivro
:BibliotecaemprestarLivro(…)
:ControladorDe
EmprestarLivro
emprestarLivro(…)
:Biblioteca
encerrarEmprestimo() :ControladorDe
EmprestarLivro
encerrarEmprestimo()
Discussão : Controladores Fachada� Um controlador fachada deve ser um objeto
(do domínio) que seja o ponto principal para as chamadas provenientes da interface com o usuário ou de outros sistemas� pode ser uma abstração de uma entidade física –
ex: TerminalDeAtendimento
� pode ser um conceito que represente o sistema –� pode ser um conceito que represente o sistema –ex: Biblioteca
� São adequados quando não há uma quantidade muito grande de eventos de sistema
� Ou quando não é possível redirecionar mensagens do sistema para controladores alternativos (ex: outros subsistemas )
Discussão : Controladores de Caso de Uso
� Deve existir um controlador diferente para cada caso de uso� Por exemplo, o ControladorDeEmprestarLivro
será responsável pelas operações iniciarEmpréstimo, emprestarLivro e encerrarEmpréstimo
� Não é um objeto do domínio, e sim uma construção artificial para dar suporte ao sistema.
� Não é um objeto do domínio, e sim uma construção artificial para dar suporte ao sistema. Ex: ControladorDeEmprestarLivro, ControladorDeDevolverLivro
� Pode ser uma alternativa se a escolha de controladores fachada deixar a classe controladora com alto acoplamento e/ou baixa coesão (controlador inchado por excesso de responsabilidades)
� É uma boa alternativa quando existem muitos eventos envolvendo diferentes processos.
Controladores inchados� Classe controladora mal projetada - inchada
� coesão baixa – falta de foco e tratamento de muitas responsabilidades
� Sinais de inchaço: � uma única classe controladora tratando todos os
eventos, que são muitos. Comum com eventos, que são muitos. Comum com controladores fachada
� o próprio controlador executa as tarefas necessárias para atender o evento, sem delegar para outras classes (coesão alta, não especialista)
� controlador tem muitos atributos e mantém informação significativa sobre o domínio, ou duplica informações existentes em outros lugares
Possíveis soluções para controladores inchados
� Acrescentar mais controladores.� Projetar o controlador de forma que ele
possa delegar o atendimento da responsabilidade de cada operação de sistema a outros objetos.
� Cuidado: Controladores de papéis podem conduzir a maus projetos(armadilha de projetar objetos semelhantes a pessoas para fazer todo o trabalho – é preciso delegar)
Corolário do Padrão Controlador
� Objetos de interfaces HM ( como objetos “janela”) e da camada de apresentação não devem ter a apresentação não devem ter a responsabilidade de tratar eventos do sistema (arquitetura em camadas)
Benefícios do Padrão Controlador e seu corolário
� Benefícios:� aumento das possibilidades de reutilização
de classes e do uso de interfaces “plugáveis”. “plugáveis”.
� conhecimento do estado do caso de uso –controlador pode armazenar estado do caso de uso, garantindo a seqüência correta de execução de operações
Cod Cópia Livro
Devolver
:Atendente
:CWindowCamada de Interface
açãoExecutada(eventoDaAção)
devolverCopia?
????:Emprestimo
devolverCopia(codCopia)
:CWindowCamada de Interface
Camada do Domínio
devolverCopia(codCopia)
Voltando ao problema do slide 57....
� Qual era o problema:� devolverCópia x Empréstimo
� Qual é a solução?� Qual é a solução?� Classe Fachada ou Controladora
Cod Cópia Livro
Devolver
:Atendente
:CWindowCamada de Interface
açãoExecutada(eventoDaAção)
devolverCopia?
:Biblioteca:Emprestimo
devolverCopia(codCopia)
:CWindowCamada de Interface
Camada do Domínio
devolverCopia(codCopia)