3
\$\begingroup\$

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
\$\endgroup\$
  • \$\begingroup\$ Is there a reason you went for this specific approach? \$\endgroup\$ – Mast Aug 1 '17 at 12:53
  • \$\begingroup\$ I want an object oriented approach, more than that not really. \$\endgroup\$ – Ovidiu Aug 1 '17 at 13:10
  • 1
    \$\begingroup\$ 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 :) \$\endgroup\$ – Mark Thomas Aug 5 '17 at 22:52
  • \$\begingroup\$ 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 \$\endgroup\$ – Jonah Aug 11 '17 at 9:38
2
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.