Back to Blog

Learning Methods of Excellent Programmers

Every experienced engineer has wrestled with the same frustration: you read a chapter, nod along, close the book — and then can't explain the concept to anyone the next morning. The gap between passive exposure and genuine understanding is where most self-taught developers stall. This post distills four hard-won learning habits that separate programmers who keep growing from those who plateau.

1. Repetition Is Not a Sign of Weakness

For deep technical domains — OS kernels, compilers, distributed consensus algorithms, numerical methods — a single pass through the material is almost always insufficient. The concepts are dense, the mental models are unfamiliar, and the vocabulary itself is a barrier on the first read.

The practical prescription: identify the top three books or authoritative references on the topic and cycle through them repeatedly. On a second reading you will notice things invisible on the first. On a third, patterns emerge that connect earlier chapters to later ones. "Push through the difficulty" is not motivational filler — it is a recognition that confusion is a normal intermediate state, not a signal to stop.

This applies equally to reading kernel source code, RFC documents, or academic papers. Grep for the same function across multiple files. Read the commit history. The understanding accumulates in layers, not in a single breakthrough moment.

2. Use It Before You Master It — Linus's Rule

Linus Torvalds's advice is often paraphrased as "to master Linux, start by using it." This sounds obvious, but it cuts against a common instinct to defer hands-on work until you feel "ready." You are never ready in advance.

The sequence that works: stand up a real system, use it for real tasks, then write small programs to probe and verify specific behaviors. Install a Linux distribution on bare metal or a VM. Configure the network manually. Write a shell script that breaks and then fix it. Implement a toy character device driver. Each of these forces you to confront the actual system rather than a mental model of it.

This principle generalizes beyond Linux. Learning TCP/IP? Run Wireshark on real traffic before reading Stevens cover to cover. Learning a database internals? Benchmark it, break it with malformed queries, read the slow query log. Using the technology as a user first gives you the concrete reference points that make the theory stick.

3. Question-Driven Learning and the Value of Writing

Understanding is not binary. The clearest signal that you understand something is the quality of the questions you can ask about it. Vague questions ("how does memory management work?") indicate surface familiarity. Specific, falsifiable questions ("does the kernel's buddy allocator merge free blocks eagerly or lazily on free()?") indicate genuine engagement with the mechanics.

The technique is to zoom in and out continuously: start with the big picture ("what problem does this solve?"), drill into a specific mechanism ("how exactly does it solve that sub-problem?"), and then zoom back out to check whether the detail fits the larger model. Repeat until the questions become specific enough that you could look up the answer definitively.

Writing — blog posts, internal wikis, rubber-duck explanations to a colleague — is the forcing function that exposes gaps in this process. You cannot write a coherent explanation of something you do not understand. The act of structuring an explanation reorganizes your mental model and surfaces the missing pieces you glossed over while reading. Even a short post written for your future self has compounding value: the re-reading six months later reveals how your understanding has evolved.

4. Build Real Products

The final test is production. Reading, experimenting, and writing are all necessary, but they remain safe — the feedback loops are forgiving and the stakes are low. Building something that real users depend on changes the dynamic entirely.

A successful product or project forces you to confront the parts you understood only approximately. Edge cases that the textbook hand-waves become bugs you have to fix at 2 a.m. Performance characteristics that seemed theoretical become the difference between a usable and an unusable system. Integration points that looked clean in isolation turn out to have subtle ordering constraints.

This is not an argument to skip the foundations — it is an argument to close the loop. Learning without building is incomplete. The most reliable signal that you have truly internalized a technology is that you shipped something non-trivial with it and it held up. Start small: a command-line tool, a weekend project, a personal dashboard. The scale of the product matters far less than the act of carrying it through design, implementation, debugging, and deployment under real constraints.


These four habits — deliberate repetition, use-first exploration, question-driven inquiry backed by writing, and shipping real products — are not shortcuts. They are the long way around, which turns out to be the fastest reliable path to genuine technical depth.