About once every other project, some portion of the source benefits from source code being arranged in a tabular format. Long lines which are juxtaposed help make dissimilar values stand out. The following table is not unlike code I have written:
setup_spi(&adc, mode=SPI_01, rate=15, cs_control=CS_MUXED, cs=0x01);
setup_spi(&eeprom, mode=SPI_10, rate=13, cs_control=CS_MUXED, cs=0x02);
setup_spi(&mram, mode=SPI_10, rate=50, cs_control=CS_DIRECT, cs=0x08);
Even if we add 4-5 more operational parameters, I find this arrangement much more readable than the short-line equivalent: setup_spi(&adc,
mode=SPI_01,
rate=15,
cs_control=CS_MUXED,
cs=0x01);
setup_spi(&eeprom,
mode=SPI_10,
rate=13,
cs_control=CS_MUXED,
cs=0x02);
setup_spi(&mram,
mode=SPI_10,
rate=50,
cs_control=CS_DIRECT,
cs=0x08);
Or worse, the formatter may keep the long lines but normalize the spaces, ruining the tabular alignment: setup_spi(&adc, mode=SPI_01, rate=15, cs_control=CS_MUXED, cs=0x01);
setup_spi(&som_eeprom, mode=SPI_10, rate=13, cs_control=CS_MUXED, cs=0x02);
setup_spi(&mram, mode=SPI_10, rate=50, cs_control=CS_DIRECT, cs=0x08);
Sometimes a neat, human-maintained block of 200 character lines brings order to chaos, even if you have to scroll a little. setup_spi(&adc, mode=SPI_01, rate=15, cs_control=CS_MUXED, cs=0x01);
setup_spi(&eeprom,
mode=SPI_10,
rate=13,
cs_control=CS_MUXED,
cs=0x02);
setup_spi(&mram, mode=SPI_10, rate=50, cs_control=CS_DIRECT, cs=0x08);The pain point you describe is real, which is why that was intentionally added as a feature.
Of course it requires a language that allows trailing commas, and a formatter that uses that convention.
I've often wished that formatters had some threshold for similarity between adjacent lines. If some X% of the characters on the line match the character right above, then it might be tabular and it could do something to maintain the tabular layout.
Bonus points for it's able to do something like diff the adjacent lines to detect table-like layouts and figure out if something nudged a field or two out of alignment and then insert spaces to fix the table layout.
And sometimes, if the code doesn't look good after automatic formatting, the code itself needs to be fixed. I'm specifically thinking about e.g. long or nested ternary statements; as soon as the auto formatter spreads it over multiple lines, you should probably refactor it.
This was more about lamenting the need for such things. Clang-format can already somewhat tabularize code by aligning equals signs in consecutive cases. I was just wishing it had an option to detect and align other kinds of code to make or keep it more table like. (Destroying table-like structuring being the main places I tend to disagree with its formatting.)
1) Horizontal scrolling sucks
2) Changing values easily requires manually realigning all the other rows, which is not productive developer time
3) When you make a change to one small value, git shows the whole line changing
And I ultimately concluded code files are not the place for aligned tabular data. If the data is small enough it belongs in a code file rather than a CSV you import then great, but bothering with alignment just isn't worth it. Just stick to the short-line equivalent. It's the easiest to edit and maintain, which is ultimately what matters most.
setup_spi(&adc, mode=SPI_01, rate=15, cs_control=CS_MUXED,
cs=0x01);
setup_spi(&eeprom, mode=SPI_10, rate=13, cs_control=CS_MUXED,
cs=0x02);
setup_spi(&mram, mode=SPI_10, rate=50, cs_control=CS_DIRECT,
cs=0x08);
of there the short-line alternative presented.I like short lines in general, as having a bunch of short lines (which tend to be the norm in code) and suddenly a very long line is terrible for readability. But all has exemptions. It's also very dependent on the programming language.
In a post-modern editor (by which I mean any modern editor that takes this kind of thing into consideration which I don't think any do yet) it should be possible for the editor to determine similarity between lines and achieve a tabular layout, perhaps also with styling for dissimilar values in cases where the table has a higher degree of similarity than the one above. Perhaps also with collapsing of tables with some indicator that what is collapsed is not just a sub-tree but a table.
But are there more examples? May be it's not high price to pay. I'm using either second or third approach for my code and I never had much issues. Yes, first example is pretty, but it's not a huge deal for me.
setup_spi(
&adc,
mode=SPI_01,
rate=15,
cs_control=CS_MUXED,
cs=0x01
);
setup_spi(
&eeprom,
mode=SPI_10,
rate=13,
cs_control=CS_MUXED,
cs=0x02
);
setup_spi(
&mram,
mode=SPI_10,
rate=50,
cs_control=CS_DIRECT,
cs=0x08
);
ftfy setup_spi(&adc,
mode=SPI_01,
rate=15,
cs_control=CS_MUXED,
cs=0x01
);
setup_spoo(&adc,
mode=SPI_01,
rate=15,
cs_control=CS_MUXED,
cs=0x01
);
setup_s(&adc,
mode=SPI_01,
rate=15,
cs_control=CS_MUXED,
cs=0x01
);
validate_and_register_spi_spoo_s(&adc,
mode=SPI_01,
rate=15,
cs_control=CS_MUXED,
cs=0x01
); setup_spi(
&adc,
mode = SPI_01,
rate = 15,
cs_control = CS_MUXED,
cs = 0x01 );
setup_spoo(
&adc,
mode = SPI_01,
rate = 15,
cs_control = CS_MUXED,
cs = 0x01 );
setup_s(
&adc,
mode = SPI_01,
rate = 15,
cs_control = CS_MUXED,
cs = 0x01 );
validate_and_register_spi_spoo_s(
&adc,
mode = SPI_01,
rate = 15,
cs_control = CS_MUXED,
cs = 0x01 );However, it is the formatting I adopt when forced to bow down to line length formatters.
This is why a Big Dictator should just make a standard. Everyone who doesn't like the standard approach just gets used to it.
Thus 80 or perhaps 120 char line lengths!
Especially 80 characters is a ridiculously low limit that encourages people to name their variables and functions some abbreviated shit like mbstowcs instead of something more descriptive.
80 is probably too low these days but it's nice for git commit header length at least.
What a terrible attitude to have when working with other people.
"Oh, I'm the only one who writes Python? Fix your setup. why should I, who know python, not write it for your sake?"
"Oh, I'm the only one who speaks German? Fix your setup. Why should I, who know German, not speak it for your sake?"
How about doing it because your colleagues, who you presumably like collaborating with to reach a goal, asks you to?
>How about doing it because your colleagues, who you presumably like collaborating with to reach a goal, asks you to?
If a someone wants me to do a certain thing in a certain way, they simply have to state it in terms of:
- some benefit they want to achieve
- some drawback they want to avoid
- as little as an acknowledged unexamined preference like "hey I personally feel more comfortable with approach X, how bout we try that instead"
I'm happy to learn from their perspective, and gladly go out of my way to accomodate them. Sometimes even against my better judgment, but hell, I still prefer to err on the side of being considerate. Just like you say, I like to work with people in terms of a shared goal, and just like you do, in every scenario I prefer to assume that's what's going on.
If, however, someone insists on certain approaches while never going deeper in their explanations than arbitrary non-falsifiable qualifiers such as "best practice", "modern", "clean", etc., then I know they haven't actually examined those choices that they now insist others should comply with. They're just parroting whatever version they imagine of industry-wide consensus describes their accidental comfort zone. And then boy do they hate my "make your setup assume less! it's the only way to be sure!". But no, I ain't reifying their meme instead of what I've seen work with my own two.
Working together with others should not mean having to limit everyone to the lowest common denominator, especially when there are better options for helping those with limitations that don't impact everyone else.
Just use descriptive variable names, and break your lines up logically and consistently. They are not mutually exclusive, and your code will be much easier for you and other people to read and edit and maintain, and git diffs will be much more succinct and precise.
Because "I" might be older or sight-impaired, and have "my" font at size 32, and it actually fills "my" (wider than yours) screen completely?
Would you advise me to "fix my eyes" too? I'd love to!
"Why should I accommodate others" is a terrible take.
80-column line lengths is a pretty severe ask.
Unless they have been a thing since the start of a project; existing code should never be affected by formatters, that's unnecessary churn. If a formatter is introduced later on in a project (or a formatting rule changed), it should be applied to all code in one go and no new code accepted if it hasn't passed through the formatter.
I think nobody should have to think about code formatting, and no diff should contain "just" formatting changes unless there's also an updated formatting rule in there. But also, you should be able to escape the automatic formatting if there is a specific use case for it, like the data table mentioned earlier.
Log statements however I think have an effectively unbounded length. Nothing I hate more than a stupid linter turning a sprinkling of logs into 7 line monsters. cargo fmt is especially bad about this. It’s so bad.
Sent from my 49” G9 Ultrawide.
What I actually want from a linter is “120, unless the trailing bits aren’t interesting in which case 140+ is fine”. The ideal rule isn’t hard and fast! It’s not pure science. There’s an art to it.
All that said, I'm interested with this 132 number, where does it come from?
Really suites each language imo Although I could probably get away with 80, habit to use tailwind classes can get messy compared to 120
But someone will always have to either scroll horizontally or wrap the text. I’m speaking as someone who often views code on my phone, with a ~40 characters wide screen.
In typography, it’s well accepted that an average of ~66 chars per line increases readability of bulk text, with the theory being that short lines require you to mentally «jump» to the beginning of the next line frequently which interrupts flow, but long lines make it harder to mentally keep track of where you are in each line. There is however a difference between newspapers and books, since shorter ~40-char columns allows rapid skimming by moving your eyes down a column instead of zigzagging through the text.
But I don’t think these numbers translate directly to code, which is usually written with most lines indented (on the left) and most lines shorter than the maximum (few statements are so long). Depending on language, I could easily imagine a line length of 100 leading to an average of ~66 chars per line.
In my experience, with programming you rarely have lines of 140 printable characters. A lot of it is indentation. So it’s probably rarely a problem to find your way back on the next line.
For C/C++ headers I absolutely despise verbose doxygen bullshit commented a spreading relatively straightforward functions across 10 lines of comments and args.
I want to be able to quickly skim function names and then read arguments only if deemed relevant. I don’t want to read every single word.
I like splitting long text as in log statements into appropriate source lines, just like you would a Markdown paragraph. As in:
logger.info(
"I like splitting long text as in log statements " +
"into ” + suitablelAdjective + " source lines, " +
"just like you would a Markdown paragraph. " +
"As in: " + quine);
I agree that many formatters are bad about this, like introducing an indent for all but the first content line, or putting the concatenation operator in the front instead of the back, thereby also causing non-uniform alinkemt of the text content.I once made a stupid mistake of having a list of directories to delete:
directories_to_delete = (
"/some/dir"
"/some/other/dir"
)
for dir in directories_to_delete:
shutil.rmtree(dir)
Can you spot the error? I somehow forgot the comma in the list. That meant that rather than creating a tuple of directories, I created a single string. So when the `for` loop ran, it iterated on individual characters of the string. What was the first character? "/" of course.I essentially did an `rm -rf /` because of the implicit concatenation.
With some expressions, like lookup tables or bit strings, hand wrapping and careful white space use is the difference between “understandable and intuitive” and “completely meaningless”. In JS world, `// prettier-ignore` above such an expression preserves it but ideally there’s a more universal way to express this.
But that's the core of this article, too; since then it's normalized to store the plain text source code in git and share it, but it mentions a code and formatting agnostic storage format, where it's down to people's editors (and diff tools, etc) to render the code. It's not actually unusual, since things like images are also unreadable if you look at their source code, but tools like Github will render them in a human digestable format.
Boy that was fast.
Some languages (java) really need the extra horizontal space if you can afford it and aren’t too hard to read when softwrapped.