3 ms·
I agree completely with the author that readability is paramount and artificial limitations are often questionable. Having said that, whenever this topic comes
by Chris_Newton 14y ago
I agree completely with the author that readability is paramount and artificial limitations are often questionable.
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.
- rdtsc 14y agoNot being able to fit the code in 80 columns easily (for me at least) is a smell test for potential problems code. 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.
- Chris_Newton 14y agois there a way to alias it to a function local name such as my_handy_function = <the above> 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?