Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

เชี่ยวชาญ Ruby Refactoring: เทคนิคจำเป็นสำหรับโค้ดสะอาด

ถ้าไม่คุ้นเคย term นี้ refactoring คือการปรับปรุงคุณภาพโค้ดโดยไม่เปลี่ยน behavior ทำให้โค้ดง่ายต่อการทำงานมากขึ้น

ในโพสต์นี้จะเรียนรู้ Ruby refactoring techniques พื้นฐาน มาเริ่มกัน!

Extract Method

Refactoring พบบ่อยที่สุดคือ 'extract method' ย้ายโค้ดจากเมธอดเก่าไปเมธอดใหม่ ทำให้ได้เมธอดเล็กๆ ชื่อ descriptive

ตัวอย่าง:

@sold_items = %w( onions garlic potatoes )
def print_report
  puts "*** Sales Report for #{Time.new.strftime("%d/%m/%Y")} ***"
  @sold_items.each { |i| puts i }
  puts "*** End of Sales Report ***"
end

เริ่ม extract ส่วน醜ที่สุด: current date generation

def print_report
  puts "*** Sales Report for #{current_date} ***"
  @sold_items.each { |i| puts i }
  puts "*** End of Sales Report ***"
end
def current_date
  Time.new.strftime("%d/%m/%Y")
end

อ่านง่ายขึ้นแล้ว แต่ไปต่อได้ extract เพิ่มจนได้โค้ดนี้:

def print_report
  print_header
  print_items
  print_footer
end
def print_header
  puts "*** Sales Report for #{current_date} ***"
end
def current_date
  Time.new.strftime("%d/%m/%Y")
end
def print_items
  @sold_items.each { |i| puts i }
end
def print_footer
  puts "*** End of Sales Report ***"
end

โค้ดยาวขึ้น แต่ไม่อ่านง่ายกว่านี้? อย่ากลัวเมธอดเล็กๆ มันดีต่อโค้ด

Refactoring Conditionals

Refactor conditionals ซับซ้อนเป็นเมธอดอ่านง่ายขึ้น

ตัวอย่าง:

def check_temperature
  if temperature > 30 && (Time.now.hour >= 9 && Time.now.hour <= 17)
    air_conditioner.enable!
  end
end

ส่วนที่ 2 ของ if ไม่อ่านง่าย extract เป็นเมธอด:

def check_temperature
  if temperature > 30 && working_hours
    air_conditioner.enable!
  end
end
def working_hours
  Time.now.hour >= 9 && Time.now.hour <= 17
end

เราตั้งชื่อ descriptive ให้ condition ทำให้อ่านง่ายสำหรับผู้อ่านอนาคต (รวมตัวเอง!)

Replace Method with Method Object

บางครั้งมีเมธอดใหญ่ out of control ยาก refactor เพราะ big methods tend to มี local variables เยอะ วิธีหนึ่ง: 'Method Object' refactoring

"Big methods are where classes go to hide." - Uncle Bob

ตัวอย่าง:

require 'socket'
class MailSender
  def initialize
    @sent_messages = []
  end
  def send_message(msg, recipient = "rubyguides.com")
    raise ArgumentError, "message too small" if msg.size < 5
    formatted_msg = "[New Message] #{msg}"
    TCPSocket.open(recipient, 80) do |socket|
      socket.write(formatted_msg)
    end
    @sent_messages << [msg, recipient]
    puts "Message sent."
  end
end
sender = MailSender.new
sender.send_message("testing")

Refactor: สร้าง class ใหม่ promote local variables เป็น instance variables จะ refactor ต่อได้โดยไม่ต้องส่ง data ไปมาระหว่างกัน

Hey! อยากพัฒนา Ruby skills ให้ก้าวกระโดด? เช็ค Beautiful Ruby Course ของผม 🙂

MailSender class หลัง refactor:

class MailSender
  def initialize
    @sent_messages = []
  end
  def deliver_message(message)
    send(message)
    @sent_messages << message
    puts "Message sent."
  end
  def send(msg)
    TCPSocket.open(msg.recipient, 80) { |socket| socket.write(msg.formatted_msg) }
  end
end

Class ใหม่ที่ introduce:

class Message
  attr_reader :msg, :recipient
  def initialize(msg, recipient = "rubyguides.com")
    raise ArgumentError, "message too small" if msg.size < 5
    @msg = msg
    @recipient = recipient
  end
  def formatted_msg
    "[New Message] #{msg}"
  end
end
sender = MailSender.new
msg = Message.new("testing")
sender.deliver_message(msg)

สรุป

ใช้ refactoring techniques นี้ช่วยปฏิบัติตาม Single Responsibility Principle และควบคุม classes และเมธอดไว้

ถ้าชอบบทความนี้แชร์ให้เพื่อนๆ ด้วย 🙂