Ruby & OOP: FizzBuzz Game

I would like a more elegant solution for this problem, I think the FizzBuzzArrayBuilder class is not used properly. Also can those if statements be removed somehow?

Any suggestion on how to improve this by still using OOP is welcome.

Problem:

Given the array [1, 2, 3, 4, ... 100], print all the elements as follows:

• if the element can be divided by 3 print: Fizz
• if the element can be divided by 5 print: Buzz
• if the element can be divided by both 3 and 5 print: FizzBuzz
• else print the number

Output: 1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, FizzBuzz ...

Solution:

class Fizz
def output
puts 'Fizz'
end
end

class Buzz
def output
puts 'Buzz'
end
end

class FizzBuzz
def output
puts 'FizzBuzz'
end
end

class Element
def initialize(value)
@value = value
end

def output
puts @value
end
end

class FizzBuzzArrayBuilder
def initialize(array)
@array = array
end

def build
result = []
@array.each do |e|
if e % 15 == 0
result << FizzBuzz.new
elsif e % 3 == 0
result << Fizz.new
elsif e % 5 == 0
result << Buzz.new
else
result << Element.new(e)
end
end
result
end
end

class Counter
def initialize(array)
@fizz_buzz_array = FizzBuzzArrayBuilder.new(array).build
end

def output_array
@fizz_buzz_array.map(&:output)
end
end

array = (1..100).to_a
Counter.new(array).output_array

• Is there a reason you went for this specific approach?
– Mast
Aug 1, 2017 at 12:53
• I want an object oriented approach, more than that not really. Aug 1, 2017 at 13:10
• I agree with Zack. This is a trivial problem and can be solved in one line of Ruby. The OO structure seems forced and a little too Java flavored. There's just no way to reason about the OO unless the problem gets a bit more sophisticated. Learning OO includes knowing when not to use it :) Aug 5, 2017 at 22:52
• I don't say this to be mean, but it should be said because it's important that you know it: this code is comedically over-engineered. You really need to ask yourself why you would ever want something like this when you can write something like this Aug 11, 2017 at 9:38

Wrong Objects

You've made objects, but you haven't really made the right ones. Your Fizz, Buzz, FizzBuzz, and Element classes are really just wrappers for a string, which is already a class.

Object oriented programming is not always the best solution for a problem. FizzBuzz itself is frankly very trivial and almost any object based approach is a needlessly complicated solution. With that said, perhaps we can redefine the problem to make it a better fit for an object oriented solution.

New problem definition

Consider this modified problem: As input you will receive a list. Each row (a rule) will have one or more numbers (divisors) and a text substitution. After parsing the list, for every number 1..100 you will either print the number or a substitution for the number. For each rule, if a number is divisible by all of the divisors, you will use the substitution. In the event of a tie, use the substitution from the rule with the most divisors. If there is still a ties use the substitution for the rule with the smallest individual divisor. For example, given "3 6 apple" and "2 9 banana" and "18 candle", they all tie for an input of 18, but "2 9 banana" has the smallest divisor, 2.

Example Input:
3 fizz
5 buzz
3 5 fizzbuzz
3 6 apple
2 9 banana
18 candle
2 3 4 dog


New Classes

Now there is opportunity for new classes, perhaps Parser that reads the rules/substitutions, Rule which contains a list of divisors, the substitution, and perhaps it supports the comparison operation <=> so that the rules can automatically resolve ties. There could also be an Engine class for iterating through 1..100 and applying the rules. There are a couple of different ways you could define the classes or even the problem here. In general though, OO solutions to trivial problems aren't a good fit.