Skip to content

Commit

Permalink
Add new article
Browse files Browse the repository at this point in the history
  • Loading branch information
carlos-talavera committed Oct 20, 2024
1 parent 059f8cd commit ba0de01
Show file tree
Hide file tree
Showing 3 changed files with 202 additions and 8 deletions.
16 changes: 8 additions & 8 deletions app/[locale]/tag-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
"frontend": 1,
"backend": 2,
"fullstack": 1,
"javascript": 10,
"typescript": 10,
"testing": 8,
"tdd": 7,
"javascript": 11,
"typescript": 11,
"testing": 9,
"tdd": 8,
"nextjs": 2,
"laravel": 3,
"php": 3,
Expand All @@ -17,10 +17,10 @@
"frontend": 1,
"backend": 2,
"fullstack": 1,
"javascript": 10,
"typescript": 10,
"testing": 8,
"tdd": 7,
"javascript": 11,
"typescript": 11,
"testing": 9,
"tdd": 8,
"nextjs": 2,
"laravel": 3,
"php": 3,
Expand Down
97 changes: 97 additions & 0 deletions data/blog/en/katas-sustainable-testing-ts/kata-08-fibonacci.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
---
title: "Kata 08 in TypeScript: Fibonacci"
series:
order: 9
title: "Sustainable Testing Katas in TypeScript"
date: '2024/10/19'
lastmod: '2024/10/19'
language: en
tags: ['testing', 'tdd', 'javascript', 'typescript']
authors: ['default']
draft: false
featured: false
summary: En este artículo de la serie "Sustainable Testing Katas in TypeScript", analizaremos la creación de una función que calcula el enésimo número de Fibonacci usando TDD y Jest.
---

