FizzBuzz Typescript & SOLID Principles
Tags: fizzbuzz, interview, typescript, solid
Published: 2020-05-24 22:30:39

---
title: FizzBuzz Typescript & SOLID Principles
published: true
description: FizzBuzz Typescript & SOLID Principles
tags: #fizzbuzz #interview #typescript #solid
---
**"FizzBuzz"** is a well-known programming assignment, often used as a little test to see if a candidate for a programming job could manage to implement a set of requirements, usually on the spot. The requirements are these:

* Given a list of numbers from 1 to n.
* If a number is divisible by 3 should be replaced with Fizz.
* If a number is divisible by 5 should be replaced with Buzz.
* If a number is divisible by 3 and by 5 should be replaced with FizzBuzz.

Applying these rules, the resulting list would become:

`1, 2, Fizz, 4, Buzz … 13, 14, FizzBuzz, 16, 17 …`

A simple solution often found online could be something like this:

```ts
class FizzBuzz
{
  generate(number: number) {
    let output: string[];
    for (let i = 1; i <= n; i++) {
        output.push(this.getReplacement(i));
    }
    return output;
  }

  getReplacement(number: number): string {
    if (number%3 === 0 && number%5 === 0) return "FizzBuzz";
    if (number%3) return "Fizz";
    if (number%5) return "Buzz";
    else return n;
  }
}

const fizzBuzz = new FizzBuzz();
const result = fizzBuzz.generate(100);
console.log(result.join(", "));
```

The Class above does the job. And solves the problem, BUT... what if we wanted to introduce a new rule? 

For example:

`If a number is divisible by 7 should be replaced with Bazz.`

## FizzBuzz Class and the Open/Closed Principle

If numbers divisible by 7 should one day be replaced with `Bazz`, **it will be impossible to implement this change without actually modifying the code of the FizzBuzz class.**

**Currently the FizzBuzz class is not open for extension, nor closed for modification.** Our current implementation violates the Open/Closed principle

> The **Open/Closed Principle** says that the code should be open for extension but closed for modification. In other words, the code should be organized in such a way that new modules can be added without modifying the existing code.

## FizzBuzz Class and the Singe Responsibility Principle 

> A class should have one, and only one, reason to change.

Our class has two responsibilities, therefore two reasons to change. 
* it generates a list of numbers and 
* it generates replacement for each number based on the FizzBuzz Rules

If we think about it. Every responsibility that a class has... *is a reason to change*.

## Re-designing our Class
How can we make our FizzBuzz class more Flexible? What is likely to change? 

The FizzBuzz rules are liable to change. And if we want to follow the **Open/Closed principle**, we should not need to modify the `FizzBuzz Class` itself.

Lets try to think about the problem we are trying to solve here.

**We want  to generate a list of numbers, replacing certain numbers with strings, based on a flexible set of "rules".**

Lets start by introducing a `RuleInterface`
```ts
interface RuleInterface {
  matches(number: number): boolean;
  getReplacement(): string;
}
```

and lets extract the rules we need to solve the `FizzBuzz` challenge into their own classes and have them implement the `RuleInterface`
```ts
class FizzRule implements RuleInterface {
  matches(number: number): boolean {
    return number % 3 === 0;
  }

  getReplacement(): string {
    return "Fizz";
  }
}

class BuzzRule implements RuleInterface {
  matches(number: number): boolean {
    return number % 5 === 0;
  }

  getReplacement(): string {
    return "Buzz";
  }
}

class FizzBuzzRule implements RuleInterface {
  matches(number: number): boolean {
    return number % 3 === 0 && number % 5 === 0;
  }

  getReplacement(): string {
    return "FizzBuzz";
  }
}
```
And finally, lets make our FizzBuzz Class **Open For Extension**.

We allow our class to get a list of rules, and build the replacements based on them. These rules must implement the `RuleInterface` making our code flexible & extensible.
```ts
class FizzBuzz {
  rules: RuleInterface[] = [];

  addRule(rule: RuleInterface) {
    this.rules.push(rule);
  }

  generate(number: number) {
    const output: string[] = [];

    for (let i = 1; i <= number; i++) {
      output.push(this.getReplacement(i));
    }

    return output;
  }

  getReplacement(number: number): string {
    for (const rule of this.rules) {
      if (rule.matches(number)) {
        return rule.getReplacement();
      }
    }
    return String(number);
  }
}

const fizBuzz = new FizzBuzz();
fizBuzz.addRule(new FizzBuzzRule());
fizBuzz.addRule(new FizzRule());
fizBuzz.addRule(new BuzzRule());
const result = fizBuzz.generate(20);

// 1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, FizzBuzz, 16, 17, Fizz, 19, Buzz
console.log(result.join(", "));

```
## FizzBuzz Class and the Dependency Inversion Principle

The last of the **SOLID principles** of class design focuses on class dependencies. It tells you what kinds of things a class should depend on:

> **Depend on abstractions, not on concretions.**

The principle tells we should always depend on abstractions(*Interfaces, Abstract Classes*) and not on concrete implementations.

Applying the Dependency Inversion principle in your code ***will make it easy for users to swap out certain parts of your code with other parts that are tailored to their specific situation***. At the same time, your code remains general and abstract and therefore highly reusable.

By introducing the `RuleInterface` and adding specific rule classes that implemented this interface, the FizzBuzz class started to depend on more abstract things, called "rules".

When creating a new `FizzBuzz` instance, concrete implementations of `RuleInterface` have to be injected in the right order. This will result in the correct execution of the FizzBuzz algorithm. 

**The FizzBuzz class itself is no longer concerned about the actual rules, which is why the class ends up being more flexible with regard to changing requirements.**

## Now the hardest part... Naming things!

>There are only two hard things in Computer Science: cache invalidation and naming things.
>
> -- Phil Karlton


Now we have a highly generic piece of code, which “**generates a list of numbers, replacing certain numbers with strings, based on a flexible set of rules”**. 

There is nothing **FizzBuzz** specific about our class anymore!

Our class is generic and it should be renamed. Maybe something like `NumberListReplacer`, *not ideal*, but more generic.

```ts
class NumberListReplacer
{
  rules: RuleInterface[] = [];

  addRule(rule: RuleInterface) {
    this.rules.push(rule);
  }

  generate(number: number) {
    let output: string[] = [];

    for (let i = 1; i <= number; i++) {
      output.push(this.getReplacement(i));
    }
    return output;
  }

  getReplacement(number: number): string {
    for (let rule of this.rules) {
      if (rule.matches(number)) {
        return rule.replacement();
      }
    }
    return String(number);
  }
}

const fizBuzz = new NumberListReplacer();
fizBuzz.addRule(new FizzBuzzRule());
fizBuzz.addRule(new FizzRule());
fizBuzz.addRule(new BuzzRule());
const result = fizBuzz.generate(100);


// ex. replace all even numbers with a 'text'
const evenNumberReplacer = new NumberListReplacer();
evenNumberReplacer.addRule(new EvenNumberRule());
const result = evenNumberReplacer.generate(100000);
console.log(result.join(", "));
```

**Links:**

* **Principles of Package Design: Creating Reusable Software Components** is a brilliant book by **Matthias Noback**, it explains the SOLID principles brilliantly(and not only), the idea for the FizzBuzz implementation on example above is taken from there. https://matthiasnoback.nl/book/principles-of-package-design/
* https://khalilstemmler.com/articles/solid-principles/solid-typescript/