Android DevConference - SOLID no Android

55
SOLID no Android Android Dev Conference 2016

Transcript of Android DevConference - SOLID no Android

Page 1: Android DevConference - SOLID no Android

SOLID no AndroidAndroid Dev Conference 2016

Page 2: Android DevConference - SOLID no Android

Esses são os slides que apresentei noAndroid Dev Conference 2016.

Acreditei que por não conter nenhum“voice over” seria justo fazer pequenas

adaptações para melhor entendimento,espero que seja útil para você!

Page 3: Android DevConference - SOLID no Android

Twitter: http://twitter.com/marcellogalhardLinkedIn: https://www.linkedin.com/in/marcellogalhardoGithub: https://github.com/marcellogalhardoE-mail: [email protected]: https://medium.com/@marcellogalhardo

Contatos.

Page 4: Android DevConference - SOLID no Android

Marcello GalhardoDesenvolvedor Android

Page 5: Android DevConference - SOLID no Android
Page 6: Android DevConference - SOLID no Android
Page 7: Android DevConference - SOLID no Android

Criado em 2000 porRobert C. Martin; 5

princípios deprogramação.

Page 8: Android DevConference - SOLID no Android

"Paciência você deveter meu jovem

Padawan."

Page 9: Android DevConference - SOLID no Android

"Quem plantagambiarras, colhe

bugs."

Page 10: Android DevConference - SOLID no Android

http://martinfowler.com/bliki/DesignStaminaHypothesis.html

Trade Off Qualidade

Page 11: Android DevConference - SOLID no Android

Princípio daResponsabilidade

ÚnicaSingle Responsibility Principle

Page 12: Android DevConference - SOLID no Android

"Uma classe deve terum, e somente um,motivo para mudar."

Page 13: Android DevConference - SOLID no Android

Violação.

Page 14: Android DevConference - SOLID no Android

public class Produto {

private String descricao; private int quantidade; private long preco;

// ... getters/setters

}

public class Pedido {

private int numeroDoPedido; private List<Produto> produtos = new ArrayList<>();

// ... getters/setters

}

Page 15: Android DevConference - SOLID no Android

public class PedidoRecyclerAdapter extends RecyclerView.Adapter<PedidoRecyclerAdapter.ViewHolder> { private List<Pedido> pedidos; public OrderRecyclerAdapter(List<Pedido> pedidos) { this.pedidos = pedidos; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(context); View v = inflater.inflate(R.layout.item_pedidos, parent, false); return new ViewHolder(v); } @Override public void onBindViewHolder(ViewHolder holder, int position) { // TODO: Faz o vínculo entre o modelo e a view } @Override public int getItemCount() { return pedidos.size(); } // ... ViewHolder e métodos

}

Page 16: Android DevConference - SOLID no Android

@Override public void onBindViewHolder(ViewHolder holder, int position) { Pedido pedido = items.get(position);

holder.numeroDoPedido.setText(pedido.getNumeroDoPedido().toString());

long total = 0; for (Produto produto : pedido.getProdutos()) { total += produto.getPreco(); } NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.US); String valorTotal = formatter.format(total); holder.valorTotalDoPedido.setText(valorTotal);

holder.itemView.setTag(pedido);}

public static class ViewHolder extends RecyclerView.ViewHolder { public TextView numeroDoPedido; public TextView valorTotalDoPedido; // FindViews.}

Page 17: Android DevConference - SOLID no Android

long total = 0;for (Produto produto : pedido.getProdutos()) { total += produto.getPreco();}NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.US);String valorTotal = formatter.format(total);holder.valorTotalDoPedido.setText(valorTotal);

Page 18: Android DevConference - SOLID no Android

Solução.

Page 19: Android DevConference - SOLID no Android

public class Pedido {

private int numeroDoPedido; private List<Produto> produtos = new ArrayList<>();

// ... getters/setters

public long getValorTotalDoPedido() { long total = 0; for (Produto produto : pedido.getProdutos()) { total += produto.getPreco(); } return total; }

public String getValorTotalDoPedidoFormatado() { long total = getValorTotalDoPedido(); NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.US); String valorTotal = formatter.format(total); return valorTotal; }

}

Page 20: Android DevConference - SOLID no Android

@Override public void onBindViewHolder(ViewHolder holder, int position) { Pedido pedido = items.get(position); holder.numeroDoPedido.setText(pedido.getNumeroDoPedidoFormatado()); holder.valorTotalDoPedido.setText(pedido.getValorTotalDoPedidoFormato()); holder.itemView.setTag(pedido);}

Page 21: Android DevConference - SOLID no Android

Rigidez.

Page 22: Android DevConference - SOLID no Android

Princípio doAberto e Fechado

Open/Closed Principle

Page 23: Android DevConference - SOLID no Android

"Você deve ser capaz deestender um

