Ruby Rspec Timer - โซลูชันการปรับโครงสร้างใหม่

ฉันแก้ไขคำถาม TestFirst.org 09_timer สำหรับการทดสอบ Ruby Rspec แล้ว รหัสของฉันใช้งานได้ แต่ฉันไม่ชอบมัน มันยาวมาก ความคิดเห็นและ/หรือข้อเสนอแนะในการปรับปรุงจะได้รับการชื่นชมอย่างมาก โปรดใส่คำอธิบายเพื่อชี้แจงข้อเสนอแนะใด ๆ เป้าหมายคือการสร้างตัวจับเวลาด้วยตัวแปรอินสแตนซ์ @seconds ซึ่งเริ่มต้นเป็น 0 จากนั้นส่งคืนค่าทั้งหมดเป็นสตริงที่มีรูปแบบชั่วโมง นาที วินาที: 00:00:00 12 วินาที => 00:00:12; 66 วินาที => 00:01:06; และ 4000 วินาที => 01:06:40. ขอบคุณ รหัสด้านล่าง

class Timer

    attr_accessor :seconds

    def initialize
      @seconds = 0
    end

    def padded(n)
      "0#{n}"
    end

    def time_string
      hours = @seconds/3600
      h_minutes = ((@seconds%3600)/60)
      minutes = @seconds/60
      m_seconds = @seconds%60
      second = @seconds
      seconds = ""

      if @seconds < 60
        if second < 10
          second =  padded(second)
        end
        seconds << "00:00:#{second}"
      elsif @seconds > 3600
        if hours < 10
          hours = padded(hours)
        end
        if h_minutes < 10
          h_minutes = padded(h_minutes)
        end
        if m_seconds < 10
          m_seconds = padded(m_seconds)
        end
        seconds << "#{hours}:#{h_minutes}:#{m_seconds}"
      else
        if minutes < 10
          minutes = padded(minutes)
        end
        if m_seconds < 10
          m_seconds = padded(m_seconds)
        end
        seconds << "00:#{minutes}:#{m_seconds}"
      end
      @seconds = seconds    
    end

end

person Jeremiah McCurdy    schedule 27.01.2014    source แหล่งที่มา


คำตอบ (1)


มีหลายสิ่งเล็กๆ น้อยๆ ที่คุณสามารถทำได้เพื่อทำให้ชั้นเรียนของคุณง่ายขึ้น และการเปลี่ยนแปลงองค์กรครั้งใหญ่อีกเล็กน้อย

1) ใช้ String#rjust เพื่อปัดตัวเลข:

def padded(n)
  "#{n}".rjust(2, '0')
end

วิธีนี้ช่วยให้คุณนำไปใช้กับทุกตัวเลขได้ ไม่ว่าตัวเลขนั้นจะมีตัวเลขสองหลักอยู่แล้วหรือไม่ก็ตาม ด้วยเหตุนี้ คุณจึงสามารถกำจัดเช็คหลักเดียวทั้งหมด (if h_minutes < 10 ฯลฯ) ได้

2) กำจัดทุกสิ่งโดยเริ่มจากคำสั่ง if แรก เนื่องจากไม่มีความจำเป็นใดๆ เลย เพียงไม่กี่บรรทัดก่อนหน้านี้ คุณมี hours = @seconds / 3600, h_minutes = ((@seconds%3600)/60) และ m_seconds = @seconds%60 ซึ่งเป็นค่าเพียงสามค่าที่คุณต้องการ ใช้แผนที่แบบง่าย (สำหรับการเติม) และเข้าร่วมกับ ":" เพื่อให้ได้สตริงสุดท้าย

3) หากคุณต้องการแนวทางเชิงวัตถุ ตัวแปรชั่วโมง/นาที/วินาที แต่ละตัวของคุณอาจเป็นวิธีการ ดังนั้นผลลัพธ์ที่ได้จะมีลักษณะดังนี้:

class Timer
  attr_accessor :seconds
  def initialize
    @seconds = 0
  end

  def time_string
    [hours, minutes, m_seconds].map(&method(:padded)).join(":")
  end

  def hours
    seconds / 3600
  end

  def minutes
    (seconds % 3600)/60
  end

  def m_seconds
    (seconds % 60)
  end

  def padded(n)
    "#{n}".rjust(2, '0')
  end
end
person Zach Kemp    schedule 27.01.2014
comment
ขอบคุณมากครับคุณแซค คุณเพิ่งพัฒนาความเข้าใจของฉันไปหลายสัปดาห์อาจเป็นวิธีแก้ปัญหาง่ายๆ เพียงอย่างเดียว หนึ่งในข้อกังวลที่ใหญ่ที่สุดของฉันคือการตรวจสอบซ้ำๆ หลายครั้งซึ่งคุณทำได้โดยใช้วิธี #rjust ง่ายๆ ฉันไม่เคยคิดเรื่องนี้มาก่อนเลย และฉันไม่เคยใช้ #map ในลักษณะนี้มาก่อน แต่ต้องขอบคุณคุณที่ทำให้ตอนนี้ฉันรู้เมธอด Symbol#to_proc แล้ว ยกนิ้วให้ใหญ่ - person Jeremiah McCurdy; 28.01.2014
comment
ดีใจที่ได้ยิน jere.mac rjust เป็นหนึ่งในสิ่งเหล่านั้นในไลบรารีมาตรฐานที่ไม่ค่อยปรากฏให้เห็น แต่เป็นการดีที่จะทราบเมื่อคุณต้องการ คุณจะพบกับสิ่งต่างๆ มากมายเมื่อคุณคุ้นเคยกับภาษามากขึ้น - person Zach Kemp; 28.01.2014