2
\$\begingroup\$

I've written a Twitter bot, @answering_yelp, which responds to another Twitter bot, @hard_to_yelp. They scrape yelp reviews for sentences which start "How hard is it to..." and my bot answer with some version of how hard it is.

I recently refactored the code to handle changes to the source text as a list of command classes, instead of one ever-expanding method, or collection of methods, in my Generator class.

You can see the code in context on GitHub.

I'm wondering if I should have implemented these classes as singletons, or if there's some reason to leave the singleton declaration out.

Here's some snippets:

generator.rb (much smaller since this refactor)

class Generator

  TRANSFORMS = [
    Transforms::Substitutions,
    Transforms::Answer,
    Transforms::Question,
    Transforms::Recipient
  ]

  def initialize(source, options, recipient='hard_to_yelp')
    @source = source
    @transform_arguments = {
      options: options,
      recipient: recipient
    }
  end

  def run
    result = @source.dup
    TRANSFORMS.each { |transform| result = transform.run(result, @transform_arguments) }
    result = run until result.length <= 140
    result
  end

end

Just one of my transforms, Question, which adds a question mark if there's a questioning word present (or removes one if there isn't).

module Transforms
  class Question
    include Singleton

    QUESTION_WORDS = %w{why where which who}

    def self.run(source, arguments={})
      if is_question?(source)
        has_punctuation?(source) ? source.gsub('.', '?') : source + '?'
      else
        source.gsub('?', '.')
      end
    end

    def self.is_question?(source)
      src = source.downcase
      QUESTION_WORDS.any? { |q| src.index(q) }
    end

    private_class_method :is_question?

    def self.has_punctuation?(source)
      source.index('.') || source.index('?')
    end

    private_class_method :has_punctuation?

  end
end

Singleton pros:

  • The only public interface is the run method. Some other interface (such as the new method) is removed.
  • If I choose to keep the environment open (say, with spring), there'll be fewer objects initialised, marginally more performant.

Singleton cons:

  • It's probably not needed, if I remove the include, it still works.
  • People don't like singletons.

To singleton, or not to singleton. That is the question.

\$\endgroup\$

Your Answer

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

Browse other questions tagged or ask your own question.