IF BOM É IF MORTO
Refatoração de código com o pattern Strategy
Jackson Veroneze - jackson@jacksonveroneze.com
Mario Mendonça - mario.mendonca@gmail.com
Cenário Imagine que o Governo possua um sistema que calcula
o valor dos impostos de receitas vindas de diversas
fontes.
Codificação
public class CalculadorDeImpostos {
public double calculaImposto(double receita, String
tipoDeImposto) {
double imposto = 0;
if (tipoDeImposto.equals("IPI"))
imposto = receita * 0.15;
else if (tipoDeImposto.equals("ISS"))
imposto = receita * 0.06;
else if (tipoDeImposto.equals("ICMS"))
imposto = receita * 0.08;
return imposto;
}
}
Problema Enorme quantidade de IFs que a classe possui.
Tende a crescer à medida que novos impostos vão
sendo criados, gerando mais complexidade ao código.
Problema
public class CalculadorDeImpostos {
public double calculaImposto(double receita, String tipoDeImposto) {
double imposto = 0;
if (tipoDeImposto.equals("IPI"))
imposto = receita * 0.15;
else if (tipoDeImposto.equals("ISS"))
imposto = receita * 0.06;
else if (tipoDeImposto.equals("ICMS"))
imposto = receita * 0.08;
else if (tipoDeImposto.equals("IR"))
imposto = receita * 0.03;
else if (tipoDeImposto.equals("IOF"))
imposto = receita * 0.02;
else if (tipoDeImposto.equals("IPVA"))
imposto = receita * 0.05;
else if (tipoDeImposto.equals("CPMF"))
imposto = receita * 0.03;
else if (tipoDeImposto.equals("IPTU"))
imposto = receita * 0.07;
else if (tipoDeImposto.equals("ITR"))
imposto = receita * 0.07;
return imposto;
}
}
IF BOM É IF MORTO
Questionamento - "Mas se não posso usar nem IF, nem Switch-Case,
nem nada parecido, COMO é que vou tratar isso?"
Strategy, a salvação
SOLUÇÃO
SOLUÇÃO O padrão Strategy permite que você crie novos objetos
(ex: "IPTU", "IPVA", etc) de um mesmo grupo (ex:
"Impostos"), sem alterar a classe com a qual opera (ex:
"Calculador de Impostos").
1º passo public interface Imposto {
double calculaImposto(double receita);
}
2º passo
public class IPI implements Imposto {
public double calculaImposto(double receita) {
return receita * 0.15;
}
}
public class ISS implements Imposto {
public double calculaImposto(double receita) {
return receita * 0.06;
}
}
public class ICMS implements Imposto {
public double calculaImposto(double receita) {
return receita * 0.08;
}
}
3º passo public class CalculadorDeImpostos {
public double calculaImposto(double receita,
Imposto imposto) {
return imposto.calculaImposto(receita);
}
}
Teste do padrão
package br.eti.arquiteturacomputacional;
public class RealizaBalancoFinanceiro {
public static void main(String[] args) {
CalculadorDeImpostos calculador = new CalculadorDeImpostos();
//Calcula o imposto ICMS
Imposto icms = new ICMS();
double impostoAReceber = calculador.calculaImposto(500, icms);
System.out.println("ICMS de 500 = " + impostoAReceber);
//Calcula o imposto ISS
Imposto iss = new ISS();
impostoAReceber = calculador.calculaImposto(500, iss);
System.out.println("ISS de 500 = " + impostoAReceber);
}
}
Conclusão Podemos criar novos impostos, sem alterar qualquer
código existente. Esse padrão chama-se Strategy
porque entregamos uma estratégia (um imposto
especializado) para um contexto
(CalculadorDeImpostos).
if ($iPanamnese->getDeTpresposta() == 'O') {
$opcoes = explode(';', $iPanamnese->getDeOpcoes());
for ($x = 0; $x < count($opcoes); $x++)
$vlr[$x] = $opcoes[($x)];
$resposta = isset($values['campo' . $iPanamnese->getId()]) ?
vlr[$values['campo' . $iPanamnese->getId()]] : '';
$ranamneseI->setDeResposta($resposta);
} elseif ($iPanamnese->getDeTpresposta() == 'M') {
$opcoes = explode(';', $iPanamnese->getDeOpcoes());
for ($x = 0; $x < count($opcoes); $x++)
$vlr[$x] = $opcoes[($x)];
$resp = '0';
if (isset($values['campo' . $iPanamnese->getId()])) {
$tmp = $values['campo' . $iPanamnese->getId()];
if (is_array($tmp)) {
foreach ($tmp as $opcao)
$resp .= $vlr[$opcao] . ';';
$resp = substr($resp, 0, strlen($resp) - 1);
} else {
$resp = 'NDA';
}
}
$ranamneseI->setDeResposta($resp);
} elseif ($iPanamnese->getDeTpresposta() == 'R') {
$resp = '0';
if (isset($values['campo' . $iPanamnese->getId()])) {
$opcoes = explode(';', $iPanamnese->getDeOpcoes());
if (isset($values['campo' . $iPanamnese->getId()])) {
$resp = $opcoes[$values['campo' . $iPanamnese->getId()]];
}
}
$ranamneseI->setDeResposta($resp);
} elseif ($iPanamnese->getDeTpresposta() == 'V' || $iPanamnese->getDeTpresposta() == 'D' ||
$iPanamnese->getDeTpresposta() == 'N') {
if (isset($values['campo' . $iPanamnese->getId()])) {
$ranamneseI->setDeResposta($values['campo' . $iPanamnese->getId()]);
}
}
Referências http://www.arquiteturacomputacional.eti.br/2013/02/p
adrao-de-projeto-strategy.html
http://marconems.blogspot.com.br/2010/06/if-bom-e-
if-morto.html

