Hacker News
Cyclomatic Complexity in C#
Deukhoofd
|next
[-]
I think generally when you run into something like this, the better way to handle it is to sit back, and reconsider how your overall handling is designed.
bunderbunder
|next
|previous
[-]
That means that it really only counts explicit branching. So, for example, in an OO language like C#, calling a virtual method doesn’t increment cyclomatic complexity even though the method invocation could go down many code paths. Potentially thousands if you’re dealing with a common interface like IEnumerable. If you’re working on a library then the number of potential code paths in this kind of situation is unbounded.
As an aside, it’s interesting to think how it might apply to a language like Smalltalk that doesn’t even have if or switch statements.
OO isn’t the only monkey wrench, either. Higher-order functions also introduce forms of branching that cyclomatic complexity doesn’t measure.
Again that doesn’t make it a useless metric. Just don’t think that a cyclomatic complexity limit in your codebase is some sort of maintainability panacea. Some of the least comprehensible functions I’ve deciphered had quite low cyclomatic complexities.
wvenable
|root
|parent
|next
[-]
Taking the example provided in the article, I don't feel like the new code is meaningfully less complex. In fact, since it added some additional indirection, I could argue it's slightly more complex.
The core code with the nested if statements is something that I would probably refactor in some other way entirely. Maybe by taking advantage of other language features. It is a toy example so it's hard to say but that's part that feels like it needs simplification and untouched in this example.
bunderbunder
|root
|parent
[-]
You could additionally test the three helper functions. But the original tests against ProcessOrder would still be needed for completeness, so they wouldn’t necessarily add much except in an Uncle Bob style, “He who dies with the largest burden of gratuitous micro-tests wins,” sort of way.
Now if I really wanted to make that code easier to test, I’d instead be looking into ways to make the whole thing less stateful. Temporal coupling is much more confusing than if statements.
RaftPeople
|root
|parent
|previous
[-]
In agreement with your post, this research that measures cognitive load via EEG and time spent shows that the metrics we use for complexity and readability are only partial matches to what is going on: https://pmc.ncbi.nlm.nih.gov/articles/PMC9942489/
throwyawayyyy
|next
|previous
[-]
ivm
|next
|previous
[-]
runningmike
|next
|previous
[-]
[1] https://nocomplexity.com/documents/codeaudit/complexitycheck...
thomasmg
|root
|parent
[-]
ozim
|root
|parent
[-]
Worst things happen always when 2 or more systems are combined because each system might be simple on its own, yet a combination is always much more complex.
BoiledCabbage
|root
|parent
|next
[-]
For something the the prior statement it is never a weird question to ask of there actually evidence of this or just it seems like it should be true so we believe it.
There are tons of things that seem like they would obviously be true, but it turns out they aren't.
ozim
|root
|parent
|next
[-]
That is just maths here working. Two systems combined always will have more states and inputs/outputs.
There is nothing to check here as it can be proven purely by maths.
Complex systems having more attack surface are obviously less secure.
They might be less interesting for attackers if they have to scan huge attack surface like IPv6 vs IPv4 but no one is claiming IPv6 network is more secure.
bunderbunder
|root
|parent
|next
|previous
[-]
It’s also the case that some of the most common sources of vulnerabilities, such as SQL injection, introduce no additional cyclomatic complexity. Heck, buffer overflows are good for your cyclomatic complexity - those array bounds checks are all extra branches.
pixl97
|root
|parent
[-]
Now, it's probably not a direct correlation. I'd think security bugs are more likely from programmers that unintentionally raise CC without really realizing it. Aka, overreaching their own knowledge when simpler structures are avaliable.
bunderbunder
|root
|parent
[-]
Here’s an oldie but goodie: https://cs.du.edu/~snarayan/sada/teaching/COMP3705/lecture/p...
I’ve personally had better success thinking of it as more of a measure of readability than of quality.
saghm
|root
|parent
|previous
[-]
woggy
|next
|previous
[-]
Personally I have a some tools that build dependency graphs (C# and Python) and store the results in a local database. Agents seem quite good at poking at this and coming up with refactor ideas. Graph analysis tools are useful here, simple application will detect cyclical dependencies, but I encourage the agents to use more complex tools like clustering to poke at the data.