Ask HN: What are some examples of good code?
I keep reading on HN that I'm order to become a better developer I need to write code everyday, and more importantly read other people's code.
What are some examples of good code that you've seen?
Personally I'm interested in Ruby on Rails and I've recently started going through GitLab-CE[1] but what is your favor code?
[1]: https://gitlab.com/gitlab-org/gitlab-ce
167 comments
[ 3.5 ms ] story [ 209 ms ] threadboth in python, but beautiful code, well structured and you would not need any docs, just read the code
I used to do requests but like I said, moved away. I sometimes do pygments to discuss how different lexers etc. are "plugged" in and also to show how messy the command line parsing code there is.
This batch will probably be a little different since I'm reworking it completely. The syllabus for the first batch is here if you're interested in what we covered http://thelycaeum.in/blog/2014/06/10/mentoring_course_time_t...
https://github.com/antirez/redis/blob/4.0/src/cluster.c
cough
Yep
It's definitely not uncommon, but yes, that file is on the long side. However, it is rather clean and well-organized.
It may be due to the poor module system (header files) of C where you end up making files slightly longer than ideal because splitting into two files means also adding some header files and thus adding to the maintenance burden.
When writing C code, I usually strive to put a whole "module" in a single file, so that no "private" interfaces have to be put in header files. Everything that needs to be exposed in order to test a module goes in the public interface.
It's a tradeoff and C being C doesn't help (and C++ wouldn't really help here IMO), but I see nothing wrong with the file you picked. It's a bit long but it looks well done to my C programmer eyes.
I also see lots of prototypes (all?!) defined at the top of the file instead of in a header file. They could be made static.
Also, the generic type "int" isn't a good idea because it can change, it helps avoid porting problems to specify the size (int32_t, uint64_t, etc.)
And the memcpy()'s should be changed to memcpy_s().
On the bright side, the comments are quite good and plentiful. Refreshing!
Had a ton of fun jumping around.
During the prototype phase, anything goes, speed is paramount, you just have to make it sort of work. Don't get hung up practicing pretty looking code during this phase.
You should always practice, but don't get hung up.
Prototype given the green light? Ready to dive into the build phase?
I'll say this, google for "coding style guide"
Where I see things fail a lot more is in the code equivalent of "How do I structure a paragraph" or "How do I organize this paper", which most things under the "style guide" umbrella don't cover.
I've also always insisted on including at least some loose guides to cover the "how do I structure a paragraph" cases. These generally are going to vary on a project by project basis, though, so they're going to be more vague as a rule.
A single file running both in python 2.7 and 3.
My advice is actually not so much different than yours. Definitely checkout the Rails internals, but keep a reserved opinion. Then contrast it with other things. From a framework/library perspective look at Sinatra or other web frameworks that that a completely different philosophy. Try to understand the advantages and disadvantages to many approaches.
Again, I want to stress that my intent is not to be critical of Rails (heck it provides the bulk of my paycheck and I'm very grateful it exists!). My intent is really to say not to be so hung up about finding good code, but rather take a long term view of comparing different approaches and thinking through for yourself what you think is good. People who have a different view point than mine, shed light in corners that I won't look. That's always a good thing.
It's in Python and a single file but it comes with a wonderful description and shows how a complicated task can be broken down into a few small and powerful functions.
It's also the reason for trying to break down larger systems into smaller, elegant components.
I assume that as a developer you are interested in solving (business?) problems through the act of writing software?
It isn't much different than being a painter I guess. To be able to be a good painter (or to be considered a good painter) you first need to have a good grasp on how to use the brush and how to handle paint (e.g. oil paint), i.e. you need to learn the technique. The more versed you become with the technique the better you will become at painting, or, over time you will become better at painting what you intent to paint, to paint what's in your minds-eye because you don't have to think about the brush and paint anymore.
When it comes to software you first need to have a good grasp on programming. This means you will need to spend time practising the act of programming. Using two languages that are very different from each other might be good. E.g. learn an imperative and functional language. In your case this might e.g. Ruby and Lisp. Your programs will need to interact with other systems so you probably need to learn about operating systems, databases, queues, networking, etc. You probably don't have to be an expert in everything but being a good all-rounder will certainly be beneficial.
Over time you will see that it becomes easier to think in solutions of the bat rather than focusing on how you're going to solve a problem. This is basically what is being referred to as experience.
So, to be a good developer you need to put in the effort and you need to put in the time. There usually aren't any short cuts. I've been doing this professionally for over 20 years and I'm still learning every day.
It hardly sounds like he is looking for a shortcut
http://aosabook.org/en/index.html
http://v6.cuzuco.com/v6.pdf
A tiny C-subset JIT:
https://news.ycombinator.com/item?id=8746054
It might even be controversial to suggest these are examples of "good code" today, because the majority of code I've seen lately seems to be overly verbose and complex. In contrast, these are extremely simple and concise for the amount of functionality they contain. I think this style has unfortunately disappeared over the decades of promoting lowest-common-denominator so-stupid-even-an-illiterate-could-read-it coding styles and enterprise OOP design-pattern bloat-ism, but when I think of "good code", I don't think of Enterprise Java; I think of code which, upon being told what it does, makes you think "wow, I never thought it would be so simple."
The same source can produce compilable code, or formatted comments.
https://github.com/antirez/redis/tree/unstable/src
I don't personally use the product, but I find the source well written and always share it as an example of nicely done C code.
Here is some nice Erlang code I like -- network packet parsing:
https://github.com/msantos/pkt/tree/master/src
Notice how concise this is:
This is due to the beauty of binary pattern matching. You could kind of do it in C by casting to a struct but notice here it is also calculating header length (HL) as part of the match operation. So it can do a bit more than just casting a binary blob to a struct.Another thing here is that it is also big endian by default so there is not need for htons(), htonl() and such functions sprinkled throughout the code.
At this point in my career I don't really value being concise at all. Which is not to say you shouldn't ever think about "Can I write less code here?" but the goal there should be writing less code to make what you're writing more robust, more stable, more readable and not just shorter.
If there's one thing I could tell every programmer early in their career (including a younger me) it would be; nobody's going to be impressed with how clever you were when they're frustrated trying to understand what the heck is going on. Including you in 6 months.
This kind of brevity is extremely helpful when thinking about a problem. You "just" have to grok the mechanics thoroughly. This really helps in designing effective higher level abstractions.
Unequivocally admonishing brevity for ostensible readability kind of ignores the trade offs. I think there are other ways to bootstrap grokkability without having to sacrifice the conceptual clarity of nicely compact code.
I'm hitting a lot of 'aha' moments which has really been emotionally satisfying, it's been a long time since I had to push myself I guess.
[1]: http://www.moserware.com/2008/04/towards-moores-law-software...
Digging through the code line by line takes a long time and while one does learn a lot, I am sure there has to be a better way of doing this.
Any static analysis tools that help in this regard? Or any other tool/approach that you might recommend?
I'm sure that wasn't their ultimate intention but there's certainly no incentive to change!
Also for an example it is also the right sized project. It i not too small and not huge (like Linux kernel) and the overall structure can be understood in a few hours of browsing through.
# define FRST(p) (((p[0]) << 8) | p[1])
ref = hslot + LZF_HSLOT_BIAS; hslot = ip - LZF_HSLOT_BIAS;
I pity all C programmers who have to deem this beautiful
It's a part of a performance sensitive mission critical infrastructure. The parts you posted are some of the core data structures that make it fast by squeezing every bit and byte that reasonably can. There are no points awarded for being pretty.
A quick browse around Redis source code looks very clean and elegant to me. There are "hard" low level parts like the stuff you quoted (out of context) and then there are "easy" parts that implement the higher level functionality. It has a decent amount of comments.
Taking one of the "nasty" bits out of context is disingenuous. Every computer program has nasty bits and they're usually there for a reason.
What's a FRST? The actual code appears to do a LE encoding of a u16, but I can't fathom why you'd call that "FRST". But maybe in context it makes more sense.
The rest, IDK. Can't tell what an "LZF hslot bias" is. Again, might make sense in context.
If I recall correctly, the file you grabbed these from had a lot of comments that thoroughly explain how it works. At least many other files in the redis repo do.
They could have named it "FIRST" or whatever FRST is short for. That would have made zero impact to the code quality but a longer name would make things clumsy. It's a file-local helper macro and not a part of any public interface or a crucial piece of the architecture.
Feel free to disagree, but picking two nasty lines out of context in an otherwise well designed and implemented code base has zero bits of information about the quality of the project.
The parent poster didn't link, so I lacked the context to really evaluate it. Your persistence at waving this away as "making sense with background knowledge of the algorithm internals" drove me to find it.
> If I recall correctly, the file you grabbed these from had a lot of comments that thoroughly explain how it works
It's fairly light on comments. Not completely devoid of them, but the code can't stand in isolation. The algorithm itself, LZF, seems to be a variation of LZO, but not notable enough to make Wikipedia.
> They could have named it "FIRST" or whatever FRST is short for.
The fact that you're unsure of this fact defeats your next point, at least for me:
> That would have made zero impact to the code quality
Why? One extra letter immediately disambiguates it, and now we know that it at least means "first".
> a longer name would make things clumsy
If you look at the file it's used in, it has exactly two uses. The readability gained from the extra vowel in this case is well worth it, and would in no way make the code "clumsy". A four-byte (five if you count the commented out code) change so that the reader doesn't need to play guess-the-word? Worth it, in my opinion.
The documentation above it too,
> just believe me, it works ;)
But why does it work? We'll never know, b/c that's bound up in the author's head.
https://github.com/id-Software/Quake
https://github.com/id-Software/Quake-2
https://github.com/id-Software/DOOM
http://www.projectoberon.com
> Seibel: I’m still curious about this split between what people say and what they actually do. Everyone says, “People should read code” but few people seem to actually do it. I’d be surprised if I interviewed a novelist and asked them what the last novel they had read was, and they said, “Oh, I haven’t really read a novel since I was in grad school.” Writers actually read other writers but it doesn’t seem that programmers really do, even though we say we should.
> Abelson: Yeah. You’re right. But remember, a lot of times you crud up a program to make it finally work and do all of the things that you need it to do, so there’s a lot of extraneous stuff around there that isn’t the core idea.
> Seibel: So basically you’re saying that in the end, most code isn’t worth reading?
> Abelson: Or it’s built from an initial plan or some kind of pseudocode. A lot of the code in books, they have some very cleaned-up version that doesn’t do all the stuff it needs to make it work.
It is a great way to find new ways of doing things, and to gain experience-based opinions, but I certainly wouldn't be doing it if I didn't have a very specific goal in mind.
Code in books is dumb. The real code to read is other code you use or interact with. eg reading the jquery source or the Rails source or code reviewing a colleague.
Almost always one does this while answering a question about this source. Trying to understand what a library call is doing or tracing a bug.
You learn a lot this way including coding tricks and style points.
Some guy says in an interview it's bullshit, so it is?
You never read other people's code? Not when the documentation's lacking? Not when the documentation's fine, for a framework say, but you need to see an example of how it's actually used in the context of a real application?
And that matches my experience: When I read code, it's precisely because the documentation is lacking, or because I want to match up an error message produced by the code with the logic preceding the error message's origin.
I think that there's also a much more similarity with analyzing a novel than reading one for pleasure. Reading code has a much greater mental tax than pleasure reading, it requires more focus to actually put together what's going on, and that's similar to analyzing a novel for a report, where you might read the same passage 4-5 times, taking notes. Or even better yet, analyzing a poem, which are often short (and often obey 80 char line width rules!) and analyzing them can require a great amount of focus and thought to decide why a poet used this word in this way, and what meaning they intended to convey and such. That's much more similar to reading code than reading a novel, and I expect also less common.
But it is very effective as a way of spotting certain kinds of bugs, while at the same time gaining a much deeper understanding of a codebase.
Reading code in a non trivial way is a very special skill that not many developers have, but that is very worthwhile to attain.
Whenever I come to a new codebase, I start by grabbing a pretty random bug and reading the code in that area. just flicking through, forcing myself to ask questions about it and finding out the answers.
actively engaging with code like that is an amazingly effective way of absorbing a codebase.
I suspect this might be a side effect of my dyslexia, but it's something which often works to my advantage.
The answer is never exact, though. Something will have 10 different solutions, and being able to look at them and discuss the tradeoffs that went into the decision is a definite skill.
To me, the Quake 1/2 source code has been an invaluable source of insight, as much for small algorithmic stuff (like collision/sliding code) than for its architecture as a whole (like game/engine separation, the edict_t system) ...
Have you never asked yourself "how did they do this" ?
Just like you can't really learn math just by reading the book, you'll "learn good code" much more effectively if you're working on it and you have to make decisions and judgments to move forward.
This.
Also, you'll have a more goal-directed path through the code, which is usually more motivating than understanding code for the sake of understanding.
Of course, there's always the pitfall that people will start making changes willy-nilly, until the code does roughly what they want, without really understanding anything.
But this will vanish as soon as you put higher quality standards to your own work. (e.g. if you want to ensure that it does the correct thing in all edge cases, or if you produce something larger than a quick hack)
... if you submit your code to the project's owner. :)
(But I know that I myself are somewhat of an outlier, since I'm a rather extreme top-down learner.)
Additionally, I've on occasion consulted the Linux kernel and PostgreSQL repos. Would recommend, although I'm definitely either lying or very ignorant if I said I was familiar with them.
1: https://github.com/defunkt/unicorn
I particularly liked Brian Kernighan's description and implementation of a regex matcher, and Travis Oliphant's discourse about multidimensional iterators in NumPy.
Worth a read.
Looking back up the talk, it points to his review of the book here: http://dtrace.org/blogs/bmc/2007/07/28/on-the-beauty-in-beau...
> More specifically: read [two specific chapters with very different attitudes on what makes code beautiful]. It seems unlikely to me that one person will come away saying that both are beautiful to them. (And I’m not talking new-agey “beautiful to someone” kind of beautiful — I’m talking the ”I want to write code like that” kind of beautiful.) This is not meant to be a value judgement on either of these chapters — just the observation that their definitions of beauty are (in my opinion, anyway) so wildly divergent as to be nearly mutually exclusive. And that’s why the title is perfect: both of these chapters are beautiful to their authors, and we can come away saying ”Hey, if it’s beautiful to you, then great.”