ruby - 避免在Ruby中改变方法参数的好习惯?
问题描述
我知道避免在 Ruby 中改变方法参数是一种很好的做法(除非这是特别的意图)。
我应该如何管理它的简单编码经验法则(在风格、命名约定等方面)是什么?
例如,这是一种好的做法吗?
def array_of_three(a, b, c)
d = a.dup
e = b.dup
f = c.dup
# Do work on d, e and f
return [d, e, f]
end
我应该如何命名方法参数与函数内可以变异的重复项?(假设上述方法是“正确的”!)
谢谢。
解决方案
Ruby 的“良好实践”通常归结为不改变您不拥有的数据。问题是所有权可能有些模糊,因此如果有疑问,您会想假设您不拥有数据并在需要对其进行变异时制作副本。
不良行为的表现方式如下所示:
a = [ 1, 2, 3 ]
do_stuff(a) # Works
do_stuff(a) # Doesn't do anything for some reason
a
# => [ ] # Hey! Who did that?
让我们说do_stuff
是一个混蛋并这样做:
def do_stuff(a)
while (v = a.pop)
puts a
end
end
这会破坏你给出的论点,这很糟糕。相反,您应该采用非破坏性方法:
def do_stuff(a)
a.each do |v|
puts v
end
end
或者,如果需要操作该结构,则制作一个副本,例如:
def do_stuff(a)
a = a.uniq.sort
while (v = a.pop)
puts v
end
end
测试您的方法是否正常运行的一个好方法是在测试中为它们提供冻结数据:
a = [ 1, 2, 3 ].freeze
do_stuff(a) # Fails trying to manipulate frozen object
我倾向于使用积极冻结的数据(例如deep_freeze
)编写单元测试,以确保无法修改参数。这很快就解决了所有权问题。
如果您的函数具有这样的方法签名:
def do_stuff(*a, **b)
# ...
end
然后,您将同时拥有a
(varargs) 和b
(kwargs),因为它们是专门针对您的方法而划分的。在所有其他情况下,您需要小心。这就是合约编程很重要的地方,因为您的方法的调用者必须知道哪些参数已移交,哪些未移交。文件必须清楚地说明这一点。
推荐阅读
- r - Calculate accuracies for k = 1:10 on cv with 5 folds using 2 given loops
- reactjs - What is the best way to handle Firestore with React?
- unity3d - Unity erased all my progress on my project back to original state
- java - ScheduledThreadPoolExecutor 的理想 corePoolSize 是多少?
- ios - Xcode 13 快速帮助窗口无法在自定义对象上启动
- javascript - 如何在 Express 中添加自定义错误消息
- mongodb - Mongodb-按键分组数组
- c++ - 类实例不保留数据
- network-programming - 是否可以使用原始 AF_PACKET 进行通信
- python - 用零值块简化块矩阵?