5
\$\begingroup\$

I am a nurse and I'm learning to code. I have coded this simple tool that helps me doing some common nursing formulas for medication. It works, however I think it is too bulky/redundant. Can you help me with some ideas for refactoring it?

class NursingFormulas
  def initialize
    puts "What do you want to do?"
    puts "1) How many tablets should I administer?"
    puts "2) How many ml should I administer?"
    puts "3) What's the ml per hour rate of my IV?"
    puts "4) What's the drop rate of my IV?"
    puts "5) Exit"
    choice = gets.chomp.to_i
    case choice
    when 1 then mass_for_mass
    when 2 then mass_for_liquid
    when 3 then iv_ml_rate
    when 4 then iv_drop_rate
    when 5 then exit(0)
    else
      exit(0)
    end
  end

  def mass_for_mass
    puts "What's the prescribed mass in mg?"
    prescribed = gets.chomp.to_f
    puts "What's the mass you've got in mg?"
    mass = gets.chomp.to_f
    result = prescribed / mass
    puts "Administer #{result} tablets"
  end

  def mass_for_liquid
    puts "What's the prescribed mass in mg?"
    prescribed = gets.chomp.to_f
    puts "What's the mass you've got in mg?"
    mass = gets.chomp.to_f
    puts "How many mL do you have?"
    ml = gets.chomp.to_f
    result = (prescribed / mass) * ml
    puts "Administer #{result} ml"
  end

  def iv_ml_rate
    puts "What's the volume in mL?"
    volume = gets.chomp.to_f
    puts "What's the time in hours?"
    time = gets.chomp.to_f
    result = (volume / time).round
    puts "The rate is #{result} ml per hour"
  end

  def iv_drop_rate
    puts "What's the volume in mL?"
    volume = gets.chomp.to_f
    puts "What's the time in hours?"
    time = gets.chomp.to_f
    time = time * 60
    puts "What's the drop factor?"
    factor = gets.chomp.to_f
    result = ((volume / time) * factor).round
    puts "The drop rate is #{result} drops per minute"
  end
end
\$\endgroup\$
  • \$\begingroup\$ You don't need classes. \$\endgroup\$ – Nakilon Jan 29 '16 at 11:24
2
\$\begingroup\$

Here is a solution using the Command Pattern.

Each action will live in its own class. I'm using some mixins so we don't have repeated code.

nursing_formulas.rb

require_relative "formulas/mass_for_mass"
require_relative "formulas/mass_for_liquid"
require_relative "formulas/iv_ml_rate"
require_relative "formulas/iv_drop_rate"

class NursingFormulas
  def initialize
    show_instructions

    @instructions = {
      1 => MassForMass.new,
      2 => MassForLiquid.new,
      3 => IvMlRate.new,
      4 => IvDropRate.new
    }

    choice = gets.chomp.to_i

    @instructions.key?(choice) ? @instructions[choice].do : exit(0)
  end

  def show_instructions
    puts "What do you want to do?"
    puts "1) How many tablets should I administer?"
    puts "2) How many ml should I administer?"
    puts "3) What's the ml per hour rate of my IV?"
    puts "4) What's the drop rate of my IV?"
    puts "5) Exit"
  end
end

mass_for_mass.rb

require_relative "mixins/mass_actions"

class MassForMass
  include MassActions

  def do
    result = ask_for_prescribed_mass / ask_for_mass
    puts "Administer #{result} tablets"
  end
end

mass_for_liquid.rb

require_relative "mixins/mass_actions"

class MassForLiquid
  include MassActions

  def do
    prescribed = ask_for_prescribed_mass
    mass = ask_for_mass
    ml = ask_for_ml

    result = (prescribed / mass) * ml
    puts "Administer #{result} ml"
  end

  def ask_for_ml
    puts "How many mL do you have?"
    gets.chomp.to_f
  end
end

iv_ml_rate.rb

require_relative "mixins/iv_actions"

class IvMlRate
  include IvActions

  def do
    volume = ask_for_volume
    time = ask_for_time

    result = (volume / time).round
    puts "The rate is #{result} ml per hour"
  end
end

iv_drop_rate.rb

require_relative "mixins/iv_actions"

class IvDropRate
  include IvActions

  def do
    volume = ask_for_volume
    time_in_min = ask_for_time * 60
    factor = ask_for_drop_factor

    result = ((volume / time_in_min) * factor).round
    puts "The drop rate is #{result} drops per minute"
  end

  def ask_for_drop_factor
    puts "What's the drop factor?"
    gets.chomp.to_f
  end
end

MIXINS

mass_actions.rb

module MassActions
  def ask_for_prescribed_mass
    puts "What's the prescribed mass in mg?"
    gets.chomp.to_f
  end

  def ask_for_mass
    puts "What's the mass you've got in mg?"
    gets.chomp.to_f
  end
end

iv_actions.rb

module IvActions
  def ask_for_volume
    puts "What's the volume in mL?"
    gets.chomp.to_f
  end

  def ask_for_time
    puts "What's the time in hours?"
    gets.chomp.to_f
  end
end
\$\endgroup\$
  • \$\begingroup\$ Hope this helps you to write more formulas in the future :) \$\endgroup\$ – Mario Pérez Jan 30 '16 at 15:29
  • \$\begingroup\$ This is pretty great <3. I'll spend some time understanding the code I like this way of doing it. Thanks a lot! \$\endgroup\$ – Heide Queen Jan 30 '16 at 16:44
  • \$\begingroup\$ You're welcome! Let me know if you don't understand something \$\endgroup\$ – Mario Pérez Jan 30 '16 at 16:48
0
\$\begingroup\$

I agree with @Nakilon for a float

All your methods are static (they do not read into the state of the class) so you do not need a class.

What you do need is a way of asking for a float that you do so many times.

Extracting asking for a float into a function will also help you add error-checking easily.

\$\endgroup\$
  • 1
    \$\begingroup\$ I know, i was planning to make more tools in the application other than the dosage calculator that's why I made it a class to separate it from the other tools but I guess it could also just be a module or something. But yes, Mario's answer is pretty much what I was looking for. :) \$\endgroup\$ – Heide Queen Jan 30 '16 at 19:18

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.