下面的Ruby代码是应该分解成更小的方法,还是应该“按原样”保留,因为如果分解它会碎片过多?我们不确定应该采用什么样的正确方法。 我们知道使用单个测试的小方法通常是最佳实践,但是在这种情况下,这样做似乎会使这些代码过于“薄”并大大降低可读性。这类代码在这个领域有哪些最佳实践?
if $?.success?
puts "Running git fetch"
`git fetch`
if $?.success?
puts "Running git reset --hard origin/#{mbranch}"
`git reset --hard origin/#{mbranch}`
if $?.success?
puts "Running git merge origin/#{branch} --no-ff -m \"STAGED:#{ticket} - #{title}\""
mergeres=`git merge origin/#{branch} --no-ff -m "STAGED:#{ticket} - #{title}"`
if $?.success?
`git log -n 1 | grep "STAGED:#{ticket}"`
if $?.success?
ret=true
if resjs eq "yes"
puts "Entering reservejs directory..."
`cd /#{dir}/zipcar-main/zipcar acs/packages/zipsite/www/reservations/reservejs`
if $?.success?
puts "Running git fetch on reservejs"
`git fetch`
if $?.success?
puts "Running git checkout master on reservejs"
`git checkout master`
if $?.success?
puts "Running git reset --hard origin/master on reservejs"
`git reset --hard origin/master`
if $?.success?
puts "Running git merge origin/#{branch} on reservejs"
`git merge origin/#{branch} --no-ff -m "STAGED:#{ticket} - #{title}"`
if $?.success?
`git log -n 1 | grep "STAGED:#{ticket}"`
if $?.success?
b=Dir.chdir("#{firstdir}")
return true
end
end
end
end
end
end
end
end
else
puts "#{mergeres}"
end
end
end
end
答案 0 :(得分:5)
你的结构尖叫需要一些迭代。而不是深度嵌套的条件,为什么不是一个步骤数组,而你只是在步骤失败时中止处理。
def do_stuff
# array of [cmd, output] pairs.
steps = [
["git fetch", "Running git fetch"],
["git reset --hard origin/#{mbranch}", "Running git reset --hard origin/#{mbranch}"],
# more steps and feedback labels
]
steps.each do |step|
cmd, feedback = step # step[0] is the command, step[1] is the feedback
puts feedback
return false unless system(cmd).success?
end
end
或者您可以使用哈希数组,甚至可以让您根据需要扩展“步骤”的定义方式。
steps = [
{
cmd: 'git fetch',
msg: 'Doing a git fetch, hold onto your butts!'
},
# more step hashes...
]
这使得步骤的线性顺序更具可读性。并且将来如果你必须在某个地方插入一个命令,你可以这样做而不会愤怒地咒骂。
根据您想要走多远,您可以创建一个Step
类来封装每一步!
steps = [
Step.new(
cmd: 'git fetch',
msg: 'Doing a git fetch, hold onto your butts!'
),
# more step instances...
]
steps.each do |step|
step.run!
return false if step.failed?
end
您甚至可以让每个步骤接受一个块,以便围绕该步骤运行任何自定义逻辑。
Step.new(
cmd: 'git fetch',
msg: 'Doing a git fetch, hold onto your butts!'
) do |result|
# run some ruby code with result of command before next step
end
并表示你可以创建一个运行步骤集合的类!
runner = StepRunner.new(
Step.new(
cmd: 'git fetch',
msg: 'Doing a git fetch, hold onto your butts!'
),
# more step instances..
)
runner.run!
if runner.success?
puts 'all steps complete!'
else
puts "failed with error: #{runner.error}"
end
但那已进入过度杀伤区。这取决于你想要这个系统的灵活性。如果这是一种常见的模式,但步骤的类型和数量各不相同,那么您可能需要更多的抽象。如果这是一个孤立的事件,你可以在更简单的一面做一些事情。
答案 1 :(得分:1)
至少,你可以通过折叠它来使它更具可读性:
begin
# do_stuff
end if $?.success?
begin
# do_stuff
end if $?.success?
可替换地:
# do_stuff
return false unless $?.success?
答案 2 :(得分:1)
在这种情况下,你应该反过来说条件,即只要不满足主流条件就让它分开。
假设您在方法foo
中拥有整个过程。然后,当条件不满足时,您可以使用return
逃离主流。
def foo
return unless $?.success?
puts "Running git fetch"
`git fetch`
return unless $?.success?
puts "Running git reset --hard origin/#{mbranch}"
`git reset --hard origin/#{mbranch}`
return unless $?.success?
puts "Running git merge origin/#{branch} --no-ff -m \"STAGED:#{ticket} - #{title}\""
mergeres=`git merge origin/#{branch} --no-ff -m "STAGED:#{ticket} - #{title}"`
return unless $?.success?
`git log -n 1 | grep "STAGED:#{ticket}"`
...
return true
end
答案 3 :(得分:0)
始终将代码分解为小块总是!!我不是Ruby忍者,但是“OK”的最大嵌套级别就像是3级,之后它只是丑陋的丑陋代码。 最好是碎片而不是那个嵌套级别肯定。如果你将来需要编辑这个东西,那肯定是痛苦的;]
答案 4 :(得分:0)
不要重现当前流行答案的大部分内容,这些答案显示了通过一系列“步骤”表示和迭代的各种方式,我只想提出以下额外的机会来增强可读性和可维护性: