338 comments

[ 3.3 ms ] story [ 242 ms ] thread
Developers need to learn how to think algorithmically. I still spend most of my time writing pseudocode and making diagrams (before with pen and paper, now with my iPad). It's the programmers' version of the Abraham Lincoln's quote "Give me six hours to chop down a tree and I will spend the first four sharpening the axe."
Question in my head is, can LLMs think algorithmically?
LLMs can't think.
LLMs can think.
Source?
I use them a lot. They sure seem thinky.

The other day I had one write a website for me. Totally novel concept. No issues.

I have a similar experience. Just thought it'd be cute to ask you both for sources. Interesting that asking you for sources got me upvoted, while asking the other guy for sources got me downvoted :)
Source?
LLMs string together words using probability and randomness. This makes their output sound extremely confident and believable, but it may often be bullshit. This is not comparable to thought as seen in humans and other animals.
unfortunately that is exactly what the humans are doing an alarming fraction of the time
One of the differences is that humans are very good at not doing word associations if we think they don't exist, which makes us able to outperform LLMs even without a hundred billion dollars worth of hardware strapped into our skulls.
that's called epistemic humility, or knowing what you don't know, or at least keeping your mouth shut, and in my experience actually humans suck at it, in all those forms
Like a bad coder with a great memory, yes
The problem is the word “producing” of the parent comment, where it should be “reproducing”.
Interesting question.

LLMs can be cajoled into producing algorithms.

In fact this is the Chain-of-Thought optimisation.

LLMs give better results when asked for a series of steps to produce a result than when just asked for the result.

To ask if LLMs “think” is an open question and requires a definition of thinking :-)

Does it really take four hours to sharpen an axe? I've never done it.
Doing it right, with only manual tools, I believe so, remembering back to one of the elder firefighters that taught me (who was also an old-school forester).

Takes about 20 minutes to sharpen a chainsaw chain these days though...

10/20 minutes to sharpen a pretty dull kitchen knife with some decent whetstones.

Also, as someone famous once said: if I had 4 hours to sharpen an axe, I'd spend 2 hours preparing the whetstones.

If I had 2 hours to prepare whetstones I’d do 1 hour of billable work and then order some whetstones online.
If I had 1 hour of billable work, I'd charge per project and upfront, to allow me to claim unemployment for the following weeks.
I don’t really know what “think algorithmically means,” but what I’d like to see as a lead engineer is for my seniors to think in terms of maintenance above all else. Nothing clever, nothing coupled, nothing DRY. It should be as dumb and durable as an AK47.
We need this to be more prevalent. But the sad fact is most architects try to justify their position and high salaries by creating "robust" software. You know what I mean - factories over factories, micro services and what not. If we kept it simple I don't think we would need many architects. We would just need experienced devs that know the codebase well and help with PRs and design processes, no need to call such a person 'architect', there's not much to architect in such a role.
I was shown what it means to write robust software by a guy with a PhD in... philosophy out of all things(so a literal philosophiae doctor).

Ironically enough it was nothing like what some architecture astronauts wring - just a set of simple to follow rules, like organizing files by domain, using immutable data structures and pure functions where reasonable etc.

Also I hadn't seen him use dependent types in the one project we worked together on and generics appeared only when it really made sense.

Apparently it boils down to using the right tools, not everything you've got at once.

I love how so much of distributed systems/robust software wisdom is basically: stop OOP. Go back to lambda.

OOP was a great concept initially. Somehow it got equated with the corporate driven insanity of attaching functions to data structures in arbitrary ways, and all the folly that follows. Because "objects" are easy to imagine and pure functions aren't? I don't know but I'd like to understand why corporations keep peddling programming paradigms that fundamentally detract from what computer science knows about managing complex distributed systems.

In my mind this is breaking down the problem into a relevant data structure and algorithms that operate on that data structure.

If for instance you used a tree but were constantly looking up an index in the tree you likely needed a flat array instead. The most basic example of this is sorting, obviously but the same basic concepts apply to many many problems.

I think the issue that happens in modern times, specially in webdev, is we aren't actually solving problems. We are just glueing services together and marshalling data around which fundamentally doesn't need to be algorithmic... Most "coders" are glorified secretaries who now just automate what would have been done by a secretary before.

Call service A (database/ S3 etc), remove irrelevant data, send to service B, give feedback.

It's just significantly harder to do this in a computer than for a human to do it. For instance if I give you a list of names but some of them have letters swapped around you could likely easily see that and correct it. To do that "algorithmically" is likely impossible and hence ML and NLP became a thing. And data validation on user input.

So algorithmically in the modern sense is more, follow these steps exactly to produce this outcome and generating user flows where that is the only option.

Human do logic much much better than computers but I think the conclusion has become that the worst computer program is probably better at it that the average human. Just look at many niche products catered to X wealth group. I could have a cheap bank account and do exactly what is required by that bank account or I can pay a lot of money and have a private banker that I can call and they will interpret what I say into the actions that actually need to happen... I feel I am struggling to actually write what's in my mind but hopefully that gives you an idea...

To answer your nothing clever , well clever is relative. If I have some code which is effectively a array and an algorithm to remove index 'X' from it, would it be "clever" code to you if that array was labeled "Carousel" and I used the exact same generic algorithms to insert or remove elements from the carousel?

