Ruby - Methods - Keyword Arguments

  • + 0 comments

    I was wondering why nobody was trying to use objects since this problem is well suited for them. Maybe it is becauseHackerRank forces silly interfaces like convert_temp on us.

    If you allow me some criticism, I'd say you are using obejcts but not taking the opportunity to benefit from designing with them im mind. Instead of writing a single class TemperatureConverter, here is how I'd write it:

    class TemperatureConverter
        def initialize(degrees)
           @degrees = degrees
        end
    
        def value
            @degrees
        end
    		
        def to(a_unit)
            a_unit.from(self)
        end
        
        def to_celsius
            subclass_responsibility
        end
        
        def to_fahrenheit
            subclass_responsibility
        end
        
        def to_kelvin
            subclass_responsibility
        end
        
        def subclass_responsibility
            raise 'Should be implemented by subclass'
        end
    end
    
    class Celsius < TemperatureConverter
        def to_celsius
            self
        end
    
        def to_fahrenheit
            Fahrenheit.new @degrees * 9/5r + 32
        end
        
        def to_kelvin
            Kelvin.new @degrees + 273.15
        end
        
        def self.from(a_temperature)
            a_temperature.to_celsius
        end
    end
    
    class Fahrenheit < TemperatureConverter
        def to_celsius
            Celsius.new (@degrees - 32) * 5/9r
        end
    
        def to_fahrenheit
            self
        end
        
        def to_kelvin
            Kelvin.new (@degrees + 459.67) * 5/9r
        end
        
        def self.from(a_temperature)
            a_temperature.to_fahrenheit
        end
    end
    
    class Kelvin < TemperatureConverter
        def to_celsius
            Celsius.new @degrees - 273.15
        end
    
        def to_fahrenheit
            Fahrenheit.new @degrees * 9/5r - 459.67
        end
        
        def to_kelvin
            self
        end
        
        def self.from(a_temperature)
            a_temperature.to_kelvin
        end
    end
    
    def convert_temp(degrees, input_scale:, output_scale: 'celsius')
        Object.const_get(input_scale.capitalize).new(degrees).to(Object.const_get(output_scale.capitalize)).value
        # or alternatively
        # Object.const_get(output_scale.capitalize).from(Object.const_get(input_scale.capitalize).new(degrees)).value
    end
    

    Look ma, no ifs!

    I am pretty sure my design can be improved as well, and the naming is also suspiciuous. Why is a unit like Kelvin a sublclass of TemperatureConverter? Take a look at Aconcagua (Measures) If you'd like to study some production quality code.