Search code examples
ruby-on-railsrubystrategy-patternopen-closed-principle

How can I refactor this ruby code using the Open/Closed principle or Strategy pattern


How can I refactor this ruby code using the Open/Closed principle or Strategy pattern ? I know that the main thought is 'software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification' but how can I use this in practice?

class PaymentService
  def initialize(payment, payment_type)
    @payment = payment
    @payment_type = payment_type
  end

  def process
    result = case payment_type
    when 'first'
      process_first
    when 'second'
      process_second
    end

    payment.save(result)
  end

  def process_first
    'process_first'
  end

  def process_second
    'process_second'
  end
end

Solution

  • In this example, instead of passing a payment_type you can build an object with a class that processes a payment:

    class FirstPayment
      def process
        'process_first'
      end
    end
    
    class SecondPayment
      def process
        'process_second'
      end
    end
    
    class PaymentService
      def initialize(payment, payment_strategy)
        @payment = payment
        @payment_strategy = payment_strategy
      end
    
      def process
        result = @payment_stategy.process
        payment.save(result)
      end
    end
    
    PaymentService.new(payment, FirstPayment.new)
    

    As a result, PaymentService behaviour can be extended by passing a new strategy (for example, ThirdPayment), but the class doesn't need to be modified, if the logic of processing the first or the second payments is changed.