For most developers these days they expect to have a class of some sort with a .append and .remove function but why isn't it just an array of structs which use the exact same functions as every single other array... That people generally will complain that that code is "clever" but in reality it is really dumb. I can see it's clearly an array being operated on but OOP has caused brain rot and developers actually don't know what that means... Wait maybe that was OPs point... People no longer think algorithmically.

---

Machine learning, Natural Language Processing

> I think the issue that happens in modern times, specially in webdev, is we aren't actually solving problems. We are just glueing services together and marshalling data around which fundamentally doesn't need to be algorithmic...

This is true and is the cause of much frustration everywhere. Employers want “good” devs, so they do complicated interviews testing advanced coding ability. And then the actual workload is equal parts gluing CRUD components together, cosmetic changes to keep stakeholders happy, and standing round the water cooler raging at all the organisational things you can’t change.

>I don’t really know what “think algorithmically means,”

I would say thinking about algorithms and data structures for algorithmic complexity not to explode.

>Nothing clever

A lot of devs use nested loops and List.remove()/indexOf() instead of maps, etc., the terrible performance gets accepted as the state of the art, and then you have to do complex workarounds not to call some treatments too often, etc., increasing the complexity.

Performance yields simplicity: a small increase in cleverness in some code can allow for a large reduction in complexity in all the code that uses it.

Whenever I do a library, I make it as fast as I can, for user code to be able to use it as carelessly as possible, and to avoid another library popping up when someone wants better performances.

> Nothing clever, nothing coupled

Yes, simple is good. Simple is not always easy though. A good goal to strive for nevertheless.

> nothing DRY

That's interesting. Would you prefer all the code to be repeated in multiple places?

Bit OP but probably means “no fancy silver bullet acronyms”.
Depends. I haven’t come up with the rubric yet but it’s something like “don't abstract out functionality across data types”. I see this all the time: “I did this one thing here with data type A, and I’m doing something similar with data type B; let’s just create some abstraction for both of them!” Invariably it ends up collapsing, and if the whole program is constructed this way, it becomes monstrous to untangle, like exponentially complicated on the order of abstractions. I think it’s just a breathtaking misunderstanding of what DRY means. It’s not literally “don’t repeat yourself”. It’s “encapsulate behaviors that you need to synchronize.”

Also, limit your abstractions’ external knowledge to zero.

Very good explanation!

> “I did this one thing here with data type A, and I’m doing something similar with data type B; let’s just create some abstraction for both of them!”

I'm guilty of this. I even fought hard against the people who wanted to keep the code duplicated for the different data types.

> “encapsulate behaviors that you need to synchronize.”

I like that!

The problem is that most developers don't not actually understand DRY. They see a few lines repeated a few times in different functions and create a mess of abstraction just to remove the repeated code. Eventually more conditions are added to the abstracted functions to handle more cases, and the complexity increases, all to avoid having to look at a couple lines of repeated code. This is not what DRY is about.
Yep, exactly. I went into further detail in another comment.
Do you have any resources for this? especially for the adhd kind - I end up going down rabbit holes in the planning part. How do you deal with information overload and overwhelm OR the exploration exploitation dilemma?
I wonder if good REPL habits could help the ADHD brain?

It still feels like you are coding so your brain is attached, but with rapid prototyping you are also designing, moving parts around to see where they would fit best.

There are 2 bad habits in programming: people that start writing code the 1st second, and people that keep thinking and investigating for months without writing any code. My solution to that: just force to do the opposite. In your case: start writing code immediately. Ni matter how bad or good. Look the youtube channel “tsoding daily” he just goes ahead. The code is not always the best, but he gets things done. He does research offline (you can tell) but if you find yourself doing just research, reading and thinking, force yourself to actually start writing code.
Or his Twitch videos. That he starts writing immediately and that we're able to watch the process is great. Moreover the tone is friendly and funny.
(comment deleted)
it's an odd analogy because programs are complex systems and involve interaction between countless of people. With large software projects you don't even know where you want to go or what's going to happen until you work. A large project doesn't fit into some pre-planned algorithm in anyone's head, it's a living thing.

diagrams and this kind of planning is mostly a waste of time to be honest. You just need to start to work, and rework if necessary. This article is basically the peak of the bell curve meme. It's not 90% thinking, it's 10% thinking and 90% "just type".

Novelists for example know this very well. Beginners are always obsessed with intellectually planning out their book. The experienced writer will always tell you, stop yapping and start typing.

Your part of your comment doesn't fit with the rest. With complex projects, you often don't even know exactly what you're building, it doesn't make sense to start coding. You first need to build a conceptual model, discuss it with the interested parties and only then start building. Diagrams are very useful to solidify your design and communicate it to others.
There's a weird tension between planning and itterating. You can never forsee anywhere close to enough with just planning. But if you just start without a plan you can easily work yourself into a dead end. So you need enough planning to avoid the dead ends, whilst starting early enough so you get your reality checks so you have enough information to get to an actual solution.

Relevant factors here are how cheaply you can detect failure (in terms of time, material, political capital, team morale) and how easily you can backtrack out of a bad design decision (in terms of political capital, how much other things need to be redone due to coupling, and other limitations).

