Когнитивная сложность Rails равна 6 (превышает допустимые 5)

#ruby-on-rails #ruby #code-climate

#ruby-on-rails #ruby #код-климат

Вопрос:

У меня есть приложение, которое подключено к CodeClimate, и оно показывает мне ошибку Method upstream_transactions has a Cognitive Complexity of 6 (exceeds 5 allowed) с указанным ниже кодом:

 def upstream_transactions(bank_account:, external_account:, external_transactions:)
  external_transactions.each do |transaction|
    next if transaction.currency != 'USD'

    transfer = BankTransfer.unscoped.find_or_create_by(
  

Эта ошибка появилась после того, как я добавил строку next if transaction.currency != 'USD' .

 def upstream_transactions(bank_account:, external_account:, external_transactions:)
  external_transactions.each do |transaction|
    next if transaction.currency != 'USD'

    transfer = BankTransfer.unscoped.find_or_create_by(
      customer_id: customer.id, transaction_identifier: transaction.transaction_id
    )
    next if transfer.deleted_at?

    transfer.update(
      date: transaction.booked_at,
      # (...) some other params
    )
  end
  Success(bank_account: bank_account, external_account: external_account)
end
  

Как избежать такой ошибки?

Ответ №1:

Вы могли бы уменьшить сложность, создав несколько вспомогательных методов, которые вы можете вызвать. Может быть

 def obtain_transfer(transaction)
  BankTransfer.unscoped.find_or_create_by(
      customer_id: customer.id, transaction_identifier: transaction.transaction_id)
end
  

В

    next unless transaction.currency == 'USD'
  

хотя вы могли бы даже

     external_transactions.select { |t| t.currency == 'USD' }.each do |transaction|
  

Следует ли вызывать метод upstream_USD_transactions вместо этого? Было бы разумно, чтобы потенциальный абонент каким-то образом знал, что он собирается отменить все переводы, не связанные с долларами США?

Ответ №2:

Это не ошибка, когнитивная сложность — это:

мера того, насколько сложно интуитивно понять единицу кода

Итак, когда вы добавили этот дополнительный оператор управления потоком next if transaction.currency != 'USD' , это усложнило тестирование кода. Добавление операторов типа if , unless , amp;amp; , и всего, что добавляет дополнительное управление логическим потоком (например, операторы переключения), увеличит сложность.

Вы можете использовать два подхода, чтобы попытаться минимизировать эту сложность:

  1. Измените добавленный оператор
  2. Измените существующий метод

Если в уже сложный метод был добавлен небольшой оператор, попробуйте взглянуть на то, что можно упростить в этом существующем методе. Подобно тому, что @nullTerminator предложил в своем ответе, разделение логики на различные вспомогательные методы может снизить сложность. Меньшие методы было бы легче тестировать, и каждый из них должен иметь меньшую когнитивную сложность.