leomurta@ic.uff.br Agenda Introduo Estilo MVC Padres Expert Creator Controller Low Coupling High Cohesion Polymorphism Pure Fabrication Indirection Dont Talk to Strangers Leonardo Murta 2 Padres GRASP Introduo A qualidade de um projeto orientado a objetos est fortemente relacionada com a distribuio de responsabilidades As responsabilidades de um projeto podem ser divididas em conhecer e fazer As responsabilidades conhecer esto relacionadas distribuio das caractersticas do sistema entre as classes As responsabilidades fazer esto relacionadas com a distribuio do comportamento do sistema entre as classes Leonardo Murta 3 Padres GRASP Introduo A principal caracterstica da atribuio de responsabilidades est em no sobrecarregar os objeto com responsabilidades que poderiam ser delegadas O objeto s deve fazer o que est relacionado com a sua abstrao. Para isso, delega as demais atribuies para quem est mais apto a fazer Quando o objeto no sabe quem o mais apto, pergunta para algum outro objeto que saiba Leonardo Murta 4 Padres GRASP Introduo Os princpios de projeto fornecem os fundamentos necessrios para o entendimento de o que um bom projeto Entretanto, no retratado claramente como se pode obter um bom projeto Para facilitar o entendimento de como fazer um bom projeto, esse conhecimento foi codificado na forma de padres Leonardo Murta 5 Padres GRASP Introduo Padres descrevem, em um formato estruturado, um problema e uma possvel soluo para este problema Padres no so criados, so descobertos! A soluo descrita foi aplicada com sucesso por especialistas da rea inmeras vezes, podendo ser considerada uma boa soluo As principais utilidades de um padro esto relacionadas com Formalizao e propagao do conhecimento Uniformizao do vocabulrio Leonardo Murta 6 Padres GRASP Introduo Uma linguagem de padres agrega um conjunto de padres relacionados para um contexto em particular No contexto de projeto orientado a objetos foi criada uma linguagem de padres conhecida como GRASP (Larman, G.; 2007) GRASP General Responsability Assignment Software Patterns Os padres GRASP descrevem os princpios fundamentais para a atribuio de responsabilidades em projetos OO Leonardo Murta 7 Padres GRASP Estilo MVC Estilos arquiteturais servem para dar uma diretriz de como a arquitetura do sistema deve ser construda Engenharia de software, diferentemente das demais engenharias, no est sujeita a leis da natureza Estilos arquiteturais so regras artificiais que devem ser seguidas pelos desenvolvedores Um dos principais estilos arquiteturais o MVC MVC = Model-View-Controller Filosofia bsica: as classes do sistema devem ser separadas em trs tipos: modelo, viso e controle Leonardo Murta Padres GRASP 8 Estilo MVC Modelo: So as classes derivadas do processo de anlise Representam os principais conceitos do domnio So usualmente persistidas em banco de dados Viso: So as classes criadas durante o projeto para fazer interface com o usurio Normalmente manipulam classes de modelo Controle: So as classes que fazem a orquestrao Leonardo Murta Padres GRASP 9 Estilo MVC Leonardo Murta Padres GRASP 10 Regras: Classes de modelo no conhece ningum (a no ser outras classes de modelo) Classes de viso conhece somente classes de modelo (e outras classes de viso) Classes de controle conhece tanto classes de modelo quanto classes de viso (e outras classes de controle) Estilo MVC Vantagens: Separao de responsabilidades clara Alto grau de substituio da forma de interface com o usurio Alto grau de reutilizao das entidades do domnio (classes de modelo) Possibilidade de mltiplas interfaces com o usurio, trabalhando de forma simultnea (modo texto, janelas, web, celular, etc.) Leonardo Murta Padres GRASP 11 Padro Expert Problema: Qual o princpio mais bsico de atribuio de responsabilidades em projeto OO? Em um sistema com centenas de classes, como selecionamos quais responsabilidades devem estar em quais classes? Exemplo: Em um sistema de PDV, quem deveria ser o responsvel pelo clculo do total de um pedido? Leonardo Murta 12 Padres GRASP Padro Expert Soluo: Atribuir a responsabilidade ao especialista O especialista a classe que tem a informao necessria para satisfazer a responsabilidade Exemplo: Em um sistema de PDV, o responsvel pelo clculo do total de um pedido deveria ser a prpria classe Pedido Leonardo Murta 13 Padres GRASP Padro Expert Benefcios: Leva a projetos onde o objeto de software faz o que o objeto real faria Mantm o encapsulamento e no aumenta o acoplamento, pois utiliza informaes prprias Distribui o comportamento uniformemente entre as classes do sistema, aumentando a coeso das mesmas Leonardo Murta 14 Padres GRASP Padro Expert Sinnimos: Colocar responsabilidades com os dados Aquele que conhece faz Quem sabe faz Animao Faz-lo eu mesmo Colocar os servios com os atributos que eles utilizam Especialista na informao Leonardo Murta 15 Padres GRASP Padro Expert (Exerccio) Desenvolva o modelo abaixo (atravs de modelo de seqncia) para inserir a responsabilidade de clculo do total do pedido segundo o padro Expert: Leonardo Murta 16 Padres GRASP Padro Creator Problema: Quem deveria ser responsvel pela criao de uma nova instncia de uma classe? A criao de objetos uma atividade comum em sistemas OO. necessrio um princpio que atribua responsabilidades para essa criao Exemplo: Em um sistema de PDV, quem deveria ser responsvel por criar um novo item de pedido? Leonardo Murta 17 Padres GRASP Padro Creator Soluo: Atribua classe A a responsabilidade de criar instncias da classe B se ao menos: A contm objetos de B A agrega objetos de B A registra objetos de B A usa de maneira muito prxima objetos de B A tem os dados necessrios para a construo de objetos de B Leonardo Murta 18 Padres GRASP Padro Creator Exemplo: Em um sistema de PDV, a classe Pedido deveria ser responsvel por criar instncias de ItemPedido Benefcio: No aumenta o acoplamento, pois a visibilidade entre as classes envolvidas j existia Padro relacionado: Acoplamento fraco Leonardo Murta 19 Padres GRASP Padro Creator (Exerccio) Desenvolva o modelo abaixo (atravs de modelo de seqncia) para determinar a responsabilidade de criao de pagamento, segundo o padro Creator: Leonardo Murta 20 Padres GRASP Padro Controller Problema: Quem deveria ser responsvel por tratar um evento de sistema? Os eventos de sistema esto associados s mensagens de sistema, que so geradas a partir dos passos dos casos de uso Exemplo: o caixa registra o cdigo e a quantidade de um item de pedido. Qual classe deve receber e tratar esse evento? Leonardo Murta 21 Padres GRASP Padro Controller Soluo: Os eventos de sistemas devem ser tratados por uma das classes abaixo: Representante do sistema como um todo (Facade) Representante do negcio ou da organizao Representante do caso de uso em questo (tratador artificial) Leonardo Murta 22 Padres GRASP Padro Controller Importante: independente da escolha de soluo, ela deve ser mantida para todo o sistema Cada caso de uso deve estar todo em uma mesma classe; Uma classe pode ter mais de um caso de uso Para manter a separao view-controller, importante que classes de viso (formulrios, janelas, applets, etc.) no sejam responsveis por esse tratamento Leonardo Murta 23 Padres GRASP Padro Controller Exemplo: o evento de registro de um item de pedido, executado pelo mtodo registraItemPedido(codigo, quantidade) pode ser executado por: PDV, representando o sistema como um todo Loja, representando o negcio ControleCompraItens, representando o caso de uso de compra de itens Leonardo Murta 24 Padres GRASP Padro Controller Os controladores devem somente coordenar a tarefa, delegando a sua execuo para os outros objetos do sistema O uso de controladores Facade (representantes do sistema ou do negcio) vlido somente quando existem poucos eventos de sistema Em sistemas com muitos eventos, o uso de tratadores artificiais, um por cada caso de uso, indicado Leonardo Murta 25 Padres GRASP Padro Controller Benefcios: A separao view-controller facilita a reutilizao de componentes especficos de negcio e permite o uso dos servios atravs de processamento em lote (batch) A utilizao de uma nica classe para todos os eventos de um caso de uso possibilita a manuteno de estado do caso de uso como atributos dessa classe O controlador deve ser somente o maestro... no deve tocar nenhum dos instrumentos (mesmo que d muita vontade) Leonardo Murta 26 Padres GRASP Padro Controller (Exerccio) Para os eventos de sistemas listados abaixo na classe virtual Sistema (vindos do caso de uso Compra de itens), defina uma atribuio de responsabilidades e argumente o motivo da sua escolha: Leonardo Murta 27 Padres GRASP Padro Low Coupling Problema: Como suportar uma dependncia baixa e aumentar a reutilizao? Modificaes em uma classe foram modificaes em outras classes Dificuldade de compreenso de uma classe isoladamente Dificuldade de reutilizao por excesso de dependncia entre classes (para pegar uma tem que pegar todas) Leonardo Murta 28 Padres GRASP Padro Low Coupling Tipos de acoplamento entre as classes A e B: A classe A subclasse da classe B A classe A tem um atributo do tipo da classe B A classe A tem um mtodo que referencia a classe B atravs de parmetro, varivel local ou retorno de mensagem A classe A depende de uma interface implementada pela classe B Leonardo Murta 29 Padres GRASP Padro Low Coupling Exemplo: Segundo o padro Creator, existem duas solues para a atribuio da responsabilidade de pagamento: Um PDV quem registra um pagamento fisicamente, logo a classe PDV quem deve criar a instncia A classe Pedido tem os dados necessrios para a construo da instncia do pagamento, logo ela quem deve criar Leonardo Murta 30 Padres GRASP Padro Low Coupling umPDV : PDV umPagamento : Pagamento umPedido : Pedido <<create>> addPagamento(umPagamento) Leonardo Murta 31 Padres GRASP Padro Low Coupling umPDV : PDV umPedido : Pedido umPagamento : Pagamento setPago(valor : Currency) <<create>> Leonardo Murta 32 Padres GRASP Padro Low Coupling Soluo: Atribuir as responsabilidades de maneira que o acoplamento permanea fraco O padro Low Coupling deve ser utilizado como um padro de avaliao de outros padres Exemplo: Se a classe Pedido criar a instncia de Pagamento, a classe PDV no ter seu acoplamento aumentado (PDV no conhece Pagamento) Leonardo Murta 33 Padres GRASP Padro Low Coupling (Exerccio) D a sua avaliao sobre o acoplamento nos problemas abaixo e indique se uma situao desejvel: Cenrio A: um sistema onde todos os objetos herdam da classe ObjetoPersistente, para que seja possvel implementar um mapeamento objeto-relacional automtico Cenrio B: um sistema onde as classes tem somente atributos primitivos e mtodos, sem nenhuma associao ou herana Leonardo Murta 34 Padres GRASP Padro High Cohesion Problema: Como manter a complexidade sob controle? As classes so difceis de compreender As classes so difceis de reutilizar As classes so difceis de manter As classes so frgeis, sendo afetadas por praticamente todas as modificaes Leonardo Murta 35 Padres GRASP Padro High Cohesion Exemplo: No exemplo da atribuio de responsabilidade de pagamento, qual das duas solues tem melhor impacto em relao coeso? Soluo: Atribuir responsabilidade de forma que as classes no fiquem sobrecarregadas, e que as suas atribuies sejam relacionadas O padro High Cohesion tambm deve ser visto como um padro de avaliao de padres Leonardo Murta Padres GRASP 36 Padro High Cohesion Exemplo: Caso o PDV assuma a responsabilidade de pagamento, provavelmente assumir todas as demais responsabilidades do sistema Assim, caso o sistema seja grande, a classe PDV ficar extremamente complexa e pouco coesa A soluo de delegao para a classe Pedido ajuda a aumentar a coeso geral do sistema Leonardo Murta Padres GRASP 37 Padro High Cohesion Alta coeso na prtica: Classes tm usualmente poucos mtodos altamente relacionados Tarefas mais complexas so delegadas a objetos associados Analogia ao mundo real: Pessoas que no delegam responsabilidades e fazem muitas coisas diferentes ao mesmo tempo tendem a no ser eficientes Leonardo Murta Padres GRASP 38 Padro High Cohesion Benefcios: Clareza e facilidade de compreenso do projeto Simplificao das atividades de manuteno Favorecimento indireto do baixo acoplamento Facilidade de reutilizao, graas classe ser muito especfica Alguns casos de coeso moderada trazem benefcios, como, por exemplo, o padro Facade Leonardo Murta Padres GRASP 39 Padro High Cohesion (Exerccio) Como seria possvel desenvolver o modelo abaixo para possibilitar o envio do catlogo de produtos atravs de mala direta, inicialmente via correio, e-mail, celular e fax, colocando em prtica o padro High Cohesion? Obs.: Lembre-se que, no futuro, novas formas de comunicao surgiro. Catalogo Leonardo Murta 40 Padres GRASP Padro Polymorphism Problema: Como tratar alternativas em funo do tipo da classe? O uso de ifs aninhados ou switch-case para selecionar comportamento em funo do tipo de classe espalha-se por todo o cdigo, dificultando a manuteno Como criar componentes de software substituveis? A necessidade de substituio de parte de um sistema pode se tornar um problema caso o sistema no tenha sido projetado para isso Leonardo Murta 41 Padres GRASP Padro Polymorphism Exemplo: No sistema de PDV, como seria possvel a seleo do tipo de autorizao de pagamento? Segundo o padro Expert, o prprio pagamento deveria saber se autorizar Leonardo Murta 42 Padres GRASP Padro Polymorphism Leonardo Murta 43 Padres GRASP Padro Polymorphism Soluo: Seleo do comportamento desejado atravs do mecanismo de polimorfismo Utilizao de polimorfismo aplicado ao conceito de interfaces para permitir a substituio de componentes Map (f rom util) HashMap (from uti l ) Map (f rom util) Hashtable (from uti l ) Leonardo Murta 44 Padres GRASP Padro Polymorphism Exemplo: Para evitar a necessidade de seleo de comportamento, a classe Pagamento deve definir o mtodo autoriza() As subclasses de Pagamento devem aplicar polimorfismo sobre o mtodo autoriza() Leonardo Murta 45 Padres GRASP Padro Polymorphism Benefcio: Facilidade de manuteno Facilidade de insero de um novo tipo de autorizao Leonardo Murta 46 Padres GRASP Padro Polymorphism (Exerccio) A utilizao do conceito de interfaces ajuda na substituio de componentes. Entretanto, como poderia ser feito refactoring de um sistema que precisa ter partes substitudas mas que no foi projetado para isso (no usa componentes)? Tente estruturar uma sistematizao simplificada para essa questo Leonardo Murta 47 Padres GRASP Padro Pure Fabrication Problema: A quem atribuir uma responsabilidade quando todas as opes ferem os princpios de acoplamento baixo e coeso alta? Exemplo: Segundo o padro Expert, a autorizao de pagamento deve ficar na classe Pagamento Entretanto, essa abordagem poder implicar em baixa coeso e alto acoplamento Leonardo Murta 48 Padres GRASP Padro Pure Fabrication Soluo: Criar classes artificiais (invenes) que tenham alta coeso e baixo acoplamento (classes puras) Exemplo: As classes artificiais ficariam responsveis por todo o conhecimento sobre a comunicao As classes de pagamento continuariam aplicando o padro Polymorphism, aliado a um mecanismo de delegao s classes artificiais Leonardo Murta 49 Padres GRASP Padro Pure Fabrication Leonardo Murta 50 Padres GRASP Padro Pure Fabrication Benefcios: Remove as caractersticas no coesas das classes do domnio de negcio Cria classes muito coesas com essas caractersticas Problemas: Cria classes altamente funcionais, que no fazem parte da realidade Se utilizado em excesso, poder transformar um sistema OO em um sistema orientado a eventos Leonardo Murta 51 Padres GRASP Padro Pure Fabrication (Exerccio) Qual das duas abordagens abaixo voc considera melhor? Justifique citando os prs e contras de cada abordagem e compare com a abordagem utilizada no exemplo anterior. Leonardo Murta 52 Padres GRASP Padro Indirection Problema: Como posso evitar o acoplamento direto? Caso uma classe seja acoplada a servios, ser impossvel reutilizar esses servios Exemplo: Para que o pagamento via carto ou cheque funcione, devem existir chamadas ao driver de modem No caso do pagamento via dinheiro, devem existir chamadas ao leitor de moeda (contra falsificao) Leonardo Murta 53 Padres GRASP Padro Indirection Soluo: Criar um objeto intermedirio, fazendo indireo para o servio So criados um ou mais nveis de indireo, para possibilitar a reutilizao e substituio de cdigo Leonardo Murta 54 Padres GRASP Padro Indirection Exemplo: Uma classe deve ser criada para representar (fazer indireo para) o modem Uma classe deve ser criada para representar (fazer indireo para) o leitor de moeda Leonardo Murta 55 Padres GRASP Padro Indirection (Exerccio) Evolua o modelo abaixo para contemplar o padro Indirection para as trs formas de pagamento. Sobre o modelo gerado, perceba que um determinado servio de autorizao pode ser visto como um componente (interfaces providas e requeridas). Leonardo Murta 56 Padres GRASP Padro Dont Talk to Strangers Problema: Como seria possvel fortalecer o encapsulamento? O conhecimento da estrutura interna de relacionamentos de uma classe pode dificultar a manuteno Exemplo: Para a classe PDV saber qual a quantia de um pagamento, ela ir consultar a classe Pedido, que fornecer o Pagamento que contm a informao Leonardo Murta 57 Padres GRASP Padro Dont Talk to Strangers umPDV : PDV umPedido : Pedido umPagamento : Pagamento umPagamento := getPagamento() quantia := getQuantia() Leonardo Murta 58 Padres GRASP Padro Dont Talk to Strangers Soluo: Segundo a Lei de Demeter, um mtodo A deve enviar mensagens somente para: O prprio objeto (this) Os prprios atributos Os argumentos do prprio mtodo A Um objeto criado no mtodo A Um elemento de alguma coleo que seja atributo, argumento ou criada no mtodo A Leonardo Murta 59 Padres GRASP Padro Dont Talk to Strangers A soluo proposta conhecida como promoo de interface, pois promove algumas operaes para a interface mais externa Exemplo: A classe Pedido deve adicionar sua interface um mtodo chamado getQuantiaPaga(), que forneceria a quantia da classe Pagamento Assim, a classe PDV perde sua dependncia em relao a classe Pagamento, o que diminui o seu acoplamento Leonardo Murta 60 Padres GRASP Padro Dont Talk to Strangers umPDV : PDV umPedido : Pedido umPagamento : Pagamento quantia := getQuantiaPaga() Result := getQuantia() Leonardo Murta 61 Padres GRASP Padro Dont Talk to Strangers A Lei de Demeter deve ser rompida em algumas situaes: Uso de classes intermedirias (broker) Uso de classes representante (proxy) Sempre que seja utilizado algum tipo de classe que tem o objetivo de fornecer objetos de outras classes (ex.: Singleton, Factory, etc.) Leonardo Murta 62 Padres GRASP Padro Dont Talk to Strangers (Exerccio) Identifique falhas no modelo abaixo, referentes ao projeto do mtodo getItensPedido() e argumente possveis solues: Leonardo Murta 63 Padres GRASP Bibliografia Craig Larman, 1999, Utilizando UML e Padres, 1 ed., Prentice-Hall Craig Larman, 2007, Utilizando UML e Padres, 3 ed., Bookman. 64 Leonardo Murta Padres GRASP Padres GRASP Leonardo Gresta Paulino Murta leomurta@ic.uff.br