The earlier you can detect bad decisions, and the easier you can revert them, the less planning you need. But sometimes those are difficult.

It also suggests that continuous validation and forward looking to detect bad decisions early can be warranted. Something which I myself need to get better at.

> Novelists for example know this very well. Beginners are always obsessed with intellectually planning out their book. The experienced writer will always tell you, stop yapping and start typing.

This is not true in general. Brandon Sanderson for example outlines extensively before writing: https://faq.brandonsanderson.com/knowledge-base/can-you-go-i...

> You just need to start to work, and rework if necessary

And making changes on paper is cheaper than in code.

I'm tempted to break out the notebook again, but... beyond something that's already merged, what situations make paper changes cheaper than code changes? I can type way faster than I can write.
I still use pen and paper. Actually as I progress with my career and knowledge I use pen and paper more and digital counterparts less.

It might be me not taking my time to learn Mathematica/Julia tho...

This is laid out pretty early on by Bjourne in his PPP book[0],

> We do not assume that you — our reader — want to become a professional programmer and spend the rest of your working life writing code. Even the best programmers — especially the best programmers — spend most of their time not writing code. Understanding problems takes serious time and often requires significant intellectual effort. That intellectual challenge is what many programmers refer to when they say that programming is interesting.

Picked up the new edition[1] as it was on the front page recently[2].

[0]: https://www.stroustrup.com/PPP2e_Ch01.pdf

[1]: https://www.stroustrup.com/programming.html

[2]: https://news.ycombinator.com/item?id=40086779

The hardest part is finding out what _not_ to code, either before (design) or after (learn from prototype or the previous iteration) having written some.
No code is faster than no code!
(comment deleted)
Sometimes you have to write it to understand why you shouldn’t have written it.
Sometimes you knew you shouldn't have written it and then did so anyway.
I think this is mostly right, but my biggest problem is that it feels like we spend time arguing the same things over and over. Which DB to use, which language is best, nulls or not in code and in DB, API formatting, log formatting, etc.

These aren't particularly interesting, and sure it's good to revisit them time and again, but these are the types of time sinks I find myself in in the last 3 companies I've worked for that feel like they should be mostly solved.

In fact, a company with a strong mindset, even if questionable, is probably way more productive. If it was set in stone we use Perl, MongoDB, CGI... I'd probably ultimately be more productive than I've been lately despite the stack.

I disagree! These decisions are fundamental in the engineering process.

Should I use steel, concrete or wood to build this bridge?

The mindless coding part starts one year later when you found that your mongoDB does not do joins, and you start implementing this as an extra layer in the client side.

What you're referring to is politics. Different people have different preferences, often because they're more familiar with one of them, or for other possibly good reasons. Somehow you have to decide who wins.
> “If it was set in stone we use Perl, MongoDB, CGI... I'd probably ultimately be more productive than I've been lately despite the stack.”

Facebook decided to stick with PHP and MySQL from their early days rather than rewrite, and they’re still today on a stack derived from the original one.

It was the right decision IMO. They prioritized product velocity and trusted that issues with the stack could be resolved with money when the time comes.

And that’s what they’ve done by any metric. While nominally a PHP family language, Meta’s Hack and its associated homegrown ecosystem provides one of the best developer experiences on the planet, and has scaled up to three billion active users.

re·con·nais·sance noun military observation of a region to locate an enemy or ascertain strategic features.
Did you want to grace us with any particular relevance of this knowledge or do you just wanna keep it to yourself?

Sadly, after all these years programming, I have yet to discern any real vulnerability in the US government.

I think it was meant as a parallel; historically light cavalry (explorers) and heavy cavalry (exploiters) had different ideals*, different command structures, and when possible even used different breeds of horses.

Compare the sorts of teams that do prototyping and the sorts of teams that work to a Gantt chart.

* the ideal light cav trooper was jockey-sized, highly observant, and was already a good horseman before enlisting; the ideal heavy cav trooper was imposing, obedient, and was taught just enough horsemanship to carry out orders but not so much that he could go AWOL.

Just guessing/reading: it's a metaphor.

You could see the recon as the thinking from the article. The enemy and terrain are the code and various risks and effects associated with changing it.

Wait… you have the diffs… why are you retyping the lost code by hand? What am I missing?
I think the diffs are evidence for the author's claim that the retyping would be a relatively easy job.
They specifically mentioned the diffs being physically printed, like, on paper. Also, it’s just a convoluted example to highlight the core idea.

    I'm confident enough to tout this number as effectively true, though I should mention that no company I work with has so far been willing to delete a whole day's work to prove or disprove this experiment yet.
Long ago when I was much more tolerant, I had a boss that would review all code changes every night and delete anything he didn't like. This same boss also believed that version control was overcomplicated and decided the company should standardize on remote access to a network drive at his house.

The effect of this was that I'd occasionally come in the next morning to find that my previous day's work had been deleted. Before I eventually installed an illicit copy of SVN, I got very good at recreating the previous day's work. Rarely took more than an hour, including testing all the edge cases.