comportamento de umaclasse, sem modificá-lo."

Page 24: Android DevConference - SOLID no Android

Violação.

Page 25: Android DevConference - SOLID no Android

public class Pedido {

private int numeroDoPedido; private List<Produto> produtos = new ArrayList<>();

// ... getters/setters

public long getValorTotalDoPedido() { long total = 0; for (Produto produto : pedido.getProdutos()) { total += produto.getPreco(); } return total; }

public String getValorTotalDoPedidoFormatado() { long total = getValorTotalDoPedido(); NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.US); String valorTotal = formatter.format(total); return valorTotal; }

}

Page 26: Android DevConference - SOLID no Android

private static final int SEM_DESCONTO = 0;private static final int DESCONTO_10_POR_CENTO = 1;private static final int DESCONTO_15_POR_CENTO = 2;

private int tipoDeDesconto;

public long getValorTotalDoPedido() { long total = 0; for (Produto produto : pedido.getProdutos()) { total += produto.getPreco(); } if (tipoDeDesconto == DESCONTO_10_POR_CENTO) { long descontoDe10PorCento = total * 0.1; total += descontoDe10PorCento; } else if (tipoDeDesconto == DESCONTO_15_POR_CENTO ) { long descontoDe15PorCento = total * 0.15; total += descontoDe15PorCento; } return total;}

Page 27: Android DevConference - SOLID no Android

public class Pedido {

private static final int SEM_DESCONTO = 0; private static final int DESCONTO_10_POR_CENTO = 1; private static final int DESCONTO_15_POR_CENTO = 2;

private int numeroDoPedido; private List<Produto> produtos = new ArrayList<>(); private int tipoDeDesconto;

// ... getters/setters

public long getValorTotalDoPedido() { long total = 0; for (Produto produto : pedido.getProdutos()) { total += produto.getPreco(); } if (tipoDeDesconto == DESCONTO_10_POR_CENTO) { long descontoDe10PorCento = total * 0.1; total += descontoDe10PorCento; } else if (tipoDeDesconto == DESCONTO_15_POR_CENTO ) { long descontoDe15PorCento = total * 0.15; total += descontoDe15PorCento; } return total; }

public String getValorTotalDoPedidoFormatado() { long total = getValorTotalDoPedido(); NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.US); String valorTotal = formatter.format(total); return valorTotal; }

}

Page 28: Android DevConference - SOLID no Android

private static final int SEM_DESCONTO = 0;private static final int DESCONTO_10_POR_CENTO = 1;private static final int DESCONTO_15_POR_CENTO = 2;private static final int DESCONTO_20_POR_CENTO = 3;private static final int DESCONTO_25_POR_CENTO = 4;

private int tipoDeDesconto;

public long getValorTotalDoPedido() { long total = 0; for (Produto produto : pedido.getProdutos()) { total += produto.getPreco(); } if (tipoDeDesconto == DESCONTO_10_POR_CENTO) { long descontoDe10PorCento = total * 0.1; total += descontoDe10PorCento; } else if (tipoDeDesconto == DESCONTO_15_POR_CENTO) { long descontoDe15PorCento = total * 0.15; total += descontoDe15PorCento; } else if (tipoDeDesconto == DESCONTO_20_POR_CENTO) { long descontoDe20PorCento = total * 0.20; total += descontoDe20PorCento; } else if (tipoDeDesconto == DESCONTO_25_POR_CENTO) { long descontoDe25PorCento = total * 0.25; total += descontoDe25PorCento; } return total;}

Page 29: Android DevConference - SOLID no Android

Solução.

Page 30: Android DevConference - SOLID no Android

public interface Desconto {

long calculaDesconto(long valor);

}

Page 31: Android DevConference - SOLID no Android

public interface Desconto {

long calculaDesconto(long valor);

}

// Padrão de Projeto: Objeto Nulo.public class SemDesconto implements Desconto {

public long calculaDesconto(long valor) { return 0; }

}

public class DescontoDe10PorCento implements Desconto {

public long calculaDesconto(long valor) { return valor * 0.1; }

}

public class DescontoDe15PorCento implements Desconto {

public long calculaDesconto(long valor) { return valor * 0.15; }

}

// Outros descontos.

Page 32: Android DevConference - SOLID no Android

Objeto Nulo

Page 33: Android DevConference - SOLID no Android

private Desconto desconto = new SemDesconto();

