• Nenhum resultado encontrado

Boas práticas com

N/A
N/A
Protected

Academic year: 2022

Share "Boas práticas com "

Copied!
58
0
0

Texto

(1)

Boas práticas com

Orientação a Objetos

Paulo Silveira

[email protected]

(2)

Rapidissímo overview

IFs e switches X herança

Vantagens e desvantagens do uso de Herança Casos errados do uso de herança

Herança versus Composição Herança versus Interfaces

Programando pensando em Interfaces

(3)

Antes de qualquer coisa:

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

(4)

Switchs e IFs

Usando polimorfismo

(5)

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;

}

}

(6)

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 toda aplicação!

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

(7)

Remodelando

class Funcionario {

public double getGastos() { return this.salario;

} }

class Diretor

extends Funcionario {

public double getGastos() { return this.salario * 1.1;

} }

Funcionario

Diretor Presidente

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

(8)

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!

(9)

Controle de Permissões

class Usuario { private int id;

private String name;

// ...

}

Usuario

Moderador Administrador O uso de herança nesse

caso é altamente dicutível!

Estamos usando apenas como exemplo.

(10)

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!

(11)

Usando polimorfismo

Usuario

Moderador Administrador

class Usuario {

public boolean hasRight(int code) { }

}

(12)

Apagando com a nova forma

public 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;

} }

(13)

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.

(14)

Pequena conclusão

Switch é uma anomalia

Polimorfismo é muito mais elegante

Você muda apenas na própria classe, não precisa concentrar lógica de negócio.

Switch é feio!

Isto não é uma regra rígida!

(15)

Vantagens da Herança

(16)

Herança, quais são as vantagens?

Reaproveitamento de código Possibilita polimorfismo

Vamos mostrar que podemos ter esses

benefícios de outras maneiras mais “leves”.

(17)

Quando não usar herança

Apredendo com os erros da Sun

(18)

O que vocês acham dessas classes?

java.util.Properties

java.util.Stack

(19)

Properties

public class Properties extends Hashtable

Properties é uma Hashtable?

Hashtable: associa Object – Object Properties: associa String - String

Properties não é uma Hashtable!

(20)

Properties

Object

Dictionary

Hashtable

Properties

(21)

O que acontece com esse código?

Object object = new Object();

Hashtable table = new Properties();

table.put(“x”, object);

table.get(“x”);

Funciona ok!

(22)

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

(23)

Último round

Properties table = new Properties();

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

table.getProperty(“x”);

Retorna null também?

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

(24)

java.util.Stack

Caso parecido

Se é uma pilha, porque posso remove(int)?

Porque posso add(int, Object)?

Herdou apenas para não ter de escrever um vetor!

PREGUIÇA!

(25)

Pequena conclusão

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

Contratos acabam sendo quebrados Difícil de mudar depois

Pergunte a si mesmo se você não está fazendo

isso por pura preguiça!

(26)

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”.

(27)

Classe Entity

class 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!

(28)

Problemas trazidos pela

herança

(29)

Considere

Funcionario

Diretor Presidente

(30)

Uso do protected

class 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;

} }

}

(31)

Uso do protected

class 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

(32)

Uso do protected

Classe filha precisa conhecer bem a mãe

Classe 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

(33)

Considere

Pessoa

Pessoa Física

Pessoa Jurídica

(34)

Método na mãe muda

Quando um método da mãe muda pode

quebrar o comportamento da classe filha

(35)

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!

(36)

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?

(37)

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?

(38)

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!

(39)

Grande árvore de herança, mais problemas

Pessoa

Pessoa Física

Pessoa Jurídica

Fornecedor Jurídico Fornecedor

Físico

(40)

Herança, lados negativos

Você ganha mais coisas do que gostaria Sua relação com sua mãe é conturbada Quebra 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!

(41)

Herança versus Composição

Usando polimorfismo

(42)

Problemas! Além dos já apresentados:

Pessoa

