There is a large gap between the quality of code that shows up in textbooks/online programming courses and the code that’s usually deployed in production.

Most of that gap has to do with the complexities of deploying, maintaining and scaling a system in production. This recent blog post does a fantastic job at providing a taste of these complexities:

https://rachelbythebay.com/w/2020/09/20/evolve/

It’s these complications that make up most of the gap between what’s in the textbooks and what’s in the real world.

Kubernetes and Docket don’t make your code more efficient, more readable, more terrible, more correct or more stable. They solve specific problems that teams encounter in one part of the software industry. Engineers writing device drivers at Apple will have a different set of tools, practices and coding standards for example - if they optimize for running tests in the factory and reducing the drain on the battery, it will be a different set of complications that will create the gap between textbook code and what’s deployed. Apple’s production quality code will look extremely different from Facebook’s because the complexities are different.

There is a small part of the gap between textbook and real world code that is not caused by domain specific nuances. It’s pretty easy to pick up those skills:

1. Use a code formatter like clang-format and/or a linter. Pick a coding style and stay consistent with it.

2. Write code to communicate intent. Name your variables and your methods so that the resulting code reads as close to prose as possible. Write your code in a way that someone you’ve never spoken to can easily figure out what’s going on and modify your code.

3. Design your APIs first. Think long and hard about your API, how it will be used, how it can be tested against, how it can be extended in the future. Read “The design of every day things” by Don Norman and pick up on what is good design.

4. Related to 3, design your API (and implement) them in a way that’ll allow as much of your code to be unit tested as possible. Have an algorithm that will run when your robot hits a wall? Pull your algorithm into a separate file, with its own API in such a way that you can compile that algorithm into a second “test” program that’ll feed it some inputs and check if it produced the expected output. Use a code coverage tool (google gcov) to see how much of your code is covered by unit tests. Aim for 98% or higher. The “should I move these lines of code to a new function” is then easily answered with “will a new function (in maybe a new file) help me increase my code coverage in unit tests?”

5. Write your code so that tiny errors blow up into catastrophic failures as quickly and as loudly as possible. Add error messages everywhere. Add asserts and static_assets everywhere. You are going to spend a lot of time tweaking and testing your code - if any change triggers a failure anywhere else - you want it to fail with a really really loud bang so that you are more likely to notice (and debug) it.

6. Avoid creating skews/variants in your code. don’t have a debug version and a release version - write code that you can test, deploy code that you have tested (exactly the same code, with no changes)

This will get you over that gap between text books and real world. The rest you will figure out as you go deeper into your domain.