Design OO

57
Design OO Mauricio De Diana

description

Apresentação feita para a equipe do IME-USP do projeto Groupware Workbench (http://code.google.com/p/groupware-workbench/).

Transcript of Design OO

Page 1: Design OO

Design OO

Mauricio De Diana

Page 2: Design OO

Atributos de qualidade

Manutenibilidade Robustez Reuso Legibilidade Testabilidade etc

Page 3: Design OO

Encapsulamento

"Esconder o estado interno de um objeto e fazer com que todas as interações com um objeto

sejam feitas através de métodos."

Page 4: Design OO

class Conta { private double saldo; // devia ser BigDecimal int getSaldo() { ... } // devia ser public void setSaldo(double novoSaldo) { ... }}

Page 5: Design OO

Conta c = new Conta();c.setSaldo(10.00); // inicializa conta double novo = c.getSaldo() + 5.00; // depósitoc.setSaldo(novo);

double novo = c.getSaldo() - 3.00; // saquec.setSaldo(novo);

Page 6: Design OO

Novo Requisito: CPMF (0,38% no saque)

Page 7: Design OO

Conta c = new Conta();c.setSaldo(10.00); // inicializa conta double novo = c.getSaldo() + 5.00; // depósitoc.setSaldo(novo);

double imp = 3.00 * 0.0038;double novo = c.getSaldo() - 3.00 - imp; // saquec.setSaldo(novo); // em mais 15 pontos do sistema... double imp = valor * 0.0038;double novo = c.getSaldo() - valor - imp; // saquec.setSaldo(novo);

Page 8: Design OO

// SEM CPMFclass Conta { private double saldo;

// Depois que o objeto é criado, // é impossível setar o saldo diretamente. Conta(double saldo) { this.saldo = saldo; } int getSaldo() { ... } void deposito(double valor) { saldo += valor; } void saque(double valor) { saldo -= valor; }}

Page 9: Design OO

Conta c = new Conta(10.00);c.deposito(5.00);c.saque(3.00);

Page 10: Design OO

class Conta { private double saldo;

Conta(double saldo) { this.saldo = saldo; } int getSaldo() { ... } void deposito(double valor) { saldo += valor; } void saque(double valor) { double imp = valor * 0.0038; saldo -= (valor + imp); }}

Page 11: Design OO

Conta c = new Conta(10.00);c.deposito(5.00);c.saque(3.00); // em mais 15 pontos do sistema... c.saque(valor);

Page 12: Design OO

Objetos consistentes

"O estado de um objeto deve ser sempre consistente."

Page 13: Design OO

class Cliente { private String cpf; private String endereco; private String cep;

String getCpf() { ... } void setCpf(String cpf) { ... } String getEndereco() { ... } void setEndereco(String endereco) { ... } String getCep() { ... } void setCep(String cep) { ... } }

Page 14: Design OO

Cliente c = new Cliente();c.getCpf().startsWith("1"); //NullPointerException

Page 15: Design OO

class Cliente { private String cpf; private String endereco; private String cep;

Cliente(String cpf, String endereco, String cep) { ... } String getCpf() { ... } void setCpf(String cpf) { ... } String getEndereco() { ... } void setEndereco(String endereco) { ... } String getCep() { ... } void setCep(String cep) { ... } }

Page 16: Design OO

Cliente c = new Cliente( "123456789-10", "R. X, 1", "12345-678");c.getCpf().startsWith("1");

Page 17: Design OO

Cliente c = new Cliente( "123456789-10", "R. X, 1", "12345-678");c.setEndereco("R. Y, 2");// faz outras coisas

Page 18: Design OO

class Cliente { private String cpf; private String endereco; private String cep;

Cliente(String cpf, String endereco, String cep) { ... } String getCpf() { ... } void setCpf(String cpf) { ... } String getEndereco() { ... } String getCep() { ... } void setEnderecoECep(String endereco, String cep) { ... } }

Page 19: Design OO

Cliente c = new Cliente( "123456789-10", "R. X, 1", "12345-678"); c.setEnderecoECep("R. Y, 2", "98765-432");

Page 20: Design OO

Entidades e Value Objects

"Muitos objetos não são definidos pelos valores de seus atributos, mas sim por uma linha de

identidade e continuidade"

"Muitos objetos não possuem identidade conceitual. Esses objetos descrevem características

de alguma coisa"

Page 21: Design OO

Cliente c = new Cliente( "123456789-10", "R. X, 1", "12345-678");c.setCpf("987654321-00");

Page 22: Design OO

class Cliente { private String cpf; private String endereco; private String cep;

Cliente(String cpf, String endereco, String cep) { ... } String getCpf() { ... } void setCpf() { ... } String getEndereco() { ... } String getCep() { ... } void setEnderecoECep(String endereco, String cep) { ... } }

Page 23: Design OO

class Cliente { private String cpf; private Endereco endereco; Cliente(String cpf, String endereco) { ... } String getCpf() { ... } String getEndereco() { ... } void setEndereco(Endereco endereco) { ... }} class Endereco { private String ruaENumero; private String cep; Endereco(String ruaENumero, String cep) { ... } // getters (sem setters)}

Page 24: Design OO

Endereco e = new Endereco("R. X, 1", "12345-678");Cliente c = new Cliente("12345678-9", e); Endereco novo = new Endereco("R. Y,2", "98765-432");c.setEndereco(novo);

Page 25: Design OO

Lei de Demeter

"Um método f de uma classe C só pode invocar métodos de:

CUm objeto criado por fUm objeto passado como argumento para fUm objeto em uma variável de instância de C"

Page 26: Design OO

class Funcionario { // devia usar generics private List tarefas = new ArrayList();

List getTarefas() { ... }}

Page 27: Design OO

Funcionario f = new Funcionario();f.getTarefas().add(new Tarefa("X"));f.getTarefas().add(new Tarefa("Y")); // remove primeiraf.getTarefas().remove(f.getTarefas().get(0));

Page 28: Design OO

class Funcionario { private List tarefas = new ArrayList();

void adicionaTarefa(Tarefa t) { tarefas.add(t); } void removePrimeiraTarefa() { tarefas.remove(tarefas.get(0)); }}

Page 29: Design OO

Funcionario f = new Funcionario();f.adicionaTarefa(new Tarefa("X"));f.adicionaTarefa(new Tarefa("Y")); // remove primeiraf.removePrimeiraTarefa();

Page 30: Design OO

class Cliente { private String cpf; private Endereco endereco; Cliente(String cpf, String endereco) { ... } String getCpf() { ... } String getEndereco() { ... } void setEndereco(Endereco endereco) { ... }} class Endereco { private String ruaENumero; private String cep; Endereco(String ruaENumero, String cep) { ... } // getters}

Page 31: Design OO

Endereco e = new Endereco("R. X, 1", "12345-678");Cliente c = new Cliente("12345678-9", end); c.getEndereco().getCep();

Page 32: Design OO

Endereco e = new Endereco("R. X, 1", "12345-678");Cliente c = new Cliente("12345678-9", end); c.endereco.cep;// não viola porque é acesso a ED

Page 33: Design OO

Princípios

Single Responsibility PrincipleOpen Closed Principle Liskov Substitution PrincipleInterface Segregation Principle Dependency Inversion Principle

(http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod)

Page 34: Design OO

SRP (Single Responsibility Principle)

"Não deve haver mais do que uma razão para uma classe ser alterada"

Page 35: Design OO

class Entrega { void setOrigem(Endereco endereco) { ... } void setDestino(Endereco endereco) { ... } void setMetodoEnvio(String metodo) { ... } Rota calcularRota() { ... } double calcularCustoEnvio() { ... } void imprimirEtiqueta() { ... }}

Page 36: Design OO

class Entrega { void setOrigem(Endereco endereco) { ... } void setDestino(Endereco endereco) { ... } void setMetodoEnvio(String metodo) { ... } Rota calcularRota() { ... }} class CalculoEnvio { double calcularCusto(Entrega entrega) { ... }} class ImpressaoEtiqueta { void imprimir(Entrega entrega) { ... }}

Page 37: Design OO

OCP (Open Closed Principle)

"Um módulo deve ser aberto para expansão efechado para modificação"

Page 38: Design OO

class Modem { void logon(TipoModem tipo) { if (tipo == TipoModem.Hayes) discaHayes(); else if (tipo == TipoModem.Courrier) discaCourrier(); else if (tipo == TipoModem.Ernie) discaErnie(); }

void discaHayes() { ... } void discaCourrier() { ... } void discaErnie() { ... }}

Page 39: Design OO

Modem m = new Modem();m.logon(TipoModem.HAYES);

Page 40: Design OO

class Modem { void logon(TipoModem tipo) { if (tipo == TipoModem.Hayes) discaHayes(); else if (tipo == TipoModem.Courrier) discaCourrier(); else if (tipo == TipoModem.Ernie) discaErnie(); else if (tipo == TipoModem.X) discaX(); }

void discaHayes() { ... } void discaCourrier() { ... } void discaErnie() { ... } void discaX() { ... }}

Page 41: Design OO

interface Modem { void disca();} class Hayes implements Modem { public void disca { ... }}

class Courrier implements Modem { public void disca { ... }} class Ernie implements Modem { public void disca { ... }} public void logon(Modem modem) { modem.disca();}

Page 42: Design OO

Modem m = new Hayes();m.logon();

Page 43: Design OO

LSP (Liskov Substitution Principle)

"Subclasses devem poder substituir suas superclasses"

Page 44: Design OO

class Retangulo { int larg; int alt; void setLarg(int larg) { this.larg = larg; } void setAlt(int alt) { this.alt = alt; } int getLarg() { return larg; } int getAlt() { return alt; } int area() { return larg * alt; }}

Page 45: Design OO

Retangulo r = new Retangulo();Cliente c = new Cliente();c.fazAlgo(r); class Cliente { void fazAlgo(Retangulo r) { r.setLarg(10); r.setAlt(20); assertEquals(10, r.getLarg()); assertEquals(20, r.getAlt()); }}

Page 46: Design OO

class Quadrado extends Retangulo { void setLarg(int larg) { this.larg = larg; this.alt = larg; }

void setAlt(int Alt) { this.alt = alt; this.larg = alt; }}

Page 47: Design OO

Retangulo r = new Quadrado();Cliente c = new Cliente();c.fazAlgo(r); class Cliente { void fazAlgo(Retangulo r) { r.setLarg(10); r.setAlt(20); assertEquals(10, r.getLarg()); assertEquals(20, r.getAlt()); }}

Page 48: Design OO

ISP (Interface Segregation Principle)

"Muitas interfaces específicas para clientes é melhor do que uma única

interface de propósito geral"

Page 49: Design OO

class Conta { void deposito(double valor) { ... } void saque(double valor) { ... } void investe(Investimento inv, double valor){...} void emprestimo(double valor) { ... }}

Page 50: Design OO

interface ContaCorrente { void deposito(double valor); void saque(double valor);} interface ContaInvestimento { void investe(Investimento inv, double valor);} interface ContaEmprestimo { void emprestimo(double valor);} class Conta implements ContaCorrente, ContaInvestimento, ContaEmprestimo { public void deposito(double valor) { ... } public void saque(double valor) { ... } public void investe(Investimento inv, double valor){...} public void emprestimo(double valor) { ... }}

Page 51: Design OO

ContaCorrente cc = new Conta();cc.deposito(10.00);cc.saque(5.00); cc.emprestimo(1.00);

Page 52: Design OO

DIP (Dependency Inversion Principle)

"Dependa de abstrações.Não dependa de coisas concretas"

Page 53: Design OO

class Cobranca { void calcula() { // faz varias coisas db.insere("TB_LOG", "Resultado: " + calc); } ...}

class Pedido { void criaPedido() { // faz varias coisas db.insere("TB_LOG", "Novo pedido: " + id); } ...}

Page 54: Design OO

interface Log { void escreve(mensagem);}

class DbLog implements Log { public void escreve(String mensagem) { db.insere("TB_LOG", mensagem); }}

Page 55: Design OO

class Cobranca { Log log; Calcula(Log log) { this.log = log; } void calcula() { // faz varias coisas log.escreve("Resultado: " + calc); } ...}

class Pedido { void criaPedido() { // faz varias coisas log.escreve("Novo pedido: " + id); } ...}

Page 56: Design OO

Log log = new DbLog(); Cobranca c = new Cobranca(log);

Page 57: Design OO

Finalizando

YAGNI (You Ain't Gonna Need It) Entender as razões por trás das regras "Pensar semanticamente, não sintaticamente"

"Accessors não são métodos"

Exceções: IoC JavaBeans Frameworks etc