Don't get me started on how programmers hate to document their code. And how management hates to spend any money on getting documentation on existing code, despite the fact that well-documented code would cut down on the time spent altering existing systems by at least a third.
Because I was very good at documenting code, mediocre at programming, I actually offered to my former bosses that if they would move me to my very own department of "Code Documentation" I would undertake to do ALL of the documentation from that moment on...and when I wasn't working on programs about to be implemented, would dig in and document the old stuff. That's the sort of person Plan Z needs.
See, most of the software I've been involved in being safety critical systems, requirements are written first. Those are an art form unto themselves since they all have to be written to state "what" the software does without stating how, and they all need to be absolutely verifiable by an independent tester before they can be approved (e.g. you can't make something "bigger" unless you specify
exact sizes and tolerances; if 8 possible logic combinations exist, there needs to be a clear understanding of the behavior for all 8 cases; etc.). Test engineers, design engineers, systems engineers, and the software engineers that will be handling the code all provide feedback and nothing is approved until everyone likes what they see.
Then the design documents are written, and if there isn't a requirement for it, it had better not show up in the design. Conversely, if there's a requirement for something, that had better show up in the design. But the design can be written (implemented) in any way that makes sense to the designer, so long as the person that wrote the requirements can parse it for review and the person who is going to implement the code can understand what the code needs to do. The design tells us what the code will do, but again, leaves "how" up to the person that gets to implement it. Design is approved only when requirements, design, and code all like what they see.
Code implements the function of the design in whatever manner they find most efficient. Similar to the relationship between requirements and design, if it isn't in the design document, it had better not be in the code. And if it is in the design document, it had better be in the code. Code is peer reviewed by other code writers and unit tested (unit tests are also reviewed) before being passed along to the build team.
When a build is put together, the build team captures a snapshot of all the functional code and documentation and builds the whole thing from scratch. After some quick checks (does it execute?) they pass the code back to the design engineers.
Design engineers then run the code on the hardware to integrate the design. When they are confident that every logical path defined in the design functions as intended, they pass the code off to the testers.
Testers then go through formal testing of the software at the requirements level. Automation is the goal here since every defined test is run on every build. If it can't be automated, it has to be done by hand - on every build.
The software is then passed up to the systems group who tests it at the system requirements level. Once they're happy with it, the software is released.
Some people familiar with code production will be picturing a classic waterfall at this point - which is close - but there's a key difference that makes all of this more efficient: At any stage, any problem can be flagged and passed back to the previous group. However many steps it takes, when the original source of the issue is found, that gets fixed and then the fix ripples back through the process again. So, if a tester finds a problem and they determine that the test is meeting the intent of the requirement but the requirement was incorrectly interpreted by the design, there might be a fix to the requirement to make it less ambiguous, a fix to the design to align to the requirement change, the fix to the code to meet the new design, unit testing, integration, and finally back to testing again.
Having worked in a slightly more "traditional" code-oriented group that prefers to use Agile code development in scrum fashion and fill in documentation after the fact for the last few years, I know how insane the structured process I'm used to can drive some coders. What they seem not to get is that by the time the design gets to them to code,
all they have to think about is how to best implement the code for efficiency. I find it's generally management that lacks the patience for the system, though. They like to see results up front, but that process is geared heavily toward showing few results up front and making up for it in the back end with fast and tight implementation and very little effort required to maintain the code. I get Agile, but since I come from computer engineering and not from computer science, not having pre-existing documentation is the bane of my existence. I'll eventually get the general idea of what someone else's code is doing, but it'll take me weeks to understand what they might have written in a day, and I probably won't ever
fully grasp all of the intricacies.
I tend to drive computer science guys wearing the "software engineer" title absolutely insane.