修正前

クラス構成

module MailSendLog
  class Base
    class << self
      def post(param)
        data = default_data.merge(
          param: param
        )

        @logger.post(@tag, data)
      end

      def default_data
        {
          tag: tag,
          specific_item: specific_item,
        }
      end

      def tag
        raise NotImplementedError, "must implement #{self.class}##{__method__}"
      end

      def specific_item
        raise NotImplementedError, "must implement #{self.class}##{__method__}"
      end
    end
  end
end

module MailSendLog
  class Recommend1 < MailSendLog::Base
    class << self
      protected

      def tag
        :recommend1
      end

      def specific_item
        '固有の値1'
      end
    end
  end
end

module MailSendLog
  class Recommend2 < MailSendLog::Base
    class << self
      protected

      def tag
        :recommend2
      end

      def specific_item
        '固有の値2'
      end
    end
  end
end

使用時

MailSendLog::Recommend1.post('paramter')
MailSendLog::Recommend2.post('paramter')

修正後

class MailSendLog
  MailType = Struct.new(:tag, :specific_item)
  Recommend1 = MailType.new(:recommend1, '固有の値1')
  Recommend2 = MailType.new(:recommend2, '固有の値2')

  def initialize(mail_type)
    @tag = mail_type.tag
    @max_item_count = mail_type.max_item_count
    @logger = Fluent::Logger::ConsoleLogger.open(STDOUT)
  end

  # continue methods...
end

使用時

mail_send_log = MailSendLog.new(MailSendLog::Recommend1)
mail_send_log.post('paramter')
mail_send_log = MailSendLog.new(MailSendLog::Recommend2)
mail_send_log.post('paramter')

利点

  • 差分を埋める程度で大したことをしていない、無意味な継承をなくせる

class Struct (Ruby 2.6.0)