80 chars per line is great
wrongsideofmemphis.com
wrongsideofmemphis.com
Even 100 can be awkward to fit into. Lord knows I've renamed variables to avoid splitting a line on several occasions.
But what a lot of posters here seem to miss is that it isn't about the width of screens for editing, it's about the width of screens for reviewing so you need twice the real estate.
Add in doing interactive merges and you need three times the width.
This really comes down to the principle of enforcing a common style (for an organization or project). A lot of people rail against "arbitrary limits" and "arbitrary style guidelines" as it's something extra they need to learn and adds no value (according to them). I've seen people here for 6+ months again still fighting this.
Such things (IMHO) have value as it adds a reasonable level of consistency across teams, it avoids commits on files due to stylistic changes (which may or may not be automatic from IDEs, etc) and, most importantly, defuses a lot of the aesthetic-driven boneheadedness that we engineers are prone to.
The last point is really important. Otherwise you'd have engineers and groups fighting over where to put curly braces, 2 space indents vs 4, whether tabs are OK, etc--none of which actually matters.
So if you feel your creativity somehow stifled over 80 characters, I'd strongly suggest you just abosrb it, get over it and move on to things that actually matter.
[1]: http://google-styleguide.googlecode.com/svn/trunk/pyguide.ht...
Wide lines are barbaric, and I'd go so far as to say that languages that can't be rendered comfortably in 80 character lines are nothing more the primitive tools of barbarians.
I agree utterly, and enjoy the irony that I read your comment displayed as http://i.imgur.com/iJNs9SV.jpg ... a full 258 characters ... HN could do with some responsive css to max-width comments above certain viewport widths!
enforcing a common style
I've seen people here for 6+ months still fighting this
Or you could, you know, just treat each other as adult, responsible individuals.
Hint: rules for the sake of uniformity don't "defuse boneheadedness". They just suppress individuals, and eventually either drive them out or tame creativity, initiative, and responsibility out of them.
I mean, come on, you say that yourself! So just acknowledge that that's what you're doing. There are processes for making better software. These kinds of style guidelines are not among them.
This is probably the most insightful comment to come out of this discussion. The exact numbers aren't all that important, but having a consistent style (including line length limits - which I'm fairly sure no one will argue that there should not be a limit) and not checking in stylistic changes (or at a minimum, disentangling them from actual changes of substance) is important.
The problem is, we as programmers obsess over details (especially the closer you get to the hardware). The key is to obsess over the correct details, or obsess once and move on.
The style guide you linked to says indents are 4 spaces. I sense the question of indent size hasn't been solved at Google yet :-) I find 2 to be too little, except for XML and HTML which are naturally indented many levels and there's no way to refactor into new functions or methods.
[Edit: added quote]
How did they do interactive merges when they were limited to 80 characters?
Yes, we realize that monitors are bigger, resolutions are higher, etc ad naseum. None of that matters. What matters is code readability. So what if you can fit 120 characters in your code editing window? I can fit more than 400 across two monitors, should the new line length limit be 400? Why stop there, why not just let lines be endless and have the editor wrap them? Answer these questions, and you've answered why people still like the 80 column guideline, or even care about code formatting at all. Code is only incidentally written for machines to execute; it should be written for people to read.
Also, it's funny to me that people talk about horizontal line length impacting readability, but never seem to talk about vertical length impacting readability as well. To me it's critical to keep related code clustered vertically as closely as possible without too much brevity: having to scroll/split view to see related pieces of code incurs a cognitive overhead. Arbitrary line breakage imposed by the 80-character limit gets in the way of that. (And don't get me started about teams that treat this as a limit instead of a guideline.)
It's critical to give programmers the tools to make their code readable (good languages with good grammar and idioms), not arbitrary restrictions that try and fail to accomplish that indirectly.
I'm calling this bluff. No, you can't. If you actually have evidence I'd truly love to see it.
Ridiculous line length is actually one of the most reliable code smells I know. Seeing something like that, I can virtually guarantee that it's an OOP-gone-wild mess of needless abstraction, tightly coupled data structures spread across a dozen files. It's going to be a spaghetti mess of nested if() constructs used where clean data-driven logic would have been better. It will be filled with commented-out-code. And it will probably have indentation that lies, lined up in incorrect columns waiting to fool the developer.
Clearly you feel differently. Prove it. :)
Feel free to criticize. That code has lots of shortcomings. Compromised readability due to line length is not one of them.
Note all the repeated use of this weird dictionary name "my_stats[condition][strand]". This thing appears, often multiple times, on ever line of that loop. You're telling me that this couldn't be made more readable by using a simple local "stats" reference name "st"? Repetition of expressions is the sign of lazy code, it's the same kind of thought process that gives us cut-and-paste bugs.
Note likewise the repated use of "kc_stats[condition]". Same deal. Same treatment.
Note likewise the oddball commented out line (assigning a tuple of m2_ci_lo_fwd, m2_ci_hi_fwd) which is disabled without explanation. Remember my list of attendant symptoms?
And, on the design side: note the mean/median/stdev calls. Those are generally pretty well-defined properties of "sets". Why is there a "Metric" postpended to the method names needlessly? Surely the reader would understand "st.stdev()" already, right? And why do the methods take five named parameters?. That's insane -- they should take zero. It looks like this is trying to pass in some extra "stuff" (maybe to control some side effects, or to filter the data) to what should be an idempotent operation on a fixed piece of data. If you have to filter, or if the object does some extra counting or whatever, those should be set up on the data ahead of time.
This code is crap. Sorry.
my_stats = {'Modified': {'+': {}, '-': {}}, 'Control': {'+': {}, '-': {}}}
for condition in 'Modified', 'Control':
for strand in '+', '-':
st = my_stats[condition][strand]
kc = kc_stats[condition]
kc = kc.metricGenerator(metric, ref_pos=ref_pos, trim=opts.exp_trim,
coverage_ceiling=opts.coverage_ceiling,
strand=strand)
st['mean'] = kc.mean()
st['median'] = kc.median()
off = st['stdev'] = kc.stdev()
if use_se:
kc.setOpts(ref_pos, metric, trim=0.0,
coverage_ceiling=opts.coverage_ceiling, strand=strand)
off /= sqrt(len(kc._getMetricData()))
st['spread_lo'] = st['mean'] - off
st['spread_hi'] = st['mean'] + off
my_report_row.extend(st['mean'], st['median'], st['stdev'],
st['spread_lo'], st['spread_hi'],
st['coverage']])In either case, both examples are literally geometrically square, which I think drives readability more than line width. When the long lines poke out and don't relate to other long lines, it's hard to read. If all the lines are long and share structure, it's just verbose, but reasonably easy to read. With that perspective, I'd say the parent's code isn't a great example of long-line code: it doesn't demonstrate a _need_ for 160 chars; I'll agree with you.
Some of us have a higher standard for "readable" code than "can be refactored so that it doesn't suck". :)
self.opts.modified_positions_fwd = [ int(p) for p in self.opts.modified_positions_fwd.split(",") ] if self.opts.modified_positions_fwd != None else []
Without explicitly attacking Python's syntax, I had to horizontally scroll left and right multiple times to understand the entire impact of this statement.Both yours and my claims are anecdotal. Unfortunately I don't know of many research studies, though I'm sure some has been done for this issue in typography.
* Duplication everywhere.
* No internal comments indicating the code's purpose.
* Long functions with too much nesting.
* Lack of constants.
* Indenting by 4 spaces (instead of 2).
* Lines like 316-320 and 326-335 should line break and indent after the first open parenthesis to avoid huge whitespace.
* Inconsistent line break usages for long lines.
* Line 412, for example, should line break at "ref_pos".
The code has many shortcomings, including readability due to extreme line length.
This is why I think it's absurd that we still use flat file text editors to code. I don't care about how functions are laid out in the file. As you said, I care about their semantic relatedness. That may vary by concern. It's almost like I want to tag each function with the features/concerns that it addresses. Then I'd like to be able to view each tag on its own, and have all its constituent parts (functions, modules, classes, etc.) laid out in a way that makes sense. Maybe that's stacked vertically, maybe side by side, or maybe something else. I'd be able to switch between views at will. Each feature branch would probably have its own view.
This would have the side benefit that a function with many tags is a new smell, but more meaningful than character or line length.
The only people I know of who are even attempting to address these issues are Brett Victor, Jonathan Edwards, and the Light Table people.
Its an extremely personal decision because it depends on the exact interface of your skill level as a programmer in general, your skill level with that particular language, your skill level in the business problem domain, AND your own peculiarities WRT to the kind of errors you make.
Given the exact workload I'm being paid for at this time I do NOT make "line" level errors or even "small block" errors but instead get tripped up on crazy "business logic" and big architectural issues. So I am better off at this moment with longer lines showing more "big picture" than with clear little lines.
What I'm getting at is on recent projects I've been making more mistakes with "which blocks of changes need to complete transactionally/atomically based on crazy business logic without causing race conditions" rather than "I need to make it really clear I'm adding these two numbers as opposed to concatenating two strings" or whatever.
This tradeoff of width vs length varies for me, project by project based on actual requirements.
Personally I think this helps "those who come after me". If you see long complicated lines that's a warning that you should tread lightly there and there's probably something complicated at the "vertical" big picture level going on, so I had to make the "horizontal" look icky to make it fit. If I'm just squirting out blah blah code and hitting enter every 20 characters you can safely assume at the big picture there is nothing very complicated going on.
A good (fine arts oil) painting analogy is which is better, portrait or landscape canvas? Well, it depends on the scene. Maybe you personally are only commissioned to paint portraits, well then...
Then the next up monitor I could do 3 columns, so I still stuck to the 80 column idea.
Using a width limit to coerce into indenting less is just plain silly. If you don't want high levels of indentation, put THAT in your coding guidelines. Don't rely on side effects.
This is about the amount of time and distance required to scan my eyes across a line to understand its meaning. How much do I have to read to understand a simple concept?
This is also about the amount of screen real-estate i have to use. We arn't programming on VT100 terminal any more, damn right. NOW I get to have the compiler output and continuous integration output to my left. The directory, class structure and documentation to my right.
I also get to split my screen to have two editors open for comparing snippets of code line by line.
Merge conflicts and diffing are hugely common operations. merges have three parallel windows open at once!
You, still, only have 80 characters to work with.
This isn't about the indentation.
From TFA: Also, having the mandatory indentation whitespace increase the line width is a good visual way of minimising the nested loops in your code and suggesting, in a subtle way, to refactor anything that is indented more than about four times.to be fair, so am I.
The author was asserting 80 character line width was easier to read.
So are many useful inventions.
The reason it matters is readability. News papers for example have been using columns for readability and to me that makes it easier to read.
Having the same for code is great.
I have 3 vertical monitors so I want to have as much of the code go vertically and then I split the monitor into 2 or 3 columns (vertically), I find I get much better productivity, and my eyes get less tired. I like scanning up and down not too far to the left of right.
I have not always followed this and looked at some old code with 160+ long lines in some places.
Besides terminals are still used when logging in via SSH into a server it is still nice to not to have to keep re-sizing the terminal according to whatever the largest line is.
MyObject object = MyObjectBuilderFactory.getBuilder().essentialProperty("the value").otherImportantProperty(42).specialThingyReference(someVariable).build();
vs MyObject object = MyObjectBuilderFactory.getBuilder().
essentialProperty("the value").
otherImportantProperty(42).
specialThingyReference(someVariable).build();
Or how about: cookies = responseObject.headers.findAll { header -> header.key == "Set-Cookie" }.collect { cookieHeader -> new Cookie(cookieHeader) }
vs cookies = responseObject.headers.findAll { header ->
header.key == "Set-Cookie" }.collect { cookieHeader ->
new Cookie(cookieHeader) }
Just because it is one statement does not mean it has to be on one line.What about?...
我品 品= 我品做厂.受做().必要产("the value").别重要产(42).特别Thingy提交(任何变量).做()
...and...
饼干s= 响应品.首s.找都{首→ 首.钥匙 ≡ "Set-Cookie"}.收集{饼干首→ 新 饼干(饼干首)}
They're on one line and more people can read it than your English version.
But second one looks like a mess either way :), partly because I am not familiar with the language, but mostly I think because brackets are opened and closed on different lines.
I'm sure you can come up with several pretty ways of breaking up every specific situation that is both aesthetically pleasing and functional (in fact I already use your first example, with slight modifications), but there is no general way that can be encoded in rulebook or indent rules of an IDE.
Sure, but there are always edge cases not covered by the rule book or IDE. For me the rulebook should say "break lines so that no single line is > 80 chars" and leave it to the programmer to do so in an intelligent way for each scenario. Or if you want a little more conformity add some guidelines like: keep a method call on one line if possible, keep each method parameter on one line if possible, when breaking a method call over several lines vertically align each parameter (indenting when a parameter consists of a long method call itself), etc. You can cover the majority of cases. Examples are helpful.
This:
return calculateFirstPart(commonObject, dataObject) +
calculateSecondPart(commonObject, aDifferentDataObject);
instead of this: return calculateFirstPart(commonObject, dataObject) + calculateSecondPart(
commonObject, aDifferentDataObject);
This: computerExplainToMe(
"Why are all my identifier names are so long?",
currentKnowledgeEngine.selectedExplanationType,
KnowledgeContext.getContextForEngine(
currentKnowledgeEngine, Language.English),
"Why is this parameter here. I don't even know what it does")
instead of this: computerExplainToMe("Why are all my identifier names are so long?",
currentKnowledgeEngine.selectedExplanationType, KnowledgeContext.
getContextForEngine(currentKnowledgeEngine, Language.English), "Why " +
"is this parameter here. I don't even know what it does")
The thing about long lines of code is that they almost always contain multiple ideas compressed into one (variable assignment, retrieval, lookups, conditionals, etc). In most programming languages we could put the whole program on one line if we really wanted to. When I see a line that is > 80 characters it makes me think I should be breaking that line up into multiple statements anyways, but depending on the language we may be saving ourselves some boilerplate or sometimes actual resources by putting it all in one line. So intelligent linebreaks are a good compromise in my opinion. We can still separate the individual expressions into readable chunks, but keep the whole expression more tightly packaged (physically and mentally) than it would be if we broke it out into multiple statements.Just for fun, here is maybe a better way to write that second one:
cookies = responseObject.headers.
findAll { header -> header.key == "Set-Cookie" }.
collect { cookieHeader -> new Cookie(cookieHeader) }This potentially leads to people simply breaking in an arbitrary place, making code less readable than without a break.
(Last example does look better. :))
Having a consistent width also means not having to rely on a randomly chosen width of the editor and then have random wrap-around code or having to resize the window horizontally or scroll horizontally when also scrolling vertically.
Most good editors will handle well multi-line splits. I use emacs I know it does, it would be silly to use MS Word to edit code.
When I started out I didn't follow the 80 column rule it is something that came with experience (also being able to afford a better monitor, paradoxical perhaps, but once I could open two windows side by side, I wanted to be able to not having to scroll either horizontally).
Personally, I prefer the 120 characters per line guideline. Most code I see starts looking very ridiculous when trying to accommodate the 80 characters max width, and it starts becoming hard to follow lines when exceeding 120 characters. So, to me a soft 120 characters guideline is the nice medium between the fact that it's no longer 1980 and the need to make lines easy to read.
Also, in most cases readability has almost nothing to do with line width (in fact it can suffer greatly from too much line breakage), and everything to do with how the programmer chooses to structure their code, aided by language idioms.
Just for comparison, I'm reading your comment at 140 characters width and I don't have much problem with that. I like my web text to occupy most of my screen. Only if I stretch it across multiple monitors to 160+ chars per line does reading become a chore.
But it is a personal taste.
With the project side panel open enough to see most of the project's directories it uses ~370px. The minimap (which I do leave open, and use, often) takes up ~50 pixels and the scroll bar for the edit window a final ~20 leaving me with 840 pixels that can show just at 100 columns. If I kill the minimap I get almost exactly 120 cols.
For me, I have no qualms about 79 cols for the limit and enjoy being able to use my windows split to half the screen and still have some breathing room around the right edge of my code. I also find it awkward to scroll horizontally to see what's going on in a long line.
This "hurr durr, we aren't on terminals anymore" argument is dumb. You aren't arguing with crotchety old geezers or people with stupid hardware choices. Quit assuming the people who disagree with you are idiots.
The other problem is that 100+ column lines are just flat out hard to read. It's hard to follow text that far across these screen. A few years ago when I was working with Objective-C I came across methods used with each variable on one line and really grew to like that.
It's similar to the way source code is laid out in books. But is that because the code is more readable that way, or is it a consequence of the layout? Books are taller than they are wide and usually have generous margins.
I do my best to keep it between 80 and 100 chars. With a horizontal screen resolution of 1920 pixels, 2 pages of such code fit nicely side by side.
But seriously - I guess there is some workflow where you would like to have 3 files side by side, but I certainly have never felt like that is something I need. I would much rather have readable, verbose variable names, which I have found to be the first thing to get axed in an 80 char column setup.
Having to go beyond about 85 characters is a good indication that you probably need some refactoring in your python code. As the idiome states, "Flat is better than nested."
Your if, in an if, in an if, in a for, in a method, in a class is probably complete garbage. Even in other languages, if you are so nested that you legitimately need 120 characters then you likely need to refactor. Your code that is nested to oblivion will prevent anyone from being able to give you a thorough code review which opens you up to unnecessary risk.
I love Python, but programming languages don't have "zen," and reality is never so ideal that an 80-character line -- in and of itself -- can ever be assumed to imply anything useful.
I used to work on some code that did a lot of subgraph matching. Subgraph matching in general is computationally expensive, so ideally you do it heuristically, searching for more likely elements of the subgraph you’re looking for first so you can skip over edges/vertices that have no potential as early as possible. Even then, if you’re looking for a complicated subgraph then you’re going to have a bunch of conditional logic that runs lots inside deeply nested loops one way or another.
That kind of code is often unwieldy, simply because the algorithms it implements are unwieldy. However, arbitrarily factoring out some of the inner levels into separate functions, which might have little meaning in themselves and little potential for reuse out of context, just means when you’re trying to review/update the code you need to look in more than one place to find it. On top of that, you’re also incurring a bunch of relatively heavy function calls (many parameters might need to be passed in for context) right in the middle of deeply nested code or you’re trusting your optimiser to inline them reliably.
So these days, whenever I see someone quoting dogma about how more than n levels of nesting are bad and your code needs refactoring if you hit their personal arbitrary limit, I cringe a little inside. Not all real world algorithms fit neatly into a dozen lines of code and a level or two of looping.
But I never ran across anything I couldn't make decent inside those 80 characters.
The other rule that I personally ignore, and when I'm managing a project I have my developers ignore, is the suggestion to use spaces instead of tab characters for indentation. Of course, with Python, you must use one or the other, but I prefer tabs.
In both cases, it comes down to my belief that individual coders should have the ability to customize their experience without forcing it on everyone else. When you use spaces instead of tabs, and indeed, when you use line continuations, you're forcing your (the author's) exact view of the source code on everyone you're working with. If you use tabs, and don't use line continuations, others with specific needs (2 character tabs, 4 character tabs, 8 character tabs, 60 character-width editors, 100 character-width editors, etc.) can, with any modern editor, customize their view (using variable-width tab stops, and soft line wrapping) to what they're comfortable with.
One observation is a fixation on horizontal space never on vertical. If you can't make sense of the big picture without scrolling vertically then you're probably doing it just as wrong as requiring horizontal scrolling to see the little picture.
Two interesting analogies:
RISC vs CISC. Doing something RISC like with simple little operations but the order and block control are super important? Go "RISC" landscape mode. Doing something ridiculous complicated at the operation level? Go "CISC" portrait mode and only do one "weird thing" per line.
Another interesting analogy is I've been in this game since 1981 and the physical display ratio has consistently gotten shorter and fatter every year (kind of like my body, sorta). Like it or not, the style trend is that someday our display hardware is only physically going to be capable of something weird like 800 characters across and only 8 lines up and down. You might have a 10 inch tall display but if 6 vertical inches are taken up by window bars and tab bars and ribbons and 25 toolbars and a bottom status bar, well you're only getting 4 vertical inches. Doesn't matter much if you like it or not, you'd best get used to it as styles don't seem to be changing, not even the 1st or 2nd derivative of the ratio over time...
On a semi-related subject, what about the vertical limit of the code? I often heard that a function should fit in one page, but that also depends on the screen resolution. Also, the 80 chars rule would increase the amount of line instead. How do people deal with that in general?
This limitation seems fairly language specific, and has a lot of side effects for the rest of your style guide.
For those using vim, I use this snippet to automatically split my window at startup:
set colorcolumn=80
is another nice way to keep yourself within the bounds, it also has the bonus of not being a hard limit, just a visual indication that you're oversteppingedit: (already mentioned)
:set cc=81
to mark the 81st column and visually nag when you go over 80 charsIf you're having trouble fitting two 100 character wide files side by side, there's two things you need to do:
#1 - get a screen with a decent resolution. 1920px wide should be standard for any developer worth his salt. Yes, this means "don't develop on a 13 inch laptop screen"... you're a developer, this is the main tool to do your job, make it a decent one.
#2 - use a real font. Courier New (or whatever the corollary is on Linux/OSX) is not a real font. I prefer proggy fonts (http://www.proggyfonts.com/index.php?menu=download)... they are incredibly more compact and still very readable... you get significantly more characters on the same line.
I anyway use the same setting when I use a laptop, though is not my main workplace.
When I work on a codebase with formatting standards I try to follow them. This is 2013, though, and when I work on my own stuff I format it to get the most readability on my Macbook or 32" 1080p desktop screen, not a VT100 from 1987.
And then someone working on your code on an eeePC will have a great time!
Makes the code harder to read
> enable word-wrap
Makes the code harder to read
> buy a higher-resolution display
Increases cost and I can't take an external on the subway/train.
> use your IDE to auto-format code according to your preferences
So, make it 80 to 120 chars per line myself
> I don't really see anybody using eeeePC for serious coding in 2013.
Because the year means sooooo much. Who are you to choose when and how I code.
I'm asking the same question when 80 chars limit is enforced on me.
Because of Python's significant indentation is exactly why I can't stand 80 char limit. Breaking lines, causing "false" visual structure destroy's Python's readability.
Seeing more logic vertically is far more important than horizontal.
I've been on teams that choose horrible names, used strange constructs, etc. just cause they fit on 80 char. Also wasting huge amount of time getting shit under 80char. Oh, and 80 char leads to people using import from over import (to avoid fully qualified names), which introduces bugs (name conflicts) and tons of confusion / lookup time wasted figuring out "process" is from some.lib and is not local,, or the one from some.other.lib
I would favor splitting only if you're indenting to line up with the first couple of tokens. In those cases the pattern is obvious as soon as I start reading, and my brain switches to scanning vertically. I find it jarring to have to switch from having read most of a line to suddenly scan vertically.
It seems like the example doesn't demonstrate the point that precedes it at all. Apparently in this example an 80 character limit doesn't promote re-factoring, it promotes splitting lines. Which makes the justification for 80 characters being a typical line length + 4 indentations a bit weak and 80 is back to being arbitrary.
But I do like the loop split better than the non-split, despite the above.
I like the smatch split too. It looks like how you'd arrange bullets in a bullet list, one below the other, so you can see/scan them at a glance, without having to labor over where the next item is in a single line.
I stick to 80 chars 99% of the time because long lines are more difficult to read.
But if a line ended up being 84 characters wide I wouldn't go replacing variable names or hacking a single function call onto multiple lines to fix it.
No one has died yet :-)
The main reason I hate it is pretty simple: I think it encourages using cryptically named variables. I find that using properly descriptive naming often leaves lines around 90 to 100 chars, particularly with 4-space indents and several arguments or a chained call. I also don't find the suggested practice of implied multi-line via unclosed parens leads to good readability in many cases.
That said, I agree there should be some limit. My usual practice is to set it at 120 chars, though I find it rare for a line to exceed 90 to 100 chars.
Also, I believe that text editors are generally catching up in this regard and doing a good job of intelligently indenting code that wraps over multiple lines. This means you can choose an editor width that suits your needs rather than having it dictated by someone's arbitrary choice.
I use a vim colorcolumn at 80 characters as a soft limit, but the hard limit for my projects is at 100 (or 99, to be exact). This has proven to be a nice guideline to write readable code, versus the 80 hardlimit that forces you to write short code (which sometimes is less readable than a clean & clear line with 90 characters).
And that isn't nice.
result = [something(value) + value * 2
for value in values]
I mean, I prefer one line, but if it has be in two (or more lines), I don't see the problem really result = [something(value) + value*2
for value in values]
I find indenting the subcaluse makes my eye flow naturally over the code. I'm normally doing this in perl, and often end up with functionalish code that looks like my @result = map { something($_) + $_*2 }
grep { valid_candidate($_) }
@all_candidates;
but the same principle seems to apply nicely to both languages.That being said, as with all things(especially guidelines), apply common sense liberally. Which in Python is one of the guidelines of pep8 on writing readable code.
An "80 char/line" guideline is nice for that.
There are modern options though:
1. Disable unnecessary stuff on your IDE. 2. Don't use a IDE, use a dedicated editor. 3. Don't use an editor from a VGA console. 4. Stop pretending you code on a vt100.
I see no wrong with a sensibly long line which is longer than 79, just as I see no wrong in keeping multiple parts of code visible at all times. There shouldn't be hard limits or carved to stone guidelines.
>Functions should be no longer than 60 lines of text and define no more than 6 parameters. [Power of Ten Rule 4]
>A function should not be longer than what can be printed on a single sheet of paper in a standard reference format with one line per statement and one line per declaration. Typically, this means no more than about 60 lines of code per function. Long lists of function parameters similarly compromise code clarity and should be avoided.
>Each function should be a logical unit in the code that is understandable and verifiable as a unit. It is much harder to understand a logical unit that spans multiple screens on a computer display or multiple pages when printed. Excessively long functions are often a sign of poorly structured code.
Having said that, whenever this topic comes up, we always seem to fall into the same trap of comparing one dubious representation (very long lines) with another (awkward breaks to avoid crossing an imaginary limit). Beyond a token comment on not nesting too deeply, and a token reply that sometimes deep nesting really is tidier than artificially separating the inner levels somehow, we rarely consider whether what we’re representing is fit for purpose. Does it really make sense to take the basic syntax we use for short expressions like
short_name(easy_param, other_param)
and try to apply it to longer expressions like full_project_name.useful_package_name.handy_function(first_param,
second_param,
third_param)
or something more complicated than a single function call? This leads to a debate where the most radical alternative proposed might be something like full_project_name.useful_package_name.handy_function(
first_param, second_param, third_param)
If you look at well typeset mathematics, which suffers a similar problem of scalability, there are often (at least) two different conventions for representing the same mathematical expression. For example, maths set using the TeX family probably has one version designed to read neatly in-line with other text, but another version designed to be clearer when set as a standalone display that might cross several lines.There are many tools for tidying up those displays, aligning things in logical ways. There are also conventions for breaking expressions too wide to fit on a single line, and sometimes those conventions do opposite things when setting an expression in-line to in displayed form, for example when deciding whether to leave a trailing + at the end of one line or move it to the start of the next. There is also a general idea that if you’re dealing with a lot of expressions that don’t fit, you should be looking to define self-contained parts of those expressions separately, and incorporate them indirectly using a more concise notation within the larger expressions. There are even subtle cross-references like numbering the key equations (only) and then adding a note like “by (1) and (2)” in the margin to help the reader navigate a complicated series of results. All of these ideas fit within the broader typography of setting a paper or thesis, where you still want good general readability in terms of (physical) line lengths, numbers of columns, use of tables, positioning of displayed content, and so on.
In programming, we have some of the same basic ideas, particularly separating out smaller parts of a larger whole as separate functions or variables for exposition, but we haven’t really developed the same depth of typographical conventions. Almost everything is based on the idea of taking that basic syntax that works on a single line for relatively short expressions and trying to make it work for arbitrarily large expressions across many lines with nothing but a line break and fixed tab/space characters as tools.
I think this is partly because our text-based editors typically don’t separate the meaning of our code from its layout. Even ideas like elastic tab stops, which might be everyday alignment tools in programming languages that use meaningful indentation, are still esoteric. A few functional languages promote ideas like “let x in y” or “x where y” syntax to help separate out subexpressions, but on the scale of functions separation implies creating a new self-contained function to do part of the work, which comes with its own scope, which means explicitly passing values in and out when they were already conveniently available in the all-in-one function.
I don’t see the controversy over X characters per line limits going anywhere until we get over these more fundamental problems of conflating code layout/presentation with code meaning. We need to be able to express the ideas in our programs systematically and have our editors and diff tools and code review software present those ideas in a suitable layout that adapts to both the idea itself and its context. Sadly, that’s not going to happen as long as we keep asking questions like how wide a tab stop should be, and not asking questions like whether we should even have tab stops at all.
Now it depends on languages, I am thinking of Python, C and Erlang here.
If you use too many:
full_project_name.useful_package_name.handy_function(...)
is there a way to alias it to a function local name such as my_handy_function = <the above>. Maybe there isn't (again it depends on language here as well).> I think this is partly because our text-based editors typically don't separate the meaning of our code from its layout.
You need a better editor. That is a solved problem. I like emacs the best. I imagine vi is just as good. It knows how to indent code based on the semantics. It knows you are in the middle of the list or just started a code block and does the right thing. (And I don't mess much with the default, an editor that does most thing reasonably form then on I assume whatever else it does to my code is now the new "right thing").
> A few functional languages promote ideas like “let x in y”
It kind of proves my point -- if you have functions that are going past the end of the screen, you need to think a bit about the code (also of course depending on language here, but most languages allow this). Break it up into functions. For functional languages like Erlang, they really encourage short functions that are 5-10 lines long. Use function clauses and pattern matching (with guards) to lay out the logical structure and so on.
I agree, though of course a single function call is a trivial example. It would be nice if we made more use of intermediate variables for exposition to simplify complicated expressions more generally, too. But somehow this sort of idea rarely seems to get promoted whenever long lines come up in discussion. :-(
You need a better editor. That is a solved problem.
I respectfully disagree. Current editors, even the most flexible, rarely do more than automatically sorting out line breaks and indentation, and rarely provide more viewing options than collapsing blocks and jumping around to one cross reference or another. I am challenging the assumption that even the same symbols in the same order are necessarily appropriate in different contexts.
I think there is a parallel here with the idea that a variable or function name can be relatively short if it’s only used locally with the full context available, but it might be better to use a longer, more detailed name or to add full qualifiers like which package/module/scope the entity lives in if it’s going to be used more widely. This is a simple case of adaptation that many programmers would apply instinctively, but it illustrates the basic principle that using the same name/representation for an idea regardless of context isn’t always helpful.
Break it up into functions.
But at the moment, breaking something into functions for ease of presentation typically equates to breaking something into functions to establish an independent scope, to allow wider reuse, or for other non-presentational reasons.
For example, most languages offer no way to break down a moderately long pipeline algorithm into stages without separating each stage into its own function, complete with manually passing all of the context in and passing all of the results back. If many stages depend on much the same general context for that algorithm and the stages don’t make much sense outside of the algorithm as a whole, might we not consider some sort of lightweight, presentational way to split things up for better readability, without implying all the side effects and maintenance overheads of full functional decomposition?