boas práticas com orientação a objetos - ime-usppeas/files/tutorialooa.pdf · herança, lados...

58
Boas práticas com Orientação a Objetos Paulo Silveira [email protected]

Upload: others

Post on 04-Jul-2020

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Boas práticas com Orientação a Objetos

Paulo [email protected]

Page 2: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Rapidissímo overview

IFs e switches X herançaVantagens e desvantagens do uso de HerançaCasos errados do uso de herançaHerança versus ComposiçãoHerança versus InterfacesProgramando pensando em Interfaces

Page 3: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Antes de qualquer coisa:

Não estou falando mal do seu código!

Page 4: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Switchs e IFs

Usando polimorfismo

Page 5: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Caso trivial

class Funcionario {private int codigo;public static final int DIRETOR = 1;public static final int PRESIDENTE = 2;

// ....public int getCodigo() {

return this.codigo;}

}

Page 6: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Em algum outro lugar..class Relatorio {

private double dinheiroGasto;private Empresa empresa; //....

public void adiciona(Funcionario f) {switch (f.getCodigo()) {

case Funcionario.DIRETOR :this.gastos += 1.1 * f.getSalario();break;

case Funcionario.PRESIDENTE :this.gastos += f.getSalario() +

empresa.getParteDosLucros();break;

}

}}

Esse tipo de código vai se espalhar por todaaplicação!

Ao criar uma nova filha de Funcionario, precisamos mudar esse(s) código(s)!

Page 7: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Remodelando

class Funcionario {public double getGastos() {

return this.salario;}

}

class Diretorextends Funcionario {public double getGastos() {

return this.salario * 1.1;}

}

Funcionario

Diretor Presidente

Cálculo dos gastos concentrado dentro da própria classe

Page 8: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

E o relatório...class Relatorio {

private double dinheiroGasto;private Empresa empresa; //....

public void adiciona(Funcionario f) {this.gastos += f.getGastos();

}}

Para adicionar uma nova classe que extende Funcionario,não teremos mais de mexer na classe Relatorio!

Page 9: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Controle de Permissões

class Usuario {private int id;private String name;// ...

}

Usuario

Moderador AdministradorO uso de herança nesse caso é altamente dicutível!

Estamos usando apenas como exemplo.

Page 10: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Primeira tentativa Ifs encadeados num

estilo switch(int)

public void apagaRegistro() {if(this.user instanceof Usuario) {

return false;}if(this.user instanceof Moderador) {

return false;}if(this.user instanceof Administrador) {

return true;}

}

Caso uma classe Colaborador fosse adicionada,precisaríamos mexer aqui também!

Page 11: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Usando polimorfismo

Usuario

Moderador Administrador

class Usuario {

public boolean hasRight(int code) {

}

}

Page 12: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Apagando com a nova formapublic void apagaRegistro() {

if(this.user instanceof Usuario) {return false;

}if(this.user instanceof Moderador) {

return false;}if(this.user instanceof Administrador) {

return true;}

}

