String Calculator

Introducción

Esta es la tercera parada en la ruta de aprendizaje de Test-Driven Development. A estas alturas, deberías estar razonablemente familiarizado con los conceptos de " red, green, refactor" y "baby steps". Si no es así, consulta las katas anteriores de este tema: FizzBuzz y Año bisiesto.

Esta kata ofrece más práctica en el diseño de software característica por característica - una parte importante de los procesos de desarrollo Agile - utilizando TDD. Cada vez que añadas una nueva característica, tendrás que adaptar tu algoritmo mediante refactorización para que soporte el nuevo comportamiento.

Las reglas de esta kata se hacen cada vez más complejas. Es recomendable abordarla añadiendo una regla a la vez. Intenta no mirar hacia delante: imagina que las reglas hubieran llegado en sesiones informativas separadas repartidas a lo largo de un proyecto de seis meses.

Instrucciones

Paso 1: Calculadora sencilla

Crea una String calculator sencilla con un solo método:

class StringCalculator {
int Add(string numbers);
}

 

El método puede tomar 1 o 2 números separados por comas, y devolverá su suma.

El método devuelve 0 cuando se le pasa la cadena vacía. Ejemplo:

Add("") // 0
Add("4") // 4
Add("1,2") // 3

 

Empieza con el test case más sencillo de una cadena vacía y sigue con uno y dos números.

Paso 2: Tamaño arbitrario de los números

Permite que el método Add maneje una cantidad desconocida de números.

Ejemplo:

Add("1,2,3,4,5,6,7,8,9") // 45

Paso 3: Separador de líneas nuevas

Permite que el método Add reconozca como separadores tanto las nuevas líneas como las comas. Los dos tipos de separadores pueden utilizarse indistintamente.

NB: Céntrate en el camino feliz - ya que esto no es código de producción, no pasa nada si el código se bloquea si se le da un input no válido (e.g. "1,\n2").

Ejemplo:

Add("1\n2,3") // 6

Paso 4: Separadores personalizados

Admite de forma opcional separadores personalizados. Para cambiar el separador, el principio de la cadena contendrá una línea separada con el siguiente aspecto: “//<separator>\n<numbers>”

Ejemplo:

Add("//;\n1;2") // 3

 

Ten en cuenta que todos los escenarios existentes deberían seguir siendo compatibles.

Paso 5: Rechazar los negativos

Llamar a Add con un número negativo lanzará una excepción negatives not allowed, y el negativo que se ha pasado.

Si hay varios negativos, muéstralos todos en el mensaje de excepción.

Ejemplo:

Add("1,-2,-3") // error: negatives not allowed: -2 -3

Paso 6: Ignorar los números superiores a 1000

Los números superiores a 1000 deben ignorarse.

Ejemplo:

Add("1001, 2") // 2

Paso 7: Separadores de longitud arbitraria

Los separadores pueden tener cualquier longitud si van rodeados de corchetes.

Ejemplo:

Add("//[***]\n1***2***3") // 6

Paso 8: Separadores múltiples de un solo carácter

Permite múltiples separadores de un solo carácter como estos: “//[delim1][delim2]\n”

Ejemplo:

Add("//[*][%]\n1*2%3") // 6

Paso 9: Separadores múltiples de mayor longitud

Gestiona separadores múltiples con cualquier longitud de carácter.

Ejemplo:

Add("//[foo][bar]\n1foo2bar3") // 6

 

Crédito: Roy Osherove

Consejos

Si añades un nuevo test y luego te das cuenta de que vas a necesitar un gran cambio en el código para que pase, puedes retirar el test (borrándolo o marcándolo como ignorado) y refactorizar el código hasta que esté listo para el nuevo test y la nueva funcionalidad.

De hecho, es una forma muy eficaz de trabajar: sólo hay que tener cuidado de no añadir nuevas funcionalidades involuntariamente mientras se refactoriza.

Soluciones