4 ms·
Doing this for every intermediate result badly harms readability. Consider McIlroy's famous 1-liner: tr -cs A-Za-z '\n' | tr A-Z a-z | sort |
by jonahx 3y ago
Doing this for every intermediate result badly harms readability.
Consider McIlroy's famous 1-liner:
tr -cs A-Za-z '\n' |
tr A-Z a-z |
sort |
uniq -c |
sort -rn |
sed ${1}q
Adding intermediate variables like "newline_delimited", "lowercased", "sorted", etc... is just pure noise. It's the equivalent of a newb programmer putting a comment over each line of simple code explaining in English what that code does, despite it being clear already.
"There are only two hard things in Computer Science: cache invalidation and naming things"
One of the great benefits of pipelines and tacit programming is the ability not to name intermediate results, especially when those results speak for themselves, are not re-used, and have no significance in isolation.
- mihaic 3y agoWhile I agree that sometimes I do break my rules myself, when I don't want to spend 15 minutes to name something, I don't think your example convinced me of your case. Would you honestly expect someone to know by heart what "sort -rn" or "uniq -c" do? This forces the reader to know what all the arguments mean by anyone reading this code. If you'd try to push this code, I wouldn't let it pass code review without a comment on each line (except plain "sort", that one's really obvious).
- jonahx 3y ago> Would you honestly expect someone to know by heart what "sort -rn" or "uniq -c" do? For people that program regularly in bash, I would. If it was a rare bash script in a code base where many team members didn't know bash well, comments would be appropriate. Even there, though, that's not the same as introducing superfluous intermediate variables. The larger point here relates to "intended audience" or "what competencies may I assume the reader has?". This is a matter of art, not science, and highly context dependent. Take an extreme version of the point you just made: const x 4*2; "Would you honestly expect someone to know by heart that `*` in JS means multiplication?" Clearly that is absurd, because that knowledge is an assumed competency. What about `**` for power? What about `^` for XOR? What about knowing that `-~x` is equivalent to `x+1`? Where exactly do you draw the line? You can "err on the side of over-commenting" but only so much, because taken to an extreme it hurts readability, and will annoy everyone. Responsibilities are distributed. Is clarification the responsibility of the author or the reader? What can I assume "a reasonable reader" should know? The answer depends on many things. But the right answer isn't a blanket policy of assuming incompetence and explaining every detail with comments or intermediate variables.
- mihaic 3y agoI think we're in agreement on the framework of the debate (rare), it's just that from personal preference we draw different lines on what information is reasonable to assume your reader has. I personally have not regretted much assuming incompetence in my future self on small things, but it's your choice to what standard you hold yourself against.
- lifthrasiir 3y ago> Adding intermediate variables like "newline_delimited", "lowercased", "sorted", etc... is just pure noise. I don't fully agree. Even when each step is fully descriptive it greatly helps to see the intermediate result, and names can be used for that as well. It is true that some intermediate names are not required, partly because some steps are best understandable in conjuction with neighboring steps (e.g. `sort | uniq -c` is a very common idiom and splitting them would do much harm than good), but a healthy dose of names would help in general. I would say that there are three major steps in this particular pipeline: normalization (`tr -cs A-Za-z '\n' | tr A-Z a-z`), frequency calculation (`sort | uniq -c`), and extraction of first ${1} largest entries (`sort -rn | sed ${1}q`). So it is reasonable to have two additional names between them. Or you can name each step with a function so that you don't need intermediate results to understand that (`norm-words | calc-freqs | keep-largest ${1}`). > It's the equivalent of a newb programmer putting a comment over each line of simple code explaining in English what that code does, despite it being clear already. That is more about repeating functional parts without describing any intention. Comments about intents and clarifications are absolutely fine. For example: counter += 1; // increment the counter by one (bad) counter += 1; // increment the global counter, don't need synchronization here (better) g_counter.incr_without_sync(); // (even better, but not always possible)