fundamentos e princípios do projeto orientado a objetos
TRANSCRIPT
Fundamentos e Princípios do ProjetoOrientado a Objetos
Autor: Evandro João [email protected]
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
Baixareutilização
Médiareutilização
Altareutilizaçã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 Responsibility Principle
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 Patternshttp://www.objectmentor.com/resources/articles/Principles_and_Patterns.pdf
Domain Driven Design Quicklyhttp://www.infoq.com/minibooks/domain-driven-design-quickly
Contratos Nuloshttp://fragmental.com.br/wiki/index.php/Contratos_Nulos
58
Referências
Lei de Demeterhttp://c2.com/cgi/wiki?LawOfDemeter
Articles for Object Oriented Designhttp://www.objectmentor.com/resources/publishedArticles.html