Crikey what a sociopath to work for. I’m sorry this happened to you.
Was your work better or worse second time around?
Probably a bit of both, but hindsight helped. It doesn't usually end up exactly the same though. Regardless, whatever I wrote worked well enough that it outlived the company. A former client running it reached out to have it modified last year.
With writing the second version is definitely better, sucks having to redo but improvement makes it worth while.
I don't have a big sample size, but 2/2 of my first embedded jobs both used network shares and copy+paste to version their code. Because I had kind-of PTSD from the first job, I right off asked the boss on the second job if they had a git repository somewhere. He thought that git is the same as Github and told me they don't want their code to be public.

When they were bought of by some bigger company, we got access to their intranet. I digged through that and found a gitlab instance. So then I just versioned my own code (which I was working on mostly on my own), documented all of it on there, even installed a gitlab runner and had a step-by-step documentary on how to get my code working. When they kicked me out (because I was kind of an asshole, I assume), they asked me to hand over my code. I showed them all of what I did and told them how to reproduce it. After that the boss was kinda impressed and thanked me for my work. Maybe I had a little positive impact on a shitty job by being an asshole and doing stuff the way that I thought would be the right way to do it.

Edit: Oh, before I found that gitlab instance I just initialized raw git repositories on their network share and pushed everything to that

You got fired and your response is to give them a gift? Fascinating.
Well, I was severely depressed and was on sick leave for quite some time, but when I was there I just did my job as best as I can. I am not an inherent asshole. I just get triggered hard when some things don't work out (no initial training, barely any documentation, people being arrogant). I just want to be better than this myself.
Bad boss or zen teacher, we will never know!
The bigger problem here is the manager getting involved with code.

Even when done with good intentions, managers being involved in code/reviews almost always ends up being net negative for the team.

Why?
There are many reasons. First a manager is not a peer but brings in a sense of authority into the mix so the discussions will not be honest. Manager's inputs have a sense of finality and people will hesitate to comment or override them even when they are questionable.

There are human elements too. Even if someone has honest inputs, any (monetary or otherwise) rewards or lack of them will be attributed to those inputs (or lack of them). Overall, it just encourages bad behaviours among the team and invites trouble.

These should not happen in an ideal world but as we are dealing with people things will be far from ideal.

Anyone who has made seious use of Microsoft Office products in the 00's and 10's knows these things to be true (or they reflexively click save every 5-10 minutes).
I would absolutely agree, for any interesting programming problem. Certainly, the kind of programming I enjoy requires lots of thought and planning.

That said, don't underestimate how much boilerplate code is produced. Yet another webshop, yet another forum, yet another customization of that ERP or CRM system. Crank it out, fast and cheap.

Maybe that's the difference between "coding" and "programming"?

> Maybe that's the difference between "coding" and "programming"?

I know I'm not alone in using these terms to distinguish between each mode of my own work. There is overlap, but coding is typing, remembering names, syntax, etc. whereas programming is design or "mostly thinking".

I usually think of coding and programming as fairly interchangeable words (vs “developing”, which I think encapsulates both the design/thinking and typing/coding aspects of the process better)
Implementing known solutions is less thinking and more typing, but on the other hand it feels like CoPilot and so on is changing that. If you have something straightforward to build, you know the broad strokes of how it's going to come together, the actual output of the code is so greatly accelerated now that whatever thinking is left takes a proportionally higher chunk of time.

... and "whatever is left" is the thinking and planning side of things, which even in its diminished role in implementing a known solution, still comes into play every once in a while.

Good programming is sometimes mostly thinking, because "no plan survives first contact with the enemy." Pragmatic programming is a judicious combination of planning and putting code to IDE, with the balance adapting to the use case.
The first run with the IDE is like completing a level of a game the first time. The second time it will be quicker.

I agree we can expand thinking to “thinking with help from tools”.

This. Programming is mostly reconnaissance, not just thinking. If you don’t write code for days, you’re either fully aware of the problem surface or are just guessing it. There’s not much to think about in the latter case.
I liked "Code is just the residue of the work"
Who hasn't accidentally thrown away a days worth of work with the wrong rm or git command? It is indeed significantly quicker to recreate a piece of work and usually the code quality improves for me.
I’ve often found it alarming to see how much better the re-do is. I wonder whether I should re-write more code.
Absolutely. Parallel to thinking LOC is a good metric, comes with "we have to reuse code" Because lots of people think, writing the code is very expensive. It is not!
writing it is not expensive. however, fixing the same bug in all the redundant reimplementations, adding the same feature to all of them, and keeping straight the minor differences between them, is expensive
Not only fixing the same bug twice, but also fixing bugs that happen because of using the same functionality in different places. For example, possible inconsistency that results from maintaining state in multiple different locations can be a nightmare, esp. in hard-to-debug systems like highly parallelized or distributed architecture.
I see "code that looks the same" being treated as "code that means the same" resulting in problems much more often than "code that means the same" being duplicated.
can you clarify your comment with some examples, because i'm not sure what you mean, even whether you intend to disagree with the parent comment or agree with it
Lets take pending orders and paid for orders as an example.

For both, there is a function to remove an order-line that looks the same. Many people would be tempted at that point, to abstract over pending and paid orders to have both reference the same function, via adding a base class of order, for example, because the code looks the same.

But for a pending order, it means removing an item from the basket, while for the paid for order, it means removing an item due to unavailability. So the code means different things.

