FizzBuzz Refactoring Challenge with Open/Closed Principle
Tags: objectorienteddesign, solidprinciple, refactoring, fizzbuzz
Published: 2020-06-04 18:17:32

---
title:  FizzBuzz Refactoring Challenge with Open/Closed Principle  
published: true
description: 
tags: ObjectOrientedDesign, SOLIDPrinciple, Refactoring, FizzBuzz
cover_image: https://raw.githubusercontent.com/OliverMensahDev/content-resources/master/code/Screenshot%20from%202020-06-03%2022-44-21.png
---

# Introduction

Have you ever heard of the [FizzBuzz](https://en.wikipedia.org/wiki/Fizz_buzz) refactoring challenge? I encountered it through an article on [Medium](https://itnext.io/fizzbuzzbazz-how-to-answer-and-how-not-to-answer-661fd8842c40). The challenge is basically about writing code that allows new requirement to be added to the FizzBuzz problem. And the author did a great job with the strategies he adopted in solving the challenge. In this article, I will share about how the **Open/Closed principle(OCP), the 'O' in the SOLID principle acronym**, will be very useful in solving this challege.

## FizzBuzz Challenge

Mostly, coding up the FizzBuzz solution is easier by just replacing a number that meets a certain condition with a new value. And it usually goes like this; multiple of 3 should be replaced with Fizz, that of 5 with Buzz, and that of both 3 and 5 with FizzBuzz. 
Below is code sample for this challenge. 

```php
<?php
class FizzBuzz
{
  public function generate(int $limit): void
  {
    for ($number = 1; $number <= $limit; $number++) {
      if ($number % 3 === 0 && $number % 5 === 0) {
        echo "FizzBuzz\n";
      } else if ($number % 3 === 0) {
        echo "Fizz \n";
      } else if ($number % 5 === 0) {
        echo "Buzz\n";
      } else {
        echo "$number \n";
      }
    }
  }
}
$fizzBuzz = new FizzBuzz();
$fizzBuzz->generate(100);
```

### Meeting new Requirements

Then here comes a new requirement to handle, such that if a number is a multiple of 7, output Bazz. For a multiple of 7 and 3, output FizzBazz. And for a multiple of 7 and 5, output BuzzBazz. 
All we need to do is just adding more checks then return what is needed to. Below is the code sample we could write for this.

```php
<?php
class FizzBuzz
{
  public function generate(int $limit): void
  {
    for ($number = 1; $number <= $limit; $number++) {
      if ($number % 3 === 0 &&  $number % 5 === 0 && $number % 7 === 0) {
        echo "FizzBuzzBazz\n";
      } else if ($number % 3 === 0 && $number % 5 === 0) {
        echo "FizzBuzz\n";
      } else if ($number % 3 === 0 &&  $number % 7 === 0) {
        echo "FizzBazz\n";
      } else if ($number % 5 === 0 && $number % 7 === 0) {
        echo  "BuzzBazz\n";
      } else if ($number % 3 === 0) {
        echo "Fizz\n";
      } else if ($number % 5 === 0) {
        echo "Buzz\n";
      } else if ($number % 7 === 0) {
        echo "Bazz\n";
      } else {
        echo "$number\n";
      }
    }
  }
}

$fizzBuzz = new FizzBuzz();
$fizzBuzz->generate(100);
```
It is simple to implement it this way. But when you consider some principles and patterns, this solution is not really scalable. Adhering to code design principes will improve how the code is designed. And that's where the Open/Closed Principle(OCP) of the SOLID principle comes to a rescue.

## Adopting Open/Closed Principle to make FizzBuzz extensible

I recently shared on [Twitter](https://twitter.com/OliverMensahDev/status/1257360189591822338) about exploring deeper into software design and architecture concepts. Through that, I learned a lot about different patterns and principles. One of which is the [SOLID] (https://en.wikipedia.org/wiki/SOLID) principle and within this, we have OCP. The **OCP** states that you should be able to extend a class' behavior without modifying it. Meaning, *a unit of code can be considered open for extension when its behavior can be easily changed without modifying it. The fact that no actual modification is needed to change the behavior of a unit of code makes it “closed” for modification.*

In our case, the FizzBuzz class should be able to add more requirement with minimal or no changes to the codebase. To do this, we need to be able to identify what is happening in each condition that determines a strategy and remove what's common into a specific abstraction such as interface, abstract class , and class.
  
If we use interfaces well, then we can easily drop in new implementations without needing to modify our existing calling code, hence lets wrap the commonalities into an interface. And the commonalities the FizzBuzz class are matching condition and value replacement. 

```php
<?php
interface RuleInterface
{
  public function matches(int $number): bool;
  public function getReplacement(): string;
}
```
After creating the interface, we then allow each specific strategy to implement the interface.

```php
<?php

class FizzRule  implements RuleInterface
{
  public function matches(int $number): bool
  {
    return $number % 3 === 0;
  }

  public function getReplacement(): string
  {
    return 'Fizz';
  }
}

class BuzzRule  implements RuleInterface
{
  public function matches(int $number): bool
  {
    return $number % 5 === 0;
  }

  public function getReplacement(): string
  {
    return 'Buzz';
  }
}

class BazzRule  implements RuleInterface
{
  public function matches(int $number): bool
  {
    return $number % 7 === 0;
  }

  public function getReplacement(): string
  {
    return 'Bazz';
  }
}

class BuzzBazzRule  implements RuleInterface
{
  public function matches(int $number): bool
  {
    return $number % 5 === 0 && $number % 7 === 0;
  }

  public function getReplacement(): string
  {
    return 'BuzzBazz';
  }
}

class FizzBazzRule  implements RuleInterface
{
  public function matches(int $number): bool
  {
    return $number % 3 === 0 &&  $number % 7 === 0;
  }

  public function getReplacement(): string
  {
    return 'FizzBazz';
  }
}
class FizzBuzzRule  implements RuleInterface
{
  public function matches(int $number): bool
  {
    return $number % 3 === 0 && $number % 5 === 0;
  }

  public function getReplacement(): string
  {
    return 'FizzBuzz';
  }
}

class FizzBuzzBazzRule  implements RuleInterface
{
  public function matches(int $number): bool
  {
    return $number % 3 === 0 &&  $number % 5 === 0 && $number % 7 === 0;
  }

  public function getReplacement(): string
  {
    return 'FizzBuzzBazz';
  }
}
```
Finally we could allow our class to make use of these specifics through dependency injection.

```php
<?php 
class FizzBuzz
{
  private $rules;

  public function __construct(array $rules)
  {
    $this->rules = $rules;
  }
  public function generateList(int $limit): array
  {
    $list = [];
    for ($number = 1; $number <= $limit; $number++) {
      $list[] = $this->generateElement($number);
    }
    return $list;
  }

  private function generateElement(int $number): string
  {
    foreach ($this->rules as $rule) {
      if ($rule->matches($number)) return $rule->getReplacement();
    }
    return (string) $number;
  }
}

$rules = [
  new FizzBuzzBazzRule,
  new FizzBuzzRule(),
  new BuzzBazzRule,
  new FizzBazzRule,
  new FizzRule(),
  new BuzzRule(),
  new BazzRule
];
$fizzBuzz = new FizzBuzz($rules);
$list = $fizzBuzz->generateList(100);
var_dump($list);

```
At the end, we can introduce different specifics that we want by just implementing the interface and passing into the the main class(FizzBuzz). With this approach, the FizzBuzz class is not likely to be modified to meet the new requirements and that's what Open/Closed principle advocates for. 

## Conclusion

We should always try as much as possible to identify some patterns in our code when solving new requirements and find out what principles could be useful in improving the codebase. 

I enjoyed putting this together and I hope you find it very useful
The sample codes can be found [here](https://github.com/OliverMensahDev/fizzbuzz-extensibility).

Let's discuss your opinion about this strategy I used, what could have been done  better and what you might have used for this problem?
Together we grow

## Further Reading

I learned most patterns/principles of class design from [Matthias Noback's](https://twitter.com/matthiasnoback) book on [Principles of Package Design](https://www.apress.com/us/book/9781484241189), maybe you can check it up

## Keep In Touch
 
Let's keep in touch as we continue to explore and learn more about software engineering. Don't forget to connect with me on [Twitter](https://twitter.com/OliverMensahDev) or [LinkedIn](https://www.linkedin.com/in/OliverMensahDev/)