3

TL;DR

最近为 Rails 项目加了一个代码分析工具叫 Reek ,用来检查代码中的坏味道。因为项目已经有一段时间了,一跑就几百个提示。平时也没工夫专门优化代码。于是我想到一个折中的办法:只检查 feature branch 中修改了的文件,针对性地优化。

思路

像大多数 CLI 一样,Reek 也可以接受额外的参数来检查指定的文件。大概如此:

$ bundle exec reek file1 file2

而同时,Git 的 diff 可以比对两个分支的改动,加一个参数 --name-only 就可以只输出改动的文件名。以下假定当前分支是 feature branch ,对比 staging 分支的情况。

# assume current branch is feature branch
$ git diff --name-only staging

file1
file2
...

我们可以写个 rake task ,通过 Ruby 调用 git diff 命令,把返回的文件名转换成一行,再传给 reek 命令。就可以达到目的。

实现

实现起来挺简单的,就只放代码了:

# lib/tasks/reek.rake
namespace :reek do
  desc "Check code smells for changed files (based on staging)"
  task :changed, [:branch] do |t, args| # 加一个 branch 参数
    branch = args[:branch] || 'staging'

    # 获取改变的文件名,剔除掉被删的文件
    re = `git diff --name-only #{branch}`
    files = re.split("\n").delete_if { |name| !File.exist?(name) }

    if files.blank?
      puts "\nNo files changed\n"
      return
    end

    # 打印一下文件列表
    puts "\nReek changed files:"
    files.each do |file|
      puts "  #{file}"
    end
    puts

    # 调用 reek
    system "bundle exec reek #{files.join(' ')}"
  end
end

需要注意的有几点:

  • 这个 task 可以通过 branch 参数修改要比较的分支,方便查看。

  • 调用 git diff 命令使用的是 "`" ,这样方便获取返回值。

  • 调用 bundle exec reek 得用 system ,因为需要把输出显示在屏幕上。

使用起来很简单:

# 默认情况,对比 staging 和当前分支
./bin/rake reek:changed

# 对比 master 分支,换成 commit 也行
./bin/rake reek:changed[master]

小结

代码分析工具是好东西,可以潜默移化地改变人的编程习惯,即使对很有经验的程序员也能起到查漏补缺的作用。但世事无绝对,分析规则是否跟项目匹配,工作流程如何改进,这些都是因人而异的,需要不停地思考和总结。

参考资料

Reek
Can I make git diff only show the changed file names and line numbers?


darkbaby123
1.4k 声望67 粉丝

引用和评论

0 条评论