Lets then take the system to have evolved further, where now on the paid for order some additional logic should be kicked off when an item is removed. If both pending and paid for orders reference the same function, you have to add conditionals or something, while if each has its own, they can evolve independantly.

And it definitely is disagreement with the parent comment. Sorry to have not elaborated on it in the first place.

In the software engineering literature, there is something known as "second system effect": the second time a system is designed it will be bloated, over-engineered and ultimately fail, because people want to do it all better, too much so for anyone's good.

But it seems this is only true for complete system designs from scratch after a first system has already been deployed, not for the small "deleted some code and now I'm rewriting it quickly" incidents (for which there is no special term yet?).

I think this was the reasoning behind the adage "make it work, make it right, make it fast" (or something along those lines).

You'd do a fairly rough draft of the project first, just trying to make it do what you intend it to. Then you'd rewrite it so it works without glaring bugs or issues, then optimise it to make it better/more performant/more clearly organised after that.

Yes, that can often result in a better-designed refactored version, since you can start with a fully-formed idea!
Not for ages and definitely not since Github- just keep committing and pushing as a backup
i've never lost work to a wrong git command because i know how to use `git reflog` and `gitk`. it's possible to lose work with git (by not checking it in, `rm -r`g the work tree with the reflog in it, or having a catastrophic hardware failure) but it is rare enough i haven't had it happen yet
This is literally impossible with GitHub Desktop and a functioning Recycle Bin
Programming is mostly planning.

When you work for companies that take programming seriously (e.g., banks, governments, automotive, medical equipment, etc.), a huge development cycle occurs before a single line of code is written.

Here are some key development phases (not all companies use all of them):

1. high level definition, use cases, dependencies; traceability to customer needs; previous correction (aka failures!) alignment

2. key algorithms, state machines, flow charts (especially when modeling fail-safety in medical devices)

3. API, error handling, unit test plan, functional test plan, performance test plan

4. Alignment with compliance rules; attack modeling; environmental catastrophe and state actor planning (my experience with banks)

After all of this is reviewed and signed-off, THEN you start writing code.

This is what code development looks like when there are people's, business's, and government's lives/money/security on the line.

So. Much. Planning.

(comment deleted)
And it's a terrible way to make anything, much less software. It's more forgivable when the cost of outer iteration is high because you're making, say, a train, but even then you design around various levels of simulation, iterating in the virtual world. The idea that you can nail down all the requirements and interfaces before you even begin is why so many projects of the type you describe often have huge cost overruns as reality highlights all the changes that need to be made.
I see this so often. It's how terrible software is written because people are afraid to change direction or learn anything new mid project.

I rewrite most of my code 2-3 times before I'm done and I'm still 5x faster than anyone else, and significantly higher quality and maintainability as well. People spend twice as long writing the ugliest, hackiest code as they would have to just learn to do it right

So you think it is smarter to, say, tell the carpenters “just start building a house” without giving them plans?

What you described is not how successful products are built and maintained; what you described is why we have world full of lots of shitty tech from “move fast and break things” ADHD-like management and young programmers that think they know everything and cry about having to do thinky work first. Literally the worst kind of programmers to have on a project.

