Hacker News new | comments | show | ask | jobs | submit login
Ask HN: What does deliberate practice look like for computer programming?
92 points by tim_sw 30 days ago | hide | past | web | 33 comments | favorite

I think you can divide programming up into a few areas.

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.

It looks like, and is often accused of reinventing wheels. Forgetting that it's not about the wheels but what the designers learned from going through the motions. Writing code that you've never written before on a daily basis is a good start. The key is to keep raising the bar, keep questioning tools, frameworks and best practices; to never get stuck on auto-pilot. Solve problems you care deeply about; or if that isn't possible yet; practice on the road-blocks, divide and conquer. At least that's what it's like for me.

Doing things you've not done before that stretch you, then generally moving on after you've done the first 10% that teaches you 90% of what there is to know. (Numbers may not be precise.)

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.

Programming more skillfully is primarily about making decisions on which feedback loops you pay attention to, and not getting stuck on ideas about feedback that seem momentarily fashionable or convenient, but lead to bad outcomes later.

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.

Deliberate practice in a nutshell - pick something that has a measurable outcome, have a target that is just slightly harder than is possible for you at the moment ("outside your comfort zone"), do it, then compare your measured results against your target, and then iterate.

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.

I think this is strictly true. Eriksson says specifically that deliberate practice is only possible when there is a body of training knowledge and trainers. However, also, he talks about how to approximate this in other fields. He suggests the "Benjamin Franklin Method"[1] as one idea and I think it could be used with small open source projects.

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.

[1] https://excellence-in-literature.com/copywork-how-benjamin-f...

One can do deliberate practice for writing prose (or poetry). The difference between a golf swing and a chunk of code is that, as you pointed out, there is a history of pedagogy such that many agree upon what makes a swing "good". But then many disagree on what makes it great. Or rather, depending on the coach, they emphasize different aspects to be tweaked and amplified. Could we not do that with code? I think fluency for basics could be emphasized at first, so the thinking could be put elsewhere sooner. This could change how students are taught at bootcamps, for example. The current bootcamp model is virtually devoid of any strategy with respect to pedagogy. They like to reference "the firehose" method, borrowing from MIT and Stanford. But they are teaching basics. Basics are deliberate practice developed skill sets. Firehose is just another way to say "we don't yet know how to teach basics but we like to overwhelm students and pretend it is some kind of teaching philosophy" . Granted, someone needs to address the issues you raise, but when they do, pedagogy might emerge. funny to contemplate how behind chess pedagogy code pedagogy is though.

Deliberate practice works for programming.

EDIT: Just saw your other post, thanks for the clarifications!

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.

This is more of a technique for learning than for practice... but one thing that I make a habit of when learning a new programming framework is deliberately typing out sample code that I've found in books or online instead of just copying and pasting it.

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.

Great technique recommendation. I make it a practice to never copy-paste an answer from StackOverflow. I always type it out by hand to grasp the meaning of each line of code properly. It's anecdotal, but I strongly feel it helps me absorb new languages and frameworks faster (and deeper).

Yep. This works even better for me when hand writing something as opposed to typing. Obviously useless for programming though :)

Not useless. I type out code from books but resort to pencil when the snippets I find difficult; that way, I can annotate and manipulate the code more intensely.

I try to understand each line as I type it. If I don't, I go stare at the documentation until I do.

I posted a link to a paper [0] about "Deliberate Performance" the other day that some may find useful. In that paper -- along with making the distinction between practice and performance -- they describe deliberate performance as:

>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.

[0] http://peterfadde.com/Research/Deliberate_Performance-PI-101...

Code jam & katas are fine. But they are not deliberate practice. They are just exercises.

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.

Attempt one Google Code Jam problem per day. Allocate one hour of intense focus to get as far as you can. Solutions and winning code examples are also there if you get stuck!


You could try TDD katas (see http://osherove.com/tdd-kata-1/ for a starting point). For me, the value in this practice is becoming hyper-proficient with your chosen development environment, not neccesarily learning TDD well. TDD is just a good problem domain that enforces the rest. I think of it in terms of "mechanics" practice. How quickly can you add a new file to your project? How quickly can you integrate it into your workflow? Do you have a tightly focused write/run/debug loop? Are you proficient with keyboard shortcuts and templates or whatever else will accelerate your speed. It's about being able to keep up with your mind when you get into flow and are ready to crank out code.

I think katas are great. So are all of the various tests you can take, as long as they provide accurate answers and information, because not all do.

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.

I use a painting/art metaphor for my practice. Usually when i want to develop a new major function or approach - or adopt a new technology - I do a "sketch".

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.

Code is both math and language.

- 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.

Not sure if linking to reddit is frowned upon here, but there's a great subreddit called r/dailyprogrammer which has fun coding challenges ranging from beginner to difficult. I've found they are great for practice because they have defined "success" states, they really make you think, and you can compare solutions with others in the comments. And you can use any language you want.

Working through a new programming book?

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.

Excellent answers already. It also involves some time problem solving on the craft at large. Take some time reading the words of people who have innovated in the field and argued with their peers. See if you can work out where the champions of OOP pushed our understanding and where they failed. See if you can understand the functional programmers have created beauty out of chaos, and where they've drunk a little too much Kool-Ade. Once you've understood, write a few example programs in those styles and languages.

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.

I have this tendency to get stuck in an incrementalist mode of coding where I'll unnecessarily "test" little changes before it really makes sense. Forcing myself to write out as much code as possible before running it, is a form of deliberate practice for me.

Get a copy of SICP and do all the exercises (and or follow along with the MIT course videos on YouTube)

Hacker Rank practice problems

Believe yourself to be competent. Never believe yourself to be wise.

Excellent question. Looking forward to read all the answers.

I assume you probably made the comment to bookmark the article? There is a 'favorite' option that does that for you.

Deliberate practice for X literally means do thing X.. i think that is simple - the best way to get better at X is do X. So it really depends on what you want to get better at.

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.

Deliberate practice is VERY different from "doing the thing." For example, there are plenty of people who take thousands of photographs and only get marginally better with each photo taken, because they simply take the photograph and move on. Deliberate practice is taking the photo, seeing what you like about the photo and what you don't, figuring out what you need to change to make it come out that way, taking the photo again, and repeating the process. It multiplies the speed by which you get better by thousands.

Well said, I recommend folks read a book called "Art and Fear" & "Talent is Overrated" to understand more about deliberate practice.

Applications are open for YC Winter 2018

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact