4 ms·
I dunno, often spaghetti code (long functions with plenty of scopes and conditionals) gets high complexity scores while ravioli code (lots of short functions wi
by _yosefk 11y ago
I dunno, often spaghetti code (long functions with plenty of scopes and conditionals) gets high complexity scores while ravioli code (lots of short functions with simple and almost-flat control flow calling each other - "lots" as in "you can't quite remember who calls who and why you're looking at this here function right now") gets low scores; while personally I'd rather have a bowl of spaghetti over a bowl of ravioli if I'm forced to choose one of the two on any day. So I'm not a huge fan of these tools. (Assigning higher complexity to longer programs does help; but then to me, wc -l is the ultimate complexity score...)
- chipsy 11y agoI agree. Ravioli code is particularly nasty because it fulfills "DRY" in the small but hurts the ability to make further changes. In both the spaghetti and ravioli situations a cyclical attack of "factor/inline/factor/inline" flushes away the worst stuff and reveals opportunities for more substantial changes, but it's easier to start from the case where there's too much inline code than to fumble through a deep callstack. That said, if your functions are pure functions, they won't contribute much to overall complexity. It's a much different situation from having a do_the_thing() method that does some mutability magic.
- barrkel 11y agoI came here to post this comment, and I fully concur. The lightbulb moment for me came when I got a job working on a compiler and had to start maintaining some long files with some very large functions. Being able to read linearly through a long, fairly flat function easily beats hopping hither and tither trying to remember which bit does what and piece the whole thing together. The real complexity in code isn't from the code itself, of course; it's in the data it works with, how it modifies the data, and how far apart bits of code that may touch the same bit of data in interleaved sequences are. It's also one of the reasons I prefer reading recursive algorithms that use pattern matching, or in a pinch, switch statements, over and above dynamic dispatch from polymorphic references. If code doesn't need to be open to extension, it's much better off exposing an enum or some other easily flat-switched thing, than implementing a recursive algorithm in almost any other form.