Rails Cognitive Complexity of 6 (exceeds 5 allowed)

2.8k views Asked by At

I've got an app which is connected to CodeClimate and it shows me an error Method upstream_transactions has a Cognitive Complexity of 6 (exceeds 5 allowed) with marked below code:

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(

This error showed up after I added line 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

How to avoid such error?

2

There are 2 answers

0
nullTerminator On

You could reduce the complexity by making a few helper methods you can call. Maybe

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

There are fewer 'nots' in

   next unless transaction.currency == 'USD'

although you could even

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

Should the method be called upstream_USD_transactions instead? Would it be reasonable for the prospective caller to somehow know it is going to discard all non-USD transfers?

0
Christine On

It's not an error, cognitive complexity is a:

measure of how difficult a unit of code is to intuitively understand

So when you added that additional flow control statement next if transaction.currency != 'USD' it added complexity to the testing of the code. Adding in statements like if, unless, &&, and anything that adds additional logic flow control (ex. switch statements) will increase the complexity.

You can take two approaches to trying to minimize this complexity:

  1. Modify your added statement
  2. Modify the existing method

If a small statement was added into an already complex method, then try taking a look at what can be simplified in that existing method. Like what @nullTerminator suggested in their answer, dividing out the logic into different helper methods could cut down the complexity. The smaller methods would be easier to test, and should each have a smaller cognitive complexity.