Retrospring is shutting down on 1st March, 2025 Read more
How would you do deliberate practice for programming?
There is way more involved in programming than just the coding: writing specifications, learning about the problem domain and the users, doing database design, user interface design, API design, software architecture, code reviews, manual testing, automated testing, technical documentation, user documentation, project management, internationalization, regulatory compliance, community management (mostly for FOSS), accessibility design, accessibility testing, deployments, monitoring, and more.
There also are tons of different types of programming that require different skillsets and priorities: web frontends, web backends, web APIs, distributed computing, mobile apps, games, desktop apps, command line tools, drivers, open source libraries, IoT, scientific computing, etc.
In some of those activities and domains, you will also need to split further on the operating systems, programming languages, DBMSes, cloud providers, spoken languages, countries, target users, and whatever else.
Many still think programmers can do everything in every domain and technology at once, when this actually involves hundreds of different skills. This is one factor in many that make muggles non-technical people expect all computers to not work and to only hinder their lives.
So the term programming is quite unclear, and you will first have to split this up into many parts and figure out which of those you want to actually master. I'm not saying you can only master one of these, I'm just saying these likely need to be handled separately. I certainly don't think you will live long enough to master them all though.
You also need to define for yourself what mastering means. Whether you see programming as an art form, as a science, as a field of engineering, as a job, or as something else I didn't think of, can change that significantly.
Then, what you should actually do really depends on what you picked, and I don't know everything about every option.
If you are trying to code a resilient server, you could first write it while assuming that everything will always go right. Then you could bring down a database that your program relies on, then start your program. If it fails, fix it, and try again. When your program at least gracefully handles this situation, you could try to start it while the database is running, and nuke that database while the program is running, which could introduce more failure modes. Or you could cause deadlocks, introduce random lag, or make the database read-only. And continue with other dependencies and other failure modes that you can imagine from your code.
If you run out of dependencies that you can mess with, try to dig deeper into the dependencies that you are not seeing; what if you just lose power then restart? What if you remove some kernel module that your program needs? What if you time travel (change the system clock or go through leap seconds)? What if you run your program in every locale? What if multiple instances of your program are running? Did you try to run a static analyzer to see if it complains about something that could go wrong? Did you try to run every single tool you can get your hands on that could help with resilience, to see if they complain about other things?
When you think you have done all you possibly could on this poor piece of code, update it. Add some requirement, something that requires changing that code, not just working from scratch, and test again. Did you reintroduce bugs? In my experience, updating existing code requires more skill, especially when it comes to other people's code or old code, and that's the thing we should be doing the most if we want to improve our coding.
Retrospring uses Markdown for formatting
*italic text*
for italic text
**bold text**
for bold text
[link](https://example.com)
for link