Pessoa Física

Pessoa Jurídica

Fornecedor Jurídico Fornecedor

Físico Fornecedor

é

Pessoa?

Aqui tem código repetido!

(43)

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?

(44)

Diminuindo acomplamento

Pessoa

Pessoa Física Fornecedor

Físico

class FornecedorFisico extends PessoaFisica {}

passa para:

class FornecedorFisico {

private PessoaFisica pessoa;

// metodos para delegar }

(45)

Acabando com código duplicado

Pessoa

Pessoa Física Fornecedor

Físico

Pessoa Jurídica

Fornecedor Jurídico

public String pegaNome() { }

public void enviaNotificacaoSobreCredito() { }

(46)

Acabando com código duplicado

Pessoa

Pessoa Física Fornecedor

Físico

Pessoa Jurídica

Fornecedor Jurídico

Fornecedor Helper

(47)

FornecedorHelper

Faz o trabalho comum aos Fornecedores Pode ser uma classe package-friendly

class FornecedorHelper { private String nome;

private String email;

public String pegaNome() { }

public void enviaNotificacaoSobreCredito() { }

}

class FornecedorJuridico {

private FornecedorHelper helper;

public void enviaNotificacaoSobreCredito() {

this.helper.enviaNotificacaoSobreCredito();

} }

(48)

Vantagens do uso da composição

Menor acoplamento, difícil de quebrar Quem faz e como faz esta escondido

Implementação pode ser trocada em runtime

(49)

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?

(50)

Será que isso pode causar transtornos?

Object

Component

Container

JComponent

JPanel

JSpinner.DefaultEditor

JSpinner.DateEditor

(51)

Herança versus Interfaces

Programando voltado para interfaces

(52)

E se eu precisasse de polimorfismo?

Utilização de Interfaces

Reaproveitamento por composição

Classes abstratas na hora da preguiça!

Talvez package-friendly

(53)

Entity como interface

interface Entity { int getID();

} Entity

Usuario

class Usuario implements Entity { // ...

public int getID() { return this.id;

} }

(54)

Entity melhorada

Entity

Usuario EntityInfo

class Usuario implements Entity { private EntityInfo info;

public int getID() {

return this.info.getID();

} }

(55)

Temos de escrever o esqueleto sempre?

Entity

Usuario

EntityInfo Abstract

Entity

(56)

“Regras” do Gang of Four

1.

Prefira composição em vez de herança

2.

Programe pensando nas interfaces e não

na implementação

(57)

Leitura recomendada

Design Patterns, Gang of Four

Effective Java, Joshua Bloch

Refactoring, Martin Fowler

(58)

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/

Referências

Documentos relacionados

Local de realização da avaliação: Centro de Aperfeiçoamento dos Profissionais da Educação - EAPE , endereço : SGAS 907 - Brasília/DF. Estamos à disposição

Resumo: Considerando a influência que as novas mídias da comunicação e da informação exercem sobre nossas vidas, o trabalho proposto visa apresentar a análise da

O uso da denominação social é exclusivo dos sócios e da administração e somente será permitido para os negócios de interesse social, sendo expressamente

A taxa do INR ideal para os paci- entes com disfunção ventricular e insuficiência cardíaca também não foi estimada por meio de estudos prospectivos e randomizados, e a taxa

Atendimento em locais indicados pela operadora, após liberação da guia TISS, de acordo com a legislação vigente. Guia de encaminhamento autorizado pelo guichê

Já agora não se me dá de confessar que sentia umas tais ou quais cócegas de curiosidade, por saber onde ficava a origem dos séculos, se era tão misteriosa como a origem do Nilo, e

Quando Jesus e os discípulos iam pelo caminho, um homem disse a Jesus: — Eu estou pronto a seguir o senhor para qualquer lugar onde o senhor

A história do direito trabalhista teve suas evoluções, e o presente trabalho vem falar da Pejotização, uma prática que vem acontecendo como forma de burlar a relação