nosso sistema esta sendo testado? Nao! TDD nao diz respeito apenas a teste, TDD e tambem uma tecnica design!Segundo Bob Martin, The act of writing a unit test is more an act of design than of verification. It is also more an act of documentation than of verification. TDD pode encaminhar a um nivel que possibilite um codigo mais modularizado, flexivel e extensivel. Este efeito surge devido a metodologia requerer que os desenvolvedores pensem no software em pequenas unidades que podem ser re-escritas, desenvolvidas e testadas independemente e integradas depois. Isto implica menores e mais classes, evitando o acoplamento e permitindo interfaces mais limpas (Wikipedia). Resumido por Martin Flower, The benefit is that thinking about the test first forces you to think about the interface to the code first. This focus on interface and how you use a class helps you separate interface from implementation.Em um dos workshops que participei, o pessoal do Caelum apresentou de maneira pratica alguns bons exemplos de como o TDD pode nos ajudar a enxergar alguns problemas de design nas nossas aplicacoes. Por exemplo, nos deram o seguinte codigo, o qual e responsavel por calcular salarios dos funcionarios de acordo com seu cargo e salario base:import static br.com.caelum.tdd.exercicio1.Cargo.DBA;import static br.com.caelum.tdd.exercicio1.Cargo.DESENVOLVEDOR;import static br.com.caelum.tdd.exercicio1.Cargo.TESTADOR;public class CalculadoraDeSalario { public double calcula(Funcionario funcionario) { if(DESENVOLVEDOR.equals(funcionario.getCargo())) { return dezOuVintePorCentoDeDescontoNo(funcionario); } if(DBA.equals(funcionario.getCargo()) || TESTADOR.equals(funcionario.getCargo())) { return quinzeOuVinteECincoPorCentoDeDescontoNo(funcionario); } throw new RuntimeException("funcionario invalido"); } private double dezOuVintePorCentoDeDescontoNo(Funcionario funcionario) { if(funcionario.getSalarioBase() > 3000.0) { return funcionario.getSalarioBase() * 0.8; } else { return funcionario.getSalarioBase() * 0.9; } } private double quinzeOuVinteECincoPorCentoDeDescontoNo(Funcionario funcionario) { if(funcionario.getSalarioBase() > 2000.0) { return funcionario.getSalarioBase() * 0.75; } else { return funcionario.getSalarioBase() * 0.85; } }}public enum Cargo { DESENVOLVEDOR, DBA, TESTADOR}Que ja possuia os testes unitarios implementados:public class CalculadoraDeSalarioTests { private CalculadoraDeSalario calculadora; @Before public void setUp() { calculadora = new CalculadoraDeSalario(); } @Test public void deveRetornar4000MenosImpostosDe20PorCentoSeDesenvolvedorGanhaMaisDe3000(){ Funcionario desenvolvedor = umFuncionario(DESENVOLVEDOR, comSalarioBase(4000.0)); double salario = calculadora.calcula(desenvolvedor); assertEquals(4000.0 * 0.8, salario, 0.000001); } @Test public void deveRetornar1000MenosImpostosDe10PorCentoSeDesenvolvedorGanhaMenosDe3000(){ Funcionario desenvolvedor = umFuncionario(DESENVOLVEDOR, comSalarioBase(1000.0)); double salario = calculadora.calcula(desenvolvedor); assertEquals(1000.0 * 0.9, salario, 0.000001); } @Test public void deveRetornar4000MenosImpostosDe25PorCentoSeDBAGanhaMaisDe2000(){ Funcionario dba = umFuncionario(DBA, comSalarioBase(4000.0)); double salario = calculadora.calcula(dba); assertEquals(4000.0 * 0.75, salario, 0.000001); } @Test public void deveRetornar1000MenosImpostosDe15PorCentoSeDBAGanhaMenosDe2000(){ Funcionario dba = umFuncionario(DBA, comSalarioBase(1000.0)); double salario = calculadora.calcula(dba); assertEquals(1000.0 * 0.85, salario, 0.000001); } @Test public void deveRetornar4000MenosImpostosDe25PorCentoSeTestadorGanhaMaisDe2000(){ Funcionario testador = umFuncionario(TESTADOR, comSalarioBase(4000.0)); double salario = calculadora.calcula(testador); assertEquals(4000.0 * 0.75, salario, 0.000001); } @Test public void deveRetornar1000MenosImpostosDe15PorCentoSeTestadorGanhaMenosDe2000(){ Funcionario testador = umFuncionario(TESTADOR, comSalarioBase(1000.0)); double salario = calculadora.calcula(testador); assertEquals(1000.0 * 0.85, salario, 0.000001); } private Funcionario umFuncionario(Cargo cargo, double salario) { Funcionario funcionario = new Funcionario(); funcionario.setNome("Martin Fowler"); funcionario.setSalarioBase(salario); funcionario.setCargo(cargo); return funcionario; } private double comSalarioBase(double salario) { return salario; }}E pediram para que fosse inserido um novo cargo, Gerente, no qual deveria incidir imposto de 20% caso o salario base fosse acima de 5000, ou 15% caso contrario. Como voce implementaria esse novo requisito? 100% dos participantes criaram o novo cargo na enumeracao e adicionaram mais um If na calculadora, solucao simples e rapida! E qual o problema disso?Aumento da complexidade e da complexidade ciclomatica;Proliferacao de if