I've long felt that this is an issue unaddressed by the industry, though I've framed it as "knowledge acquisition and dissemination." As part of building a software product, the developers acquire deep knowledge of both the problem being solved and the system that solves it. The question then becomes: how do we efficiently capture and disseminate that knowledge?
Capturing the knowledge is expensive both initially and over time as the software itself evolves. Disseminating it is expensive because it costs O(NM) time, where N is the number of people receiving the information and M is the average amount of time taken to absorb it. Dissemination is so costly, so we tend to do it in a "lazy" manner, meaning non-strict or as-needed.
I think the best software systems I have worked on do a number of things:
1. They define enough ad-hoc proofs or invariants via unit tests. It's possible to work around these by simply disabling the tests, but, assuming your team hasn't devolved to that point, the tests are an excellent source of machine-readable and machine-executable knowledge.
2. The software is designed modularly so that one can operate on a part of the system without having to understand the entire system or worry that an unrelated part of the system is going to break.
3. The system is kept as simple as possible. The less knowledge one needs to accomplish the same task, the better! This is why KISS is so important. It's not for the person writing the code so much as the person debugging it a year later! As a corollary, a simple system tends to have less dependencies. Dependencies are actually costlier than people realize. Every dependency suffers its own bitrot problems and requires knowledge to handle them as part of maintenance.
The lowest hanging fruit on any project is always documentation. Dissemination isn't O(NM) if your docs are well organized. At least, that's been my consistent experience over the years. I feel like our industry approaches documentation today the way it approached testing in the 1980s, before unit testing became widespread and culturally accepted/enforced.
The problem is, just like how at the start you find lots of devs who don't want to write unit tests, you usually have a lot of devs who resist writing (and reading) docs. They'd rather interrupt someone to ask, or thrash around, or move onto the next task the moment some code is written.
What helps:
1. Keep your docs alongside the source, in version control. This lets you gate code reviews/merges on docs being updated. Someone changed the way the code works but didn't update the docs? Then the PR is rejected until it's fixed.
2. Leading by example. If the TL for the project updates docs with their code changes, and visibly spends time gardening the docs, then they can't be accused of hypocrisy when they demand the same standards of others. Praise quality docs work when done by others.
3. Make the docs beautiful. Let people have pride in their work. It's so easy these days with great static site generators.
4. Answer questions by linking to the docs when possible, not ad hoc Slack/email/ticket discussions. If the docs don't tell someone the answer ask them to hold on for a moment, update the docs quickly and then link to them. Obviously this requires a fast / lightweight turnaround process on review and merge of docs changes, but it can be done.
5. Avoid wikis. Quality requires ownership, someone who is directly responsible and can enforce their will. Wikis don't let you do that so they become a commons, and you end up with a tragedy. Use Markdown or equivalent in a VCS repo so you can refactor docs as they expand, make sure there's someone (e.g. yourself or a trusted lieutenant) who is expected to spend time paying down docs debt every so often.
6. Docs bugs should be a thing. File them. Expect people to fix them.
7. Make it clear that people are expected to read the docs, not just write them. If someone is regularly asking colleagues questions that they could have answered by reading, ensure that's treated like other performance issues i.e. their managers know and the need for improvement is clear to them.
There's more that can be done but these things do work. The biggest problem is always passive resistance. Just like with unit testing or code review, if a culture of avoiding it grows then you'll find it hard to introduce, people will passively resist because it's not as much fun as just banging out more code.
With these approaches the robustness of a program to churn can be improved a lot, you can scale teams up quicker and productivity improves.
I believe what you're saying is true, I just haven't seen it in practice. I've long joked that the best documentation is the source code, and, really, it's not so much a joke as a truism. I've found that having readable code has resulted in the best documentation I've seen, and you don't have to worry about it being out-of-sync!
I do believe documentation is important, but, having joined recently the largest corporation I've ever been a part of where I work on products of a larger size than ever, I am amazed to find documentation here to be as bad as, or even worse, than anywhere else I've worked, and most of it is simply outdated and irrelevant. I guess I need to work somewhere that does documentation well to believe in it more.
I also consider myself a good technical writer. Unfortunately, it seems that many software developers don't share this skill, and this could be a major reason why so many resist writing it. I think a litmus test for this is whether someone prefers to share information via a document, or via an in-person meeting, a conference call, or a video recording of a meeting. Unfortunately, videos and meetings are not searchable, indexable, updateable, or quick to scan. But they seem to be preferred by the same people who don't want to write anything down.
I've used that strategy a few times now, albeit mostly with "user" facing docs where the users were other developers. My current company is tiny but I wrote both internal and user facing docs from day one, so practicing what I preach. It's pretty useful. Writing stuff down is permission to forget and I often end up consulting my own docs, especially for procedures that only happen occasionally.
In prior projects I did it too and success was mixed. On one hand, the docs we got out of it were objectively great, as in, users complimented us on the docs regularly, they were a source of competitive advantage and we could tell they worked because users would regularly show up successfully using advanced features of the product without having asked us any questions.
On the other hand, creating a self-sustaining docs culture was hard. People would do it when faced with the expectation of doing it, and often the resulting docs were fine - tech writing isn't as hard as it's sometimes made out to be - but getting other devs to really buy into it and become docs evangelists themselves was much harder. Also of course you'd have inevitable team friction when someone really hated writing stuff and would have to be forced to do it, and then they'd submit min-viable or low quality work. No different to having a team member who refuses to write tests, of course.
I think this can be solved with time, with cultural change in the industry. One problem, and please don't take this personally because I'm talking really generally here, is the view that source code is as good as documentation. I feel like lots of devs convince themselves of this because they like writing code and don't like writing docs, but I never found it to be true in practice. Any time I have to use an API or tool that has tons of missing or obsolete docs my heart sinks, partly because rummaging through source code is slow and tiring compared to reading a well written document, and partly because it tends to be a proxy for low effort work in other ways. The claim that docs are always obsolete is self-fulfilling. If you don't put in place procedures to ensure they're kept fresh and good then they'll rot, and then that's used as a justification for not putting in the effort, so it's a vicious circle. Again by analogy to testing, competent teams don't just let devs comment out tests instead of updating them, it's just not culturally accepted in high-functioning environments. Same can be true of docs.
How do you reconcile your points 4 and 1? Say I want to answer someone's question on Slack. First I have to change the docs, but doing so would require a whole PR, alongside approval, which may take one or multiple days.
You can flip the order of the steps and it works pretty well imo: answer on Slack, and then once the discussion is complete, clean up the messages and put them into the docs.
This has the added benefit that you can have some back and forth to get to the root of the question before documenting it.
The key thing is that you have to make sure to actually do the step after (transfer to docs), even if it's a quick copy-paste with minimal editing.
You can point people at the answer in the PR, or you can relax approval requirements for docs changes, or you can be someone who actually can approve docs changes yourself. There can still be ownership in that model it just doesn't require pre-approval, only post-approval.
Capturing the knowledge is expensive both initially and over time as the software itself evolves. Disseminating it is expensive because it costs O(NM) time, where N is the number of people receiving the information and M is the average amount of time taken to absorb it. Dissemination is so costly, so we tend to do it in a "lazy" manner, meaning non-strict or as-needed.
I think the best software systems I have worked on do a number of things:
1. They define enough ad-hoc proofs or invariants via unit tests. It's possible to work around these by simply disabling the tests, but, assuming your team hasn't devolved to that point, the tests are an excellent source of machine-readable and machine-executable knowledge.
2. The software is designed modularly so that one can operate on a part of the system without having to understand the entire system or worry that an unrelated part of the system is going to break.
3. The system is kept as simple as possible. The less knowledge one needs to accomplish the same task, the better! This is why KISS is so important. It's not for the person writing the code so much as the person debugging it a year later! As a corollary, a simple system tends to have less dependencies. Dependencies are actually costlier than people realize. Every dependency suffers its own bitrot problems and requires knowledge to handle them as part of maintenance.