Ruby 圈复杂度和感知复杂度
Ruby Cyclomatic and Perceived complexity
我有这个服务对象可以解析 excel 文件并将数据保存在其中。 Rubocop 将其标记为:
app/services/csv_upload.rb:17:3: C: Metrics/AbcSize: Assignment Branch Condition size for parse_spreadsheet is too high. [<14, 34, 11> 38.38/35]
def parse_spreadsheet ...
^^^^^^^^^^^^^^^^^^^^^
app/services/csv_upload.rb:17:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for parse_spreadsheet is too high. [10/6]
def parse_spreadsheet ...
^^^^^^^^^^^^^^^^^^^^^
app/services/csv_upload.rb:17:3: C: Metrics/PerceivedComplexity: Perceived complexity for parse_spreadsheet is too high. [11/7]
我该如何解决这个问题?我应该如何重构这段代码?
parse_spreadsheet
方法是它被标记的地方。
require "spreadsheet"
class CsvUpload
attr_accessor :review
def initialize(file)
Spreadsheet.client_encoding = "UTF-8"
tempfile = File.open(file.tempfile)
@spreadsheet = Spreadsheet.open tempfile
@exception_sheet = @spreadsheet.worksheet 3
@review = []
parse_spreadsheet
end
def parse_spreadsheet
@exception_sheet.each_with_index 4 do |row, index|
employee_no = row[1]
department = row[2]
date = row[3].to_datetime
time_in = row[4].to_datetime unless row[4].nil?
time_out = row[5].to_datetime unless row[5].nil?
if department == "Night"
next_row = @exception_sheet.to_a[index + 5]
next_date = next_row[3].to_datetime
next_time_in = next_row[4].to_datetime unless next_row[4].nil?
start_time = set_date_time(date, time_out) unless time_out.nil?
end_time = set_date_time(next_date, next_time_in) unless next_time_in.nil?
else
start_time = set_date_time(date, time_in) unless time_in.nil?
end_time = set_date_time(date, time_out) unless time_out.nil?
end
@employee = Employee.find_by(employee_no: employee_no)
next if @employee.nil?
@attendance_item = AttendanceItem.create(
start_time: start_time, end_time: end_time, employee_id: @employee.id
)
end
end
def to_review
@review
end
private
def set_date_time(date, time)
DateTime.new(
date.year,
date.month,
date.day,
time.hour,
time.min,
time.sec,
"+0800"
).in_time_zone
end
end
我首先为@exception_sheet:
中的每个项目设置一个单独的方法
def parse_spreadsheet
@exception_sheet.each_with_index 4 do |row, index|
handle_exception_row(row, index)
end
end
def handle_exception_row(row, index)
employee_no = row[1]
department = row[2]
date = row[3].to_datetime
time_in = row[4].to_datetime unless row[4].nil?
time_out = row[5].to_datetime unless row[5].nil?
if department == "Night"
next_row = @exception_sheet.to_a[index + 5]
next_date = next_row[3].to_datetime
next_time_in = next_row[4].to_datetime unless next_row[4].nil?
start_time = set_date_time(date, time_out) unless time_out.nil?
end_time = set_date_time(next_date, next_time_in) unless next_time_in.nil?
else
start_time = set_date_time(date, time_in) unless time_in.nil?
end_time = set_date_time(date, time_out) unless time_out.nil?
end
@employee = Employee.find_by(employee_no: employee_no)
next if @employee.nil?
@attendance_item = AttendanceItem.create(
start_time: start_time, end_time: end_time, employee_id: @employee.id
)
end
end
这修复了 parse_spreadsheet 方法,但使用 handle_exception_row
产生了新的错误。然后将其剥离:
def handle_exception_row(row, index)
employee_no = row[1]
department = row[2]
date = row[3].to_datetime
time_in = row[4].to_datetime unless row[4].nil?
time_out = row[5].to_datetime unless row[5].nil?
handle_attendance_creation(employee_no: employee_no, department: department, date: date, time_in: time_in, time_out: time_out)
end
def handle_attendance_creation(employee_no:, department:, date:, time_in:, time_out:)
if department == "Night"
next_row = @exception_sheet.to_a[index + 5]
next_date = next_row[3].to_datetime
next_time_in = next_row[4].to_datetime unless next_row[4].nil?
start_time = set_date_time(date, time_out) unless time_out.nil?
end_time = set_date_time(next_date, next_time_in) unless next_time_in.nil?
else
start_time = set_date_time(date, time_in) unless time_in.nil?
end_time = set_date_time(date, time_out) unless time_out.nil?
end
@employee = Employee.find_by(employee_no: employee_no)
next if @employee.nil?
@attendance_item = AttendanceItem.create(
start_time: start_time, end_time: end_time, employee_id: @employee.id
)
end
end
您可能仍会在 handle_attendance_creation
上遇到错误,但希望您能看到这是怎么回事。剔除采用所需参数的更小的方法,您将到达那里
我有这个服务对象可以解析 excel 文件并将数据保存在其中。 Rubocop 将其标记为:
app/services/csv_upload.rb:17:3: C: Metrics/AbcSize: Assignment Branch Condition size for parse_spreadsheet is too high. [<14, 34, 11> 38.38/35]
def parse_spreadsheet ...
^^^^^^^^^^^^^^^^^^^^^
app/services/csv_upload.rb:17:3: C: Metrics/CyclomaticComplexity: Cyclomatic complexity for parse_spreadsheet is too high. [10/6]
def parse_spreadsheet ...
^^^^^^^^^^^^^^^^^^^^^
app/services/csv_upload.rb:17:3: C: Metrics/PerceivedComplexity: Perceived complexity for parse_spreadsheet is too high. [11/7]
我该如何解决这个问题?我应该如何重构这段代码?
parse_spreadsheet
方法是它被标记的地方。
require "spreadsheet"
class CsvUpload
attr_accessor :review
def initialize(file)
Spreadsheet.client_encoding = "UTF-8"
tempfile = File.open(file.tempfile)
@spreadsheet = Spreadsheet.open tempfile
@exception_sheet = @spreadsheet.worksheet 3
@review = []
parse_spreadsheet
end
def parse_spreadsheet
@exception_sheet.each_with_index 4 do |row, index|
employee_no = row[1]
department = row[2]
date = row[3].to_datetime
time_in = row[4].to_datetime unless row[4].nil?
time_out = row[5].to_datetime unless row[5].nil?
if department == "Night"
next_row = @exception_sheet.to_a[index + 5]
next_date = next_row[3].to_datetime
next_time_in = next_row[4].to_datetime unless next_row[4].nil?
start_time = set_date_time(date, time_out) unless time_out.nil?
end_time = set_date_time(next_date, next_time_in) unless next_time_in.nil?
else
start_time = set_date_time(date, time_in) unless time_in.nil?
end_time = set_date_time(date, time_out) unless time_out.nil?
end
@employee = Employee.find_by(employee_no: employee_no)
next if @employee.nil?
@attendance_item = AttendanceItem.create(
start_time: start_time, end_time: end_time, employee_id: @employee.id
)
end
end
def to_review
@review
end
private
def set_date_time(date, time)
DateTime.new(
date.year,
date.month,
date.day,
time.hour,
time.min,
time.sec,
"+0800"
).in_time_zone
end
end
我首先为@exception_sheet:
中的每个项目设置一个单独的方法def parse_spreadsheet
@exception_sheet.each_with_index 4 do |row, index|
handle_exception_row(row, index)
end
end
def handle_exception_row(row, index)
employee_no = row[1]
department = row[2]
date = row[3].to_datetime
time_in = row[4].to_datetime unless row[4].nil?
time_out = row[5].to_datetime unless row[5].nil?
if department == "Night"
next_row = @exception_sheet.to_a[index + 5]
next_date = next_row[3].to_datetime
next_time_in = next_row[4].to_datetime unless next_row[4].nil?
start_time = set_date_time(date, time_out) unless time_out.nil?
end_time = set_date_time(next_date, next_time_in) unless next_time_in.nil?
else
start_time = set_date_time(date, time_in) unless time_in.nil?
end_time = set_date_time(date, time_out) unless time_out.nil?
end
@employee = Employee.find_by(employee_no: employee_no)
next if @employee.nil?
@attendance_item = AttendanceItem.create(
start_time: start_time, end_time: end_time, employee_id: @employee.id
)
end
end
这修复了 parse_spreadsheet 方法,但使用 handle_exception_row
产生了新的错误。然后将其剥离:
def handle_exception_row(row, index)
employee_no = row[1]
department = row[2]
date = row[3].to_datetime
time_in = row[4].to_datetime unless row[4].nil?
time_out = row[5].to_datetime unless row[5].nil?
handle_attendance_creation(employee_no: employee_no, department: department, date: date, time_in: time_in, time_out: time_out)
end
def handle_attendance_creation(employee_no:, department:, date:, time_in:, time_out:)
if department == "Night"
next_row = @exception_sheet.to_a[index + 5]
next_date = next_row[3].to_datetime
next_time_in = next_row[4].to_datetime unless next_row[4].nil?
start_time = set_date_time(date, time_out) unless time_out.nil?
end_time = set_date_time(next_date, next_time_in) unless next_time_in.nil?
else
start_time = set_date_time(date, time_in) unless time_in.nil?
end_time = set_date_time(date, time_out) unless time_out.nil?
end
@employee = Employee.find_by(employee_no: employee_no)
next if @employee.nil?
@attendance_item = AttendanceItem.create(
start_time: start_time, end_time: end_time, employee_id: @employee.id
)
end
end
您可能仍会在 handle_attendance_creation
上遇到错误,但希望您能看到这是怎么回事。剔除采用所需参数的更小的方法,您将到达那里