Ask HN: Writing code with diff-readability in mind?

15 points by Syrup-tan ↗ HN
While this isn't a very dire or pressing matter, I think it would be interesting to discuss.

It's often considered good practice to use trailing commas in multi-line arrays (where language syntax rules permit); e.g.

  [
    'a',
    'b',
    'c',
  ]

going further, would it also make sense to start an else-if check train with ``if false; ' ' ? e.g.

  if false;
  else if check 1; etc
  else if check 2; etc
  else if check 3; etc

for a real-ish world example:

  https://gist.github.com/Syrup-tan/c78f781c9b500b802fec#file-w-sh-L33-L56
  https://gist.github.com/Syrup-tan/c78f781c9b500b802fec#file-w2-sh-L33-L56
the second way grants a refactor-er the ability to re-order the elif checks without modifying any of the statements, reducing the chance of basic errors. It also makes diffs simpler to read.

However, in exchange, it sort of violates ``Principle of Least Surprise ' ', as someone reading the code may not understand what the ``if false; then :; ' ' is doing there. ( ``: ' ' is the null-operation in sh)

I'd love to hear more thoughts on this practice.

edits: readability & highlighted section in gist ( no wording changes )

14 comments

[ 4.6 ms ] story [ 38.9 ms ] thread
? Those pages are identical.

[EDIT] Anyway, aside from your suggestion of "if false", yes writing code to make diffs smaller or cleaner is good in my opinion. On this specific point, why not just start with "if check 1"?

With JavaScript enabled on GitHub, the separate links highlight different sections of the code.

If you start with if check 1 (such as in w.sh), a refactor-er would have to s/elif/if on check 2 and s/if/elif on check 1 if he wants to swap their order. By having all of the checks start with elif (such as in w2.sh), the refactor-er can change the order of the checks without having to modify them, making cleaner diffs.

Not code, but docs, here is what I do:

Start each sentence on a new line (I have a perl script that formats text like this).

The reason is that when you version control the docs it's easier to pick out the diffs if the sentences are boundaries.

It's simple, easy, makes looking at diffs faster.

> It also makes diffs simpler to read.

I find that there's a pretty direct conflict between trying to keep diffs 'pretty' and the quality of the ever-growing code.

In my experience, code quality is only achieved and sustained by continual refactoring. When this continual refactoring attempts to satisfy easy-to-read diffs the objective stops being to simplify the code itself and rather to simplify the delta -- which limits/checks the simplicity the code can achieve.

That's a good insight! At one point last year I found myself in the trap of playing 'delta golf', to the extent that I would leave extra {...} blocks around if it meant not having to de-dent a dozen statements.

It was definitely an unnecessary self-imposed constraint that grew out of an adversity to merge conflicts.

i think one rule of thumb to follow is to keep each diff focused.

making a functional change? e.g. adding a new feature / fixing a bug? don't try to clean up neighbouring patches of code, just make the change in a way that is easy to review

refactoring / cleaning up code / changing namespaces in 1000 files? don't make functional changes!

trying to review a diff that has superficial changes to 1000s of files and also a few hidden surprise functional changes is a complete nightmare.

note: just because the revision history should be cleanly separated like this, doesn't mean you have to work like this. you can make interleaved functional changes and refactors when you are working locally - you just need to use your version control's history editing capability to tease apart / re-order your changes and commit them separately.

Changing if/else sequences that cannot be written as switch/match constructs in that way is probably too rare to make this a good idea.
Diffs are a secondary concern. Writing code that is well-structured and readable as it currently exists is the most important thing.
I have come to prefer putting commas in lists at the beginning of things

SELECT

field1

,field2

,field3

,field4

FROM table

More easy to realize you are missing separators and it just looks nicer to me.

This is so pointless and really looks like breaking convention for the sake of it
It's actually not a terribly uncommon code convention. I've seen a lot of C written with this style.

Personally, I don't see the value if your code fits in one screen width, but I'm certainly not going to refactor a code base away from this style if it's been in place for years.