[HN Gopher] -2000 Lines of Code ___________________________________________________________________ -2000 Lines of Code Author : pcr910303 Score : 394 points Date : 2021-03-08 16:07 UTC (6 hours ago) (HTM) web link (www.folklore.org) (TXT) w3m dump (www.folklore.org) | methyl wrote: | If you want to read about flawed metrics, how they affect the | production and what to do about it in a form of interesting novel | - check out The Goal by Elijjahu M. Goldratt. It's a classic, but | gets recommended seldom for how good it is. | meepmorp wrote: | There are some fascinating stories on the site, including some | ones about Bill Atkinson (the programmer here) that really help | to flesh out the sheer absurdity of asking him, in particular, to | fill out a sheet like that. I believe he personally wrote | something like 2/3 of the original Macintosh ROM. | | edit: here's one that I find to be an interesting character | study: | https://www.folklore.org/StoryView.py?story=Round_Rects_Are_... | Twirrim wrote: | Years ago I worked for an ISP & managed hosting company as third | line support. 1st and 2nd line support were pretty good, and | would handle a lot of the cases that came through. | | Generally by the time it'd reach us, it was something requiring | more in depth troubleshooting. | | They introduced a metric to measure ticket performance. The rough | idea was "faster it's resolved, the better" (reasonable measure, | if you're also tracking customer satisfaction), combined with | "fewer interactions with customer the better" which was an | absolutely stupid way to measure performance. | | About a month after it came out, we were getting chewed out for | our "conversion score" being low. Too many interactions with | customers, and tickets taking a while to handle. No shit, we're | the top tier of support. If it got to us it was _bound_ to take | time to resolve, and almost certainly involved a lot of customer | interaction. | | One of the engineers in the team managed to dig up how to get a | "conversion" rate report up for any support engineer, though not | the code that generated the figures, and very quickly realised | that the way to get 100% conversion rate was just to resolve and | immediately re-open the ticket as soon as you picked it up. We | all promptly started doing that, and they stopped chewing us out. | | If you incentivise the wrong behaviour, you're going to get | results you likely don't want. | sanj wrote: | I once removed 4 lines of code. | | The change, annualized, was somewhere around $12M in profit. | | I'm still pretty proud of making -$3M/LOC! | cbsks wrote: | One of my most proud accomplishments was reducing the size of a | driver from ~3000 lines of code to ~800. The file was 15 years | old and had been modified by many people since. There were | conditionals that were impossible to hit, features that had been | abandoned years ago, duplicate code, and lots of comments that | didn't match the code anymore. After my changes and a few new | tests, the driver had full MCDC code coverage and the code | actually matched the device specification! | Zelphyr wrote: | > There were conditionals that were impossible to hit | | The number of times I've seen: if (my_var == | 'some value' || true == false) { ... } | | Why do people do this instead of commenting out the code?! | xdavidliu wrote: | Just to clarify, what do you mean "instead of commenting out | the code"? The above is equivalent to if | (my_var == 'some value') { ... } | | which is not the same as commenting it out entirely. | giomasce wrote: | Because if you comment out the code you don't benefit any | more from the compiler checking that the inner block is still | legal, or from your IDE to do the refactoring operations you | want. The code would bit rot much faster in a comment (or | removed from the code base altogether). | | The thing I really can't understand is why you would compare | a boolean condition to `true` instead of checking the | condition itself (in other words, writing `false` instead of | `true == false`). Also, let me suggest to use `&&`, not `||`. | And while we're at that, I would actually write: | if (false && my_var == 'some value') { ... } | | just in case operator `==` can have side effects or relevant | computational cost in your language. | [deleted] | klyrs wrote: | I have used constructs like this in debugging / exploration | phases (especially in languages without good debuggers, when | print debugging is unavoidable or just faster). I'd be | horribly embarrassed if they got committed. But... the | snippet you posted isn't equivalent to a comment; `x or | false` is equivalent to `x`. So it's actually equivalent to a | commented-out short-circuit if (my_var == | 'some value' || true == false) { ... } //if (my_var == 'some | value') { ... } if (my_var == 'some value' || | true == true) { ... } //if (true) { ... } if | (my_var == 'some value' && true == false) { ... } //if | (false) { ... } | | That said... I would never use the comparisons `true == true` | and `true == false`... that's just silly | drewzero1 wrote: | > that's just silly | | Right? Wouldn't it be more readable to use just 'true' or | 'false' instead of the comparisons, or is that not a | feature in some languages? I don't understand what might be | gained from the extra comparison, besides confusion. | | if (my_conditional || true) { etc } | teolandon wrote: | That's not equivalent to commenting out the code block, it's | just equivalent to if (my_var == 'some | value') { ... } | ulucs wrote: | Why even comment out? We have version control for a reason | Zelphyr wrote: | I guess I've been assuming they did that because they | wanted to temporarily disable whatever was within the | conditional block but, yeah, you're right. Just delete it | if you don't want that to run. Either way, that code should | never be committed. | slaymaker1907 wrote: | Version control is not immediately visible to future | developers. You need to know that there is something to | look for, particularly if it is a frequently changed file. | gregmac wrote: | Really the only time a future developer will care about | the old code is when there's a bug in the current code. | (Or maybe an edge case like a request to "make it work | like it used to in v1.0"). | | Looking at history via "blame" is useful to see why a bug | was introduced (was it fixing another bug, and if so, is | your fix going to break that bug again?), and how long | it's existed for. | | Leaving old code commented out doesn't help either with | of those things. Unless maybe it's accompanied by lots of | comments and date stamps, in which case you've not only | re-invented a very crappy, half-baked version control | system, but also made the code hard to read and work | with. | JoeAltmaier wrote: | That is a win for everybody! | | My similar story was removing a 10,000 line module that built | hundreds of different packets for sending over a mailbox to a | wifi module. Each method was almost identical, with the | exception of building a slightly different header. | | I replaced it with a template that given the structure, built a | packet to send it. Less than 1 page of code. | jjice wrote: | There is nothing more satisfying than refactoring code to | something nice and condensed, but still very readable. A lot of | my personal favorite experiences come from working with trees, | since recursive code can be so lean and beautiful. I write a | 5ish line function to generate a graphviz file to render by AST | once and I still look back on that as beautiful code. | hctaw wrote: | The tricky side of this is languages that encourage terseness | through "clever" syntax. | | But that's arguing syntax instead of principle, I think | generally "less code" means "fewer expressions to evaluate" | noveltyaccount wrote: | +1 to this. Code is fundamentally harder to read than write. | If I use clever syntax, my plain-English comments make up the | difference for characters saved :) | apozem wrote: | That's awesome. Clearing out cruft without breaking anything or | losing functionality is tricky, but man does it feel good. | Zelphyr wrote: | I had a manager once tell a co-worker (who is easily one of the | best programmers I have ever worked with), "There's no way this | can work. There's not enough code." | | Why we keep promoting these people into positions of management | is beyond me. | beaconstudios wrote: | This take is probably going to be controversial here, but I | suspect that most metrics don't accomplish anything beyond giving | control freak managers a sense of control or insight. | | Most complex processes can't be reduced to a handful of simple | variables - it's oversimplification at its worst. The best you | can do is use metrics for a jumping-off point for where something | /might/ be going wrong and thus start engaging with actual humans | (or reading code/logs/some other source of feedback). Too often | I've had to deal with management who go straight from metrics to | decisions and end up making bad decisions (or wasting everyone's | time shuffling paper to generate good looking metrics). | munk-a wrote: | I don't disagree that metrics can cause problems - but they | could also helpful when working on difficult problems. I don't | know of one that exists but there are times that a really tough | nut lands on my desk and I can't bring back a solution for a | few weeks A good metric would highlight the fact that, a week | in, while I may have no solution to the problem, progress is | being made. | | Right now our metric is basically - talk to the developer and | try and see if he's BSing you and goofing off, that's super | subjective and very vulnerable to personal biases, but, it is a | metric - it's just not an objective metric. | | I don't know what it is - I've never seen evidence of a good | one out there - but I don't begrudge managers trying to find | new objective measures for productivity. I'd be quite excited | to see one myself. | beaconstudios wrote: | The mistake is in trying to quantify a qualitative issue. | Trying to reduce progress building a program to the number of | lines and such. It inherently doesn't make any sense and it's | not possible to accurately represent such things as a number | or collection of numbers without losing all the detail (and | thus, being wrong). | | The idea that only truths expressable in abstract equations | are objective and thus true is exactly the kind of false | belief that gets us in trouble. | | > Right now our metric is basically - talk to the developer | and try and see if he's BSing you and goofing off, that's | super subjective and very vulnerable to personal biases, but, | it is a metric - it's just not an objective metric. | | That isn't a metric. Metric, having the same root as metre, | is about measuring. What you're talking about there is a | heuristic, and they're much more effective for tracking | qualitative issues. | jrochkind1 wrote: | It gets even worse, the metric can _harm_. As suggested in the | OP, if the number of lines of code you wrote was supposed to | show your productivity, programmers will start optimizing for | maximizing lines of code, which will make their code worse. | | Goodhart's law rephrased by Marilyn Strathern: "When a measure | becomes a target, it ceases to be a good measure" | https://en.wikipedia.org/wiki/Goodhart%27s_law | | Campbell's law: "The more any quantitative social indicator is | used for social decision-making, the more subject it will be to | corruption pressures and the more apt it will be to distort and | corrupt the social processes it is intended to monitor" | https://en.wikipedia.org/wiki/Campbell%27s_law | beaconstudios wrote: | Yes precisely this, because you close your feedback loop not | over the actual result you wish to achieve, but a crude | numerical reduction which probably won't correct your actions | effectively (as per your example, optimising for lines | written rather than features shipped). | andrewflnr wrote: | > This take is probably going to be controversial here, but... | | You then state what seems to be the mainstream view on HN. | Certainly I don't see it as controversial, just kind of obvious | beaconstudios wrote: | I figure it to be controversial because I see the HN crowd as | leaning more towards maths/reductionism/measuring than | intuition/holism/feedback and while I'm specifically levying | the anti-quantification argument against managers in this | case it also applies to that approach in general. | SamBam wrote: | A large percent of HN are software developers, and no | developer wants to be held to some metric by some non- | developer boss. | andrewflnr wrote: | Yeah, but OTOH we're mostly software people who have seen | first-hand what happens when you try to apply naive metrics | to software. In other fields you're more likely to be | right. | bawolff wrote: | I'm not sure why you would think this is controversial. Fot | example, Goodhart's law is commonly cited around here and its | saying roughly something similar. | beaconstudios wrote: | Goodharts law applies to using a metric as a target. I'm | talking about metrics being bad for measuring because they | inherently overgeneralise. | AmericanChopper wrote: | In order to get any insight into whether a chosen course of | action is working or not, you need to be able to perform some | type of measurement. All of these measurements are called | metrics. The default single metric that every company has | available to them is revenue, but really you want to have | feedback loops that provide insight prior to performing a | measurement to determine whether you're bankrupt or not. The | more precisely you try to measure something, the more | uncertainty and error you're going to introduce to your | measurements, something that's true for all forms of empirical | measurement. | | If you point was that companies are generally bad at doing | this, or that they often measure the wrong things, or that the | process can be abused, or that you should not attempt to | measure something beyond a certain level of precision, then I'd | agree with you. But to write the entire process off as useless | is just as unproductive as the problematic situation you're | criticizing. | beaconstudios wrote: | There's measurements (say, increase in customer retention as | a % after a new feature is deployed) and then there's | heuristics (discussing the feature with customers to gauge | sentiment, being careful not to fall prey to bias or lead the | customer's answers). | | My point is that an obsession with empiricism can make you | think that only #1 is valid evidence and thus use it for | qualitative analysis where it should not be used. | | Only using metrics for feedback is giving yourself tunnel | vision. | zeroxfe wrote: | So, what would you do differently? Say you run an organization | with 200 engineers all with different levels of skill. You have | a budget, maybe a year of runway, and a set of deliverables. | | How would you, as a leader, keep track of how your organization | is running? | [deleted] | beaconstudios wrote: | By implementing a systems solution similar to Stafford Beer's | VSM (https://en.m.wikipedia.org/wiki/Viable_system_model). Or | to ovrrsimplify the idea, self-managing teams which integrate | with their environment for feedback and management for | direction (which I believe is the agile/lean practices done | properly). | | The specific approach to metrics I was referencing as being | better is known in cybernetics as an algedonic alert. It | doesn't seek or claim to provide information, it only rings | the bell of "investigate this area", like a CloudWatch alert | for your organisation. | | Using metrics to make decisions is the mistake in my mind. | Ma8ee wrote: | The Streetlight effect [0]. Just because you think that it is | the only place that you can see anything doesn't mean that it | is meaningful to look there. A number with high precision | doesn't mean it will tell you anything meaningful. Some | problems just don't have any easy solutions. | | So in your example, you just have to rely on the judgement of | all your professional project leaders and architects and what | they tell you. | | [0] https://en.wikipedia.org/wiki/Streetlight_effect | protomyth wrote: | Say what you want about Steve Balmer but he had the right | attitude towards that https://www.youtube.com/watch?v=kHI7RTKhlz0 | ChrisMarshallNY wrote: | The best code is the code I don't write. | | As a manager, I would value a developer that spent a week, | refining a small, high-quality, robust and performant class, than | one that churned out rococo monsters in a short period of time. | | I tend to write a lot of code, and one of the things that I do, | when I refactor, is look for chunks I can consolidate or remove. | | OO is a good way to do that. It's a shame it's so "out of | fashion," these days. The ability to reduce ten classes into ten | little declarations of five lines each, because I was able to | factor out the 300 lines of common functionality, is a nice | feeling. | | An interesting metric for me, is when I run cloc on my codebase. | I tend to have about a 50/50 LoC (Lines of Code) vs. LoC (Lines | of Comments). | fredley wrote: | I am a staunch code minimalist. Less code is (almost?) always | better. The best, fastest, cleanest code is the code that doesn't | exist at all. Always aim to write the least code. Less code is | less maintenance, it's less to grok for the next person to read | it. | computerex wrote: | I agree with this, with the side note that simple code is | better than clever code when working with a team of people for | most things. Barring performance constraints, I'd choose the | code that's easier to grok/simpler even if it's more LOC. | fredley wrote: | Yes. Code is read many more times than it's written, so | optimise for the common case. | jugg1es wrote: | I think there is a big difference between the the amount of | code versus the number of decisions a piece of code has to | make. When I think of 'code minimalism', I think of it along | the lines of reducing the number of decisions made, but that | doesn't always track with the amount of code. Bugs are always | going to increase as the number of decisions are increased. | [deleted] | jackson1442 wrote: | Exactly. You can get to the goal of less lines rather easily | but it results in absolutely disgusting code since you're | doing things like creating overly complex lines with nested | ternary expressions. | | Easy to read code with fewer decisions should be the goal of | a code minimalist. | dnautics wrote: | I don't think this is always true. For example, if you are | writing tests, the DRY rule of three doesn't apply. It's very | okay to repeat code if it prevents a layer of indirection for | the person who is reading the test. | dang wrote: | I puzzled about that for years and concluded that tests are a | completely different kind of system, best thought of as | executable requirements or executable documentation. For | tests, you don't want a well-factored graph of abstractions-- | you want a flat set of concrete examples, each as | independently understandable as possible. Duplication | actually helps with that, and since the tests are executable, | the downsides of duplication don't bite as hard. | | A test suite with a lot of factored-out common bits makes the | tests harder to understand. It's similar to the worked | examples in a math textbook. If half a dozen similar examples | factored out all the common bits (a la "now go do sub-example | 3.3 and come back here", and so on), they would be harder to | understand than spelling out the common steps each time. They | would also start to use up the brain's capacity for | abstraction, which is needed for understanding the math that | the exercises illustrate. | | There are two different cognitive styles: the top-down | abstract approach of definitions and proofs, and the bottom- | up concrete approach of examples and specific data. The brain | handles these differently and they complement one another | nicely as long as you keep them distinct. Most of us secretly | 'really' learn the abstractions via the examples. Something | clicks in your head as you grok each example, which gives you | a mental model for 'free', which _then_ allows you to | understand the abstract description as you read it. Good | tests do something like this for complex software. | | Years ago when I used to consult for software teams, I would | sometimes see test systems that had been abstracted into | monstrosities that were as complicated as the production | systems they were trying to test, and even harder to | understand, because they weren't the focus of anybody's main | attention. No one really cares about it, and customers don't | depend on it working, so it becomes a sort of twilight zone. | Bugs in such test layers were hard to track down because no | one was fresh on how they worked. Sometimes it would turn out | that the production system wasn't even being tested, because | the monster middle layer did so much magic. | | An example would be factory code to initialize objects for | testing, which gradually turns into a complex network of | different sorts of factory routines, each of which contribute | some bit and not others. Then one day there's a problem | because object A needs something from both factory B and | factory C, but other bits aren't compatible, so let's make a | stub bit instead and pass that in... All of this builds up ad | hoc into one of those AI-generated paintings that looks sort | of like reality but also like a nightmare or a bad | psychedelic trip. The solution in such cases was to gradually | dissolve the middle layer by making the tests as 'naked' as | possible, and the best technique we had for that was to | shamelessly duplicate whatever data and even code we needed | to into each concrete test. | ketamine__ wrote: | https://mobile.twitter.com/dhh/status/1368957511118843908 | | True? | rkangel wrote: | I used to think this and have come to realise that this is | definitely not true. The problem that a thorough automated | test suite can cause is that it becomes very painful to | refactor code. | | As you add code, the best structure for that code changes and | you want to refactor. I'm not just talking here about pulling | some shared code into a new function, I'm talking about | moving responsibilities between modules, changing which data | lives in which data structures etc. These changes are the key | to ensuring your code stays maintainable, and makes sense. | Every unit test you add 'pins' the boundary of your module | (or class or whatever is appropriate to your language). If | you have lots of tests with repeated code, it can take 5 | times as long to fix the tests as it can to make the actual | refactors. This either means that refactors are painful which | usually means that people don't do them as readily (because | the subconscious cost-benefit analysis is shifted). | | If - on the other hand - you treat your test suite as a bit | of software to be designed and maintained like any other, | then you improve this situation. Multiple tests hitting the | same interface are probably doing it through a common helper | function that you can adjust in one place, rather than in 20 | tests. Your 'fixtures' live in one place that can be updated | and are reused in multiple places. This usually means that | your test suite helps more with the transition too - you get | more confidence you've refactored correctly. | | The other part of this problem (which is maybe more | controversial?) is that I try not to rely too much on lots of | unit tests, and lean more on testing sets of modules | together. These tests prove that modules interact with each | other correctly (which unit tests do not), and are also | changed less when you refactor (and give confidence you | didn't break anything when you refactor). | sneak wrote: | I used to have this approach, but when you start to take deps | into account, it is often preferable to have a medium amount of | code in your own codebase (that eliminates some bulky deps) to | a small, fast, clean/easy to read in full codebase that depends | on some large external libraries that bloat the overall size of | "lines of code in use in this application". | | Now I am a dependency minimalist (as much as is practical, it's | a continuous gradient trade-off and naturally YMMV) more than I | am a pure code-written-here minimalist. | | I'll happily double my SLOC for most small apps if it means my | app can be stdlib only. | fredley wrote: | Yes, fully agree. The only thing worse than code you have | written is code you haven't. | folkrav wrote: | To a point. Some things are complex enough that relying on | a well tested and supported third-party makes way more | sense than re-inventing the wheel. | colejohnson66 wrote: | I think a great example of that is GUI toolkits. If your | program is supposed to be cross platform, using something | like Qt, GTK, wxWidgets, etc. is generally preferred to | writing your own GUI code. | srgpqt wrote: | Those GUI toolkits only look and behave acceptably on | linux, because every other linux app uses those toolkits. | They look horrible and incredibly jarring on windows and | mac. | | Can still be fine for opensource/hobby work, anything | professional needs better integration with the individual | platform native UI apis. | | Which is one of the reasons Electron became so popular -- | nobody has any expectations from a webapp UI, yet they | still look better than Qt/GTK/wx on average... | Wowfunhappy wrote: | Shouldn't you be counting the lines of code in the | dependency? | tyingq wrote: | I imagine the trouble there is that you often pull in a | library for some smallish, but suitable subset of what it | can do. | colejohnson66 wrote: | A big problem with that is: what counts as a dependency? If | I pull in Qt, am I supposed to add how many lines of code | are in the parts I'm using? Many would say yes. But does | using the Win32 API count? glibc? Where is the line drawn? | toast0 wrote: | Every piece of code you rely on is a dependency. | | You may not be able to count lines of win32 code, and its | awfully hard to make a patch, but if it's broken and you | depend on it, your product is broken. | | There's also a multiplier that should be attached though. | Most products don't have developer time or skills to | write their own OS, so there's value in using someone | else's even if it's probably more code than a custom | built one that only satisfies the needs of the product. | renewiltord wrote: | The real reason objective measures don't work is that this | is a subjective thing. When you think about the good things | about code (readability, maintainability, extensibility) | they don't lend themselves to mechanical analysis. | | We can proxy a little but the core problem is that the | function that spits out your metrics for those actually has | a hidden parameter of the audience you are writing for and | the purpose it is for. | | So when the audience is highly familiar with Linux (the | kernel and platform) idioms, you could choose an exotic | microkernel with far fewer SLOC and actually have true | lower score. | | Of course that's pointlessly edge case, but the natural | simple easier to understand version of that is just using a | different utility library instead of the one currently used | in the codebase. This one could be smaller by far and still | be worse in truth. | lstamour wrote: | Another way of looking at it is that your dependencies are | still part of your code and to minimize those as well. It | can't easily be taken literally because who really wants to | consider the Linux kernel and glibc as part of their everyday | app dependencies unless writing code very close to the metal, | but at the same time it can be a very useful perspective to | have. Especially when you consider that you might (for | security) need to code review all those dependencies as they | change over time. | vidarh wrote: | A reasonable approximation, to me, is whether or not | another developer should be expected to have at least a | reasonable understanding of the API of that dependency. | | E.g. we don't generally count (g)libc because a | C-programmer should be familiar with the C API. We don't | count Linux syscalls for the same reason, generally. But we | might want to keep in mind that many APIs have dark corners | that few users of the API are aware of, and so we may make | exceptions. | | But the more obscure the API, the more important it is to | count the complexity of the dependency as well. | | Both because it increases the amount of code your team must | learn to truly understand the system, and because if it is | obscure it also reduces the chance that you can hire | someone to compartmentalise the need for understanding that | dependency as well. | Havoc wrote: | You can tell it's folklore by the part where they stop making him | fill out the form | | 3/10 for realism | mynameisash wrote: | "It seems that perfection is attained not when there is nothing | more to add, but when there is nothing more to remove." - Antoine | de Saint Exupery | noarchy wrote: | There are still companies trying to impose metrics on software | development. It isn't just lines of code, it may also include | commits per day. And this isn't even taking into account various | "Agile"-related metrics, like story points per sprint and the | like. | | I wonder if we should name the companies who do this, or if it is | fighting a losing battle? In the end, some management just wants | to look at charts. | Zelphyr wrote: | One of the greats is "number of bugs fixed". You're practically | begging your less-than-ethical programmers to create silly bugs | so they can "fix" them and get a cookie. | | Edit to add: This happens outside of programming as well. I | know a guy who worked at AT&T as a DSL Installation & Repair | tech. They had such a focus on how long techs spent on a given | job (less time was encouraged, more time was penalized) that a | lot of his co-workers would go to the DSLAM and snip a wire so | that they would be called out the next day to fix the problem. | He pushed back so heavily on the poor incentive of "getting | your numbers up" that he eventually got written up for | insubordination. We need a larger eye-roll emoji. | Jtsummers wrote: | Of questionable ethics, at one office there was no _reward_ | for finishing a large number of tasks. But there was an | implicit _penalty_ for delays and the tasks were not properly | segregated by effort. One of the testers had something like | 300-400 test cases he was automating. The majority were | simple, minutes to an hour of work, and easily sharing common | code. 50 or so were large, taking several days or even a | couple weeks of effort. Even though he, technically, could | have finished the majority of test cases in a couple weeks, | he knew that they 'd expect that pace to continue. | Consequently, he left all those small cases for later. It was | simpler this way than fighting the misperception that all the | work was of similar effort. If he ever seemed to be falling | behind, he'd churn out 20+ test cases on Friday and the | reports for the week looked good to management. | | I've never done this myself, but I've seen developers do | similar things rather than fight management. Measuring and | rewarding the right things is important. | quercusa wrote: | There's a old Dilbert to that effect. Wally: "I'm going to | write myself a minivan!" | einpoklum wrote: | More than the story itself, the website: | | https://www.folklore.org/ | | is packed with stories which will make you smile, cry, or more | enlightened. Or all of the above at the same time. | josalhor wrote: | Just the other day I was in my logistics class and the professor | started deviating into something that I believe was pure | nonsense. | | He started the lecture by analyzing how many pieces a machine | could manufacture per day. Fair enough. He extended the model to | measure different ratios of capacity. Makes sense. | | Then he tried to extend the model to all machines, including | humans. His example was: "How do you measure the capacity of a | legal team?". I thought it was a trick question, so I answered | (paraphrasing) "You can't answer that question the same way you | answer for the machine. You can't give a single metric." He told | me I was wrong and that the _right_ measure would be (total | number of working hours/day). | | I was tempted to try to convince him otherwise. The analogy was | deeply flawed. He certainly measured the machines in (number of | pieces / day) but measured the legal team in (hours/day). So, in | analyzing a machine, you take into account its efficiency, but | you don't do the same thing for humans. | | I believe that is exactly the same thing that is going on in the | post. Managers/Logistics/Economists are very susceptible to this | kind of generalization pitfalls. | | Edit: Given that this answer has generated some discussion I feel | the need to expand on it. The legal team was not expected to sell | their services "by the hour". In fact, any discussion about how | their services were sold was shut down by the professor. From his | point of view, the lawyers were machines and he was asking the | question "how much can this machine produce?" | | Yes, other students also suggested taking the number of billable | hours/revenue into account, but that's not the answer the | professor was looking for. | | I don't criticize whether his answer is not _technically_ right, | but I feel it holds no real-world meaning. It was a purely | academic question that leads nowhere instead of having a debate | about how you measure the productivity of a group of human | beings. And on top of that, his final answer was definitive and | (from his point of view) was irrefutable. | rebuilder wrote: | Well, lawyers are famously expensive. And time is money. So | presumably a sufficiently expensive legal team will actually | produce hours, and the measurement is perfectly reasonable. | [deleted] | program_whiz wrote: | There's a simple mathematical argument to thwart your prof. | Imagine an equation of two or more variables (such as | "capacity"). For example the "capacity" of a storage unit is an | equation relating height, width, and depth to volume (3 | independent variables). | | Any such equation can only be represented by a single number | ("capacity" or "productivity") if all variables are dependent | (and therefore, there is only one independent variable in the | equation). | | So the assertion your professor is making is that the | "capacity" of a team is always exactly dependent on hours | worked per day, and any other proposed dimension of capacity | (such as years experience, field of study, languages spoken, | cases won, relationships with judges) are dependent on "hours | worked per day". If he agrees any one of those variables | affects capacity, but does not depend on "hours worked per | day", then a single number can never reduce the dimensionality | of the output (you need at minimum 2 numbers to represent two | independent variables, you can never "collapse" the data). | thaumasiotes wrote: | > Imagine an equation of two or more variables (such as | "capacity"). For example the "capacity" of a storage unit is | an equation relating height, width, and depth to volume (3 | independent variables). | | > Any such equation can only be represented by a single | number ("capacity" or "productivity") if all variables are | dependent (and therefore, there is only one independent | variable in the equation). | | This doesn't seem right. You can have storage units with | varied combinations of height, width, and depth, sure. But | whether that matters depends on what you want to use them to | store. An example of an approach that doesn't work would be | storing unboxed fragile antique dollhouses. They have weird | shapes, so you can't fill the floor area, and you can't stack | them, so adding height to the storage unit doesn't add any | capacity. | | Except that of course you wouldn't just toss them into a | garage and call it a day. (They'd break!) You'd keep them in | boxes. Those pack and stack perfectly. Suddenly volume is | what matters again, and increasing the width, length, or | height of the unit by 10% will increase the amount you can | store by about 10%. | | This is even more obvious if you're storing water or oxygen. | Fluids take the shape you give them. Your unit might have | length, width, and height (though it really shouldn't... you | want to store fluids in cylinders), but the only thing that | matters for how much water you can put in there is volume. | Retric wrote: | The Knapsack problem is arguably a counter argument to | measuring storage space by volume. | | However, air freight is a much more direct one. You have 2 | largely independent measurements for weight and volume with | either being the limiting metric for each load. | thaumasiotes wrote: | Yes, in air freight weight and volume are independently | significant. | | But the point of my comment is that it isn't true that -- | as the parent comment asserted -- it is impossible to | usefully report multidimensional data with a one- | dimensional value. To the contrary, it is quite possible | that the multidimensional data adds zero value over the | one-dimensional summary. | Akronymus wrote: | If you can barely store a box in a storage slot, increasing | the space doesn't allow you to store more boxes. | | You can't really assume a 100% packing rate along with | increasing x dimension by y% meaning you can store y% more | stuff | thaumasiotes wrote: | You can as long as the size of your box is significantly | smaller than the size of your warehouse. This is in fact | the general case. | | It's even truer if you're considering larger expansions; | increasing the length of your warehouse by 200% will mean | you can store 200% more stuff regardless of how awkward | the original fit was. | Viliam1234 wrote: | how many pieces a machine can manufacture = output | | working hours = input | | Would the professor be okay to pay me for the time I spend | reading web? I mean, from his perspective, it is the time I | spend that is important, not what I do. | lmilcin wrote: | There is certain need for people to be able to simplify | problems in terms that they can understand an manage. | | This is necessary, because humans have very limited capacity to | understand world around them and otherwise it would not be | possible to make _informed_ decisions, as gathering all | relevant information would necessarily take practically | infinite amount of time. | | From that point of view I understand people like your professor | is mostly result of bias also called Dunning Kruger effect. | This is basically lack of education in a given area. You need | at least some knowledge in an area to be able to appreciate | complexity and unknown unknowns. | | If you don't want to be that guy, the best medicine is first to | learn to be self aware, second to be aware of various biases | (including Dunning Kruger effect) that you are subject to and | third to get some knowledge/experience in an area you are | trying to make decisions in. | ulucs wrote: | The underlying question is: what is the firm's utility from the | lawyers? If the firm is not doing anything themselves but | outsourcing the team, person-hours is the correct answer. | | If the team is doing work for the firm, but you don't want to | complicate the model, you can stick a labor-enhancing constant | (to allow for heterogeneity between workers) and use "work" as | a unit. Sure this model is wrong, but all models are wrong. | We're just trying to create some useful ones. | program_whiz wrote: | See my response above, but this suffers the same problem. | Economics people talk about "utility" as a single number, | when in reality its a multi-dimensional (perhaps infinitely | dimensional) number. Because it depends on a multitude of | independent variables (age, health, experience, intelligence, | expertise, efficiency, relationships, persausion / charisma, | etc.), it can never be simplified. This also makes it | impossible to compare two utility values, because there's no | way to strictly order variables in many dimensions (without | arbitrary reduction in complexity that loses information like | calling "cost" or "hours worked" the primary axis and sorting | on that). | ulucs wrote: | You're right that the map is not the territory, but it | doesn't change the fact that you need a map to navigate. No | science is comprehensive enough to fully model the | territory (even physics) | kortex wrote: | Turns out, machines also have some sort of duty cycle. Most | mechanical contraptions can run faster than spec, at the | expense of wear, heat, jams, and ruined parts. So you can't | even measure machines in widgets/hour without more info. | 908B64B197 wrote: | Really curious what school is this? | | > Edit: Given that this answer has generated some discussion I | feel the need to expand on it. The legal team was not expected | to sell their services "by the hour". In fact, any discussion | about how their services were sold was shut down by the | professor. From his point of view, the lawyers were machines | and he was asking the question "how much can this machine | produce?" | | Pricing the value of in-house counsel is an interesting problem | in itself (because they typically don't bill by the hour). One | could use an insurance policy pricing model (the worst that | could happen is a very costly loss in a lawsuit) to determine | what's the counsel protecting the company from. | josalhor wrote: | > Really curious what school is this? | | My local university. If you want the specific school, my | handle is associated with my real-world identity. It won't be | hard to figure out. | | > Pricing the value of in-house counsel is an interesting | problem in itself (because they typically don't bill by the | hour). | | Absolutely! | | > One could use an insurance policy pricing model (the worst | that could happen is a very costly loss in a lawsuit) to | determine what's the counsel protecting the company from. | | Also true. The lack of cost analysis in my classes worries me | very much. | 908B64B197 wrote: | > Also true. The lack of cost analysis cost in my classes | worries me very much. | | Time to transfer somewhere else? | josalhor wrote: | I am fine where I am. I will graduate next year in | Computer Science and Bussiness Management with good | grades. I thought about quitting and enrolling in | Computer Science and Mathematics when I started. But I | think I can make a bigger impact in the world by staying | in my current program. | mumblemumble wrote: | Responding to your edit: It's ironic that your professor seems | to have taken pains to rule out all of the framings that would | render their assertion correct, in (I presume) an effort to try | and come up with some sort of universal rule that works in any | industry and any context. | | I'm pretty sure it's due to exactly that sort of hubris that | business school folks have invited so much disdain. The domain | in which you're operating simply cannot be dismissed as an | inconsequential detail. | | Tangentially, there is a subset of law firms that do operate as | if total hours worked is the only thing that matters. Over the | past decade or so, they've been _rapidly_ losing ground to law | firms that, by not thinking that way, manage to do a better job | of producing the kinds of output that clients actually want. | josalhor wrote: | To be fair to my professor, the question does make sense in | the context of the subject. That is, the subject focuses on | answering questions like: How much I am producing? How much | could I produce? How do I measure that? Etc. The subject | intentionally ignores business models. | | So, the question "How do you measure the capacity of a legal | team?" (note it says capacity), makes sense. It's the answer | I disagree with. | AlexCoventry wrote: | But doesn't capacity imply some kind of fungible unit, | whereas outputs of intellectual labor tend to be non- | fungible? | josalhor wrote: | My professor thinks otherwise | | As for my personal opinion, I haven't reflected on it too | much, but I think capacity implies a quantitative (edit: | measurable may be a better word?) output, but not | necessarily fungible. | mumblemumble wrote: | Some legal work product is reasonably fungible, | especially at the level of corporate law. | | What I think that a lot of management type folks fail to | realize, though, is that both the quality of knowledge | workers' output and the rate at which they produce it | tends to drop precipitously when they are tired. I | wouldn't be at all surprised if a lawyer who works 35 | hour weeks can get more done in a given calendar period | than one who works 90 hour weeks. Big name law firms, | though, bill by the hour, and, even if they share this | conviction, they know that their clients went to business | school, and have therefore been trained not to understand | it. | Gibbon1 wrote: | I can see why, my limited experience with white shoe law | firms was they billed us 100 hours for the 10 minutes it took | a legal secretary to do a search and replace on another | contract they did for someone else. | samwillis wrote: | No, I think he is right. Assuming the aim is to optimise for | profitability, the machines output items are chargeable but it | is a lawyers hours that are chargeable - so optimise (and | measure) hours! | | (There are obviously some "jobs" a lawyer does that tend be | charged at a fixed rate such as conveyancing, which you would | want to optimise for throughout) | josalhor wrote: | > No, I think he is right. Assuming the aim is to optimise | for profitability, the machines output items are chargeable | but it is a lawyers hours that are chargeable | | I have updated the post to expand on your observation. | appstorelottery wrote: | It seems to me that one measure of productivity in a law firm | is billable hours, however in the case of a litigator - it's | also successful case outcome. Again, it's billable hours | towards an outcome. So I can understand this heuristic based | approach, on the other hand it seems like you're tending | towards the quantitative side? | | Generalizations or rules of thumb can actually outperform | complex quantitative approaches to decision making. Look at the | 1/N heuristic for portfolio management for example. | | Anyhow just my opinion - something for your curious mind to | consider ! | legulere wrote: | This way of thinking has originated with scientific management, | also known as Taylorism. | nickelcitymario wrote: | You were both right, and it all depends on your definition of | productivity. In economic terms, I believe the standard way of | looking at this is to consider how much economic activity | resulted. | | For lawyers, most of them sell hours. The more hours they bill, | the more productive they are. | | Most businesses who hire programmers do not make their money by | billing programmer hours. So that metric wouldn't work. Lines | of code seems reasonable until you think it through. Honestly, | I don't know that anyone has come up with a good solution for | measuring programmer productivity. | | But lawyers? They're in the business of selling time in 15 | minute increments. Their productivity is simple to measure in | this respect. | ncallaway wrote: | What about the general counsel of an in-house legal team? | | Surely they care about their underlying activities and not | just number of legal hours worked, right? | | I have to believe there is a legal team somewhere in the | world that is measured on productivity beyond just "number of | billable hours" generated. | nickelcitymario wrote: | I imagine an in-house team is being paid a salary or a | retainer, in which case their work hours are moot. (Not a | lawyer, so I could be wrong.) | | I think the problem is the word "productivity". When we say | that word, we're implicitly suggested there's a simple | integer or decimal that can capture whether a person's | wages are money well spent or not. For most professions, | programming included, I am highly skeptical of the | existence or even potential for such a number. | tetha wrote: | > I imagine an in-house team is being paid a salary or a | retainer, in which case their work hours are moot | | I would not call it moot, but opportunity cost - and | opportunity cost is very hard to measure. Technical debt | is similar. | | If you have current lawsuites to handle and avoid cost, | their hours are better spend doing that than dishes. If | you have future law suites to avoid... that get's even | more tricky. | nickelcitymario wrote: | I meant "moot" only in so far as it's a useful measure of | productivity. | | If the hours aren't tied to either the cost or the price, | then I don't know how they can be tied to productivity in | an economic sense. | ncallaway wrote: | Sure, I wasn't disagreeing with your overall point. I was | just pushing back on the last sentence: | | > But lawyers? They're in the business of selling time in | 15 minute increments. Their productivity is simple to | measure in this respect. | | I don't think all lawyers are in that business. There are | plenty of in-house counsel that aren't in that business. | Just as there are plenty of engineers and software | developers that _are_ in the business of selling time in | 15 minute increments. | | I just don't think the productivity question actually | breaks down along professional lines, but rather on | business model lines (which, again, I think we're in | agreement about your main point) | nickelcitymario wrote: | I was going to say "I didn't say all", but you're right, | I didn't qualify. I meant the majority of lawyers, which | I think is still accurate. | | I also agree it doesn't break down along professional | lines. Just used lawyers as an example, but I shoulda | been clearer about my intent. | ncallaway wrote: | Ah, sure, makes sense. Lawyers do skew more into service | providers rather than in house, so make sense as an | example of that. | program_whiz wrote: | Can you represent all the values in an equation of two | variables using only a single variable? Only if the two | are completely dependent (and therefore its actually an | equation of just one variable). If the 2nd variable | contains any information, its an impossible ask (and | therefore the worth of people can only be boiled down to | "productivity" if literally every measurable dimension of | worth is 100% dependent on productivity). | planet-and-halo wrote: | Well this gets back to the question of the output. For the | law firm itself, this might be a valid approach. For the | client, though, this is a terrible way to measure | productivity. At a certain point hours may even be inversely | proportional to productivity (assuming the client's output is | desirable legal outcomes). This works very much the same as | software engineering, except that usually (ignoring the case | of consulting firms) all of the work is done in-house. | nickelcitymario wrote: | Completely agreed. | PeterisP wrote: | But the question in the grandparent post was about capacity | - and in this regard, if some customer needs "X much" of | legal services performed, then it's reasonable to state | that if your legal team that can devote twice as much hours | to that customer, it has twice as much capacity. | JoeAltmaier wrote: | This may explain why lawyers are motivated to stir things up, | rather than settle them. They're motivated by the wrong | metric. | | As an Engineer, I sell my time by the hour too. No different | than the lawyer. Yet I try to finish things efficiently. Huh. | nickelcitymario wrote: | > As an Engineer, I sell my time by the hour too. | | As in you literally bill for hours, and the more hours you | work, the more you get paid? | | Most programmers that I know (which is obviously not a | great metric) either get paid a salary (which is divorced | from actual hours worked) or they get paid by the hour but | have no say over how many hours they will. In both cases, | time is independent from productivity. Therefor, there's no | harm (and really only benefits) to coding efficiently. | | But if you a) control how much time you work (like lawyers | do, to an extent), and b) get paid for your time, then yes | the incentives are setup to encourage you to be | inefficient. Completely agreed. | the_only_law wrote: | I'm guessing they're an independent contractor or | freelancer of some sort. | JoeAltmaier wrote: | Yup | nickelcitymario wrote: | And that's great! But there's a reason I used qualifiers | like "most", not "all". | | If you bill by the hour, there's a reasonable (but not | necessarily correct or optimal) case to be made for | measuring your productivity in terms of billable hours. | | But it makes zero sense to do so if your hours are | disconnected from the economic activity that results from | your work. In such cases, it would be completely | arbitrary to measure hours and call that a measure of | productivity. Just as arbitrary as lines of code. | smabie wrote: | I'm sure lawyers think they try and settle things | efficiently as well. | | The software engineering profession is riff with wasted | work: rewrites, new bullshit services and tech, insanely | complex clustering and cloud deployments, etc. | wahern wrote: | > This may explain why lawyers are motivated to stir things | up, rather than settle them. They're motivated by the wrong | metric | | Most lawyers I know have many clients and are swamped with | work. They have little incentive to "stir things up". It's | similar with accountants and plumbers in my city. They | aren't trying to make more work for themselves because they | already have their hands full. | | But in regional markets where supply isn't so constrained | relative to demand then, sure, there's an incentive to | make-work once you've wrangled a client, just as with any | other profession. | tibbar wrote: | Paradoxically, if you optimize for billable hours on your | first job, you might never get to that highly-compensated | 100th job. A selection effect of sorts. | frenchy wrote: | > You were both right, and it all depends on your definition | of productivity | | Sure, but at some point, you can pick a definition that is so | far removed from what was intended, that this exercise is | utterly meaningless. | nickelcitymario wrote: | > Sure, but at some point, you can pick a definition that | is so far removed from what was intended, that this | exercise is utterly meaningless. | | You could say that anytime there's any lack of clarity | about what is meant by any given term, | | With "productivity", you could reasonably mean any number | of things. | | It's not like someone said "pizza" and I said "that depends | on what you mean by pizza". You _could_ say that (is a | calzone a pizza?), but it wouldn 't be reasonable to do so. | | In the case of productivity, I think it's reasonable to | clarify what is meant. | | P.S. Was your use of "utterly meaningless" an intentional | pun? | mesozoic wrote: | The real answer is revenue generated/hour | rkagerer wrote: | Wow. Even with such a basic analogy, there are still more | useful metrics you could pick... contracts closed, cases won, | client files completed, cigars smoked. | [deleted] | csours wrote: | Even in terms of widgets per hour, you need to be VERY careful | to include measures of quality. | | 1 - Underlying defects will absolutely sink your downstream | production rate. | | 2 - If you only measure widgets per hour, the machine will make | more, but smaller widgets (See Soviet Nail factory story - | https://skeptics.stackexchange.com/questions/22375/did-a-sov... | ) | | 3 - Quality has a quantity all it's own. Many times, better | widgets will improve efficiency many times over their own cost | of production. | | 4 - Your professor was real dumb. | jacobwilliamroy wrote: | Your professor clearly knows nothing about legal work. Don't | tell him that though, you'll just piss him off. | | Thank him for his "wisdom" but make sure you do it in a | convincing way. Finish the class, get your A, move on with your | life. You don't need him to acknowledge he's wrong, you just | need him to give you good marks. | niccl wrote: | This makes me think of something that's intrigued me for a | while: what's the productivity of a yacht racer? The better | they are, the less time they spend actually racing in | competitions. | | Doesn't this mean that by your professor's metric they are | becoming less productive? | wiml wrote: | I would say that a yacht racer, or other athlete's, "output" | is their wins/ranking in competitions. There are devils in | the details of how you assign a simple number to that, and | Goodhart's law is always lying in wait, but that seems to be | the right kind of thing to measure. | | More cynically, you could measure a racer by the amount of | revenue generated by sponsorships, ad placement on the yacht | hull, endorsement fees/kickbacks, etc.. If you have two | equally competitive racers, but one is more mediagenic, | perhaps that one has higher "productivity"? If a racer often | loses, but does so in engaging, nailbiting ways that create a | following, perhaps that one is "productive"? A wrestling | "heel" may lose their bouts but be a successful character, | say. | jetrink wrote: | You would be interested in Sabermetrics, which is the use of | statistics to quantify the contribution of baseball players | to the outcomes of the games they play in. Yacht racing is | also a competitive team activity and you could define the | productivity of a racer in terms of how much that person's | efforts contributed to the position or time their yacht | finished a race in. It's a relative measure and would have to | be defined relative to other racers or to a fictive | 'standard' racer. | minitoar wrote: | For something high risk like that it might be you only | "produced" something if you placed. | csours wrote: | Disclaimer: I work for GM - this is solely my own opinion. | | Whenever I hear people in the automotive industry boast about the | complexity and lines of code in vehicles I weep and shake my | head. | Jtsummers wrote: | It happens in aerospace as well. I had a manager boasting, | once, about the skill of his people and the product with | something like, "This was 100k lines of code!". In working with | some of those people (a couple specific individuals) later I | realized that the 100k lines of code was probably reducible to | 10-20k lines of code if it was anything like their later work. | The code they wrote worked, but was not extendable or | comprehensible by anyone but them, and I spent more time | refactoring and shrinking their work than actually extending | it. | tregoning wrote: | Related :) | https://twitter.com/tregoning/status/1286329086176976896 | dhosek wrote: | I track my progress on the novel I'm writing by word count. I've | had more than a few days of negative word count writing days | which have invariably been some of my more productive days. | hinkley wrote: | Sometimes I wish I kept a better count of my deletions, because | the 'best' I ever recorded was just under 600 lines and I | honestly feel a little regret that other people are managing much | bigger deletions. | | I think the real reason is that as I moved to refactoring (as | part of that 600 LOC experience), my deletions per year went up | but my deletions per story regressed toward the mean. | closeparen wrote: | There are various ways to extract this from Git, see for | example: https://shinglyu.com/web/2018/12/25/counting-your- | contributi... | dang wrote: | If curious, past threads: | | _-2000 Lines of Code_ - | https://news.ycombinator.com/item?id=10734815 - Dec 2015 (131 | comments) | | _-2000 lines of code_ - | https://news.ycombinator.com/item?id=7516671 - April 2014 (139 | comments) | | _-2000 Lines Of Code_ - | https://news.ycombinator.com/item?id=4040082 - May 2012 (34 | comments) | | _-2000 lines of code_ - | https://news.ycombinator.com/item?id=1545452 - July 2010 (50 | comments) | | _-2000 Lines Of Code_ - | https://news.ycombinator.com/item?id=1114223 - Feb 2010 (39 | comments) | | _-2000 Lines Of Code (metrics == bad) (1982)_ - | https://news.ycombinator.com/item?id=1069066 - Jan 2010 (2 | comments) | pvg wrote: | Looks like you have a small quoting problem in the query you | generate with the 'past' link and -2000 blows it up. | jansan wrote: | Was there really a 5+ year gap since the last thread? We should | not let this happen again. | dang wrote: | Perhaps someone will find other cases of this story showing | up. | utopcell wrote: | (-: | taneq wrote: | So you're saying the last thread was -2000 days from now? | TheDudeMan wrote: | > they stopped asking Bill to fill out the form, and he gladly | complied. | | Compiled with what? Can one comply with an absence of request? | JoeAltmaier wrote: | Consider the cost of lines of code in a solution. Double the | lines means double the time spent to simply type them in. Double | the time later to read them. Probably many more times than double | to re-understand them. Double the time to explain them. Double | the compile time. Execution time is probably around double. | | It's not just twice as good to write shorter code. Its something | like 64X as good. By some ways of thinking. | Jtsummers wrote: | It's definitely a compounding issue as you grow and shrink | SLOC. | | One bit of code I received was somewhere in the range of 5-10k | SLOC when handed to me. I reduced it to around 1k SLOC. | | The original included numerous duplications, had a function | that was itself on the order of 1-2k SLOC, was miserable to | extend (which path do I need to follow to insert this new | conditional? which paths will be impacted if I remove this | conditionals?). Fortunately it wasn't _shipped_ code, but it | was useful for testing the embedded system. | | My refactoring involved, first, re-coding one of the larger, | outer if-else-if sequences as a simple switch/case. This | quickly revealed which variables were common to a large number | of the branches and could be brought to a higher level of | scope. Then common series of statements were parameterized and | extracted to functions (preambles and postambles, setup and | teardown, if you will). Several hundred lines were replaced | with something like one 20-line function which took a single | parameter and one call to it with the parameter that was | previously evaluated through some hairy if-else-if sequence. | | Once completed, new test sequences could easily be coded up or | were available because there was already a path that led to it, | you just had to feed it a different value or series of values | to trigger that path. Then we could automate the whole thing | because we knew what the parameters were that clearly led to | each branch. | | In the end the code was 5-10x smaller, but immensely more | valuable. | carapace wrote: | > 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. | | ~Dijkstra (1988) "On the cruelty of really teaching computing | science (EWD1036). | | https://en.wikiquote.org/wiki/Edsger_W._Dijkstra | mangomania wrote: | Good job! | khaledh wrote: | 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 wrote: | Some 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 wrote: | There 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 | | [1] https://en.wikipedia.org/wiki/Software_metric | LanceH wrote: | The 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 wrote: | It 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 wrote: | I 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 wrote: | For VS Code have used this on the past: https://marketplace | .visualstudio.com/items?itemName=kisstkon... | | and this one https://marketplace.visualstudio.com/items?ite | mName=Stepsize... | | These two haven't tried before but doing it now: | | https://marketplace.visualstudio.com/items?itemName=selcuk- | u... | | https://marketplace.visualstudio.com/items?itemName=TomiTur | t... | Waterluvian wrote: | Perfect. This is what I was curious about. Haven't heard of | either. Thank you. | gurkendoktor wrote: | If 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#Cor | relat... | colonelpopcorn wrote: | Except it's not easy to follow. Why does kind 15 return a | parsed object of kind 5? That's not counting the | complexity of each function called, either. | johncolanduoni wrote: | I think they were using the numbers as stand-ins for what | would be in reality names be descriptive names (foo, bar, | etc.). | gurkendoktor wrote: | Ouch, sorry for the typo. But I'll double down on this: | The fact that the typo is so obvious underlines that the | structure is easy to follow :) | wvenable wrote: | > case KIND_15: return parseObjectOfKind5(); | | I don't like this type of code for exactly this reason. | Twisol wrote: | The association between the two has to be written | somewhere. Can you provide an alternative approach that | isn't vulnerable to typos? | wvenable wrote: | This is basic DRY violation. The number is duplicated | twice and that can get out of sync (as in the example). | | I think everyone has coded this way out of expedience and | some of us have eventually messed it up too. But you | could, for example, use a macro in C to only list the | number once. It might not be a trade-off worth making | though. | | Personally, I've used reflection to do this kind of | mapping of enums to functions in a language that supports | reflection. | Twisol wrote: | > This is basic DRY violation. The number is duplicated | twice 2 and that can get out of sync (as in the example). | | I think it's pretty clear that the number is a | placeholder for something reasonable, e.g. making an | association between two distinct sets of concepts. You'll | still be vulnerable to copy-paste or typo issues. | | > Personally, I've used reflection | | Now you have _two_ problems (and still have to maintain | an association between two sets of concepts). | wvenable wrote: | I don't think most enum-to-function mappings are distinct | sets of concepts. | | In my own code, I have used the enum name to map to a set | of functions related to that enum value. The association | is implicit in the name of the enum value and the name of | the functions. No way to mess that up like this. | | If it was: case: KIND_BOX: return | parseObjectOfKindBox(); | | It's no difference. Still repeating "Box". | gurkendoktor wrote: | The code was inspired by a piece of Java code that | rendered geometric primitives. It was basically case | "box": return parseBox(); as you suggested in your other | post. | | Turning "box" into "parseBox" using string operations and | then using reflection to call the right method is an | approach I'd consider in Ruby, but definitely not in | Java. It breaks IDE features like "Find Usages" and | static analysis, and the code to dynamically invoke a | Java method is more annoying to review than the boring | repetition in my posted snippet. | Jtsummers wrote: | Their point seems to be in the mismatch of names. Imagine | seeing this sequence, with names instead of numbers: | switch(HTTP_METHOD) { case PUT: processPut(...); | case POST: processPost(...); case GET: | processDelete(...); // wtf case DELETE: | processGet(...); // mate? } | | To the reader that appears to be an error even if it is | precisely the thing you want to happen. | Leherenn wrote: | Depends on your language, but you could use the type | system instead; e.g. the function is chosen by the | compiler based on the type of the value. | | In more dynamic languages, you could probably use | introspection. | | Lastly, this does not alleviate the association issue, | but I prefer the alternative of declaring the | associations in an array/map somewhere, and using | map[enum_value]() instead of the switch. | slaymaker1907 wrote: | In a lot of ways, I think the map solution is actually | worse. There isn't an easy way to figure out what code is | used for a given enum value with the map alone. The | searchability depends on how the map is initialized. Not | to mention a map will always introduce null or option | types that you have to handle. | | A map can be a good solution though, particularly if it's | something like mapping enum values to strings that is | constructed via EnumClass.values().map... or something so | that you know the map is a total function. | gurkendoktor wrote: | Using a map also completely sidesteps the point of | cyclomatic complexity because there are no code paths to | count anymore; now they're data. And even though the | function does the same as before, the linter will | congratulate you on the low complexity. | nawgz wrote: | I mean, hilarious point, but I'm not sure it's valid. | Clearly he's numbering things here, but I am guessing in | the real world you're far likelier to see tests of typing | or some not-numerically-indexed value rather than | literally numbered ENUMs | wvenable wrote: | This can happen with any enum to function mapping. You | cut and paste and forget to change one or the other. | | In C, you could use a macro in this call to make sure | that the name/number is only specified once. | nawgz wrote: | I mean, this can happen with any code by that logic if | you're cut and pasting. | | I think the real issue is types aren't included in the | example. I work in much higher-level languages, but if | you are passing strongly typed objects thru and your | switch is derived on this typing, it's probably going to | be illegal in your type system to return certain results. | | If your type system doesn't validate your results, then | you'll be prone to the class of error you are discussing. | Maybe that's common in C. | oftenwrong wrote: | This is one of the benefits of Cognitive Complexity: | | https://www.sonarsource.com/docs/CognitiveComplexity.pdf | | >Switches | | >A `switch` and all its cases combined incurs a single | structural increment. | | >Under Cyclomatic Complexity, a switch is treated as an | analog to an `if-else if` chain. That is, each `case` in | the `switch` causes an increment because it causes a | branch in the mathematical model of the control flow. | | >But from a maintainer's point of view, a switch - which | compares a single variable to an explicitly named set of | literal values - is much easier to understand than an | `if-else if` chain because the latter may make any number | of comparisons, using any number of variables and values. | | >In short, an `if-else if` chain must be read carefully, | while a `switch` can often be taken in at a glance. | slaymaker1907 wrote: | Great paper! I particularly liked how they treat boolean | expressions. It kind of has a mathematical justification | as well since a series of only && or || is trivial for a | SAT solver. | | I disagree with them on assuming method calls being free | in terms of complexity. Too much abstraction makes it | difficult to follow. I've heard of this being called | lasagna code since it has tons of layers (unnecessary | layers). | | Maybe the complexity introduced by overabstraction | requires other tools to analyze? It's tricky to look at | it via cylcomatic complexity or cognitive complexity | since it is non-local by nature. | Waterluvian wrote: | That'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 wrote: | Speaking 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 wrote: | It 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 wrote: | Feels 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." | Twirrim wrote: | My 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. | khaledh wrote: | 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. | | 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 wrote: | Developers 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 | | 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. | stocknoob wrote: | "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 wrote: | I'd expect nothing less wise from Dijkstra. I feel like every | week I learn something new from that man. | mumblemumble wrote: | I 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 wrote: | The 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. | [deleted] | rakoo wrote: | To 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. | ragnese wrote: | I 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. | richardwhiuk wrote: | > Sure, it's not "code" | | I utterly reject this assertion. | [deleted] | mikepurvis wrote: | I'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. | jaylo2015 wrote: | Agree. 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 wrote: | I 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 wrote: | I wonder if they then normalize this by years of experience | klingon78 wrote: | This 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. | AnimalMuppet wrote: | > 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. | sdevonoes wrote: | Nowadays that should be phrased as: fewer features is better. But | management doesn't understand. They always want more features to | be delivered (and faster than our competitors!), and so we end up | with more code to maintain and in the need of hiring more | developers (that's actually another excuse as well to migrate our | stuff to microservices!). | | Companies only want to grow, they don't care anymore about | polished products. | | Of course, I'm generalizing, there are some few companies that | care about the product, but they are just a few. | neha555 wrote: | RSMSSB Stenographer Admit Card 2021 | https://karnatakastateopenuniversity.in/rsmssb-stenographer-... | jansan wrote: | Aaah, now I understand how people came up with the strange idea | to place opening curly brackets into a new line. Suddenly this | all makes sense. | Scarblac wrote: | Those few days that I managed -1000 lines of real code are among | the happiest work-related days I had. It feels so good to find a | simple solution that enables you to remove so much. | lambda_obrien wrote: | Is there anywhere which optimizes for LOC count today? I figure | everyone knows by now LOC is a bad metric. | Waterluvian wrote: | Folklore.org is full of fascinating anecdotes. | | I'm starving for more stories of this size from CS history. PARC, | Bell Labs, wherever! I'm sure there's thousands of fun little | stories out there. | everybodyknows wrote: | The management psychology side of this wants a sequel from some | veteran who was in the meetings and is now ready to confess: | | > ... wrote in the number: -2000. | | > I'm not sure how the managers reacted to that, but I do know | that after a couple more weeks, they stopped asking _Bill_ to | fill out the form, and he gladly complied. | | _Bill_ -- but what about the rest of the team? The devil's | answer: They were expected to keep supplying the number, because | line management was forwarding the stats up, having previously | "sold" upper management on their value. And to admit error on | such a fundamental is career-threatening. | mshockwave wrote: | It's crazy that even in 2021, I know some of the teams are still | measuring productivity by LOC _only_. People just never learn the | lesson since '80 | adolph wrote: | Ssh, this may be a feature, not a bug. | | See CIA (OSS) manual for details. | | https://www.openculture.com/2015/12/simple-sabotage-field-ma... | newlisper wrote: | Use Java, problem solved. | goostavos wrote: | I'd be happy if lessons from the '60s-'70s(ish?) could be | applied. Despite Mythical Man Month being 'required reading', I | still sit in planning meetings where management discusses how | they'll make a baby in 1 month because they're putting 9 | "resources" on it. | segfaultbuserr wrote: | > Measuring programming progress by lines of code is like | measuring aircraft building progress by weight. - Bill Gates | (alleged) | | According to Wikiquote there is no primary source to show he | really said that. Nevertheless, Steve Ballmer did, | | > "In IBM there's a religion in software that says you have to | count K-LOCs, and a K-LOC is a thousand line of code. How big a | project is it? Oh, it's sort of a 10K-LOC project. This is a | 20K-LOCer. And this is 5OK-LOCs. And IBM wanted to sort of make | it the religion about how we got paid. How much money we made | off OS 2, how much they did. How many K-LOCs did you do? And we | kept trying to convince them - hey, if we have - a developer's | got a good idea and he can get something done in 4K-LOCs | instead of 20K-LOCs, should we make less money? Because he's | made something smaller and faster, less KLOC. K-LOCs, K-LOCs, | that's the methodology. Ugh anyway, that always makes my back | just crinkle up at the thought of the whole thing." | | Not really a fan of either of them, but we can all agree on the | quote. | asdff wrote: | Must be great for those teams. Want to make an argument for a | raise to non-tech management? Start writing paragraph comments | and flowery code. ___________________________________________________________________ (page generated 2021-03-08 23:00 UTC)