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

Шрифт
Фон

desvantagens dessa abordagem.

3.1. O problema dos números romanos

Casa do Código

3.1

O problema dos números romanos

Numerais romanos foram criados na Roma Antiga e eles foram utilizados em todo o

seu império. Os números eram representados por sete diferentes símbolos, listados

na tabela a seguir.

I, unus, 1, (um)

V, quinque, 5 (cinco)

X, decem, 10 (dez)

L, quinquaginta, 50 (cinquenta)

C, centum, 100 (cem)

D, quingenti, 500 (quinhentos)

M, mille, 1.000 (mil)

Para representar outros números, os romanos combinavam estes símbolos, co-

meçando do algarismo de maior valor e seguindo a regra:

Algarismos de menor ou igual valor à direita são somados ao algarismo de

maior valor;

Algarismos de menor valor à esquerda são subtraídos do algarismo de maior

valor.

Por exemplo, XV representa 15 (10 + 5) e o número XXVIII representa 28 (10 + 10

+ 5 + 1 + 1 + 1). Há ainda uma outra regra: nenhum símbolo pode ser repetido lado

a lado por mais de 3 vezes. Por exemplo, o número 4 é representado pelo número IV

(5 - 1) e não pelo número IIII.

Existem outras regras (especialmente para números maiores, que podem ser li-

das aqui [33]), mas em linhas gerais, este é o problema a ser resolvido. Dado um

numeral romano, o programa deve convertê-lo para o número inteiro correspon-

dente.

20

Casa do Código

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

3.2

O primeiro teste

Conhecendo o problema dos numerais romanos, é possível levantar os diferentes

cenários que precisam ser aceitos pelo algoritmo: um símbolo, dois símbolos iguais,

três símbolos iguais, dois símbolos diferentes do maior para o menor, quatro símbo-

los dois a dois, e assim por diante. Dado todos estes cenários, uns mais simples que

os outros, começaremos pelo mais simples: um único símbolo.

Começando pelo teste deve entender o símbolo I. A classe responsável pela con-

versão pode ser chamada, por exemplo, de ConversorDeNumeroRomano, e o método

converte(), recebendo uma String com o numeral romano e devolvendo o valor in-

teiro representado por aquele número:

[TestFixture]

public class ConversorDeNumeroRomanoTest

{

[Test]

public void DeveEntenderOSimboloI()

{

ConversorDeNumeroRomano romano = new ConversorDeNumeroRomano();

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

Assert.AreEqual(1, numero);

}

}

Veja que nesse momento, esse código não compila; a classe ConversorDeNume-

roRomano, bem como o método Converte() não existem. Para resolver o erro de

compilação, é necessário criar classe, mesmo que sem uma implementação real:

public class ConversorDeNumeroRomano

{

public int Converte(string numeroEmRomano)

{

return 0;

}

}

21

3.2. O primeiro teste

Casa do Código

De volta ao teste, ele agora compila. Ao executá-lo, o teste falha. Mas não há pro-

blema; isso já era esperado. Para fazê-lo passar, introduziremos ainda uma segunda

regra: o código escrito deve ser sempre o mais simples possível.

Com essa regra em mente, o código mais simples que fará o teste passar é fazer

simplesmente o método converte() retornar o número 1:

public int Converte(string numeroEmRomano)

{

return 1;

}

Desenvolvedores, muito provavelmente, não ficarão felizes com essa implemen-

tação, afinal ela funciona apenas para um caso. Mas isso não é problema, afinal a

implementação não está pronta; ainda estamos trabalhando nela.

Um próximo cenário seria o símbolo V. Nesse caso, o algoritmo deve retornar 5.

Novamente começando pelo teste:

[Test]

public void DeveEntenderOSimboloV()

{

ConversorDeNumeroRomano romano = new ConversorDeNumeroRomano();

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

Assert.AreEqual(5, numero);

}

Esse teste também falha. Novamente faremos a implementação mais simples que

resolverá o problema. Podemos, por exemplo, fazer com que o método converte()

verifique o conteúdo do número a ser convertido: se o valor for I, o método retorna 1; se o valor for V, o método retorna 5:

public int Converte(string numeroEmRomano)

{

if(numeroEmRomano.Equals("I")) return 1;

else if(numeroEmRomano.Equals("V")) return 5;

return 0;

}

Os testes passam (os dois que temos). Poderíamos repetir o mesmo teste e a

mesma implementação para os símbolos que faltam (X, L, C, M, ...). Mas nesse mo-

mento, já temos uma primeira definição sobre nosso algoritmo: quando o numeral

romano possui apenas um símbolo, basta devolvermos o inteiro associado a ele.

22

Casa do Código

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

Ao invés de escrever um monte de ifs para cada símbolo, é possível usar um

switch, que corresponde melhor ao nosso cenário. Melhorando ainda mais, ao invés

do switch, é possível guardar os símbolos em uma tabela, ou no C#, em um mapa

entre o algarismo e o inteiro correspondente à ele. Sabendo disso, vamos nesse mo-

mento alterar o código para refletir a solução:

public class ConversorDeNumeroRomano

{

private static Dictionary<string, int> tabela =

new Dictionary<string, int>() {

{"I", 1},

{"V", 5},

{"X", 10},

{"L", 50},

{"C", 100},

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

0
Шрифт
Фон

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