Ruby Rspec Timer - solusi pemfaktoran ulang

Saya memecahkan pertanyaan TestFirst.org 09_timer untuk pengujian Ruby Rspec. Kode saya berfungsi tetapi saya tidak menyukainya. Ini sangat panjang. Setiap komentar dan/atau saran untuk perbaikan akan sangat dihargai. Harap sertakan penjelasan untuk memperjelas saran apa pun. Tujuannya adalah membuat Timer dengan variabel instan @detik yang diinisialisasi ke 0, lalu mengembalikan semua nilai sebagai string dengan format jam, menit, detik: 00:00:00. Jadi 12 detik => 00:00:12; 66 detik => 00:01:06; dan 4000 detik => 01:06:40. Terima kasih. Kode di bawah.

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 sumber


Jawaban (1)


Ada beberapa hal kecil yang dapat Anda lakukan untuk menyederhanakan kelas Anda, dan beberapa perubahan besar dalam organisasi.

1) Gunakan String#rjust untuk mengisi angka:

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

Ini memungkinkan Anda menerapkannya ke setiap nomor, terlepas apakah nomor tersebut sudah memiliki dua digit atau belum. Sebagai konsekuensinya, Anda dapat menghilangkan semua pemeriksaan satu digit (if h_minutes < 10, dll).

2) Singkirkan semuanya mulai dari pernyataan if pertama, karena tidak ada yang diperlukan. Hanya beberapa baris sebelumnya, Anda memiliki hours = @seconds / 3600, h_minutes = ((@seconds%3600)/60), dan m_seconds = @seconds%60, yang merupakan tiga nilai yang Anda perlukan. Terapkan peta sederhana (untuk padding), dan gabung dengan ":" untuk sampai pada string terakhir Anda.

3) Jika Anda menginginkan pendekatan berorientasi objek, setiap variabel jam/menit/detik Anda bisa menjadi sebuah metode, sehingga Anda akan mendapatkan sesuatu yang lebih seperti ini:

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
Terima kasih banyak Zach. Anda baru saja meningkatkan pemahaman saya selama berminggu-minggu mungkin dalam satu solusi sederhana. Salah satu kekhawatiran terbesar saya adalah seringnya pemeriksaan tunggal berulang yang Anda lakukan dengan metode #rjust yang sederhana. Aku bahkan tidak pernah mempertimbangkan hal ini. Dan saya belum pernah menggunakan #map sedemikian rupa, tetapi terima kasih kepada Anda sekarang saya mengetahui metode Simbol#to_proc. Acungan jempol. - person Jeremiah McCurdy; 28.01.2014
comment
Senang mendengarnya, jere.mac. rjust adalah salah satu hal di perpustakaan standar yang jarang muncul, namun sebaiknya diketahui saat Anda membutuhkannya. Anda akan menemukan banyak hal seperti itu seiring dengan semakin akrabnya Anda dengan bahasa tersebut. - person Zach Kemp; 28.01.2014