If bom é if morto

  • 1.
    IF BOM ÉIF MORTO Refatoração de código com o pattern Strategy Jackson Veroneze - jackson@jacksonveroneze.com Mario Mendonça - mario.mendonca@gmail.com
  • 2.
    Cenário Imagine queo Governo possua um sistema que calcula o valor dos impostos de receitas vindas de diversas fontes.
  • 3.
    Codificação public class CalculadorDeImpostos{ public double calculaImposto(double receita, String tipoDeImposto) { double imposto = 0; if (tipoDeImposto.equals("IPI")) imposto = receita * 0.15; else if (tipoDeImposto.equals("ISS")) imposto = receita * 0.06; else if (tipoDeImposto.equals("ICMS")) imposto = receita * 0.08; return imposto; } }
  • 4.
    Problema Enorme quantidadede IFs que a classe possui. Tende a crescer à medida que novos impostos vão sendo criados, gerando mais complexidade ao código.
  • 5.
    Problema public class CalculadorDeImpostos{ public double calculaImposto(double receita, String tipoDeImposto) { double imposto = 0; if (tipoDeImposto.equals("IPI")) imposto = receita * 0.15; else if (tipoDeImposto.equals("ISS")) imposto = receita * 0.06; else if (tipoDeImposto.equals("ICMS")) imposto = receita * 0.08; else if (tipoDeImposto.equals("IR")) imposto = receita * 0.03; else if (tipoDeImposto.equals("IOF")) imposto = receita * 0.02; else if (tipoDeImposto.equals("IPVA")) imposto = receita * 0.05; else if (tipoDeImposto.equals("CPMF")) imposto = receita * 0.03; else if (tipoDeImposto.equals("IPTU")) imposto = receita * 0.07; else if (tipoDeImposto.equals("ITR")) imposto = receita * 0.07; return imposto; } }
  • 6.
    IF BOM ÉIF MORTO
  • 7.
    Questionamento - "Masse não posso usar nem IF, nem Switch-Case, nem nada parecido, COMO é que vou tratar isso?"
  • 8.
  • 9.
  • 10.
    SOLUÇÃO O padrãoStrategy permite que você crie novos objetos (ex: "IPTU", "IPVA", etc) de um mesmo grupo (ex: "Impostos"), sem alterar a classe com a qual opera (ex: "Calculador de Impostos").
  • 11.
    1º passo publicinterface Imposto { double calculaImposto(double receita); }
  • 12.
    2º passo public classIPI implements Imposto { public double calculaImposto(double receita) { return receita * 0.15; } } public class ISS implements Imposto { public double calculaImposto(double receita) { return receita * 0.06; } } public class ICMS implements Imposto { public double calculaImposto(double receita) { return receita * 0.08; } }
  • 13.
    3º passo publicclass CalculadorDeImpostos { public double calculaImposto(double receita, Imposto imposto) { return imposto.calculaImposto(receita); } }
  • 14.
    Teste do padrão packagebr.eti.arquiteturacomputacional; public class RealizaBalancoFinanceiro { public static void main(String[] args) { CalculadorDeImpostos calculador = new CalculadorDeImpostos(); //Calcula o imposto ICMS Imposto icms = new ICMS(); double impostoAReceber = calculador.calculaImposto(500, icms); System.out.println("ICMS de 500 = " + impostoAReceber); //Calcula o imposto ISS Imposto iss = new ISS(); impostoAReceber = calculador.calculaImposto(500, iss); System.out.println("ISS de 500 = " + impostoAReceber); } }
  • 15.
    Conclusão Podemos criarnovos impostos, sem alterar qualquer código existente. Esse padrão chama-se Strategy porque entregamos uma estratégia (um imposto especializado) para um contexto (CalculadorDeImpostos).
  • 16.
    if ($iPanamnese->getDeTpresposta() =='O') { $opcoes = explode(';', $iPanamnese->getDeOpcoes()); for ($x = 0; $x < count($opcoes); $x++) $vlr[$x] = $opcoes[($x)]; $resposta = isset($values['campo' . $iPanamnese->getId()]) ? vlr[$values['campo' . $iPanamnese->getId()]] : ''; $ranamneseI->setDeResposta($resposta); } elseif ($iPanamnese->getDeTpresposta() == 'M') { $opcoes = explode(';', $iPanamnese->getDeOpcoes()); for ($x = 0; $x < count($opcoes); $x++) $vlr[$x] = $opcoes[($x)]; $resp = '0'; if (isset($values['campo' . $iPanamnese->getId()])) { $tmp = $values['campo' . $iPanamnese->getId()]; if (is_array($tmp)) { foreach ($tmp as $opcao) $resp .= $vlr[$opcao] . ';'; $resp = substr($resp, 0, strlen($resp) - 1); } else { $resp = 'NDA'; } } $ranamneseI->setDeResposta($resp); } elseif ($iPanamnese->getDeTpresposta() == 'R') { $resp = '0'; if (isset($values['campo' . $iPanamnese->getId()])) { $opcoes = explode(';', $iPanamnese->getDeOpcoes()); if (isset($values['campo' . $iPanamnese->getId()])) { $resp = $opcoes[$values['campo' . $iPanamnese->getId()]]; } } $ranamneseI->setDeResposta($resp); } elseif ($iPanamnese->getDeTpresposta() == 'V' || $iPanamnese->getDeTpresposta() == 'D' || $iPanamnese->getDeTpresposta() == 'N') { if (isset($values['campo' . $iPanamnese->getId()])) { $ranamneseI->setDeResposta($values['campo' . $iPanamnese->getId()]); } }
  • 17.