Baixe o app para aproveitar ainda mais
Prévia do material em texto
Fundamentos e Princípios do Projeto Orientado a Objetos Autor: Evandro João Agnes evandroagnes@yahoo.com.br 2 Abstração Seleção de alguns aspectos relevantes a uma determinada análise, suprimindo outros Serviços e atributos aplicáveis a objetos dentro de um determinado contexto 3 Classes e Objetos Classe Descrição de um conjunto de objetos similares Abstratas ou Concretas Objeto Reúnem na mesma estrutura: Atributos (dados) que definem o estado Operações que definem o comportamento e manipulam os dados Identidade de objetos Retenção de estado 4 Encapsulamento Esconder detalhes de implementação do estado e comportamento do objeto Objetos são acessados apenas pela interface externa definida para eles Detalhes de implementação das classes podem ser alterados sem que as aplicações necessitem de alterações 5 Mensagem Comunicação feita entre objetos Chamadas a métodos 6 Herança Permite que novas classes sejam construídas usando código e características declaradas em outras classes Relação do tipo “é um” entre classes Super-classes e sub-classes Sub-classe herda todos atributos e métodos da super-classe 7 Polimorfismo Propriedade na qual uma chamada genérica de um método pode ser executada de diferentes maneiras de acordo com o objeto que fez a chamada Exemplo Classe Reta: método desenhar() Classe Círculo: método desenhar() 8 Relacionamentos Associação Relação do tipo “tem um” entre objetos Agregação Relação do tipo “todo-parte” Dependência fraca Composição Relação do tipo “todo-parte” Dependência forte 9 Interdependência Elementos que compartilham alguma necessidade Tipos de Interdependência Nome Tipo ou classe Convenção Algoritmo Posição Valor Identidade 10 Interdependência Princípios Minimizar a interdependência total através do encapsulamento Minimizar qualquer interdependência que cruze as fronteiras do encapsulamento Maximizar a interdependência dentro das fronteiras do encapsulamento Abusos Função amigável Herança sem restrição Detalhes internos do algoritmo de uma classe relevantes para outras classes 11 Domínios Domínio de Aplicação Domínio de Negócio Domínio de Arquitetura Domínio de Base Baixa reutilização Média reutilização Alta reutilização Domínio de Apresentação 12 Grau de dependência ou acoplamento Conjunto de classes que uma classe se baseia para operar Grau de dependência pode ser Direto Indireto Classes em domínios altos tem alto grau de dependência indireto e classes em domínios baixos tem baixo grau de dependência indireto 13 Grau de dependência ou acoplamento Acoplamento é o caminho para o Lado Negro da Força! Conduz para complexidade Conduz para confusão Conduz ao sofrimento Uma vez que você inicie o caminho para o Lado Negro, ele sempre irá dominar seu destino. “Consumir você ele irá!” Desacoplar através de abstrações e interfaces! 14 Lei de Demeter Cada unidade deve conhecer apenas unidades intimamente relacionadas a ela Segundo a Lei de Demeter as mensagens devem ser enviadas apenas para: si mesmo - métodos do objeto seus objetos - atributos da instância parâmetros recebidos pelo método objetos criados pelo método 15 Coesão Classes com alta coesão Todas as características contribuem para a abstração de tipo implementada pela classe Classes com baixa coesão Apresenta um conjunto de características diferentes 16 Problemas de coesão Coesão de instância mista Ter algumas características que são definidas apenas para alguns objetos da classe Coesão de domínio misto Uma classe contém um elemento que cria dependência com uma classe de domínio diferente que não tem qualquer tipo de negócio com a classe* Coesão de papel misto Uma classe contém um elemento que diretamente cria dependência de uma classe de mesmo domínio que não tem qualquer tipo de negócio com a classe* * Uma classe B não tem qualquer tipo de negócio com A se A puder ser plenamente definida sem qualquer noção de B 17 Problema: Coesão de instância mista 18 Problema: Coesão de domínio misto 19 Problema: Coesão de papel misto 20 Espaço-estado e comportamento Espaço-estado de uma classe é a totalidade de estados permitidos para qualquer objeto da classe Cada componente do estado (atributos) de um objeto define uma dimensão É o conjunto de valores de dimensões válidas para um objeto O modo como o objeto muda de estado é o seu comportamento O comportamento permitido de uma classe é o conjunto de transições que o objeto pode fazer entre os estados do espaço-estado 21 Espaço-estado e comportamento O espaço-estado de uma subclasse deve estar contido inteiramente dentro do espaço-estado da superclasse O espaço-estado de uma subclasse pode ter mais dimensões que a superclasse 22 Invariante de classe Condição que todo objeto da classe deve satisfazer em todo o seu ciclo de vida São restrições no espaço-estado do objeto A invariante nunca deve ser quebrada 23 Pré-condições e pós-condições Devem garantir a invariante do objeto Toda operação tem uma pré-condição e uma pós- condição A pré-condição é uma condição que deve ser verdadeira quando a operação começar a executar A pós-condição é uma condição que deve ser verdadeira quando a operação finalizar sua execução 24 Conformidade de tipo Um sub-tipo deve se conformar a seu super-tipo O sub-tipo pode ser utilizado em qualquer contexto em que o super-tipo seja esperado A invariante da subclasse deve ser pelo menos tão forte quanto a invariante da super-classe A pré-condição de qualquer operação deve ser igual ou menos restritiva que a operação correspondente da super-classe A pós-condição de qualquer operação deve ser igual ou mais restritiva que a operação correspondente na super-classe 25 Comportamento fechado O comportamento herdado deve respeitar a invariante da sub-classe Nem sempre é possível, neste caso deve-se efetuar alguma ação corretiva evitar herança dos métodos que não respeitem a invariante suprimir os métodos de modo que ele não tenha efeito (possivelmente lançando uma exceção) estar preparado para reclassificar o objeto 26 Projeto de Qualidade Fácil de entender Fácil de alterar Fácil de reusar 27 Projeto Ruim Rígido Difícil de alterar Uma alteração requer uma cascata de outras alterações Impacto das alterações não consegue ser previsto Frágil A cada alteração novos erros aparecem em áreas aparentemente desconectadas Imobilizado Sem muita possibilidade de reuso Partes desejadas de um componente possui muitas partes indesejadas para o reuso 28 Projeto Ruim Pegajoso Alterações corretas são mais difíceis de fazer que as erradas (bacalhau!) Obscuro Difícil de entender Complexidade desnecessária Repetição desnecessária 29 Princípios de Projeto Princípio da Responsabilidade Única The Single Responsibility Principle (SRP) Princípio do Aberto-Fechado The Open-Closed Principle (OCP) Princípio de Substituição de Liskov The Liskov Substitution Principle (LSP) 30 Princípios de Projeto Princípio da Inversão de Dependência Dependency Inversion Principle (DIP) Princípio de Reuso de Composição The Composite Reuse Principle (CRP) Princípio de Segregação de Interface The Interface Segregation Principle (ISP) 31 The Single Responsibility Principle Uma classe deveria ter apenas uma razão para mudar Responsabilidade = razão para mudança Múltiplas responsabilidades = acoplamento alto, baixa coesão Responsabilidades são eixos de alteração Se uma classe faz mais de uma coisa, separe em classes diferentes 32 The Single ResponsibilityPrinciple Podemos melhorar este projeto!!! 33 The Single Responsibility Principle 34 The Single Responsibility Principle public class Grupo { private List servidores; public List getServidores() { return servidores; } public void setServidores(List servidores) { this.servidores = servidores; } } public class Servidor { private String login; private Grupo meuGrupo; public Servidor (String login, Grupo grupo) { this.login = login; this.meuGrupo = grupo; meuGrupo.getServidores().add(this.login); } } Exemplo de código... 35 The Single Responsibility Principle public class Grupo { private HashMap servidores; public HashMap getServidores() { return servidores; } public void setServidores(HashMap servidores) { this.servidores = servidores; } } public class Servidor { private String login; private Grupo meuGrupo; public Servidor (String login, Grupo grupo) { this.login = login; this.meuGrupo = grupo; meuGrupo.getServidores().put("login", this.login); } } E se alterarmos a lista de servidores para um HashMap? A classe Servidor precisa ser alterada também... 36 The Single Responsibility Principle public class Grupo { private HashMap servidores; public void incluirServidor(Servidor servidor){ // Regra para inserir Servidor... } } public class Servidor { private String login; private Grupo meuGrupo; public Servidor (String login, Grupo grupo) { this.login = login; this.meuGrupo = grupo; meuGrupo.incluirServidor(this); } } Se a regra para incluir servidor for responsabilidade do Grupo, o código da classe Servidor não precisa ser alterado... 37 The Open-Closed Principle Classes devem estar abertas para extensão e fechadas para modificação Quando os requisitos mudam (e eles mudam!) o projeto deve permitir estender o comportamento adicionando novo código e não alterando o comportamento do código existente Se a alteração de uma classe ou método resultar em uma cascata de alterações em outras classes e métodos, você tem um projeto “ruim” 38 The Open-Closed Principle Separe o que varia Encapsular o que varia para que não afete o resto do código Menos conseqüências indesejadas Mais flexibilidade Abstração e polimorfismo são a chave para este princípio 39 The Open-Closed Principle public class Matricula { private BigDecimal totalCred; private String tipoMatr; private Obrigacao obrigacao; public void matricular(){ // ... obrigacao.calcular(totalCred, tipoMatr); } } public class Obrigacao { public BigDecimal calcular(BigDecimal creditos, String tipo){ BigDecimal valor = null; if (tipo.equals("curricular")) { // Calcula matricula curricular } else if (tipo.equals("extra-curricular")){ // Calcula valor extra-curricular } else { // Calcula valor padrao } return valor; } } 40 The Open-Closed Principle 41 The Liskov Substitution Principle Conformidade de Tipo Sub-tipos podem substituir super-tipos Guia para criação de abstrações Contratos Violando este princípio podemos violar também o Princípio do Aberto-Fechado 42 The Liskov Substitution Principle 43 The Liskov Substitution Principle public class Bolsa { /** * Pre-condicao: valor não pode ultrapassar o devido * @param valor Valor do desconto lancado */ public void lancarDesconto(BigDecimal valor){ } } public class Financiamento extends Bolsa { /** * Pre-condicao: deve ser menor que o devido * @param valor Valor do desconto lancado */ public void lancarDesconto(BigDecimal valor){ } } 44 The Liskov Substitution Principle 45 Dependency Inversion Principle Dependa de abstrações (ou interfaces) e não de classes concretas Programe para uma interface, não para uma implementação Explora o polimorfismo Interface pode ser um super-tipo Alterações em classes que implementam uma interface não quebram código cliente 46 Dependency Inversion Principle 47 The Composite Reuse Principle Preferir a composição em relação a herança Herança excessiva pode causar fragilidade e hierarquias complexas de classes Herança pode quebrar o encapsulamento Com herança podemos sobrescrever um método, às vezes indesejável. Na composição os métodos devem ser utilizados como foram definidos Novas funcionalidades podem ser agregadas sem alteração no código existente (Princípio do Aberto- Fechado) 48 The Composite Reuse Principle Herança Comportamento é herdado Não podemos alterar o comportamento sem escrever mais código Composição Comportamento como um atributo Mais flexibilidade Permite alterar o comportamento em tempo de execução 49 The Composite Reuse Principle Exemplo de uso de herança: 50 The Composite Reuse Principle Mesmo exemplo utilizando composição e CRP: 51 The Composite Reuse Principle Outro exemplo com herança: 52 The Composite Reuse Principle Cálculo do bônus passou a ser diferente para os empregados em tempo integral O que fazer para garantir um bom reuso sem código duplicado? Mas... 53 The Composite Reuse Principle 54 The Interface Segregation Principle Interfaces para específicos tipos de cliente são melhores que uma interface de propósito geral Clientes não deveriam ser forçados a depender de interfaces que eles não utilizam Interfaces muito grandes podem introduzir acoplamentos não desejados entre os clientes ISP não recomenda que seja criada uma interface para cada classe cliente, mas que as classes sejam classificadas por tipo Caso 2 ou mais tipos de clientes utilizem o mesmo método, este deve estar em ambas interfaces 55 The Interface Segregation Principle 56 The Interface Segregation Principle 57 Referências Fundamentals of Object-Oriented Design in UML - Meilir Page-Jones Head First Design Patterns - Elisabeth Freeman, Eric Freeman, Bert Bates and Kathy Sierra Design Principles e Design Patterns http://www.objectmentor.com/resources/articles/Principles_and_Patterns.pdf Domain Driven Design Quickly http://www.infoq.com/minibooks/domain-driven-design-quickly Contratos Nulos http://fragmental.com.br/wiki/index.php/Contratos_Nulos 58 Referências Lei de Demeter http://c2.com/cgi/wiki?LawOfDemeter Articles for Object Oriented Design http://www.objectmentor.com/resources/publishedArticles.html Parte 1: Fundamentos OO Abstração Classes e Objetos Encapsulamento Mensagem Herança Polimorfismo Relacionamentos Slide 9 Slide 10 Slide 11 Slide 12 Slide 13 Slide 14 Slide 15 Slide 16 Slide 17 Slide 18 Slide 19 Slide 20 Slide 21 Slide 22 Slide 23 Slide 24 Slide 25 Slide 26 Slide 27 Slide 28 Slide 29 Slide 30 Slide 31 Slide 32 Slide 33 Slide 34 Slide 35 Slide 36 Slide 37 Slide 38 Slide 39 Slide 40 Slide 41 Slide 42 Slide 43 Slide 44 Slide 45 Slide 46 Slide 47 Slide 48 Slide 49 Slide 50 Slide 51 Slide 52 Slide 53 Slide 54 Slide 55 Slide 56 Exercicios Fundamentos OO Slide 58
Compartilhar