"TDD te hace escribir código más desacoplado, lo cual mejora el diseño del sistema."
-- ✍️ Robert C. Martin (Uncle Bob)
Aprender algo es costoso, incluirlo en tu rutina lo es aún más. Tenemos que visualizar el objetivo para motivarnos. E ir paso a paso para no desmotivarnos.
Venga, vamos a continuar con nuestro micro sistema bancario según vimos en la introducción a TDD.
Test first
Supongamos que nos piden que el sistema sea capaza de obtener un balance a partir de transacciones anteriores.
FEATURE: a BankClient account
As_a: high level service
I_want_to: have a class where deposit money
In_order_to: accumulate several amounts of money for MUCH later
Pues empezamos por especificar nuestros deseos: un método llamado getBalance
estaría bien.
describe('GIVEN: a calculate balance function', () => {
test('WHEN I make a deposit of 10 THEN any new instance should returns the running balance of 10', () => {
const inputSut = new BankClient();
const input = 10;
inputSut.deposit(input);
const sut = new BankClient();
const actual = sut.getBalance();
const expected = 10;
expect(actual).toEqual(expected);
});
});
Con esto podemos empezar, obviamente habría que incluir más casos. Pero tenemos la idea.
Better implementation
La implementación en la clase BankClient
no es para el premio Turing de informática; pero tiene algo implícitamente bueno: Se ha creado un método, se ha nombrado según el uso esperado y usando el código ya hecho, como la propiedad this.balance
.
getBalance() {
return this.balance;
}
Dependencias
Recuerda que nos piden que las transacciones se persistan. De modo que habrá que disponer de funciones que almacenen y que lean transacciones. Pero no nos han dicho nada de su implementación.
Desde luego no queremos incorporar a la prueba el conocimiento de cómo se haga la implementación. Y al mismo tiempo nos interesará mucho mantener las pruebas sencillas, con la menor necesidad de dobles y mocks.
Mejoras paso a paso
Y con esta tranquilidad vamos incorporando funcionalidad. Siempre definiendo antes la prueba. Viendo el fallo por falta de implementación y luego hacerla pasar de manera minimalista.
Refactored
Es el siguiente nivel. Mejorar el código, y si es necesario la prueba, pero manteniendo segura la funcionalidad. Esto produce buenos resultados probados y mejor diseño.
Si el código está desacoplado es muy sencillo mantenerlo. Este es el objetivo del software bien diseñado. Para conseguirlo merece la pena el esfuerzo invertido.