Search code examples
rubyoopsingle-responsibility-principleguard-clause

Guard Clauses and the Single Responsibility Principle (SRP)


Currently reading the fantastic book 'Practical Object Orientated Design In Ruby' and working through a simple kata to really practice some of the principals it discusses.

I have a method that does the following:

def release_bike
  capacity_empty_error if empty?
  bike
end

This 'releases a bike object' from my DockingStation class (I am aware that the bike object should be an argument, but for the time being I just want the method to return the bike object, not remove it).

The #capacity_empty_error does the following:

def capacity_empty_error
  raise "Docking Station is empty."
end

And #empty? looks like:

def empty?
  bike == nil
end

Where bike is a wrapper method for my instance variable @bike. The current capacity of the the DockingStation class is therefore 1, since the code assumes it is full when #bike is set to something (I plan to add proper capacity later).

So hopefully that explains my code, please ask questions and suggest improvements if not, the question I want to ask is:

I feel that the guard clause line in #release_bike:

capacity_empty_error if empty?

is one responsibility for the method and the return of bike on the next line down is a second responsibility. Tis then obviously breaks SRP, but I cannot see how to use a guard clause except as adding it to an existing method as a second responsibility.

Can it be done? How have others achieved it?


Solution

  • What about moving functionality to other classes/modules?

    module BikeChecker
      def capacity_empty_error
        raise "Docking Station is empty."
      end
    
      def release_bike
        capacity_empty_error if empty?
      end
    
      def empty?
        false
      end
    end
    
    class YourClass
      include BikeChecker
    
      def release_bike
        super
        bike
      end
    
      def empty?
        bike == nil
      end
    end 
    

    You can give up the #empty? method from BikeChecker, i left it here for better understanding