Become a Better Developer by Reading Source Code
stevejgordon.co.uk
stevejgordon.co.uk
Some of the earliest conversations I recall were about the trap of taking Comp Lit too seriously and not spending enough time on the craft. Eventually your inner critic creates fear that your work isn't good enough, and it becomes a self fulfilling prophecy.
I spent the next decade watching helplessly as the inner critic ate my friend's hopes and dreams one by one. In her head, she was going to be a great fiction writer. But the only thing of hers I ever remembered was her persuasive writing. She was passionate about her causes, but somehow also had it in her head that this wasn't 'real writing', and I didn't have the gravitas to convince her she was wrong.
And so the sad fact is that if you look at what I've written and shown to people, and what she's written and shown to people, it would be charitable to say she's done three times as much as I have, to an audience perhaps ten times as large. Me, who only briefly wanted to be a writer in grade school, whose only college-level English class was a technical writing class.
I am not a Writer, but I write. She is a Writer, and doesn't.
But even so, I've got body parts stuck in this same trap. I write a lot less code that some other people. But I also work hard to make sure that I'm on the right side of the Pareto principle. It's not the lines that count but how you use them, or so I reason. But I've started noticing the consequence of that choice, and trying to find a new balance between quantity and quality. Old habits die hard.
To quote a famous parable of the pottery class
The ceramics teacher announced on opening day that he was dividing the class into two groups. All those on the left side of the studio, he said, would be graded solely on the quantity of work they produced, all those on the right solely on its quality. His procedure was simple: on the final day of class he would bring in his bathroom scales and weigh the work of the “quantity” group: fifty pounds of pots rated an “A”, forty pounds a “B”, and so on. Those being graded on “quality”, however, needed to produce only one pot – albeit a perfect one – to get an “A”. Well, came grading time and a curious fact emerged: the works of highest quality were all produced by the group being graded for quantity. It seems that while the “quantity” group was busily churning out piles of work – and learning from their mistakes – the “quality” group had sat theorizing about perfection, and in the end had little more to show for their efforts than grandiose theories and a pile of dead clay.
The best way to get better at creative pursuits is to create. Then get feedback. As much feedback as you can find.
I've certainly found this to be true with programming. I can read great code and books about how to code, but I've really become a better programmer through writing lots of code.
Not true as in a something that happened, but true as in the underlying concept.
Gladwell talks about hours of practice, but it has to be conscious practice.
But this parable has always been strange to me because if your target is quantity, it seems errors, in that context, are things that slow you down in production not quality issues.
You will learn to be fast, not good.
It makes an interesting case study for this sort of thing. Both were prolific; but Don Quixote is clearly the greatest work in the Spanish corpus despite Lope having vastly more written. But to some degree both authors are remembered.
You need to either have good taste yourself or an arbiter who can tell you where you went wrong.
Of course at some point you reach a skill level where this no longer works. You still need as many cycles as you can get, but the cycles get longer because it just takes time to do the bigger and better things you can do now.
https://github.com/mirror/busybox/blob/master/shell/math.c
Some funny comments like "Think about it. * It makes sense."
This is so cool. Nobody would write code like this today
One of my favorite exercises though is to port code from one language to another. Reading the code gets you to one level of understanding. Implementing it yourself while following along gets you to another level. But translating it really gets you a level of mastery of what the code is doing.
Decompiling .NET and earlier reading leaked windows source code have given me the revelation that the people working on these systems are regular people like you and me. Somehow I thought MS or Apple code was something special but it really wasn’t.
But I agree: reading source code is good for learning and also empathy. It’s way too easy to look at a code base for five minutes and declare this needs to be totally rewritten because the previous devs wrote bad code
I tried to include small/interesting repos to do weird/cool things so people can learn about it. Eg, this code: https://github.com/evilsocket/opensnitch (UI in Python but the logic is Go)
---
Some people here are mentioning code reviews for their teams and how they don’t enjoy that.
I would say this article is missing a fair point. I’ve learned a lot by just browsing Github.
For example if I’m interested in solving a Caching problem I’ll skip some of the open source libraries around caching and how it’s implemented.
Often times you run into a very elegant and readable solution that someone has created. And the most interesting takeaway from that is that you can get inside the persons head around API design and implementation.
When I stumble upon an awesome elegant library I always either take a mental note about it or try a small sample implementation of my own. This has helped me synthesize great APIs designs over my career. You develop your own style over time by picking and choosing your elegant solutions, and eventually you also come up with your own bright ideas through language features or loopholes that come across as exceptionally elegant.
I made a conscious decision to start installing all my dependencies into a folder within my project source-code so that I can painlessly jump to the dependency's source and read it. (E.g. in the Ruby world, this means installing to "./vendor" in your project).
The effect of doing this is that it's easier for me to read the source code of a library than it is for me to leave Vim and look up the docs online. Voilà, now I'm reading more source.
Then I don't have to think about dependencies as much, albeit in Python there's always a struggle with that :P
And about the "what if i don't understand it" bit, i would suggest one goes and reads https://news.ycombinator.com/item?id=15903771 ;-)
I rarely feel this way with Kotlin or Java libs, and I'm only slowly warming up to TypeScript code.
[0] http://linuxfromscratch.org/lfs/view/stable-systemd/chapter0...
But even that the main file is 11000+ lines of code.
I'm not a C programmer but these projects have this Quality in common that transcends the programming language (I think). Opinions?
Resources:
https://cvsweb.openbsd.org/src/bin/
https://www.openbsd.org/anoncvs.html
https://www.openbsd.org/ (where I got the above links, on the left side under "Getting Source")
There really should be a list of "good" codebases for people to look at and study. If anyone has any good backend Node.js codebase recommendations, I'd love to take a look.
Maybe it's because of the responsibility (why didn't you caught this bug in the review?), but it's really difficult.
The first rule is to care and understand what the code is trying to do.
I find that editing the code makes a big difference. Find something to chage. Refactor something. Add a tiny (even meaningless) feature. This forces you to understand what the code is doing. That, in turn, forces you to explore the code and to read it. It also gives you a gauge to judge the code against. Why did they do it that way? What if I changed it? Oh, I see why the couldn't do it like that. Yes, their solution is quite nice. That kind of thing.
I very frequently refactor PRs at work and show my refactoring to nobody. Usually it's 6 of 1 half a dozen of the other. However, it gives me an idea about how flexible the code is. Or I might start to implement the next feature that's likely to touch that code. Not TDD. Just sketching some code and seeing how easy it is.
If you've never tried it, I highly recommend it.
Actually, I wouldn't mind a comprehensive guide about it. It needs not to go in the details in all of them but at least should name them.