> The katas of this series are proposed exercises in the excellent course [Testing Sostenible con TypeScript](https://academy.softwarecrafters.io/p/curso) by Miguel A. Gómez and Carlos Blé
## Introduction

The [Fibonacci sequence](https://www.cuemath.com/numbers/fibonacci-sequence/) is a fascinating mathematical sequence, with applications that range from biology to informatics. In this article, we will explore how to apply TDD to implement a function that calculates the nth [Fibonacci](https://www.thoughtco.com/leonardo-pisano-fibonacci-biography-2312397) number. We will see how the development patterns known as [Green Bar Patterns](https://www.tddbuddy.com/references/green-bar-patterns.html), proposed by [Kent Beck](https://londonspeakerbureau.com/speaker-profile/kent-beck/), guide us to an effective solution.

<TOCInline toc={props.toc} exclude="Introduction" locale={props.locale} asDisclosure />

## Fibonacci Sequence

The Fibonacci sequence starts with the numbers 0 and 1, and each subsequent number is the sum of the previous two: 0, 1, 1, 2, 3, 5, 8, and so on. This sequence, popularized in Europe by the Italian mathematician Fibonacci, is a classic example of exponential growth and it is found in various areas of study.

Our goal is to build a `fibonacci` function which, given an integer number `n`, returns the nth Fibonacci number. We use TDD not only to ensure that our implementation is correct, but also to illustrate the `Green Bar Patterns`.

## Green Bar Patterns

To keep the article brief, we will see the implementations and the tests will be understood from the examples.

### Fake Implementation

We start with a fake implementation to make a test pass quickly. For example, for `fibonacci(0)`, we simply return 0.

```ts
function fibonacci(number: number) {
return 0;
}
```

### Triangulation

By adding more test cases, we use triangulation to refine our implementation. This pattern helps us to generalize the solution from specific cases. For example, we handle `fibonacci(1)` by returning 1 and then we verify that `fibonacci(2)` is the sum of the previous two.

```ts
function fibonacci(number: number) {
if (number === 0) return 0;
return 1;
}
```

This would work for `fibonacci(2)` because:

`fibonacci(2)` $=$ `1`

`fibonacci(2)` $=$ `fibonacci(1)` $+$ `fibonacci(0)` $=$ `1` $+$ `0` $=$ `1`

### Obvious Implementation

As we add more cases, we move on to a recursive implementation that reflects the mathematical definition of Fibonacci. This allows us to handle any number in the sequence.

```ts
export function fibonacci(number: number) {
if (number === 0) return 0;
if (number === 1) return 1;
return fibonacci(number - 1) + fibonacci(number - 2);
}
```

It may seem odd that the obvious implementation is not necessarily of one line or very short, but in this case, by implementing a function that follows a mathematical definition, it is possible to say that it is trivial to translate this definition into a function.

It is also important to mention that if we know the obvious implementation, we have to use it and there is no need for us to go through fake implementation or triangulation.

### One to Many

This pattern is the last one. It doesn't apply here, since it is used when we have data collections and we start from the case of a single element and at the end we generalize for many. But it is good for us to know it because by understanding it, it is obvious that the solution to a problem of this type is easier to reach if we take a specific case to build the general case. This is what is known in logic as **induction**.

## Challenges Encountered

- **Recursion Efficiency.** Recursion is clear and direct, but it can be inefficient for big numbers because of redundant calculations. Considering memoization or an iterative implementation is key to improve performance.

- **Exhaustive Test Coverage.** Ensuring that all variations, from the base cases to higher numbers, are covered by tests is crucial for code robustness.

- **Continuous Refactoring.** Keeping the code clean and modular is essential. It is common that we initially place implementations and tests in the same file, so this process involves moving the `fibonacci` function out of the file containing the tests, in addition to optimizing the code structure.

## Link to GitHub repository

You can find this kata, and the rest of them, [here](https://github.com/carlos-talavera/katas-sustainable-testing-ts).

## Conclusion

This exercise of implementing the Fibonacci sequence using TDD provides us a valuable opportunity to practice development patterns and face common programming challenges. Through the fake implementation, triangulation, the obvious implementation and the one-to-many approach, we not only achieve the right solution, but also refine our ability to think in a systematic and disciplined way. That's why by applying these patterns and practices, we can address complex problems with confidence and clarity.

I hope this article has helped you to understand these patterns. If you have a question or want to share something, leave it in the comments :)
97 changes: 97 additions & 0 deletions data/blog/es/katas-sustainable-testing-ts/kata-08-fibonacci.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
---
title: "Kata 08 con TypeScript: Fibonacci"
series:
order: 9
title: "Katas Testing Sostenible con TypeScript"
date: '2024/10/19'
lastmod: '2024/10/19'
language: es
tags: ['testing', 'tdd', 'javascript', 'typescript']
authors: ['default']
draft: false
featured: false
summary: En este artículo de la serie "Katas Testing Sostenible con TypeScript", analizaremos la creación de una función que calcula el enésimo número de Fibonacci usando TDD y Jest.
---

> Las katas de esta serie son ejercicios propuestos en el excelente curso [Testing Sostenible con TypeScript](https://academy.softwarecrafters.io/p/curso) de Miguel A. Gómez y Carlos Blé
## Introducción

La [serie de Fibonacci](https://www.cuemath.com/numbers/fibonacci-sequence/) es una sucesión matemática fascinante, con aplicaciones que abarcan desde la biología hasta la informática. En este artículo, exploraremos cómo aplicar TDD para implementar una función que calcula el enésimo número de [Fibonacci](https://www.thoughtco.com/leonardo-pisano-fibonacci-biography-2312397). Veremos cómo los patrones de desarrollo conocidos como [Green Bar Patterns](https://www.tddbuddy.com/references/green-bar-patterns.html), propuestos por [Kent Beck](https://londonspeakerbureau.com/speaker-profile/kent-beck/), nos guían hacia una solución efectiva.

<TOCInline toc={props.toc} exclude="Introducción" locale={props.locale} asDisclosure />

## Serie de Fibonacci

La serie de Fibonacci comienza con los números 0 y 1, y cada número subsiguiente es la suma de los dos anteriores: 0, 1, 1, 2, 3, 5, 8, y así sucesivamente. Esta secuencia, popularizada en Europa por el matemático italiano Fibonacci, es un ejemplo clásico de crecimiento exponencial y se encuentra en diversas áreas de estudio.

Nuestro objetivo es construir una función `fibonacci` que, dado un número entero `n`, devuelva el enésimo número de Fibonacci. Utilizamos TDD no solo para asegurar que nuestra implementación es correcta, sino también para ilustrar los `Green Bar Patterns`.

## Green Bar Patterns

Para mantener el artículo breve, veremos las implementaciones y las pruebas se sobreentenderán a partir de los ejemplos.

### Implementación Fake

Comenzamos con una implementación falsa para hacer que una prueba pase rápidamente. Por ejemplo, para `fibonacci(0)`, simplemente devolvemos 0.

```ts
function fibonacci(number: number) {
return 0;
}
```

### Triangulación

Al agregar más casos de prueba, utilizamos la triangulación para refinar nuestra implementación. Este patrón nos ayuda a generalizar la solución a partir de casos específicos. Por ejemplo, manejamos `fibonacci(1)` devolviendo 1 y luego verificamos que `fibonacci(2)` sea la suma de los dos anteriores.

```ts
function fibonacci(number: number) {
if (number === 0) return 0;
return 1;
}
```

Esto funcionaría para `fibonacci(2)` porque:

`fibonacci(2)` $=$ `1`

`fibonacci(2)` $=$ `fibonacci(1)` $+$ `fibonacci(0)` $=$ `1` $+$ `0` $=$ `1`

### Implementación Obvia

A medida que añadimos más casos, pasamos a una implementación recursiva que refleja la definición matemática de Fibonacci. Esto nos permite manejar cualquier número en la secuencia.

```ts
export function fibonacci(number: number) {
if (number === 0) return 0;
if (number === 1) return 1;
return fibonacci(number - 1) + fibonacci(number - 2);
}
```

Puede parecer extraño que la implementación obvia no sea necesariamente de una línea o muy corta, pero en este caso, al implementar una función que sigue una definición matemática, es posible decir que es trivial plasmar esta definición en una función.

De igual manera es importante mencionar que si conocemos la implementación obvia, hay que usarla y no hay necesidad de pasar por la implementación fake ni la triangulación.

### Uno a Muchos

Este patrón es el último. No aplica aquí, pues se utiliza cuando tenemos colecciones de datos y partimos del caso de un solo elemento y al final generalizamos para muchos. Pero es bueno conocerlo porque al entenderlo, resulta obvio que la solución de un problema de este tipo sea más fácil de alcanzar si tomamos un caso específico para construir el caso general. Esto es lo que se conoce en lógica como **inducción**.

## Retos Encontrados

- **Eficiencia de la Recursión.** La recursión es clara y directa, pero puede ser ineficiente para números grandes debido a cálculos redundantes. Considerar la memoización o una implementación iterativa es clave para mejorar el rendimiento.

- **Cobertura Exhaustiva de Pruebas.** Asegurar que todas las variaciones, desde los casos base hasta números más altos, estén cubiertas por pruebas es crucial para la robustez del código.

- **Refactorización Continua.** Mantener el código limpio y modular es esencial. Es común que inicialmente coloquemos implementaciones y pruebas en el mismo archivo, por lo que este proceso incluye mover la función `fibonacci` fuera del archivo que contiene las pruebas, además de optimizar la estructura del código.

## Enlace al repositorio de GitHub

Puedes encontrar esta kata, y el resto de ellas, [aquí](https://github.com/carlos-talavera/katas-sustainable-testing-ts).

## Conclusión

El ejercicio de implementar la serie de Fibonacci utilizando TDD nos proporciona una valiosa oportunidad para practicar patrones de desarrollo y enfrentar desafíos comunes en la programación. A través de la implementación fake, la triangulación, la implementación obvia y el enfoque de uno a muchos, no solo logramos una solución correcta, sino que también refinamos nuestra habilidad para pensar de manera sistemática y disciplinada. Es por eso que al aplicar estos patrones y prácticas, podemos abordar problemas complejos con confianza y claridad.

Espero que este artículo te haya ayudado a entender estos patrones. Si tienes alguna duda o quieres compartir algo, déjalo en los comentarios :)

0 comments on commit ba0de01

Please sign in to comment.