---
title: Features and Bugs Addendum
teaser:
tags: web,ruby
author: Jon Yurek
published_on: 2007-06-04
---

I was inspired by both [Jared's previous
post](https://thoughtbot.com/blog/features-and-bugs) and the [Ruby Quiz for
last Friday](http://www.rubyquiz.com/quiz126.html) and wrote my FizzBuzz using
the Open-Closed principle. Here's the main program:

```ruby
# fizzerbuzzer.rb
class FizzerBuzzer

  def self.filters
    @filters ||= []
  end

  Dir.glob("*_filter.rb").sort.each{|f| require f }

  def self.filter(i)
    filters.collect do |filter|
      filter.filter(i)
    end.compact.join("")
  end

  def self.fizzbuzz
    (1..100).each do |i|
      result = filter(i)
      puts result.empty? ? i : result
    end
  end
end

FizzerBuzzer.fizzbuzz
```

It's built the way it is so that you can change the way the code executes
without having to change fizzerbuzzer.rb yourself. It looks for files ending in
`_filter.rb` in the same directory and executes them. The classes they implement
need to `respond_to? :filter` and they need to place an instance of themselves
into the `filters` array. Wonderful extensability!

As for the filters themselves, they have to be named in order so the `glob`
picks them up the right way (because we're not writing BuzzFizz). Here's the
filter for Fizzing.

```ruby
# 01_fizz_filter.rb
class FizzFilter
  def filterable?(index)
    index % 3 == 0
  end
  def filter(index)
    "Fizz" if filterable? index
  end
end
FizzerBuzzer.filters << FizzFilter.new
```

And the same one for Buzzing.

```ruby
# 02_buzz_filter.rb
class BuzzFilter
  def filterable?(index)
    index % 5 == 0
  end
  def filter(index)
    "Buzz" if filterable? index
  end
end
FizzerBuzzer.filters << BuzzFilter.new
```

There, doesn't that feel nice and extensible? For comparison, though, here's a
much shorter one

```ruby
(1..100).each do |i|
  result = []
  result << "Fizz" if i % 3 == 0
  result << "Buzz" if i % 5 == 0
  result << i if result.empty?
  puts result.join("")
end
```

Doesn't the nonflexibility of that just _kill_ you?
