辅助分支条件过高robocop进攻

问题描述

我已经编写并优化了这样的代码

  def issues_json_for_v2(skip_avatar = false)
    @result_json ||= { results: [] }
    return if @result_set['issues'].empty?
    @result_set['total_entries'] = @result_set['meta']['total']
    fr_issues = @result_set['issues']
    user_hash = fr_results_hash(@result_set['users'])
    project_data = fr_results_hash(@result_set['projects'])
    if @suggest
      add_suggest_results_fr_issues(fr_issues,project_data)
    else
      fr_issues.each do |issue|
        p_data = project_data[issue['project_id']] if issue
        if issue && issue['owner_id']
          issue_json = append_fr_user_details_to_issue(safe_send(:fr_issue_json,issue,p_data),user_hash)
        else
          issue_json = safe_send(:fr_issue_json,p_data)
        end
        @result_json[:results] << issue_json
      end
    end
    return @result_json[:results] if @size.nil?
    add_fr_prj_meta_data(fr_issues)
    @result_json[:results]
  end

我还是得到

issue_json_for_v2的分配分支条件大小太大。

在保持可读性的同时,我可以做些什么优化。

这是我遇到此问题的另一种方法

  def project_json(project,id)
    human_display_id = project['key']
    title = sanitize_fr_data(project['name'])
    description = project['description'].blank? ? '' : project['description']
    description = sanitize_fr_data(description)
    prg = project['progress']
    percent_completion = (prg['done'] == 0) ? 0 : (prg['done'] * 100) / (prg['todo'] + prg['in_progress'] + prg['done'])
    current_time_zone = ActiveSupport::TimeZone::MAPPING[current_user.time_zone]
    start_date = project['start_date'].nil? ? '--' : project['start_date'].in_time_zone(current_time_zone).strftime(date_time_format)
    end_date = project['end_date'].nil? ? '--' : project['end_date'].in_time_zone(current_time_zone).strftime(date_time_format)
    return { result_type: 'project',content: %{#{title} (#{human_display_id})},path: fr_project_path(project['key']) } if @suggest
    {
      id: id,title: title,project_display_id: human_display_id,description: truncate(description,length: 250),owner: project['owner_id'],start_date: start_date,end_date: end_date,progress: {todo: project['progress']['todo'],in_progress: project['progress']['in_progress'],done: project['progress']['done']},percent_completion: percent_completion,}
  end

解决方法

ABC指标专门用于帮助提高可读性。通常,如果您达到ABC限制,则该代码的可读性可能会比您想象的要低得多,因为该方法干得太多。

我建议:

  • 考虑通过该方法(分支)有多少种不同的方式
  • 考虑如何测试所有这些分支,或者至少执行每个代码路径

如果您想弄清楚实际需要做什么,那么您对ABC指标所指出的内容就会有所了解。

要重构您的代码,我将:

  • @result_json提取到将确保始终创建访问器方法的后面,然后在您的问题方法中调用result_json而不是@result_json
def result_json
  @result_json ||= { results: [] }
end
  • 分离出处理@result_set的逻辑-考虑创建一个包装结果集并提供适当访问器的类,例如
class ResultSet
  def initialize(hsh)
    @hsh = hsh
  end

  def total_entries
    @hsh['meta']['total']
  end

  def issues
    @hsh['issues']
  end

  def users
    # obviously... you need the fr_results_hash method available here too
    @user_hash ||= fr_results_hash(@hsh['users'])
  end

  def project_data
    @project_data ||= fr_results_hash(@hsh['projects'])
  end
end

然后,您可以在result_set = ResultSet.new(@result_set)之类的方法中使用此方法,并直接调用result_set.project_data之类的实例方法,而无需创建局部变量来保存每个数据。

  • 假设@result_set['issues']是一个数组,在数组(.compact)上调用fr_issues.compact.each do |issue|将会从数组中删除所有nil值,这是我想的您在if issue块中检查fr_issues.each时要防备。这意味着您可以删除这些条件,因为它们不会发生。

更一般而言,该方法中@variables的使用率很高。这使得该方法在没有上下文的情况下很难理解。考虑这些对象是否真的应该是实例方法,或者应该将其范围限定在方法本身之内。

您的第二种方法有问题,这是因为三元运算的过度使用,需要将这些值分配给方法中的变量。创建一些辅助方法会有所帮助,例如:

start_date = project['start_date'].nil? ? '--' : project['start_date'].in_time_zone(current_time_zone).strftime(date_time_format)
end_date = project['end_date'].nil? ? '--' : project['end_date'].in_time_zone(current_time_zone).strftime(date_time_format)

拥有:

def format_date(value)
  value.nil? ? '--' : value.in_time_zone(current_time_zone).strftime(date_time_format)
end

然后在您的方法中,只需使用format_date(project['start_date'])format_date(project['end_date'])。因为调用它们没有复杂性,所以只需直接在最终哈希中调用它们,而不是将它们分配给变量即可。 同样,在返回哈希中添加方法def project_completion_percent(progress)然后直接调用project_completion_percent(project['progress'])将摆脱2个分配和一个分支。另一个想法...格式化description的方法将意味着您可以摆脱方法中的2行代码,2个赋值和一个分支。

还有更多优化,但希望可以提供足够的指针

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...