public long getValorTotalDoPedido() { long total = 0; for (Produto produto : pedido.getProdutos()) { total += produto.getPreco(); } // Não é necessário verificar se o desconto é null, pois // sempre existirá um desconto vazio: SemDesconto. desconto = desconto.calculaDesconto(total); return total + desconto;}

Page 34: Android DevConference - SOLID no Android

public class Pedido {

private int numeroDoPedido; private List<Produto> produtos = new ArrayList<>(); private Desconto desconto = new SemDesconto();

// ... getters/setters

public long getValorTotalDoPedido() { long total = 0; for (Produto produto : pedido.getProdutos()) { total += produto.getPreco(); } desconto = desconto.calculaDesconto(total); return total + desconto; }

public String getValorTotalDoPedidoFormatado() { long total = getValorTotalDoPedido(); NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.US); String valorTotal = formatter.format(total); return valorTotal; }

}

Page 35: Android DevConference - SOLID no Android

Princípio daSubstituição de

LiskovLiskov Substitution Principle

Page 36: Android DevConference - SOLID no Android

"Classes derivadasdevem ser

substituíveis porsuas classes base."

Page 37: Android DevConference - SOLID no Android

Violação.

Page 38: Android DevConference - SOLID no Android

// Violação do Princípio de Liskov.

public interface Carro {

public void partidaNoMotor();}

public class Ferrari implements Carro {

@Override public double partidaNoMotor() { // TODO: Lógica. }}

public class Tesla implements Carro {

@Override public void ligaCarro() { // TODO: Lógica. }

@Override public double partidaNoMotor() { // TODO: Lógica. }}

// Iniciar Carro.public void iniciarPartidaDeCarro(Carro carro) { carro.partidaNoMotor();}

Page 39: Android DevConference - SOLID no Android

// "Tentativa de correção" do princípio de Liskov.

public void iniciarPartidaDeCarro(Carro carro) { if (carro instanceof Tesla) { Tesla tesla = (Tesla) carro; tesla.ligaCarro(); } carro.partidaNoMotor();}

Page 40: Android DevConference - SOLID no Android

Solução.

Page 41: Android DevConference - SOLID no Android

// Correção do Princípio de Liskov

public interface Carro { public void partidaNoMotor();}

public class Ferrari implements Carro {

@Override public double partidaNoMotor() { // TODO: Implementação. }

}

public class Tesla implements Carro {

// Implementação do ligaCarro();

@Override public double partidaNoMotor() { if (!estaDescarregado) { ligaCarro(); } // TODO: Implementação. }

}

// Iniciar Carro.public void iniciarPartidaDeCarro(Carro carro) { carro.partidaNoMotor();}

Page 42: Android DevConference - SOLID no Android

Princípio daSegregação de

InterfaceInterface Segregation Principle

Page 43: Android DevConference - SOLID no Android

"Muitas interfacesespecíficas são

melhores do queuma interface

única."

Page 44: Android DevConference - SOLID no Android

Violação.

Page 45: Android DevConference - SOLID no Android

public interface OnClickListener {

void onClick(View v);

void onLongClick(View v);

void onTouch(View v, MotionEvent event);

}

Page 46: Android DevConference - SOLID no Android

// Violação do Princípio da Segregação de Interfaces

Button botao = (Button) findViewById(R.id.botao);botao.setOnClickListener(new View.OnClickListener {

public void onClick(View v) { // TODO: Faz algo bem legal... } public void onLongClick(View v) { // Não precisamos disso. }

public void onTouch(View v, MotionEvent event) { // Disso também não. }

});

Page 47: Android DevConference - SOLID no Android

Solução.

Page 48: Android DevConference - SOLID no Android

// Correção do Princípio da Segregação de Interfaces.

public interface OnClickListener { void onClick(View v);}

public interface OnLongClickListener { void onLongClick(View v);}

public interface OnTouchListener { void onTouch(View v, MotionEvent event);}

Page 49: Android DevConference - SOLID no Android

Princípio daInversão da

DependênciaDependency Inversion Principle

Page 50: Android DevConference - SOLID no Android

"Dependa de umaabstração e não de

umaimplementação."

Page 51: Android DevConference - SOLID no Android

Violação.

Page 52: Android DevConference - SOLID no Android

// Violação do Princípio da Inversão de Dependência.

class Presenter {

private final UsuarioRepositorio usuarioRepositorio = new UsuarioRepositorio();

// TODO: Implementação diversas.

}

class UsuarioRepositorio {

public getUsuario() { // TODO: Recupera o usuário conectado. }

}

Page 53: Android DevConference - SOLID no Android

Solução.

Page 54: Android DevConference - SOLID no Android

// Correção do Princípio da Inversão de Dependência.

class Presenter {

private final UsuarioRepositorio usuarioRepositorio;

@Inject public Presenter(UsuarioRepositorio usuarioRepositorio) { this.usuarioRepositorio = usuarioRepositorio; }

// TODO: Implementação diversas.

}

interface UsuarioRepositorio {

Usuario getUsuario();

}

class UsuarioManager implements UsuarioRepositorio {

@Override public getUsuario() { // TODO: Recupera o usuário conectado. }

}

Page 55: Android DevConference - SOLID no Android