本篇將介紹撰寫 Rails 的過程中整個重構的過程,比較偏向一個方向,以一個簡單的例子為例,假設我們請求 API 獲取 Active 的 User 列表:
以下的程式是一個很常見的方法,但這段程式碼中,不只打 Api + parser + 過濾 active user,這樣的方式並沒有辦法讓程式碼只負責一件事情。
response = Request.call('some_url')
parsed_response = JSON.parse(response)
eligible_users = []
parsed_response['people'].each do |person|
if person['active'] == true
eligible_users << {
name: "#{person['firstName']} #{person['lastName']}",
email: person['emailAddress']
}
end
end
eligible_users
Parser 的責任在負責接收並提供方法來 return User
response = Request.call('some_url')
parser = PeopleParser.new(response)
eligible_users = []
parser.people.each do |person|
if person['active'] == true
eligible_users << {
name: "#{person['firstName']} #{person['lastName']}",
email: person['emailAddress']
}
end
end
eligible_users
我們需要一個 pure ruby object 來處理 person
class Person
def initialize(attributes)
@attributes = attributes
end
def active?
@attributes['active']
end
def email
@attributes['emailAddress']
end
def name
"#{@attributes['firstName']} #{@attributes['lastName']}"
end
end
有了上述的 Person Object 我們的 Parser 可以再來進行修改
class PeopleParser
def initialize(raw_response)
@raw_response = raw_response
end
def people
@parsed_json['people'].map { |attributes| Person.new(attributes) }
end
private
def parsed_json
@parsed_json ||= JSON.parse(@raw_response)
end
end
response = Request.call('some_url')
parser = PeopleParser.new(response)
eligible_users = []
parser.people.each do |person|
if person.active?
eligible_users << {
name: person.name,
email: person.email
}
end
end
eligible_users
再來繼續重構:
接下來我們要命名一個 to_h
來組成 name + email 的 hash
class Person
def initialize(attributes)
@attributes = attributes
end
def to_h
{
name: name,
email: email
}
end
def active?
@attributes['active']
end
def email
@attributes['emailAddress']
end
def name
"#{@attributes['firstName']} #{@attributes['lastName']}"
end
end
程式碼也變得更直觀跟可讀性了
response = Request.call('some_url')
parser = PeopleParser.new(response)
eligible_users = parser.people.select(&:active?).map(&:to_h)