1. Mechanics, how well can you navigate and type using the tools you have available. To practice this an easy thing to do is formatting your code without any automatic formatting. In vim for example, this helps you learn the commands.
2. Reasoning/problem solving. This one is harder to practice and really requires experience. Always have a project and spend time trying different solutions. A nice characteristic of software is you can usually just undo if something was wrong, so don't be afraid to experiment.
3. Research- it's safe to assume someone else already solved a problem. Use google to find their solution and read how they solved the problem. Never be afraid to open up someone else's code.
An incomplete lost: 3D graphics programming, write a compiler or interpreter, write an emulator (Gameboy is popular), write a web server starting from a socket, learn a new language paradigm, grab a raspberry pi and do something with gpio, find a friendly open source project and close some bugs, and so on.
I'm an advocate of the "T shape", where you are deep in one or two things ("pi shaped") but have dabbled in lots of things.
I would not that while katas as others suggest are not bad, they are usually count for just one skill. You may learn a lot of clever tricks and some useful math, but what you get out of them will plateau before you get to the end of the katas set.
Write prototyping code that solves an existing problem as nearly as you can manage, and then figure out how to improve it on one or more metrics:
* smaller SLOC (automatic programming, data abstractions, etc)
* better portability, fewer dependencies, simpler build processes
* better throughput, latency, or resource usage(memory, storage, bandwidth, energy)
* eliminate one or more classes of errors(e.g. off by ones, null dereferences)
* better user interfaces, better documentation and accessibility
* more efficient development of the prototype
* better working environment (workflow, tools and knowledge of the tools, automations for convenience)
Oftentimes, you can make one change and improve several metrics. Other times you sacrifice one to get others. There are bad tradeoffs like code golfing or premature optimization. Having the prototype already in hand is crucial in all cases since it gives you a spec to bump up against when you're at risk of falling off track. If you're more daring this can take the form of an existing shipping codebase.
I am not entirely sure deliberate practice works for programming. I've been following Anders Eriksson's work for 10+ years, and it seems most applicable when applied to domains that have a history of training. Want to learn how to sing really well? You can probably do it. Want to be the best basketball free-thrower in the world? Probably.
It's the lack of a body of trainers and training that hurt, because deliberate practice talks about having quantifiable goals and the ability to compare how you did it versus how it's supposed to be done. E.g. have a trainer in golf means the trainer can critique your strike.
If I ever figure out deliberate practice for programming, you can bet for damn sure I'll write a book.
Also, projects like exercism.io use other learners as the trainers. I think Eriksson calls this the "top gun" method, based on the flight school and movie.
Could you please provide some elaboration on your comment? As it stands, it doesn't explain how that works or why you believe that, and I think others would find that valuable.
It's the equivalent of writing out notes by hand from a school textbook instead of just photocopying the pages... some how the process of actually re-typing it out causes it to stick in my mind better. And then later, when you're really "in the zone", you don't break your focus by needing to keep referring back to the book, it's already embedded in your muscle memory and you just keep plowing away.
>the effort to increase domain expertise while engaged in routine work activity.
They then go on to give four types of exercises to focus on:
repetition, timely feedback, task variety, and progressive difficulty.
Deliberate practice is about working on your weak area till you're no longer weak in that area.
You MUST perform a retrospective on all your projects. Ask yourself what you struggle with often, what are your pain points? Identify them, then work on them. The mistake I often see is that most developers create more problems for themselves by attacking multiple problems at once. If you have XYZ problem, and you decide to use a new language, a new framework, a new cloud service/API, a new DB and a new design style you have never used before. You will never be sure your pain point.
What you must do in this world of too many choices is LEARN TO CONSTRAIN. Pick a language, DB, framework, etc that you know. Nothing should be new to you but the problem. Yes, it's true that your existing tools might not have everything you need. LEARN TO BE RESOURCEFUL. With that said, attack the problem, if you have any issues, it will be obvious and apparent.
Let's say you have a great project you understand through and through and you wish to learn a new DB. Keep all things constant, rewrite your old project and the only thing that should be new is the DB. Repeat till you master the DB.
You must limit your problem to ONE and ONLY ONE at a time. This allows you to measure and correct faster if on the wrong course.
However, I don't spend time on those. I'm not saying that you shouldn't, but I don't want to do it just like I don't want to go to a karate class. I have nothing against karate, but I don't want to hit and kick people. Similarly, I don't want to code the answer to some problem that someone else came up with, just because it's a kata or test.
I've been a programmer for more years than a lot of the people on HN have been alive and a professional developer for close to 20 years. That doesn't make my opinion right. In fact, I think the majority of you are probably better developers than I am.
But, if you don't like katas and don't like tests- don't feel bad about yourself. You might be like me. I just like to find my own problems and attempt to solve them. And that's ok. There might not always be a place for me as a developer, but there will always be a place for developers that think like that.
As long as you don't hurt anyone, just be yourself.
The sketch is a standalone project that embodies what I want to understand. It could be React with a basic router and a test framework. I'll iterate on that. Sometimes several times. Then I integrate into the projects I'm working on.
Usually this is verifiable in some form. Being reliably testable is one. But others could be micro-benchmark performance. Occasionally the aim is just to re-write in a different language.
In the future, if I wanted to make a structural change (e.g. a different router) - I'll go back to the sketch and make the change. Sometimes I also do a sketch from scratch. However, I find working on the original sketch informs changing the production code a lot better.
In "deliberate practice" terms that's a very macro-level approach, but it's a balance that's worked for me.
- Deliberate literature practice involves as much (or more) reading as it does writing. Tangentially, code review is an important way to both learn how other people express ideas in other ways, and to learn new features and tricks to express yourself in a given language.
- Deliberate practice in mathematics begins with rote memorization, and later with repeated application of algorithms. So practice could first involve typing common algorithms, including brackets and other grammar, until they (e.g. a FOR loop) can be typed from memory. Or possibly automating this step, and practicing using the automation. Later practice could involve repeated application of algorithms - possibly algorithms of your own making.
Answering questions on Stack Exchange?
Watching marginally related recorded talks at conventions?
Focusing on the thing for an extended period of time while exploring new territory?
The muscles you're wanted to exercise are pattern recognition and lateral thinking, all in the problem solving family.
So, find a problem, them solve it.
In understanding the radical designs and patterns that great coders have used and argued about, you'll see you own code style change, even unconsciously.
Practice for algorithms could mean doing a lot of leetcode/interview style algo problems.
Practice for working with large codebases means practicing reading/understanding code quickly. So maybe picking a large scary open source project and trying to make a contribution.
Reinventing wheels like andreasgonewild is the most useful and fun kind of practice IMO. Pick a cool technology and make it yourself from scratch. Maybe in a new area you know nothing about. A distributed KV store? A stack-based programming language? A code formatter?
If you develop something big like that, you will surely exercise all the muscles it takes to develop something. Reading too many tutorials or watching too many videos is narrowly exercising the "learning" muscle. Solving algorithmic puzzles is narrowly exercising the "CS fundamentals" muscle. But the best workout to prepare to chop wood is to chop wood.