I'm talking about engineering, not manufacturing. I'm not suggesting not thinking, I'm saying that you cannot design every aspect of a system without learning more about the design. It's just a restatement of "Gall's law" (in scare quotes because it's obviously not an actual law). Alternatively it's the obvious way of working given the principles espoused in the agile manifesto.
Your absolutism is at odds with reality. Engineering and manufacturing are literally joined at the hip, and both require a significant amount of planning. If you disagree with this, well, good luck with your engineering career, is all I can say!
Precisely! The idea that you can set down the requirements and all the design decisions before you even start thinking about the implementation is completely flawed.

The engineering/manufacturing dichotomy was just with respect to your statement about carpenters. Even then, expediency on the part of the manufacturer will often result in design changes.

> companies that take programming seriously (e.g., banks, governments, automotive, medical equipment, etc.)

(Some) banks (sometimes) hire armies of juniors from Accenture. I wouldn't say they take programming seriously.

My government had some very botched attempts at creating computer systems. They're doing better these days, creating relatively simple systems. But I wouldn't say they're particularly excellent at programming.

Somewhere in that list you need to add some time for certification, plus rework after certification failure!

Not only does it take a week, but each attempt costs a few tens of thousands of dollars.

Off topic. I'm not a developer but I do write code at work, on which some important internal processes depend. I get the impression that most people don't see what I do as work, engaged as they are in "busy" work. So I'm glad when I read things like this that my struggles are those of a real developer.
Sounds like you are a "real developer". Don't sell yourself short.
This is why domain knowledge is key. I work in finance, I've sat on trading desks looking at various exchanges, writing code to implement this or that strategy.

You can't think about what the computer should do if you don't know what the business should do.

From this perspective, it might make sense to train coders a bit like how we train translators. For example, I have a friend who is a translator. She speaks a bunch of languages, it's very impressive. She knows the grammar, idioms, and so on of a wide number of languages, and can pick up new ones like how you or I can pick up a new coding language.

But she also spent a significant amount of time learning about the pharmaceutical industry. Stuff about how that business works, what kinds of things they do, different things that interface with translation. So now she works translating medical documents.

Lawyers and accountants are another profession where you have a language gap. What I mean is, when you become a professional, you learn the language of your profession, and you learn how to talk in terms of the law, or accounting, or software. What I've always found is that the good professionals are the ones who can give you answers not in terms of their professional language, but in terms of business.

Particularly with lawyers, the ones who are less good will tell you every possible outcome, in legalese, leaving you to make a decision about which button to press. The good lawyers will say "yes, there's a bunch of minor things that could happen, but in practice every client in your positions does X, because they all have this business goal".

---

As for his thought experiment, I recall a case from my first trading job. We had a trader who'd created a VBA module in Excel. It did some process for looking through stocks for targets to trade. No version control, just saved file on disk.

Our new recruit lands on the desk, and one day within a couple of weeks, he somehow deletes the whole VBA module and saves it. All gone, no backup, and IT can't do anything either.

Our trader colleague goes red. He calms down, but what can you do? You should have backups, and what are you doing with VBA anyway?

He sits down and types out the whole thing, as if he were a terminal screen from the 80s printing each character after the next.

Boom, done.

> This is why domain knowledge is key.

Very true. There’s a huge difference developing in a well known vs. new domain. My mantra is that you have to first be experienced in a domain to be able to craft a good solution.

Right now I am pouring most of my time in a fairly new domain, just to get an experience. I sit next to the domain experts (my decision) to quickly accumulate the needed knowledge.

> This is why domain knowledge is key.

Yeah but in my country all companies have a non-compete clause which makes it completely useless for me to learn any domain-specific knowledge because I won't be able to transfer it to my next job if current employer fires me. Therefore I focus on general programming skills because these are transferable across industries.

The transferable skill is learning and getting on top of the business, then translating that to code. Of course you can't transfer the actual business rules; every business is different. You just get better and better at asking the right questions. Or you just stick with a company for a long time. There are many businesses that can't be picked up in a few weeks. Maybe a few years.
cripes what country is that
In some countries (Austria), the company that you have a non-compete clause with should pay you a salary if you can’t reasonably be employed due to it. So it is not enforced most of the time.
> This is why domain knowledge is key

In the comment thread, I keep seeing prescriptions over and over for the one way that programming should work.

Computer programming is an incredibly broad discipline that covers such a broad range of types of work. I think it is incredibly hard to make generalizations that actually apply to the whole breadth of what computer programming encompases.

Rather than trying learn or teach one perfect one single methodology that applies accross every sub field of programming, I think that one should aim to build a toolbag of approaches and methodologies along with an understanding where they tend to work well.

> This is why domain knowledge is key. > Lawyers and accountants are another profession where you have a language gap.

I fully agree with you. However, my experience as a software engineer with a CPA is that, generally speaking, companies do not care too greatly about that domain knowledge. They’d rather have a software engineer with 15 years working in accounting-related software than someone with my background or similar and then stick them into a room to chat with an accountant for 30 minutes.

> how can you experiment with learning on-the-job to create systems where the thinking is optimized?

Best optimization is less interruptions as reasearch shows their devastating effect on programming:

- 10-15 min to resume work after an interruption

- A programmer is likely to get just one uninterrupted 2-hour session in a day

- Worst time to interrupt: during edits, searches & comprehension

I've been wondering if there's a way to track interruptions to showcase this.

[0] http://blog.ninlabs.com/2013/01/programmer-interrupted/

This and a high demand for my time is why I am roughly a magnitude more productive when I am in home office. Nobody bothers me there and if they do I can decide myself when to react.

If you want to tackle particularly hard problems and you get an interruption every 10 to 20 minutes you can just shelve the whole thing, because chances are you will just produce bullshit code that produces headache down the line.

This is why I work at night 80% of the time. It's absolutely not for everyone, it's not for every case, and the other 20% is coordination with daytime people, but the amount of productivity that comes from good uninterrupted hours long sessions is simply unmatched. Once again, not for everyone, probably not for most.
I once led a project to develop a tool that tracks how people use their time in a large corporation. We designed it to be privacy-respecting, so it would log that you are using the Web browser, but not the specific URL, which is of course relevant (e.g. Intranet versus fb.com). Every now and then, a pop up would ask the user to self-rate how productive they feel, with a free-text field to comment. Again, not assigned to user IDs in order to respect privacy, or people would start lying to pretend to be super-human.

We wrote a Windows front end and a Scala back end for data gathering and roled it out to a group of volunteers (including devs, lawyers and finace people even). Sadly the project ran out of time and budget just as things were getting interesting (after a first round of data analysis), so we never published a paper about it.

We also looked at existing tools such as Rescue Time ( https://www.rescuetime.com/ ) but decided an external cloud was not acceptable to store our internal productivity data.

If you ask a manager to hold an hour's meeting spread across 6 hours in 10 min slots you will get the funniest looks.

Yet developers are expected to complete a few hours of coding task in between an endless barrage of meetings, quick and short pings & syncups over slack/zoom.

For the few times I've had to work on the weekends at home, I've observed that the difference in the quality of work done over a (distraction free) weekend is much better than that of a hectic weekday.

> If you ask a manager to hold an hour's meeting spread across 6 hours in 10 min slots you will get the funniest looks.

This is a great analogy I haven’t heard it before. They think it’s like that quick work where you check your calendar and throw in your two cents on an email chain. It’s not. Much more like holding a meeting.

The horrible trap of this is being able to get so little work done during the day, that you end up risking any but possibly all of your otherwise free time compensating for some company's idiotic structure, and this is a catastrophe
Funnily enough this happened to me.

Earlier in my career I had a very intense, productive working day and then blundered a rebase command, deleting all my data.

Rewriting took only about 20 minutes.

However, like an idiot, I deleted it again, in the exact same way!

This time I had the muscle memory for which files to open and where to edit, and the whole diff took about 5 minutes to re-add.

On the way out to the car park it really made me pause to wonder what on earth I had been doing all day.

Sometimes you really wonder where your time went. You can spend 1 hour writing a perfect function and then the rest of the day figuring out why your import does work in dev and not in prod.

I also once butchered the result of 40 hours of work through a loose git history rewrite. I spent a good hour trying different recovery options (to no avail) and then 2 hours typing everything back in from memory. Maybe it turned out even better then before, because all kind of debugging clutter was removed.

Sometimes, I spend an hour writing a perfect function, and then spend another hour re-reading the beauty of it, just to be pointed out how imperfect the function is in the PR review :))
In case you didn’t know, doesn’t delete the commit. You can use `git reflog` to find the commits you were recently on and recover your code.
And most of the time thinking about things that should not be done.
A good explanation of this is given on SICP. Ist about solving the problem, not getting the computer to do something.
Agree and disagree. Certain programming domains and problems are mostly thinking. Bug fixing is often debugging, reading and comprehension rather than thinking. Shitting out CRUD interfaces after you've done it a few times is not really thinking.

