I still remember the behemoth of a commit that was "-60,000 (or similar) lines of code". Best commit I ever pushed.
Those were fun times. Hadn't done anything algorithmically impressive since.
But a lot is opportunity. Like, I had the opportunity to work on an old PHP backend, 500ms - 1 second response times (thanks in part to it writing everything to a giant XML string which was then parsed and converted to a JSON blob before being sent back over the line). Simply rewriting it in naive / best practices Go changed response times to 10 ms. In hindsight the project was far too big to rewrite on my own and I should have spent six months to a year trying to optimize and refactor it, but, hindsight.
I've "invented" all sorts of old patents, all sorts of algorithms, including the PID algorithm. I think it helped form a very practically useful "intuition".
But, I've noticed that some people are passionately against this type of self exploration.
Although that's also often an invitation for hallucinations so you have to be even more careful than usual.
uncatchable, so I won't even try.
:)
no worries.
It's the difference between hearing a lecture from a "bad" professor in Uni and watching a lecture video by Feynman, where he tries to get rid of scientific terms, when explaining things in simple terms to the public.
As long as you get a definition for your terms, things are manageable.
One way to often arrive at it is to just draw some graphs, on paper/whiteboard, and manually step through examples, pointing with your finger/pen, drawing changes, and sometimes drawing a table. You'll get a better idea of what has to happen, and what the opportunities are.
This sounds "Then draw the rest of the owl," but it can work, once you get immersed.
Then code it up. And when you spot a clever opportunity, and find the right language to document your solution, it can sound like a brilliant insight that you could just pull out of the air, because you are so knowledgeable and smart in general. When you actually had to work through that specific problem, to the point you understood it, like Feynman would want you to.
I think Feynman would tell us to work through problems. And that Feynman would really f-ing hate Leetcode performance art interviews (like he was dismayed when he found students who'd rote-memorize the things to say). Don't let Leetcode asshattery make you think you're "not good at" algorithms.
Yet, you ask someone "how do you build an efficient LFU" and get blank stares (I just LOVE the memcache solution of regions and probabilistic promotion/demotion).
Jokes aside, could I get a layman's explanation of the graph theory stuff here? Sounds pretty cool but the terminology escapes me
It’s because every task was doing a database call but they had a whole repo and aws lambdas for running it. Stupidest thing I’ve ever seen.
Your example raises some serious red flags. Did it ever dawned upon you that the reason these background tasks were offloaded to a dedicated service might have been to shed this load from your main server and protect it from handling sudden peaks in demand?
These background tasks are all database calls. That means the cpu is just waiting on the database for the majority of the call. Most modern servers can handle 10k of these calls concurrently. And you can do this off of one not so powerful CPU. Even half a cpu can handle this. Of course it depends on the CPU but you get my point.
The database is the bottleneck. The database is the thing that needs to be scaled first before you scale servers. This is the most common web application pattern. One way is providing more compute to the database (sharding is better then increasing cpu power as the bottleneck in the database is usually filesystem access not cpu power). Another way is to have a queue buffer the traffic spikes. Both of these are addressing an issue with the database first.
In most web apps. All the server does is wait for a database. The database is doing compute. You never want the server to do compute as that becomes what we call a “blocking call.” These blocking calls are the ones you offload to an external service as these calls “block” entire cpu threads. database calls do not “block” as the server will context switch to another green thread during database calls.
If you work somewhere where you’re scaling crud servers but not after scaling a central database it usually means you’re in a company that doesn’t get it and overemphasizes on “architecture” over common sense. It’s actually extremely common in lower tier small companies to have not so smart people build things like this that don’t make any sense. They aren’t thinking coherently and I’ve seen tons of people who just miss this common sense notion.
I’ll be Frank. It’s stupid and defies common sense. It’s likely you are doing this? But it’s also extremely commonplace.
Given two graphs one is a tree you cannot determine if the tree is a subgraph of the other graph in one walk through?
It’s only possible if you’re given additional information? Like a starting node to search from? I’m genuinely confused?
http://www.nsl.com/papers/samefringe.htm
If you flatten both of your trees/graphs and regard the output as strings of nodes, you reduce your task to a substring search.
Now if you want to verify if the structures and not just the leave nodes are identical, you might be able to encode structure information into you strings.
I was thinking in terms of finding all subgraph isomorphisms. But this definitely is O(N) if all you need is one solution.
But then I thought about it even further and this reduces to sliding window problem. In this case you still need to travel to each node in the window to see if there’s a match.
So it cannot be that you traverse each node once. Not if you want to find all possible subgraph isomorphisms.
Imagine a string that is a fractal of substrings:
rrrrrrrrrrrrrrrrrrrrrrrrrrrr
And the other one: rrrrrrr
Right? The sliding window for rrrrrrr will be 7 in length and you need to traverse that entire window every time you move it. So by that fact alone every node is traversed at least 7 times.There’s also a role called being an algorithms engineer in standard tech companies (typically for lower level work like networking, embedded systems, graphics, or embedded systems) but the lack of an engineering background may hamstring you there. Engineers working in crypto also use a fair bit of algorithms knowledge.
I do low level work at a top company, and you only use algorithms knowledge on the job a couple of times a year at best.
I heard from someone who was in that field, that the main qualification for such a job is analytical ability and mathematics knowledge, apart from programming skills, of course.
These days it's very different, mostly large-ish distributed systems.
The graph that is to be determined as a subset is a tree. From there he says it can be done in an algorithm that only traverses every node at most one time.
I’m assuming he’s also given a starting node in the original graph and the algorithm just traverses both graphs at the same time starting from the given start node in the original graph and the root in the tree to see if they match? Standard DFS or BFS works here.
I may be mistaken. Because I don’t see any other way to do it in one walk through unless you are given a starting node in the original graph but I could be mistaken.
To your other point, The algorithm inherently has to also be statefull. All traversal algorithms for graphs have to have long term state. Simply because if your at a node in a graph and it has like 40 paths to other places you can literally only go down one path at a time and you have to statefully remember that node has another 39 paths that you have to come back to later.
I oversimplified the problem :). Really it was about generating an isomporhic-ish view, based on some user defined rules, of an existing graph, itself generated by a subgraph isomorphism by a query language.
Think a computer network as a graph, with various other configuration items like processes, attached drives, etc (something also known as a CMDB). Query that graph to generate a subgraph out of it. Then use rules to make that subgraph appear as a tree of layers (tree but in each layer you may have additional edges between the vertices) because trees are efficient, non-complex representation on 2d space (i.e. monitors).
However, a child node in that tree isn't necessarily connected directly to the parent node. E.g. one of the rules may be "display the sub network and the attached drives in a single layer", so now the parent node, the gateway, has both network nodes (directly connected to it) and attached drives (indirectly connected to it) as direct descendants.
Extend this to be able to connect through any descendant, direct or indirect (gateway -> network node -> disk -> config file -> config value - but put the config value on the level of the network node and build a link between them to represent the compound relationship).
Walk through the original subgraph while evaluating the rules and build a "trace back" stack to let you understand how to build each layer even in the presence of compound links while performing a single walkthrough instead of nm (original vertices rules for generation).
As I said, that was a lot of fun. I miss those days.
You are starting at a specific node in the graph and saying that if there’s an isomorphism the target tree root node must be equivalent to that specific starting node in the original graph.
You just walk through the original graph following the pattern of the target tree and if something doesn’t match it’s false otherwise true? Am I mistaken here? Again the target being a tree is a bit irrelevant. This will work for any subgraph as long as as you are also given starting point nodes for both the target and the original graph?
the select-a-bunch-of-code-and-then-zap-it-with-the-Del-key is the best hardware algorithm.
Otherwise just downvote or flag I guess, but this comment of yours just reads as an insult to a person that maybe did not put the most effort into writing their comment, but seems genuine to me at least.
Is this, from elsewhere in the thread, a system rethink, https://github.com/dotnet/runtime/pull/36715/files ?
I've worked on a product that reinvented parts of the standard library in confusing and unexpected ways, meaning that a lot of the code could easily be compacted 10-50 times in many place, i.e. 20-50 lines could be turned into 1-5 or so. I argued for doing this and deleting a lot of the code base, which didn't take hold before me and every other dev left except one. Nine months after that they had deleted half the code base out of necessity, roughly 2 MLOC to 1 MLOC, because most of it wasn't actually used much by the customers and the lone developer just couldn't manage the mess on his own.
I wouldn't call that a system rethink.
They couldn't. I would go find the code that caused a bug, fix it and discover that the bug was still there. Because previous students had, rather than add a parameter to a function, would make a copy and slightly modify it.
I deleted about 3/4 of their code base (thousands of lines of Turbo Pascal) that fall.
Bonus: the customer was the Department of Energy, and the program managed nuclear material inventory. Sleep tight.
In addition to not breaking existing code, also has added benefit of boosting personal contribution metrics in eyes of management. Oh and it's really easy to revert things - all I have to do is find the latest copy and delete it. It'll work great, promise.
I'm distrustful on unit testing as I've seen too many tests written to make code coverage numbers but that don't actually test the functions they are aimed at. A non-trivial number which run the function asynchronously and then report a successful run before the function even finishes executing, meaning that even throwing errors don't fail the tests (granted, part of that is on the testing framework for letting unexpected errors ever result in a pass).
Are you sure there's anything needing cleaning up?
If you're talking about duplicate code showing up in 50 places then your problem is not code duplication but incompetent developers not being able to maintain a project.
If instead you're talking about code with a passing resemblance showing up in 2 or 3 places then odds are you're actually looking at more maintainable code straight in the eye and you're not able to understand how that makes the project more maintainable.
For other code it's an absolute stink and i agree. But for data transforms... I've seen the alternative, a neatly abstracted in-house library of abstracted combinations of dataframe operations with different parameters and.. It's the most aesthetically pleasing unfathomable hell I've ever experienced.
So now, when munging dataframes, i will be much faster to reach for 'copy that function and modify it slightly' - maintenance headache, but at least the result is readable.
The demanding / loud person can and should be ignored; as a developer, you are responsible for code quality and maintainability, not your / their manager.
Are you sure it's code duplication?
I mean, read your own description: the new function does not need to support edge cases. Having to handle edge cases is a huge code smell, and a clear sign of premature generalization.
And you even admit the guy was more productive and added less bugs?
There is a reason why the mistakes caused by naive approaches to Don't Repeat Yourself (DRY) are corrected with Write Everything Twice (WET).
They just aren’t making changes to the shared function, so they don’t need to test existing functionality still works, just their single use case.
Source code for each portal was stored in a separate Git repository. I've asked the original authors how am I supposed to fix bugs that affect all the portals or develop new functionality for all the portals. The answer was to backport all fixes manually to all copies of the source code.
Then I've asked: isn't it possible to use a single source repository and use feature flags to customize appearance and features of each portals. Original authors said that it is impossible.
In 2-3 months I've merged the code of 4-5 portals into one repository, added feature flags, upgraded the framework version, release went flawlessly, and it was possible to fix a bug simultaneously for all the portals or develop a new functionality available across all the countries where the company operated. It was a huge relief for me as copying bugfixes manually was tedious and error-prone process.
It was so long ago it feels half mythical to me.
These are my favorite (in a sense) programmer stories--that there's these incomprehensible piles of rubbish that somehow, like, run The World and things, and yet somehow things manage to work (in an outwardly observable sense).
Although, I recall two somewhat recent stories where this wasn't the case. The unemployment benefits fiascos during early Covid-era, and some more recent air traffic control-related things (one which effected me personally).
Negative 2000 Lines of Code (1982) - https://news.ycombinator.com/item?id=33483165 - Nov 2022 (167 comments)
-2000 Lines of Code - https://news.ycombinator.com/item?id=26387179 - March 2021 (256 comments)
-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)
Note for anyone wondering: reposts are ok after a year or so (https://news.ycombinator.com/newsfaq.html).In addition to it being fun to revisit perennials sometimes (though not too often), this is also a way for newer cohorts to encounter the classics for the first time—an important function of this site!
I've told this story to every client who tried schemes to benchmark productivity by some single-axis metric. The fact that it was Atkinson demonstrates that real productivity is only benchmarkable by utility, and if you can get a truly accurate quantification for that then you're on the shortlist for a Nobel in economics.
Bill Atkinson has died - https://news.ycombinator.com/item?id=44210606 - June 7, 2025 (277 comments)
I didn't see that post, but I'm glad we're able to remember Bill through humorous anecdotes and eternally relevant lessons like this.
My manager has it pinned on the breakroom wall.
[0]: https://thedailywtf.com/articles/The-Defect-Black-Market
I'm trying to socialize my team to get more in the habit of this, but it's been hard. It's not so much that I get pushback, it's just that tasks like "clean up the feature flag" get thrown into the tech debt pile. From my perspective, that's feature work, it just happens to take place after the feature goes live instead of before. But it's work that we committed to when we decided to build the feature, so no, you don't get to put it on the tech debt board like it was some unexpected issue that came up during development.
Curious to hear other perspectives here, I do worry that I'm a bit too dogmatic about this sometimes. Part of it maybe comes from working in shared art / maker spaces a lot in the past, where "clean up your shit" was rule #1, and I kind of see developers leaving unused code throughout the codebase for features they owned through the same lens.
For some reason new devs keep telling me how easy it is to implement features.
Really wonder why that is. The managers keep telling me that refactoring is a nice-to-have thing and not necessary and maybe we have time next sprint.
You just have to do it without telling anyone, it improves velocity for everyone. It's architecture work on the small scale.
Of course, lately anything trivial I ask codex to do - but there is still fun in figuring out what trivial thing I should have it take on next.
It needs to be rewarded properly to be prioritized.
I haven't seen a lot of other good suggestions for how to accomplish this, so maybe you're being just the right amount of dogmatic.
Taking you to literally mean you have a separate board for tech debt, that's your problem right there.
https://forum.cursor.com/t/cursor-yolo-deleted-everything-in...
The developer who wrote it was a smart guy, but he had never worked on any other JS project. All state was stored in the DOM in custom attributes, .addEventListeners EVERYWHERE... I joke that it was as if you took a monk, gave him a book about javascript, and then locked him in a cell for 10 years.
I started refactoring pieces into web components, and after about 6 months had removed 50k lines of code. Now knowing enough about the app, I started a complete rewrite. The rewrite is about 80% feature parity, and is around 17k lines of code (not counting libraries like Vue/pinia/etc).
So, soon, I shall have removed over 200,000 loc from the project. I feel like then I should retire as I will never top that.
This is exactly where these comparisons break down. Obviously you don't need as much code to get passable implementations of a fraction of all the features.
I'd rather have 250,000 lines of code but 230,000 of that is in battle tested libraries. And of which only 20,000 lines are what we ever need to read/write.
You make a fair point that a basic framework can be expressed with much less code.
And that the remaining 20% probably contains more edge cases with proportionally more code.
But do you think the last 20% will eventually make up anywhere near 233k lines of code?
The real save here comes from rewriting: seeing all the common denominators and knowing what's ahead.
I've had a similar experience (see other comment), the original author was a junior developer at best, but unfortunately, a middle-aged, experienced developer, one of the founders of the company, and very productive. But obviously, not someone who had ever worked in a team or who had someone else work on their codebase.
Think functions thousands of lines long, nested switch/case/if/else/ternary things ten levels deep, concatenated SQL queries (it was PHP because of course), concatenated JS/HTML/HTML-with-JS (it was Dojo front-end), no automated tests of any sort, etc.
I couldn't believe my eyes. I was working in my own project beside this team with the list, so thankfully I was left out of the whole disaster.
A guy I knew wasn't that lucky. I saw how he suffered from this harmful list. Then I told him a story about the Danish film director Lars von Trier I recently had heard. von Trier was going to be chosen to appear in a "canon" list of important Danish artists that the goverment was responsible for. He then made a short film where he took the Danish flag (red with a white cross) and cut out the white lines and stitched it together again, forming a red communist flag. von Trier was immediately made persona non grata and removed from the "canon".
Later that day my friend approached the bugs caused/fixed list, cut out his own line, taped it together and put it on the wall again. I never forget how a PL came in the room later, stood and gazed at the list for a long time before he realized what had happened. "Did you do this?" he asked my friend. "Yes", he answered. "Why?", said the PL. "I don't want to be part of that list", he answered. The next day the list was gone.
A dear memory of successful subversion.
Simple, to the point, love it. "I'm not playing your stupid management games".
The lead dev was a hard core c programmer and had no perl experience before this job. He handed me a 200 line uncommented function that he wrote and was not working. It was a pattern matcher. I replaced it with 6 lines of commented perl with regex that was very readable (for a regex).
Since he had no idiomatic understanding of perl he did not accept it and complained to management. We had to bring in the local perl demigod to arbitrate(at 21 was half my age at the time, but smart as a whip). Ruled in my favor and the lead was pissed.