Passa para: public void apagaRegistro() {

if(this.user.hasRight(Permissions.DELETE){return false;

}}

Page 13: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

E ao criarmos a classe Colaborador...class Colaborador extends Usuario {

public boolean hasRight(int code) {

// monte de ifs e switchs ☺

}

}Código de permissões não esta mais concetrado em um único lugar, cada classe é responsável pelo seu.

Page 14: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Pequena conclusão

Switch é uma anomaliaPolimorfismo é muito mais eleganteVocê muda apenas na própria classe, não precisa concentrar lógica de negócio.Switch é feio!

Isto não é uma regra rígida!

Page 15: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Vantagens da Herança

Page 16: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Herança, quais são as vantagens?

Reaproveitamento de códigoPossibilita polimorfismo

Vamos mostrar que podemos ter esses benefícios de outras maneiras mais “leves”.

Page 17: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Quando não usar herança

Apredendo com os erros da Sun

Page 18: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

O que vocês acham dessas classes?

java.util.Propertiesjava.util.Stack

Page 19: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Properties

public class Properties extends Hashtable

Properties é uma Hashtable?

Hashtable: associa Object – Object

Properties: associa String - String

Properties não é uma Hashtable!

Page 20: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

PropertiesObject

Dictionary

Hashtable

Properties

Page 21: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

O que acontece com esse código?

Object object = new Object();

Hashtable table = new Properties();table.put(“x”, object);table.get(“x”);

Funciona ok!

Page 22: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Um pouco pior....

Object object = new Object();

Properties table = new Properties();table.put(“x”, object);table.getProperty(“x”);table.get(“x”);

Compila perfeitamente, mas só retorna o object quando chamado pelo .get, e pelo getProperty volta Null. Como adivinhariamos isso?

Parece então que são duas tabelas separadas. Uma para Object-Object, e outra para String String

Page 23: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Último round

Properties table = new Properties();

table.put(“x”, “y”);table.getProperty(“x”);

Retorna null também?

Não, dessa vez acontece o “esperado”.

Page 24: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

java.util.Stack

Caso parecidoSe é uma pilha, porque posso remove(int)?Porque posso add(int, Object)?Herdou apenas para não ter de escrever um vetor!

PREGUIÇA!

Page 25: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Pequena conclusão

Nunca usar herança quando a relação não éclaramente “é um”.

Contratos acabam sendo quebradosDifícil de mudar depoisPergunte a si mesmo se você não está fazendo isso por pura preguiça!

Page 26: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Lembram-se desse caso?

Usuario

Moderador Administrador

Moderador é um Usuario?

Usuario as vezes esta no papel de moderador ou administrador, mas a relação não é exatamente “é um”.

Page 27: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Classe Entityclass Entity {private int id;private String name;private String description;// gets e sets

}class Usuario extends Entity {}

“é um” faz sentido? É um estado de Usuário? É um papel de Usuário?

Veremos como resolver isso com composição!

Page 28: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Problemas trazidos pela herança

Page 29: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Considere

Funcionario

Diretor Presidente

Page 30: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Uso do protectedclass Funcionario {protected double salario;protected int idade;

}class Diretor extends Funcionario {

public double getGastos() {if(this.idade < 35) {

return salario;}else {

return salario * 1.1;}

}}

Page 31: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Uso do protectedclass Funcionario {protected double salario;protected int idade;

}

class Funcionario {protected double salario;protected Calendar nascimento;

}

O que acontece com a classe Diretor?

Não compila? Isto não é o mais grave, ele poderia estar em outro jar, e ele vai começar a lançar Errors

Page 32: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Uso do protected

Classe filha precisa conhecer bem a mãeClasse mãe não pode mudar sua representação interna com facilidade! Quebra de encapsulamento.Protected define um contrato forte para a mãe que não tem muito utilidade para quem esta de fora!

Métodos protected não são tão malvados assim

Page 33: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Considere

Pessoa

PessoaFísica

PessoaJurídica

Page 34: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Método na mãe muda

Quando um método da mãe muda pode quebrar o comportamento da classe filha

Page 35: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Conhecemos a interface publica da classe

class PessoaJuridica {public void adicionaNota(Nota nota) {}public void adicionaVariasNotas(List<Nota> notas) {}

}Não conhecemos bem essa classe!

Page 36: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Fornecedor quer saber quantas transcoes!class FornecedorJuridica extends

PessoalJuridica {private int transacoes;public void adicionaNota(Nota nota) {

this.transacoes++;super.adicionaNota(nota);

}public void adicionaVariasNotas(List<Nota> notas) {

this.transacoes += notas.size();super.adicionaVariasNotas(notas);

}public int getTransacoes() {

return this.transacoes;}

}

List notas = ... // lista com 3 notas

f.adicionaVariasNotas(notas);

f.getTotalTransacoes();

Funciona?

Page 37: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Depende!

class PessoaJuridica {public void adicionaNota(Nota nota) {

this.vetorzinho[posicao++] = nota;}public void adicionaVariasNotas(List<Nota> notas) {

for(Nota n : notas) {this.vetorzinho[posicao++] = n;

}}

}

List notas = ... // lista com 3 notas

f.adicionaVariasNotas(notas);

f.getTotalTransacoes();

Resultado?

Page 38: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Mudança na classe mãe!

class PessoaJuridica {public void adicionaNota(Nota nota) {

this.vetorzinho[posicao++] = nota;}public void adicionaVariasNotas(List<Nota> notas) {

for(Nota n : notas) {// ...this.adicionaNota(n);

}}

}

List notas = ... // lista com 3 notas

f.adicionaVariasNotas(notas);

f.getTotalTransacoes();

E agora que mamãe mudou?

A resposta é 6!

Page 39: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Grande árvore de herança, mais problemas

Pessoa

PessoaFísica

PessoaJurídica

FornecedorJurídico

FornecedorFísico

Page 40: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Herança, lados negativos

Você ganha mais coisas do que gostariaSua relação com sua mãe é conturbadaQuebra de encapsulamento

Não use herança apenas por reaproveitamento de código da classe mãe!Não use herança apenas pelo polimorfismo!

Page 41: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Herança versus Composição

Usando polimorfismo

Page 42: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Problemas! Além dos já apresentados:

Pessoa

PessoaFísica

PessoaJurídica

FornecedorJurídico

FornecedorFísico

FornecedoréPessoa?

Aqui tem código repetido!

Page 43: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

FornecedorJuridico é Pessoa?

É sim, mas estamos utilizando algo como Pessoa p = new Fornecedor() ? Ou recebendo Fornecedor como Pessoa?

Aumentado a hierarquia, como representaríamos alguem como Fornecedor e Consumidor?

Page 44: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Diminuindo acomplamentoPessoa

PessoaFísica

FornecedorFísico

class FornecedorFisico extends PessoaFisica {}

passa para:class FornecedorFisico {

private PessoaFisica pessoa;

// metodos para delegar

}

Page 45: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Acabando com código duplicado

Pessoa

PessoaFísica

FornecedorFísico

PessoaJurídica

FornecedorJurídico

public String pegaNome() {

}public void enviaNotificacaoSobreCredito() {}

Page 46: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Acabando com código duplicado

Pessoa

PessoaFísica

FornecedorFísico

PessoaJurídica

FornecedorJurídico

FornecedorHelper

Page 47: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

FornecedorHelperFaz o trabalho comum aos FornecedoresPode ser uma classe package-friendlyclass FornecedorHelper {

private String nome;private String email;public String pegaNome() {}public void enviaNotificacaoSobreCredito() {}

}

class FornecedorJuridico {private FornecedorHelper helper;public void enviaNotificacaoSobreCredito() {

this.helper.enviaNotificacaoSobreCredito();}

}

Page 48: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Vantagens do uso da composição

Menor acoplamento, difícil de quebrarQuem faz e como faz esta escondidoImplementação pode ser trocada em runtime

Page 49: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Antes de usar herança

Estou fazendo por preguiça?É uma relação de é um?Não é um estado em que a classe pode ficar?Não é um papel que a classe pode tomar?

Page 50: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Será que isso pode causar transtornos?Object

Component

Container

JComponent

JPanel

JSpinner.DefaultEditor

JSpinner.DateEditor

Page 51: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Herança versus Interfaces

Programando voltado para interfaces

Page 52: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

E se eu precisasse de polimorfismo?

Utilização de InterfacesReaproveitamento por composiçãoClasses abstratas na hora da preguiça! Talvez package-friendly

Page 53: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Entity como interfaceinterface Entity {

int getID();

}Entity

Usuario

class Usuario implements Entity {

// ...

public int getID() {

return this.id;

}

}

Page 54: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Entity melhorada

Entity

Usuario EntityInfo

class Usuario implements Entity {

private EntityInfo info;

public int getID() {

return this.info.getID();

}

}

Page 55: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Temos de escrever o esqueleto sempre?

Entity

Usuario

EntityInfoAbstract

Entity

Page 56: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

“Regras” do Gang of Four

1. Prefira composição em vez de herança2. Programe pensando nas interfaces e não

na implementação

Page 57: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Leitura recomendada

Design Patterns, Gang of FourEffective Java, Joshua BlochRefactoring, Martin Fowler

Page 58: Boas práticas com Orientação a Objetos - IME-USPpeas/files/TutorialOOA.pdf · Herança, lados negativos Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada

Obrigado! Perguntas e Respostas

Você pode ver esta palestra em:

http://www.paulo.com.br/

Agradecimentos:

Nos vemos no BrasilOne!

http://www.brasilone.com.br/