Other posters have it right I think. Fluency with the requisite domains greatly reduces the thinking time of programming.

Debugging is not thinking? Reading, understanding and reasoning about why something is happening is THE THING thinking is about.

Fluency increases the speed in which you move to other subjects but does not reduce your thinking, you're going to more complex issues more often.

It's not just thinking though. You're not sitting at your desk quietly running simulations in your head, and if a non programmer was watching you debug it would look very busy.
I'd wager the more technically fluent people get the more they spend time on thinking about the bigger picture or the edge cases.

Bug fixing is probably one of the best example: if you're already underwater you'll want to bandaid a solution. But the faster you can implement a fix the more you'll have leeway, and the more durable you'll try to make it, including trying to fix root causes, or prevent similar cases altogether.

Fluency in bug fixing looks like, "there was an unhandled concurrency error on write in the message importing service therefore I will implement a retry from the point of loading the message" and then you just do that. There are only a few appropriate ways to handle concurrency errors so once you have done it a few times, you are just picking the pattern that fits this particular case.

One might say, "yes but if you see so many concurrency related bugs, what is the root cause and why don't you do that?" And sometimes the answer is just, "I work on a codebase that is 20 years old with hundreds of services and each one needs to have appropriate error handling on a case by case basis to suit the specific service so the root cause fix is going and doing that 100 times."

This is why I just don't care about my keyboard, mouse, monitor etc beyond a baseline of minimum comfort.

Typing at an extra 15 wpm won't make a lick of difference in how quickly I produce a product, nor will how often my fingers leave the keyboard or how often I look at the screen. Once I've ingested the problem space and parameters, it all happens in my head.

It probably depends on the project?

When I'm writing something from scratch in a few months I can bash it all out on a small laptop - it is (as you say) all in my head, I just need to turn it into working code.

If I'm faced with some complicated debugging of a big existing system, or I've inherited someone elses project, that gets much easier with a couple of giant monitors to look at numerous files side by side - plus a beefier machine to reduce compile/run times as I'll need to do that every few mins.

You may care more about picking a keyboard & mouse/trackpad/trackball/etc if/when you start to experience pain in your wrists/hands and realise the potential impact on your career if it worsens! Similar situation with seating and back pain.

I often feel that having a "comfortable" keyboard/mouse/monitor is more important than a fast CPU or a fancy graphics card - just because of that slight extra feeling of pleasure/ease that lasts all day long :-).

The advantage of them is that my monitors and keyboards usually last a long time so putting money into them is not as wasteful as putting it into some other components.

One thing that surprised me though is that I recently bought a KVM to switch from desktop to laptop instead of a second monitor and this turned out to be both better and much cheaper. I gave away an older monitor to a relative and found that not having to turn to look at a 2nd monitor was actually nicer. Initially I really didn't want to do this and really wanted another screen but I had to admit afterwards that 1 screen + KVM was better for me.

RAM and disc space just matter up to the point of having enough so that I'm not wasting time trying to manage them to get work done.

May I ask which brand of KVM you selected? I have a Dell laptop and want a "docking" configuration for my desk, the simpler the better.
It was a very cheap thing off Amazon. I'm in the UK so you might not have it - the brand name is "VPFET KVM Switch 2x1" and it has 4 usb, 1 HDMI outputs and 2x(1 HDMI,1 usb) inputs.

It's the cheapest in their range, I think (about £30) - they have better ones.

Not massively flexible. Has a clicker switch which you could put on the floor if you wanted to let you flip displays. Not super fast at switching.....but it does the job for me. YMMV!

