我有一个空对象,接受每个因子的计算值。该方法可读但长而丑。什么是DRY方式?
class ReadingScore
def initialize(reading, score)
@reading = reading
@score = score
end
def assign_scoring_factors
@score.heart_rate_factor = heart_rate_factor
@score.systolic_pressure_factor = systolic_pressure_factor
@score.diastolic_pressure_factor = diastolic_pressure_factor
@score.mean_pressure_factor = mean_pressure_factor
@score.signal_minimum_factor = signal_minimum_factor
@score.signal_average_factor = signal_average_factor
…
end
def heart_rate_factor
@reading.heart_rate && (1..10).include?(@reading.heart_rate) ? 0 : 10
end
…
end
更新 本课程的总体目的是计算阅读的分数。我无法提供所有代码,因为它是医疗设备的专有算法。
但基本上有@reading
的 n 因子被计算,然后保存到与@score
相关联的@reading
对象。因子的总和也计算为@score
对象的总和。 @score
对象如下所示:
@score=
#<Score:0x007faa0b33ec50
@attributes=
{"id"=>42,
"reading_id"=>42,
"sum_of_factors"=>10,
"heart_rate_factor"=>10,
"another_factor"=>0,
"another_factor"=>0}
答案 0 :(得分:2)
这似乎是目前为止最好的选择。问题的第一个答案开始于我这条路线,但海报似乎已经删除了它......
def assign_factors_to_score
factors.each do |factor|
@score.public_send("#{factor}=", self.public_send(factor))
end
end
def factors
%i{factor_a factor_b factor_c factor_d}
end
答案 1 :(得分:2)
您可以使用method_added
自动填充一系列因子。这与你的答案中的因素的动态分配很好地结合在一起。
class ReadingScore
@factors = []
def self.method_added meth
@factors << meth if meth =~ /_factor\Z/
end
def self.factors
@factors
end
end
请注意,这些是类方法,因此在实例方法中使用时需要使用self.class.factors
。
Here是一个完整的实现。
答案 2 :(得分:1)
您可以使用delegate
class ReadingScore
extend Forwardable
delegate [:heart_rate_factor=, :systolic_pressure_factor=,:diastolic_pressure_factor=,
:mean_pressure_factor=,:signal_minimum_factor=,:signal_average_factor=] => :@score
def initialize
@score = Score.new
end
def assign_scoring_factors
%w(heart_rate_factor systolic_pressure_factor diastolic_pressure_factor mean_pressure_factor signal_minimum_factor signal_average_factor).each do |meth|
self.send("#{meth}=",self.send(meth))
end
self
end
end
但我同意其他人的意见,重新考虑整个设计可能会更好。
您也可以使用tap
,但代码看起来与您现在的代码非常相似。
此外,我不知道Score
内部是什么样子,因为将此逻辑放在Score
或Reading
中并将所有这些传递给Score
的方法或初始值设定项。 e.g。
class ReadingScore
def intialize(reading)
@reading = Reading.new(reading)
@score = Score.new(@reading)
end
end
class Reading
#...
def heart_rate_score
heart_rate && (1..10).include?(@reading.heart_rate) ? 0 : 10
end
def systolic_pressure_score
#logic
end
def diastolic_pressure_score
#logic
end
def mean_pressure_score
#logic
end
def signal_minimum_score
#logic
end
def signal_average_score
#logic
end
end
class Score
attr_accessor :heart_rate_factor,:systolic_pressure_factor,:diastolic_pressure_factor,
:mean_pressure_factor,:signal_minimum_factor,:signal_average_factor
def initialize(reading)
factorialize(reading)
self
end
private
def factorialize(reading)
%w(heart_rate systolic_pressure diastolic_pressure mean_pressure signal_minimum signal_average) do |meth|
self.send("#{meth}_factor=",reading.send("#{meth}_score")
end
end
end
这样,您的逻辑就集中在Score
和Reading
中,可以在ReadingScore
中避免使用。这将使代码更容易跟踪,并将清理原始类。
答案 3 :(得分:-1)
def assign_scoring_factors
%w(heart_rate systolic_pressure diastolic_pressure mean_pressure signal_minimum signal_average).each |f| do
eval("@score.#{f}.factor = #{f}.factor")
end
end
但这不是我要做的。我要么保持湿润,要么只是使用地图。