Ask HN: What is the single most important concept to understand for programming?

19 points by Nadya ↗ HN
Or alternatively - what was the single concept that made you have an "Ah ha!" moment where everything you had read about and learned before fell into place?

I ask because nearly a year ago - I finally had my "Ah ha!" moment. Now, while I always had understood arrays on a basic level, they never truly "clicked" with me and I often found it difficult to read from or manipulate multi-dimensional arrays. One day though - it clicked and everything else fell into place. My efficiency skyrocketed and I went from feeling like a script kiddie to feeling I actually finally understand what's going on.

I'm going to be in charge of training some juniors at the company I work for. I believe good teaching should focus on the things that provide the greatest value for understanding - so I'm crowdsourcing other peoples' epiphanies in hopes of giving my juniors their own. :)

15 comments

[ 3.5 ms ] story [ 42.3 ms ] thread
Not that it is very practical, but recursion is probably one of the most important things to "click". Once you truly understand recursion, I feel like you can understand most other core concepts like dynamic programming even.

My pragmatic answer is OOP.

There is no silver bullet.
I know there isn't a single silver bullet - which is why I'm trying to crowdsource many potential bullets. ;)
I'm not sure there's a single concept. I teach programming from scratch and I find there's a few inflection points

Point 1: if-else, loops, arrays, pointers. Fizzbuzz is a surprisingly clever exercise which covers all the hard parts.

Point 2: Project management, i.e. to-do lists and Agile. Without it, there's the paralysis of having "too much" to do.

Point 3: OOP.

Point 4: Hacking. The delicate balance between planning and winging it, and getting the best ROI out of technical debt.

The moment I figured out that the world is messy, but programs can't be. A lot of concepts are very easy to describe in natural language but are very hard to write down unambiguously.
My "click" was the realization that, in complex interactive applications, we, as programmers, should not impose our often incorrect notions of how the users will interact with the application. In fact, I was quite surprised how differently people do that.
The Church-Turing thesis and its implications. Turing completeness is one of the roots of the field and likely has implications that go far beyond into realms like the origin of life and cosmology.

Others more concrete ones include recursion, how to build simple VMs, and many data structures.

Obsessive attention to details. Tell them that it is imperative that they indent their code correctly all the time. Those who take that advice to heart can become good programmers, those who can't will forever be lousy.
In my (admittedly PL-influenced) view the primary concepts in programming are:

1) Compositionality - primarily via functions which implement substitution, but also composition of larger program units, e.g. via (ML-style) modules.

2) Recursion and induction -- sure, imperative languages make recursive solutions impractical, but ultimately most data structures (including programs) are defined inductively and algorithms on them are most clearly defined recursively.

3) Abstraction vs. representation (e.g. via existentials/modules, not necessarily or even primarily via OO).

I don't think these things are particularly complicated (although the proper semantics for modules is) but can't be learned overnight.

I think when I was learning BASIC it was GOSUB/RETURN - somewhere around there I started to understand how the computer processed information.

My most recent:

If you are working on PHP associative arrays are the secret sauce, once you grok that with HTML forms, session storage, and DB fields you will rock.

Not to worry too much about perfection in "theory". You can abuse inheritance a bit, give a function a weird name from time to time, have a long method and it doesn't matter as much as you'd think.
Composition: Smart programs are made of dumb components (or at least specialized components) with clear responsibilities and boundaries. If components are too interdependent, they need to be refactored.

From that you directly get other key concepts:

OOP principles (minus inheritance): What objects hide is as important as what they expose.

Test-Driven-Development: Code the test, then fix the code to pass the test.

Build only what you need: Components should be as simple as possible but no simpler. Keep the future in mind but don't build future features until they are needed (and better understood).

Apart from the long list of things that are great when you finally get them, here's an insight I keep seeing as valuable:

Nothing is made of magic. Everyone cooks with water. That doesn't mean everything has to be simple or easy, and understanding the theories behind things can be really challenging, but it shouldn't keep us from opening the lid of things once in a while.

While there's a lot of people in programming that are naturally inclined to do that anyway, there are also those who don't dare venture into how something works, which is one of the biggest reason for cargo-culting in my view.

Plus, if you're willing to look at how established things work at least at some level, you're pretty much guaranteed to find useful insights.

I think those that want to learn, will have many personal aha moments. I see them as details (recursion, if else or ternary, functions, predicates, threads, etc...).

2 things I always try to pass on are:

Whatever you write, you don't write for yourself but for the company. (e.g. one-liners that make others waste time)

Team's efficiency is more important then your own (e.g. 10 boring minutes can save hours for next dev).