I use a 32-inch Viewsonic monitor with this. It's the most expensive monitor I've ever bought but it's nothing special when you look at what's out there. I't just lovely to use. :-) I think a purist would complain bitterly about refresh rates or whatever but I just love it and I spend my time reading web pages or code or watching the odd video.

Now with Github Copilot it's even worse/better – whether you like to type or not. Now it's 1) think about the problem, 2) sketch types and functions (leave the body empty), 3) supervise Copilot as it's generating the rest, 4) profit.
I think this is true for certain categories of coding more so than others.

Copilot is above all fantastic for outputting routine tasks and boilerplate. If you can, through the power of thinking, transform your problem into a sequence of such well-formed already-solved tasks, it can basically be convinced to do all the key-pressing for you.

In the 2020s, we still have software engineering managers that think of LOC as a success metric.

“How long would it take you to type the 6 hours work of diff?” is a great question to force the cognitively lazy software manager to figure out how naive that is.

Nowadays I feel great when my PRs have more lines removed than added. And I really question if the added code was worth the added value if it’s the opposite.

Conversely, how long would it take the average manager to re-utter any directions they gave the previous day?
This is a good article to send to non-programmers. Just as programmers need domain knowledge, those who are trying to get something out of programmers need to understand a bit about it.

I think I recognise that tiny diffs that I might commit can be the ones that take hours to create because of the debugging or design or learning involved. It's all so easy to be unimpressed by the quantity of output and having something explained to you is quite different from bashing your head against a brick wall for hours trying to work it out yourself.

This. The smallest pieces of code I’ve put out were usually by far the most time consuming, most impactful and most satisfying after you “get it”. One line commits that improve performance by 100x but took days to find, alongside having to explain during syncs why a ticket is not moving.
(comment deleted)
(comment deleted)
Great article, thanks for sharing!
I certainly notice folks who code about 30 minutes a day line-wise, but that's just because they're distracted, or don't care.

Also, very very rarely is someone just sitting around and pondering the best solution. It happens, and yes it's necessary, but that's forgetting that for so much work the solution is already there, because one has already solved it a thousand times!

This article is straight gibberish except for perhaps a small corner of the industry, or beginners.

It's also: "Damn I just wrote this whole new set of functions while I could have added some stuff to this existing class and it would have been more elegant... Let me start over..."

Writing (code) is thinking.

Exactly. The code is the feedback loop.
To me, it's the exact opposite. It's beginners who spend a lot of time coding, because of inexperience, and bad planning. The first thing they do when they have a problem, is to open their editor and start coding. [1]

I have been in this career for 20 years, I'm running my solo company now, and I'd say I spend on average 2 hours coding a day. I spent 10 hours a day just thinking, strategizing, but also planning major features and how to implement them efficiently. Every time I sit down to code something without having planned it, played with it or left it to simmer in my subconscious for a couple days, I over-engineer or spend time trying an incorrect approach that I will have to delete and start again. When I was an employee, the best code was created when I was allowed to take a notepad, a cup of coffee and play with a problem away from my desk, for however long I needed.

One hour of thinking is worth ten hours of terrible code.

---

1: If our programming languages were better, I would do the same. But apart from niche languages like Lisp, modern languages are not made for exploratory programming, where you play and peel a problem like an onion, in a live and persistent environment. So planning and thinking are very important simply because our modern approach to computing is suboptimal and unrefined.

Various programming paradigms (modular programming, object-oriented, functional, test-driven etc) have developed to reduce precisely this cognitive load. The idea being that it is easier to reason and solve problems that are broken down into smaller pieces.

But its an incomplete revolution. If you look at the UML diagram of a fully developed application its a mess of interlocked pieces.

Things get particularly hard to reason about when you add concurrency.

One could hypothesize that programming languages that "help thinking" are more productive / popular but not sure how one would test it.

At my previous job, I calculated that over the last year I worked there, I wrote 80 lines of non-test, production code. 80. About one line per 3-4 days of work. I think I could have retyped all the code I wrote that year in less than an hour.

The rest of the time? Spent in two daily stand up meetings [1], each at least 40 minutes long (and just shy of half of them lasted longer than three hours).

I should also say the code base was C, C++ and Lua, and had nothing to do with the web.

[1] Because my new manager hated the one daily standup with other teams, so he insisted on just our team having one.

Were the intense daily meetings any help? I can imagine that if there's a ticket to be solved, and I can talk about the problem for 40 minutes to more experienced coworkers, that actually speeds up the necessary dev time by quite a lot.

Of course, it will probably just devolve into a disengaged group of people that read emails or Slack in another window, so there's that.

80% of meetings are useless. Especially long ones.
Not really. It was mostly about tests. Officially, I was a developer for the team (longest one on the team). Unofficially I was QA, as our new manager shut out QA entirely [1] and I became the "go-to" person for tests. Never a question about how the system worked as a whole, just test test tests testing tests tests write the new tests did you write the new tests how do we run the tests aaaaaaaaaaah! Never mind that I thought I had a simple test harness set up, nope. They were completely baffled by the thought of automation it seems.

[1] "Because I don't want them to be biased by knowing the implementation when testing" but in reality, quality went to hell.