DesenvolvimentoOrientado a Objetos e Componentes Nilseu Padilha [email protected] Autor: Prof. Federico Delgado Agenda Introdução: Padrões de Projeto GRASP Patterns Padrões de Projeto Em inglês, Design Patterns Começando pelo início: O que é um padrão ? ◦ Maneira testada ou documentada de alcançar um objetivo qualquer: Padrões são comuns em várias áreas da engenharia Padrões não são invenções originais ◦ Design Patterns, ou Padrões de Design/Projeto Padrões para alcançar objetivos na engenharia de software Inspirado em "A Pattern Language" de Christopher Alexander, sobre padrões de arquitetura de cidades, casas e prédios "Design Patterns" de Erich Gamma, John Vlissides, Ralph Jonhson e Richard Helm, conhecidos como "The Gang of Four",ou GoF, descreve 23 padrões de projeto úteis. Padrões de Projeto "Cada padrão descreve um problema que ocorre repetidas vezes em nosso ambiente, e então descreve o núcleo da solução para aquele problema, de tal maneira que podese usar essa solução milhões de vezes sem nunca fazê-la da mesma forma duas vezes” ◦ Christopher Alexander, sobre padrões em Arquitetura "Os padrões de projeto são descrições de objetos que se comunicam e classes que são customizadas para resolver um problema genérico de design em um contexto específico” ◦ Gamma, Helm, Vlissides & Johnson, sobre padrões em software Padrões de Projeto Possui quatro elementos essenciais: ◦ nome do padrão: referência para descrevermos um problema do projeto, suas soluções... uma ou duas palavras; vocabulário; documentação. ◦ problema: em que situação aplicar o padrão; explica o problema e seu contexto. ◦ solução: descreve os elementos que compõem o padrão de projeto, seus relacionamentos, responsabilidades e colaborações; descrição abstrata de problema de projeto ◦ consequências: resultados, análises das vantagens e desvantagens da aplicação do padrão (espaço, tempo, linguagens flexibilidade e extensibilidade de um projeto) de alta coesão e baixo acoplamento ◦ Aprender um vocabulário comum ◦ Compreender sistemas existentes ◦ Saber a melhor forma de converter um modelo de análise em um modelo de implementação ◦ Ter um caminho e um alvo para refatoramento . abstração para construir código reutilizável. herança. modularidade.Padrões de Projeto E porque aprender ? ◦ Aprender com a experiência dos outros Aprender os padrões ajudam um novato a agir mais como um especialista ◦ Programar melhor com orientação a objetos ◦ Desenvolver software de melhor qualidade Os padrões utilizam eficientemente polimorfismo. eficiente. composição. Padrões de Projeto Como descrever um padrão? ◦ Nome e classificação do padrão ◦ Intenção e objetivo: também conhecido como motivação ◦ Aplicabilidade ◦ Estrutura ◦ Participantes ◦ Colaborações ◦ Conseqüências ◦ Implementação ◦ Exemplo de código ◦ Usos conhecidos ◦ Padrões relacionados . em C#. sistemas distribuídos.Padrões de Projeto Quais classificações ? ◦ Há vários catálogos de padrões em software: Muitos são específicos a uma determinada área (padrões J2EE. etc.) ◦ Veremos os seguintes catálogos de padrões: MVC: Model-View-Controller (camadas) GRASP: General Responsibility and . padrões para concorrência. padrões de implementação em Java. expressas na forma de padrões Esses padrões exploram os princípios fundamentais de sistemas OO ◦ 5 padrões fundamentais ◦ 4 padrões avançados Se você conhece os padrões GRASP.Padrões de Projeto : GRASP GRASP: General Responsibility and Assignment Software Patterns Introduzidos por Craig Larman em seu livro “Applying UML and Patterns” Os padrões GRASP descrevem os princípios fundamentais da atribuição de princípios fundamentais da atribuição de responsabilidades a objetos. pode dizer que compreende o paradigma orientado a objetos . Padrões de Projeto : GRASP Tipos: ◦ Básicos Creator (Criador) Expert (Especialista da Informação) Low Coupling (Baixo Acoplamento) High Cohesion (Alta Coesão) ◦ Avançados Polymorphism (Polimorfismo) Pure Fabrication (Fabrição/Inveção Pura) Indirection (indireção) Protected Variations (Variações Protegidas) . .Padrões de Projeto : GRASP Responsabilidade: ◦ Um contrato ou obrigação de um tipo ou classe (Booch e Rumbaugh) ◦ Responsabilidades estão relacionadas às obrigações de um objeto em termos de seu comportamento. .) Iniciar ações em outros objetos(delegação). Controlar e coordenar atividades em outros objetos.Padrões de Projeto : GRASP Dois tipos de responsabilidades básicas: ◦ Fazer (doing) Fazer algo ele próprio(criar um objeto.. .. Conhecer objetos relacionados. executar uma operação. ◦ Conhecer (knowing) Conhecer dados privados encapsulados. . Métodos são implementados para satisfazer as responsabilidades ◦ Uma responsabilidade pode ser cumprida por um único método ou uma coleção de métodos trabalhando em conjunto Padrões de projeto são princípios para guiar a atribuição de responsabilidades aos objetos.Padrões de Projeto : GRASP Responsabilidade não é a mesma coisa que um método. .GRASP : Especialista Problema: qual é o princípio mais básico de atribuição de responsabilidades a objetos ? Solução: Atribuir responsabilidade ao especialista da informação. quem seria o responsável por calcular o valor total da venda? E o valor parcial? E por unidade? Sales SalesItem Register ProductDescript ion .GRASP : Especialista Exemplo: no sistema de venda. GRASP : Especialista O valor ficará armazenado no atributo value do objeto ItemDeVenda (SalesItem) Mas quem possui conhecimentos necessários para calculá-la? . . pois conhece a todos os itens e suas quantidades. que é utilizado para calcular o valor total da venda. o objeto Venda deve receber esta atribuição.GRASP : Especialista Pelo padrão especialista. GRASP : Especialista . utilizar o Modelo Conceitual Lembrar que existem especialistas parciais que colaboram numa tarefa ◦ informação espalhada comunicação via mensagens .GRASP : Especialista Onde procurar pela classe especialista? ◦ Começar pelas classes já estabelecidas durante o projeto ◦ Se não encontrar. GRASP : Especialista Benefícios: ◦ Mantém encapsulamento. favorece o acoplamento fraco ◦ O comportamento fica distribuído entre as classes que têm 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? . ◦ Se uma das seguintes condições for verdadeira. a classe é forte candidata: Classe B agrega objetos de classe A Classe B contém objetos de classe A Classe B registra objetos de classe A Classe B usa objetos de classe A Classe B tem os valores iniciais que serão passados para objetos de classe A. quando de sua criação .GRASP : Criador Problema: Quem deveria ser responsável pela criação de uma nova instância de alguma classe ? Solução: Padrão Criador ◦ A classe A deve ser criado por outro (classe B) que o possua como parte (agregação) ou esteja fortemente associado a ele. quem deve ser responsavel pela criação de objetos da classe ItensDeVenda (SalesItem) ? Sales Register .GRASP : Criador Exemplo: ◦ Ao registrar itens de uma venda. então ela é uma forte candidata .GRASP : Criador A classe Sales (Venda) agrega muitos SalesItem (ItensDeVenda). 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 .GRASP : Criador Objetivo do padrão: definir como criador o objeto que precise ser conectado ao objeto criado em algum evento Escolha adequada favorece acoplamento fraco Objetos agregados. GRASP : Acoplamento Baixo Problema: Como suportar baixa dependência. tem conhecimento de. sistemas. subsistemas. ou depende de outros elementos ◦ um elemento com acoplamento baixo (fraco) não é dependente de muitos outros elementos ◦ elementos incluem classes. etc . tem conhecimento de. baixo impacto devido a mudanças e reuso constante? Solução: Padrão Acoplamento Baixo ◦ é uma medida de quão fortemente um elemento está conectado a. ou depende de outros é uma medida de quão fortemente um elemento está conectado a. A GRASP : Acoplamento Baixo ClasseA tem um atributo do tipo ClasseB . esta referência se dá através de um parâmetro ou variável local do tipo ClasseB ou por um objeto do tipo ClasseB retornado pela chamada de algum método . referencia uma instância de ClasseB. GRASP : Acoplamento Baixo A ClasseA tem um método que. de alguma forma. Tipicamente. GRASP : Acoplamento Baixo A ClasseA é uma subclasse da ClasseB . GRASP : Acoplamento Baixo A ClasseB é uma interface e a ClasseA implementa esta interface . algumas sofrem dos seguintes problemas: ◦ modificações locais forçadas decorrentes de modificações em classes relacionadas ◦ são mais difíceis de entender isoladamente ◦ são mais difíceis de reutilizar. pois .GRASP : Acoplamento Baixo Uma classe com acoplamento forte (ou alto) depende de muitas outras classes Tais classes podem ser indesejáveis. ◦ considere o seguinte diagrama de classes parcial do estudo de caso Sales Payment Register ◦ precisamos criar uma instância de Pagamento (Payment) e associá-la a Venda (Sale). . Use esse princípio para avaliar alternativas. Que classe deve ser responsável por isto? ◦ como Registradora (Register) “registra” um Pagamento no domínio do mundo real.GRASP : Acoplamento Baixo Exemplo: ◦ atribuir responsabilidade de modo que o acoplamento permaneça baixo. GRASP : Acoplamento Baixo Solução 1: ◦ A instância de Registradora pode então enviar uma mensagem addPayment (adicionarPagamento) para a Venda. passando junto o novo Pagamento como parâmetro ◦ esta atribuição acopla a classe Registradora ao conhecimento da classe Pagamento . GRASP : Acoplamento Baixo Solução 2: . baseado na atribuição de responsabilidades. apóia o Acoplamento Baixo? .GRASP : Acoplamento Baixo Qual dos projetos. o solução 2 no qual Venda faz a criação de um Pagamento.GRASP : Acoplamento Baixo Em ambos os casos consideramos que Venda deve ser acoplada ao conhecimento de Pagamento A solução 1. no qual Registradora cria Pagamento adiciona acoplamento de Registradora a Pagamento. não aumenta o acoplamento Pensando em acoplamento o solução2 mantém um acoplamento global mais baixo Este exemplo nos mostra como dois padrões de projetos distintos (Criador e Baixo Acoplamento) podem sugerir soluções diferentes . é um fator a considerar no aperfeiçoamento de um projeto. É UM PRINCÍPIO DE AVALIAÇÃO que você aplica ao avaliar todas as decisões de projeto . tais como Especialista e Coesão Alta.GRASP : Acoplamento Baixo Na prática o nível de acoplamento não pode ser considerado isolado de outros princípios. Acoplamento Baixo é um princípio a se ter em mente durante todas as decisões de projeto. é uma meta subjacente a ser considerada continuamente. No entanto. mas deve ser considerado ao se atribuir responsabilidade ◦ Uma subclasse é fortemente acoplada à sua superclasse. reduzindo o impacto de modificações ◦ Não pode ser considerado isoladamente. ◦ Não temos uma forma absoluta de medir acoplamento ◦ Podemos avaliar e ver quais as conseqüências na prática ◦ O caso extremo de Acoplamento Baixo é quando não existe acoplamento entre classes. um sistema OO é composto de objetos conectados que se comunicam por mensagens .GRASP : Acoplamento Baixo Considerações: ◦ Favorece o projeto de classes independentes. GRASP : Acoplamento Baixo Vantagens: ◦ Não é afetado por mudanças em outros componentes ◦ É simples de entender isoladamente ◦ É conveniente para reutilização . ◦ Uma classe com coesão baixa faz coisas não relacionadas e trabalha demais.GRASP : Alta Coesão Problema: Como manter os objetos focados. constantemente afetadas por modificações . inteligíveis e gerenciáveis e com efeito colateral apoiar o acoplamento baixo? Solução: Atribuir uma responsabilidade de forma que a coesão permaneça alta. elas sofrem dos seguintes problemas: são difíceis de compreender são difíceis de reutilizar são difíceis de manter são delicadas. não queremos isto. GRASP : Alta Coesão Como um princípio básico. ◦ a funcionalidade desses métodos é altamente relacionada. . uma classe com alta coesão: ◦ tem um número relativamente pequeno de métodos. e não faz trabalho de mais. assumindo uma parte da .. Que classe deve ser responsável por isto? ◦ Solução 1: Registradora manda uma mensagem makePayment() para Venda. passando como um parâmetro o novo Pagamento A responsabilidade de criar um pagamento fica para Registradora.GRASP : Alta Coesão As classes com baixa coesão geralmente representam um grau de abstração muito alto e de grande granularidade. ou então assumiram responsabilidades que deveria ter sido delegadas a outros objetos Exemplo: ◦ vamos analisar o exemplo usado no padrão Acoplamento Baixo e analisá-lo quanto a Coesão Alta ◦ Precisamos cria uma instância de Pagamento e associá-la a Venda.. .GRASP : Polimorfismo Problema: Como tratar diferentes comportamentos baseado num mesmo tipo de objeto? Solução: Utilizar o polimorfismo ao objeto que pode apresentar mais de um tipo de comportamento. GRASP : Polimorfismo O uso de ifs aninhados ou switchcase para selecionar comportamento em função do tipo de classe espalha-se por todo o código. dificultando a manutenção A necessidade de substituição de parte de um sistema pode se tornar um problema caso o sistema não tenha sido projetado para isso . a classe Pagamento deve definir o método autoriza() As subclasses de Pagamento devem aplicar polimorfismo sobre o método autoriza() .GRASP : Polimorfismo No nosso exemplo Para evitar a necessidade de seleção de comportamento. GRASP : Polimorfismo Benefício: ◦ Facilidade de manutenção ◦ Facilidade de inserção de um novo tipo de autorização . uma classe fictícia que possibilite alta coesão. baixo acoplamento e o . mas as soluções oferecidas pelo “Especialista” não são apropriadas? Solução: Atribua um conjunto coeso de responsabilidade a uma classe artificial que não representa um conceito no domínio da aplicação.GRASP : Pura Inveção Problema: Que objeto deve ter a responsabilidade quando você não quer violar “ Alta Coesão” e “ Baixo Acoplamento”. Várias outras classes no projeto .GRASP : Pura Inveção O especialista nos diz para atribuir a responsabilidade à classe Venda. por exemplo). uma vez que ela conhece os dados de venda. A classe Sales(Venda) tem de ser associada à interface do banco de dados relacional (JDBC. Considere no entanto as seguintes implicações: Salvar um objeto no Banco de Dados implica em uma série de operações não relacionadas ao conceito de venda. GRASP : Pura Inveção Classes de persistência e autenticação são candidatas a usar o padrão “Pura Invenção” . GRASP : Pura Inveção No nosso exemplo As classes de pagamento continuariam aplicando o padrão Polimorfismo. aliado a um mecanismo de delegação às classes artificiais . que não fazem parte da realidade ◦ Se utilizado em excesso. poderá transformar um sistema OO em um sistema orientado a eventos .GRASP : Pura Inveção Benefícios: ◦ Remove as características não coesas das classes do domínio de negócio ◦ Cria classes muito coesas com essas características Problemas: ◦ Cria classes altamente funcionais. GRASP : Indireção Problema: Como posso evitar o acoplamento direto? Caso uma classe seja acoplada a serviços. será impossível reutilizar esses serviços. para possibilitar a reutilização e substituição de código . Solução: Criar um objeto intermediário... São criados um ou mais níveis de indireção. fazendo indireção para o serviço. devem existir chamadas ao driver de modem .GRASP : Indireção Exemplo: Para que o pagamento via cartão ou cheque funcione. fazendo indireção para o serviço. . São criados um ou mais níveis de indireção.GRASP : Indireção Criar um objeto intermediário. para possibilitar a reutilização e substituição de código. GRASP : Indireção Exemplo: ◦ Uma classe deve ser criada para representar (fazer indireção para) o modem ◦ Uma classe deve ser criada para representar (fazer indireção para) o leitor de moeda . GRASP : Variação Protegida Problema: Como atribuir responsabilidades a objetos. subsistemas e sistemas. atribua . de modo que as variações ou a instabilidade nesses elementos não tenham um impacto indesejável sobre outros elementos? Solução: Identifique pontos de variação ou instabilidade prevista. atribuindo responsabilidades para criar uma interface estável em torno deles. Na variação protegida temos as variações evolutivas e as variações corretivas.GRASP : Variação Protegida Toda aplicação tem pontos de variação. . identifique os pontos de variação ou instabilidade prevista. TomCat. localiza qual local de destino e entrega ao local correto. etc. framework Spring. ◦ Máquinas Virtuais – simulam vários sistemas em um único meio físico. dá maior portabilidade aos sistemas em ambientes instáveis. ◦ Pesquisa de serviços – é ter alguém que forneça serviços. ◦ Projetos dirigidos por dados (dataDriver design) – troca de informações entre aplicações através de arquivos configurados por exemplo XML. . Engine Regras. e ter alguém que consome os serviços disponibilizados. ◦ Projetos dirigidos por interpretadores – são aplicações que interpretam ambientes ou sistemas diferentes. podemos citar como exemplo o novo paradigma SOA. por exemplo JVM.GRASP : Variação Protegida Mecanismos de Variações Protegidas ◦ Agentes (Brokers) – é encarregado de levar as requisições que recebe. . ◦ Princípios da substituição de Liskov – como mecanismo de variação protegida a substituição de Liskov prevê que se declararmos classes como interface qualquer classe poderá implementar a superclasse. se alguém vier a mudar a tabela que está consultando. GRASP : Variação Protegida Mecanismos de Variações Protegidas ◦ Projetos reflexivos ou de meta-dados – nesse caso reflete o que tem dentro da classe. não se restringe a propriedades. . isso irá prejudicar sua consulta. C#. etc. exemplos de linguagens que não se preocupa com definições são: linguagem EIFFEL. métodos. alterando apenas o nome das colunas. ◦ Acesso Uniforme – não se preocupa com a estrutura da linguagem. etc. tudo é igual seja ele com definições de propriedade. métodos ou procedimentos. procedimentos. por exemplo: o normal a se fazer em uma consulta em banco de dados é pesquisar pelo catalogo do banco e não a colunas. no caso de uma consulta pelo catalogo do banco o problema descrito acima não irá acontecer pois sua consulta irá solicitar ao catalogo que por sua vez possui o índice da tabela que está consultando e assim retornará os dados da coluna relacionada a consulta.