Slide 1

Slide 1 text

SOLID no Android Android Dev Conference 2016

Slide 2

Slide 2 text

Esses são os slides que apresentei no Android 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ê!

Slide 3

Slide 3 text

Twitter: http://twitter.com/marcellogalhard LinkedIn: https://www.linkedin.com/in/marcellogalhardo Github: https://github.com/marcellogalhardo E-mail: [email protected] Medium: https://medium.com/@marcellogalhardo Contatos.

Slide 4

Slide 4 text

Marcello Galhardo Desenvolvedor Android

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

Criado em 2000 por Robert C. Martin; 5 princípios de programação.

Slide 8

Slide 8 text

"Paciência você deve ter meu jovem Padawan."

Slide 9

Slide 9 text

"Quem planta gambiarras, colhe bugs."

Slide 10

Slide 10 text

http://martinfowler.com/bliki/DesignStaminaHypothesis.html Trade Off Qualidade

Slide 11

Slide 11 text

Princípio da Responsabilidade Única Single Responsibility Principle

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

Violação.

Slide 14

Slide 14 text

public class Produto { private String descricao; private int quantidade; private long preco; // ... getters/setters } public class Pedido { private int numeroDoPedido; private List produtos = new ArrayList<>(); // ... getters/setters }

Slide 15

Slide 15 text

public class PedidoRecyclerAdapter extends RecyclerView.Adapter { private List pedidos; public OrderRecyclerAdapter(List 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 }

Slide 16

Slide 16 text

@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. }

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

Solução.

Slide 19

Slide 19 text

public class Pedido { private int numeroDoPedido; private List 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; } }

Slide 20

Slide 20 text

@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); }

Slide 21

Slide 21 text

Rigidez.

Slide 22

Slide 22 text

Princípio do Aberto e Fechado Open/Closed Principle

Slide 23

Slide 23 text

"Você deve ser capaz de estender um comportamento de uma classe, sem modificá-lo."

Slide 24

Slide 24 text

Violação.

Slide 25

Slide 25 text

public class Pedido { private int numeroDoPedido; private List 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; } }

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

Solução.

Slide 30

Slide 30 text

public interface Desconto { long calculaDesconto(long valor); }

Slide 31

Slide 31 text

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.

Slide 32

Slide 32 text

Objeto Nulo

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

public class Pedido { private int numeroDoPedido; private List 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; } }

Slide 35

Slide 35 text

Princípio da Substituição de Liskov Liskov Substitution Principle

Slide 36

Slide 36 text

"Classes derivadas devem ser substituíveis por suas classes base."

Slide 37

Slide 37 text

Violação.

Slide 38

Slide 38 text

// 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(); }

Slide 39

Slide 39 text

// "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(); }

Slide 40

Slide 40 text

Solução.

Slide 41

Slide 41 text

// 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(); }

Slide 42

Slide 42 text

Princípio da Segregação de Interface Interface Segregation Principle

Slide 43

Slide 43 text

"Muitas interfaces específicas são melhores do que uma interface única."

Slide 44

Slide 44 text

Violação.

Slide 45

Slide 45 text

public interface OnClickListener { void onClick(View v); void onLongClick(View v); void onTouch(View v, MotionEvent event); }

Slide 46

Slide 46 text

// 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. } });

Slide 47

Slide 47 text

Solução.

Slide 48

Slide 48 text

// 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); }

Slide 49

Slide 49 text

Princípio da Inversão da Dependência Dependency Inversion Principle

Slide 50

Slide 50 text

"Dependa de uma abstração e não de uma implementação."

Slide 51

Slide 51 text

Violação.

Slide 52

Slide 52 text

// 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. } }

Slide 53

Slide 53 text

Solução.

Slide 54

Slide 54 text

// 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. } }

Slide 55

Slide 55 text

No content