Reports functions that have a too high cognitive complexity.
You can configure the threshold above which a function will be reported (15 in the example configuration below).
config =
[ CognitiveComplexity.rule 15
]
What is cognitive complexity?
Cognitive complexity is not to be confused with "Cyclomatic Complexity", which has a different way of measuring the
complexity.
Here's an explanation extracted from free white paper
provided by SonarSource, the creators of the concept.
Cognitive complexity tries to measure how hard it is to understand a function, primarily focusing on the control structures
that hinder the understanding of a function by reading it from top to bottom in one go, like you would for a novel.
A Cognitive Complexity score is assessed according to three basic rules:
Ignore structures that allow multiple statements to be readably shorthanded into one
Increment (add one) for each break in the linear flow of the code
Increment when flow-breaking structures are nested
Some small differences may be found between the implementation detailed in the paper and this rule, as the idea was
formulated more on imperative programming languages, and may not be applicable to a pure functional language like Elm.
This rule is an experiment. I don't know if this will be more useful or detrimental, and I haven't yet figured out what
the ideal complexity threshold for Elm projects is.
I would for now recommend to use it with a very high threshold to find places in your codebase that need refactoring,
and eventually to enable it in your configuration to make sure no new extremely complex functions appear. As you refactor more
and more of your codebase, you can gradually lower the threshold until you reach a level that you feel happy with.
Please let me know how enabling this rule works out for you!
Complexity breakdown
Following is a breakdown of how the complexity of a function is computed:
If expression: Increases complexity by 1 + nesting, and increases nesting.
else if also increases complexity by 1 + nesting, but doesn't further increase the nesting.
else doesn't increase the complexity.
-- Total: 4
a =
if b then -- +1
if c then -- +2, including 1 for nesting
1
else
2
else if d then -- +1
3
else -- +0
4
Case expression: Increases complexity by 1 + nesting, regardless of how many cases are handled, and increases nesting.
-- Total: 3
a =
case b of -- +1
A -> 1
B -> 2
C ->
case c of -- +2, including 1 for nesting
_ -> 3
D -> 4
Let functions: Increases nesting.
-- Total: 2
a =
let
fn b = -- increases nesting
if b then -- +2, including 1 for nesting
1
else
2
constant = -- Not a function, no increase
True
in
fn constant
Anonymous functions: Increases nesting.
-- Total: 2
a things =
List.map
(\thing -> -- increases nesting
case thing of -- +2, including 1 for nesting
Just _ -> 1
Nothing -> 2
)
things
Logical operator suites: Increase complexity by 1 for every discontinuation of the suite
a && b -- +1
-- This is still the same logical construction as
-- above, and therefore about as hard to understand
a && b && c && d && e -- +1
-- Total: 3
a && b && c -- +1
|| d -- +1 for breaking the chain of && with a ||
|| not (e || f) -- +1 for breaking the chain
-- with a `not` of a binary operation
Recursive function calls (direct or indirect): Increase complexity by 1 for each different call
-- Total: 2
fun1 n =
fun2 n -- +1
+ fun2 n -- +0, already counted
+ fun1 n -- +1
-- Total: 1
fun2 n =
fun1 n -- +1
The original metric increases the complexity for other
structures that the Elm language doesn't have.
Try it out
You can try this rule out by running the following command:
The cognitive complexity is set to 15 in the configuration used by the example.
Thanks
Thanks to the team at SonarSource for designing the metric and for not restricting its use.
Thanks to G. Ann Campbell for the different talks she made on the subject.
Reports functions that have a too high cognitive complexity.
You can configure the threshold above which a function will be reported (
15in the example configuration below).What is cognitive complexity?
Cognitive complexity is not to be confused with "Cyclomatic Complexity", which has a different way of measuring the complexity.
Here's an explanation extracted from free white paper provided by SonarSource, the creators of the concept.
Some small differences may be found between the implementation detailed in the paper and this rule, as the idea was formulated more on imperative programming languages, and may not be applicable to a pure functional language like Elm.
You can read about how is works in the complexity breakdown section below.
When (not) to enable this rule
This rule is an experiment. I don't know if this will be more useful or detrimental, and I haven't yet figured out what the ideal complexity threshold for Elm projects is.
I would for now recommend to use it with a very high threshold to find places in your codebase that need refactoring, and eventually to enable it in your configuration to make sure no new extremely complex functions appear. As you refactor more and more of your codebase, you can gradually lower the threshold until you reach a level that you feel happy with.
Please let me know how enabling this rule works out for you!
Complexity breakdown
Following is a breakdown of how the complexity of a function is computed:
else ifalso increases complexity by 1 + nesting, but doesn't further increase the nesting.elsedoesn't increase the complexity.The original metric increases the complexity for other structures that the Elm language doesn't have.
Try it out
You can try this rule out by running the following command:
The cognitive complexity is set to 15 in the configuration used by the example.
Thanks
Thanks to the team at SonarSource for designing the metric and for not restricting its use. Thanks to G. Ann Campbell for the different talks she made on the subject.