A kata is an exercise in karate where you repeat a form many, many times, making little improvements in each.
If you think of it, not just karate experts, but expert musicians, sportsmen and women, and many other professionals practice in this manner. But for some reason programmers don't. It's like we prefer programmers to play tournaments all the time without really perfecting their stroke or style. It's time we realized this is not good enough; at least not for developers who strive to be craftsmen.
Developers need a solid foundation in theory - a good understanding of basic computing concepts, algorithms, and a very good understanding of the programming language and stack they work with. But theory all by itself will not take us very far. All experienced programmers agree that we need to get our hands dirty to really learn how to code. Coding katas take this a step further by giving us a more organized approach to get our hands dirty. After all it's not possible to become a great soccer player by randomly hitting the ball. We have to practice in an organized way, where we can practice individual moves to perfection. Similarly, to become a great developer, we have to master individual concepts and skills to perfection through sustained practice.
What makes a good practice session
One of the most important aspects of any kind of practice is the design of the practice sessions themselves. Athletes who run long distance devise all sorts of practice sessions; sometimes they run with heavy weights tied to their ankles, they train uphill, downhill, on rocky terrain and all sorts of different situations. Each practice session is specifically designed to improve some aspect of their performance. Similarly, coding katas must be designed to help developers train in specific concepts or skill and they must be designed for maximum efficiency and effectiveness.
Software developers face an interesting challenge which athletes don't. Athletes spend more time training than in actual tournaments or races. For software developers the ratio is tipped int he other direction. We spend more time working on actual projects and have very little time for practice sessions. This makes it even more important for these exercises to be specific and efficient.
The first requirement for a good practice session is not to have any pressure. This is why real-world production projects do not lend themselves to practice. In real life projects we don't have the liberty to perfecting our craft without worrying about how long it all takes. But this is the crowning glory of a good practice session - no pressure and enough time for deep learning. While doing katas it's important not to have any specific deadline, but to focus on learning.
The second requirement is to have a specific goal for the kata. For example, at the beginners level it could be something as simple as mastering how to traverse a list. At the intermediate level it may be mastering recursion which includes not only invoking a recursive call, but also understanding the exit condition, how a stack overflow occurs, and maybe even understanding tail recursion. At the advanced level a kata could take the form of refactoring a peice of code to improve it by implementing it with a specific design pattern. You could try to master any concept or skill as long as it's specific and there is a way to verify your mastery over the concept.
The third requirement refers to the exercise problem itself which should be appropriate for the goal. The problem should neither be too broad, nor too narrow. For example if you are trying to master how to sort a list, then make sure the problem provides an unsorted list which needs to be sorted. In this case it would be incorrect to make the practitioner first fire a database query to get some data which they eventually have to sort. What I am really trying to say is, don't make the practitioner do extra steps which may distract them from the main goal, but at the same time don't spoon feed them by giving them a ready made solution. Sweating is important - but for the correct reasons.
The third requirement is to repeat the practice at least a few times before moving on to a more complex goal. Ideally, we want multiple exercises for the same concept, but if that's not possible then repeat at least once before moving on. We programmers are often an impatient bunch - I know because I have been one. We often think that just looking at something is enough, or simply solving a problem once is good enough for it to be imprinted in our brains. This viewpoint is more often than not, pretty optimistic and deluded. The brain needs to practice something repeatedly for the neural pathways to create what is known as a chunk. So even if you feel like you get merge-sort after solving just one problem, it will do you good to solve at least a few for the brain to really get it.
The fourth requirement is to practice at the sweep spot. It is the spot which is neither too simple nor too difficult. For example if you are a Python developer who is past the beginner level, you won't gain much if you spend a day practicing how to iterate across a list of items. You also won't get much if you try to practice working with an advanced concurrency library. The right kind of practice at this stage would be to work with list comprehensions or something similar. If we practice with tasks that are too easy, we will soon get bored. On the other hand tasks which are too difficult, will overwhelm us. The best way to learn is to practice at just the right level of difficulty; where the task is out of the comfort zone to create some tension, but not so far out that we are clueless about how to proceed.
The fifth requirement is to get automated or human feedback whenever possible. I won't call this a requirement because it is not always possible to get feedback, but we should try and get it as often as possible. Wherever possible, a kata should be backed by test code to verify the result. For example, a kata designed to learn sorting algorithms can easily be backed with test cases to verify if the code is correct. However, that may not be possible for practice sessions that involve working with design patterns. Although, for such sessions it would be useful to have a friend critique the code. Sometimes submitting code to a peer review website such as codereview.stackexchange.com
can help a lot. There's something very special about community feedback. It's diverse, rich, and complete. If one reviewer misses a point, someone else will pick it up. Sometimes participants even critique a critique, making the learning even more richer and fun.