Aniche Mauricio - Test-Driven Development: Teste e Design no Mundo Real com .NET стр 10.

Шрифт
Фон

{"D", 500},

{"M", 1000}

};

public int Converte(string numeroEmRomano)

{

return tabela[numeroEmRomano];

}

}

Ambos os testes continuam passando. Passaremos agora para um segundo ce-

nário: dois símbolos em sequência, como por exemplo, II ou XX. Começando

novamente pelo teste, temos:

[Test]

public void DeveEntenderDoisSimbolosComoII()

{

ConversorDeNumeroRomano romano = new ConversorDeNumeroRomano();

int numero = romano.Converte("II");

Assert.AreEqual(2, numero);

}

Para fazer o teste passar de maneira simples, é possível simplesmente adicionar

os símbolos II na tabela:

23

3.2. O primeiro teste

Casa do Código

private static Dictionary<string, int> tabela =

new Dictionary<string, int>() {

{"I", 1},

{"II", 2},

{"V", 5},

{"X", 10},

{"L", 50},

{"C", 100},

{"D", 500},

{"M", 1000}

};

O teste passa. Mas, apesar de simples, essa não parece uma boa ideia de imple-

mentação: seria necessário incluir todos os possíveis símbolos nessa tabela, o que

não faz sentido.

É hora de refatorar esse código novamente. Uma possível solução seria iterar em

cada um dos símbolos no numeral romano e acumular seu valor; ao final, retorna

o valor acumulado. Para isso, é necessário mudar a tabela para guardar somente

os símbolos principais da numeração romana. Uma possível implementação deste

algoritmo seria:

private static Dictionary<string, int> tabela =

new Dictionary<char, int>() {

{'I', 1},

{'V', 5},

{'X', 10},

{'L', 50},

{'C', 100},

{'D', 500},

{'M', 1000}

};

public int Converte(string numeroEmRomano)

{

int acumulador = 0;

for(int i = 0; i < numeroEmRomano.Length; i++)

{

acumulador += tabela[numeroEmRomano[i]];

}

24

Casa do Código

Capítulo 3. Introdução ao Test-Driven Development

return acumulador;

}

De String para Char?

Repare que o tipo da chave no mapa mudou de String para Character.

Como o algoritmo captura letra por letra da variável numeroEmRomano,

usando o método charAt(), que devolve um char, a busca do símbolo

fica mais direta.

Os três testes continuam passando. E, dessa forma, resolvemos o problema de

dois símbolos iguais em seguida. O próximo cenário são quatro símbolos, dois a

dois, como por exemplo, XXII, que deve resultar em 22. O teste:

[Test]

public void DeveEntenderQuatroSimbolosDoisADoisComoXXII()

{

ConversorDeNumeroRomano romano = new ConversorDeNumeroRomano();

int numero = romano.Converte("XXII");

Assert.AreEqual(22, numero);

}

Esse teste já passa sem que precisemos fazer qualquer alteração. O algoritmo

existente até então já resolve o problema. Vamos então para o próximo cenário: nú-

meros como IV ou IX, onde não basta apenas somar os símbolos existentes.

Novamente, começando pelo teste:

[Test]

public void DeveEntenderNumerosComoIX()

{

ConversorDeNumeroRomano romano = new ConversorDeNumeroRomano();

int numero = romano.Converte("IX");

Assert.AreEqual(9, numero);

}

Para fazer esse teste passar, é necessário pensar um pouco melhor sobre o pro-

blema. Repare que os símbolos em um numeral romano, da direita para a esquerda,

sempre crescem. Quando um número a esquerda é menor do que seu vizinho a di-

reita, esse número deve então ser subtraído ao invés de somado no

acumulador. Esse

algoritmo, em código:

25

3.2. O primeiro teste

Casa do Código

public int Converte(String numeroEmRomano)

{

int acumulador = 0;

int ultimoVizinhoDaDireita = 0;

for(int i = numeroEmRomano.Length - 1; i >= 0; i--)

{

// pega o inteiro referente ao simbolo atual

int atual = tabela[numeroEmRomano[i]];

// se o da direita for menor, o multiplicaremos

// por -1 para torná-lo negativo

int multiplicador = 1;

if(atual < ultimoVizinhoDaDireita) multiplicador = -1;

acumulador +=

tabela[numeroEmRomano[i]] * multiplicador;

// atualiza o vizinho da direita

ultimoVizinhoDaDireita = atual;

}

return acumulador;

}

Os testes agora passam. Mas veja, existe código repetido ali. Na linha em que

o acumulador é somado com o valor atual, tabela[numeroEmRomano[i]] pode ser

substituído pela variável atual. Melhorando o código, temos:

acumulador += atual * multiplicador;

A refatoração foi feita com sucesso, já que os testes continuam passando. Ao

próximo cenário: numeral romano que contenha tanto números invertidos, como

IV, e dois símbolos lado a lado, como XX. Por exemplo, o número XXIV, que

representa o número 24.

Começando pelo teste:

[Test]

public void DeveEntenderNumerosComplexosComoXXIV()

{

ConversorDeNumeroRomano romano = new ConversorDeNumeroRomano();

int numero = romano.Converte("XXIV");

26

Casa do Código

Capítulo 3. Introdução ao Test-Driven Development

Assert.AreEqual(24, numero);

}

Esse teste já passa; o algoritmo criado até então já atende o cenário do teste.

Ainda há outros cenários que poderiam ser testados, mas já fizemos o suficiente para

discutir sobre o assunto.

3.3

Refletindo sobre o assunto

De maneira mais abstrata, o ciclo que foi repetido ao longo do processo de desen-

volvimento da classe acima foi:

Escrevemos um teste de unidade para uma nova funcionalidade;

Ваша оценка очень важна

0
Шрифт
Фон

Помогите Вашим друзьям узнать о библиотеке