8 ms·
My favorite quote about this topic: Measuring programming progress by lines of code is like measuring aircraft building progress by weight. - Bill Gates M
by khaledh 6y ago
My favorite quote about this topic:
Measuring programming progress by lines of code is like measuring aircraft building progress by weight. - Bill Gates
My personal point of view is that: every line of code you write is a liability. Code is not an asset; a solved problem is.
Edit: To clarify, I'm definitely not encouraging writing "clever" short code. Always strive to write clear code. You write it once, but it will be read (and potentially changed) many, many times.
- Waterluvian 6y agoSome take "line of code" literally. Others see it as a stand-in for complexity. Because one can certainly make a short program that's far more of a liability than a long one. I'm wondering if there's a quality term for a "unit of complexity" in code? Like when a single line has 4 or 5 "ideas" in it.
- segfaultbuserr 6y agoThere are many metrics for measuring the logic complexity of code. An early and best-known one is Cyclomatic Complexity [0] - The more possible execution paths, the higher the score. You can find more at Software Metric [1]. [0] https://en.wikipedia.org/wiki/Cyclomatic_complexity https://en.wikipedia.org/wiki/Cyclomatic_complexity [1] https://en.wikipedia.org/wiki/Software_metric https://en.wikipedia.org/wiki/Software_metric
- Waterluvian 6y agoPerfect. This is what I was curious about. Haven't heard of either. Thank you.
- gurkendoktor 6y agoIf there is a useful metric, then I haven't found it yet. The data on cyclomatic complexity[1] does not convince me, and in practice, the linters I've seen have complained about boring code like this: switch (foo) { case KIND_1: return parseObjectOfKind1(); case KIND_2: return parseObjectOfKind2(); case KIND_3: return parseObjectOfKind3(); ... case KIND_15: return parseObjectOfKind5(); case KIND_16: return parseObjectOfKind16(); } There are 16 paths and yet this code is easy to follow. There is no substitute for human judgement (code reviews). [1] https://en.wikipedia.org/wiki/Cyclomatic_complexity#Correlation_to_number_of_defects https://en.wikipedia.org/wiki/Cyclomatic_complexity#Correlat...
- Waterluvian 6y agoThat's what I was thinking about when I used "ideas". To me there's one main idea in all that code: "we are returning a parsed object of a kind" Not that I'm trying to sell "ideas". I don't even know. But it's this very loose concept that floats around my mind when writing code. How many ideas are there in a stanza? Ahh too many. I should break out one of the larger ideas to happen before.
- segfaultbuserr 6y agoSpeaking of measuring "ideas", the holy grail of complexity metric is Kolmogorov complexity - theoretically, the inherent complexity of a piece of data (including code) can be defined as the shortest possible program that generates it. For example, 20 million digits of pi or a routine that uses 20 branches to return the same object has low Kolmogorov complexity, because it's easy to write a generator for that, meanwhile a parser is more complex. But it's only a mathematical construction and is uncomputable, just like the halting problem. In real life, for some applications a good compression algorithm like LZMA is sufficient to approximate it. But I'm not sure if it's suitable for measuring computer programs - it would still have a strong correlation to the number of lines of code.
- nitrogen 6y agoIt kind of encourages you to use a lookup table or polymorphism, which isn't far off from what the compiler is likely to do with that switch statement. As for correlation to number of defects, another important factor is maintainability (velocity of new features in growing programs, keeping up with infrastructure churn in mature programs). If reducing perceived complexity improves maintainability, and if measuring cyclomatic complexity despite its flaws helps reduce perceived complexity, then it's still a useful metric.
- Waterluvian 6y agoFeels like one of those classic, "no one tool gives you the one correct answer. They all give you data and you come to an informed conclusion having utilized one or many of them."
- LanceH 6y agoThe real measure you want is the cyclomatic complexity divided by the complexity required by the problem. The problem with line counting (or cyclo counting) is that it assumes a constant ratio.
- Hammershaft 6y agoIt is not trivial to understand the necessary complexity of a problem. In SICP, there's an early practice problem that asks you to turn a recursive number pattern generator into an iterative generator. What the problem doesn't tell you is that the generator obscured by complex recursion is actually creating a tribbonaci number sequence. This hidden insight turns a difficult problem into a trivial problem.
- LanceH 6y agoI certainly didn't mean to imply it was trivial (or even possible). I'm just pointing out that assuming increasing LoC implies an increase in necessary complexity is just wrong.
- agustif 6y agoFor VS Code have used this on the past: https://marketplace.visualstudio.com/items?itemName=kisstkondoros.vscode-codemetrics https://marketplace.visualstudio.com/items?itemName=kisstkon... and this one https://marketplace.visualstudio.com/items?itemName=Stepsize.tech-debt-tracker https://marketplace.visualstudio.com/items?itemName=Stepsize... These two haven't tried before but doing it now: https://marketplace.visualstudio.com/items?itemName=selcuk-usta.code-complexity-report-generator https://marketplace.visualstudio.com/items?itemName=selcuk-u... https://marketplace.visualstudio.com/items?itemName=TomiTurtiainen.js-complexity-analysis https://marketplace.visualstudio.com/items?itemName=TomiTurt...
- kccqzy 6y ago> The more possible execution paths, the higher the score. Great! Now we can all begin to write branchless code. Make branch prediction miss a thing of the past!
- mywittyname 6y agoYou jest, but I had a manager who loved Cyclomatic complexity as a measure of programmer ability. I tried in vain to convince him that CC was measuring the complexity of the underlying business logic, not my programming ability. I wasted a lot of brainpower cutting down CC in my code doing terrible things like storing function names as strings in hashmaps, i.e., String fn = codepaths.get(if_statement_value); obj.getClass().getDeclaredMethod(fn).invoke(param,...); Because that could replace several 'if' checks, since function calls weren't branches. Of course, no exception handling, because you could save branches by using throws Exception. To this day, I wonder if Cyclomatic complexity obsession helped make "enterprise Java" what it is today.
- nybble41 6y agoThe worst part is that this doesn't even reduce the cyclomatic complexity of the code. You replaced conditional branches with table lookups, indirect function calls, and exceptions, but you still have the same number of paths through the code—or perhaps more with the extra code for the table lookups. In the end you're just hiding the real complexity from the tools. Minimizing cyclomatic complexity might actually be a reasonable approach, if the complexity were accurately measured without these blind spots. For example, any indirect calls should be attributed a complexity based on the number of possible targets, and any function that can throw an exception should be counted as having at least two possible return paths (continue normally or branch to handler / re-throw exception) at each location where it's called.
- khaledh 6y agoI'm definitely not encouraging writing "clever" short code. Always strive to write clear code. You write it once, but it will be read (and potentially changed) many, many times. As for complexity metrics, this is a contentious topic. It's hard to quantify "ideas" or "concepts". I think this is the part where technical design reviews and good code reviews help keep in check.
- WorldMaker 6y agoDevelopers have tried to build metrics for "complexity" over the years. Cyclomatic Complexity is often pointed to as one of the more successfully deployed: https://en.wikipedia.org/wiki/Cyclomatic_complexity https://en.wikipedia.org/wiki/Cyclomatic_complexity As with any metric, it's something to take as useful "advice" and becomes a terrible burden if you are optimizing for/against it directly. (Such as if you are incentivized by a manager to play a game of hitting certain metric targets.) It's also interesting to note that a complete and accurate complexity metric for software is likely impossible due to it being an extension/corollary of the Halting Problem.
- Twirrim 6y agoMy IDE spits out a warning when I reach a certain level of complexity in a method, using Mccabe's Cyclomatic Complexity as a measure. It roughly maps with "too many if statements" in my case.
- stocknoob 6y ago"My point today is that, if we wish to count lines of code, we should not regard them as “lines produced” but as “lines spent”: the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger." -E. Dijkstra
- jjice 6y agoI'd expect nothing less wise from Dijkstra. I feel like every week I learn something new from that man.
- mumblemumble 6y agoI prefer the Gates version. Dijkstra's implicit premise rather naively assumes that it is somehow less expensive to produce fewer lines of code. It's arguably such an absolute statement that it subtly encourages people to engage in undesirable behaviors such as playing code golf at work. Gates's, on the other hand, accurately captures the reality: while, all else being equal, a lighter-weight design is preferable to a heavier one, it takes some skill and effort to actually produce the lighter design. Which leaves open the possibility that doing so may not actually be worth the effort.
- msla 6y agoThe relevant metric isn't lines but concepts: Which code does it in the fewest new ideas? Generally, that's the best, where "new ideas" would be ideas new to a domain expert. For example, in a video game, each of the specific monster types is an idea someone who is an expert in that game would know. The ideas in the memory management code are new. You can't remove all code relevant to a specific monster without removing that monster, at which point you're no longer implementing the same game, but slimming down the number of new concepts in the memory management code is not directly relevant to gameplay. In short: Make program logic similar to business logic.
- klingon78 6y agoThis is great. Another thing is that sometimes leaving things as-is can be better than making changes. The problem you might be avoiding is change. Things that are bad should probably be fixed, though.
- ragnese 6y agoI agree. But, like everything, even this concept gets abused. Example: "Zero code solutions". Hell, we even had that back in the old days with Java frameworks doing a ton of configuration via XML files. Sure, it's not "code", but it's basically the same thing and still a liability. Especially if there's a very steep learning curve to all of the features/configurations that you'll never use. A more subtle problem with abusing this idea is the over-dependency on third party code. Sure, it might look like you haven't written any code when you do `npm install foo`, but really, you've just placed a bunch of trust in some other person. Do you vet your dependencies' authors the same way you vet potential employees at your company? There's a fine line and it's an art form figuring out when to bring in outside code or to NIH it. IMO, of course.
- deleted 6y ago[deleted]
- mikepurvis 6y agoI'm hitting this right now with having just inherited maintenance of a complicated CI pipeline with a lot of intermediate containers based on generated Dockerfiles, all of which runs by bind-mounting docker.sock— basically stuff that might have been best practice 3-4 years ago, but for which there are absolutely better solutions now. Anyway, it's interesting evaluating those potential solutions, because certain things like going to a daemonless, rootless, bind-less build based on podman/buildah is a no-brainer, but the next frontier beyond that has a bunch of tools like ocibuilder, cekit, ansible-bender, etc which want to establish various ways of declaratively expressing an image definition, and although the intent is good there, it's absolutely not worth getting sucked into long-term dependence on pre-1.0 tools with single-digit number of contributors and an uncertain maintenance future.
- richardwhiuk 6y ago> Sure, it's not "code" I utterly reject this assertion.
- jaylo2015 6y agoAgree. But then the problem becomes how to count solved problems. One equally terrible practice is to count number of tickets solved. I found this is somewhat true in my career: bug fixes == job security. I cannot morally accept this but I have seen this again and again.
- Cd00d 6y agoI think it's in the application for DE Shaw that you're asked to number the lines of code you've written in your career in the various languages you claim to have experience in.
- asdff 6y agoI wonder if they then normalize this by years of experience
- AnimalMuppet 6y ago> My personal point of view is that: every line of code you write is a liability. Very true... but also false in a way. Here's a little bit of functionality that has to be in there to implement the way we're solving the problem. That code is a liability; it would be better to solve the problem in a way where we don't need this bit of code. But given that we're solving it this way, let's say that this little bit of functionality may be implemented in one line, which is almost unreadable, or in five very clear lines. That one line is far more of a liability than the five lines are.
- rakoo 6y agoTo be more precise, every line of code is debt. You get immediate benefits (working software) but you need to pay recurring obligations (bugs). Just like debt, there is a right amount to have: too much and you are incapacitated because you owe more than you can produce, too little and you don't have enough runway to produce what you want. Note that I'm talking about from a company's point of view.
- deleted 6y ago[deleted]