Live data from Hacker News

How to reduce the cognitive load of your code

chrismm.com

171–180 of 239 posts

Re: How to reduce the cognitive load of your code

#171
post #162

Earlier quoted context omitted.

One approach that can help is to name things based on what the functions actually do. validateSortDisplayedItems { validation Logic ... sortDisplayedItems(); //Actually sorts items. } This can be harder to maintain, but really long names end up a useful code smell.

I find it a bit...incorrect. I mean, your above code LIES. If I call validateSortDisplayedItems, I don't validate, I validate AND sort. Plus, what do you do if you have "validateItems" and "sortItems", and then one function that calls them each in turn? call it "validateAndSortItems"? Yuck.

Depends on the Validation Logic. I like the style that basically works like this:

  validateSortDisplayedItems
  {
   if(!DisplayedItemsValid())
   {
     CorrectDisplayedItems();
     if(!DisplayedItemsValid())
     {
       DisplayValidationError();
       return;
     }
   }
   sortDisplayedItems(); //Actually sorts items.
  }
AKA validate means try and make valid, not verify that data isValid. So, you can't just do if(isValid) sort; the bonus is unrecoverable errors end up at leaf nodes vs. the happy path.

At the high level, your function might be sortClicked, which can then respond to that by calling a wide range of functions. (userCanSort,SortData,UpdateDisplay)

PS: I find the validate > correct loop is generally the important and error prone part of code, so I give it priority. The happy path where everything works is more or less an addendum.

Re: How to reduce the cognitive load of your code

#172

Earlier quoted context omitted.

It doesn't really sound like the same thing I'm talking about, to be honest. And I find the idea of a tool that automatically rewrites machine readable code into a natural language to be of dubious value beyond use cases where someone is first picking up the language. Similar to those tools that exist to generate comments in the form "Set global position" based on a method named setGlobalPosition. It just creates red…

I think you might be misunderstanding what "literate programming" is. It's a method of programming where you embed code inside English language documentation. The idea is to be able to present the documentation in a way that is useful to a human, but have the compiler extract the computer code and reassemble it in the way that the computer would like to see it. Literate coffeescript does not have the tools for extrac…

Sorry. I'm familiar with literate programming, but I mistook one of your statements:

> formats the output in a similar way - you have the english text in a pane on the left and the code in a pane on the right

... to be a description of a system that didn't really sound like what I had in mind, and didn't really sound like literate programming, either. After reading this comment and a reread of your original one, I understand I was wrong in my interpretation of what you meant. Sorry about that.

Re: How to reduce the cognitive load of your code

#173
post #47
post #21

No one ever mentions formatting. I really like aligning multiline blocks, adding whitespace and useless braces here an there. e.g: Having just a single space between function name and arguments makes it look less like a call. Yet almost all lint presets/defaults forbid this. Typography is all about the whitespace between letters forming easily recognizable shapes.

All this is solved by a linter though, there's no point even trying to remember this, just define your linter rules and let it deal with it. It might not be the default linter styles, but set up your linter for your project and give your mind more important things to focus on.

I didn't know linters had become so advanced. Can you recommend any which work on DSLs (including custom ones), and warn about 2D alignment issues? For example, here's some Nix code I have open right now:

     annotateAsts    = import ./annotateAsts.nix    { inherit stdenv annotatedb;    };
     runTypes        = import ./runTypes.nix        { inherit stdenv annotatedb jq; };
     dumpAndAnnotate = import ./dumpAndAnnotate.nix { inherit downloadAndDump;      };
It would be nice to have a tool rate various equivalent arrangements and warn if it finds one with a significantly better score, e.g. showing me the above if I'd given it something more confusing like:

     annotateAsts = import ./annotateAsts.nix { inherit stdenv annotatedb; };
     runTypes = import ./runTypes.nix { inherit stdenv annotatedb jq; };
     dumpAndAnnotate = import ./dumpAndAnnotate.nix { inherit downloadAndDump; };
Of course, as well as formatting it would be nice for equivalent representations of the same expression to be compared, e.g. using an SMT solver or genetic programming. For example, in Nix the variable names after "inherit" can be in any order, so it's easy to find permutations which highlight common elements (like "stdenv" and "annotatedb" above); if I'd written these in a different order (e.g. "inherit jq annotatedb stdenv;" on line two), it would be nice to be shown rearrangements which score more highly.

It's not just linters either. I can't even find an indenter which handles 2D alignment. For example, indenting something like (random bash code I have open at the moment):

    jq -n --argfile asts        
Emacs wants to put the second '--argfile' directly beneath '-n', which is clearly confusing compared to the above. If linters solve all typography issues, are there any which can be queried for the local-optimal indentation on a line-by-line basis?

Re: How to reduce the cognitive load of your code

#174
post #117

Earlier quoted context omitted.

Re: "null != variable": I don't think it's necessarily confusing, it's just that usually we tend to think of the elements we're working with (variables, objects, functions, etc...) as taking on values, and so linguistically, we ask "is my thing null?" Not, "is nullness something that applies to my thing?" Hence "thing operation value" is arguably cognitively cheaper than "value operation thing." So you could argue th…

I think the point was, that as soon as you are aware that typos of "=" and "==" are common, and hard to catch mechanically, the _habit_ of using the (constant == myvar) pattern can suddenly be seen as having more value as a hedge against human error. I'd rather write it that way, and then later change it in code review to `(myvar == constant)`, than risk writing it as `(myvar = constant)` and have it sneak through. G…

I would disagree that they are hard to catch mechanically. GCC will warn about it with -Wparentheses, which is included in -Wall.

Re: How to reduce the cognitive load of your code

#175
I've thought about this quite a bit from a language design standpoint. I've come to realize the following:

1) Reduce the number of variables that need to be kept track of in order to make a function easier to understand.

2) Avoid metaprogramming unless there is a clear need for it (doing something over and over).

3) DRY isn't always good. Sometimes being more verbose is easier to read than being clever so you don't have to type as much. Concentrate on readability first.

4) When there are a lot of interacting components consider the DCI pattern. It will save the developer from bouncing from file to file, module to module, just to understand the flow of an algorithm. Each time a developer needs to look up a different file more cognitive load is introduced. An algorithm should be easy to follow in a single file with code in sequential order. The opposite of this is message passing and having components pass messages to other components.

5) Syntax matters. Unfortunately once you choose your stack there isn't much you can do about this. Some syntaxes are much noisier than others. Every little bit of noise adds more cognitive load. Don't believe me, try do long division with Roman numerals.

6) Compress complex concepts into shorter ones. This builds on the Sapir-Whorf hypothesis. This might be a moving a part of an algorithm into its own function or storing an intermediate state in its own variable (as opposed to function composition 4 levels deep). `map` is much simpler to understand than `for (var i=0; i7) Spend time getting to know your editor. When you can reduce the amount of muscle movement required to perform an action it generally reduces the cognitive load as well. Not to mention making you more productive.

Re: How to reduce the cognitive load of your code

#176
post #154

Earlier quoted context omitted.

For me it's not that it's confusing, it's annoying to read because it indicates that the programmer didn't actually take the time to learn the language, and is instead writing it as C/PHP something else where expressions in if statements don't need to be explicitly boolean (the examples in the article are Java). If they wrote that, what else do they not understand about the language?

What if it is 0 but not null? I write in a few different languages throughout a typical week. It is nice to have some explicit statements when juggling between them. I know them very well, but it is still tricky when going back and forth.

That also wouldn't even compile. I also write in multiple languages, and for languages for which this is an issue I use a linter. This isn't even an issue in C if you compile everything with the appropriate flags (-Wall or -Wparentheses).

Re: How to reduce the cognitive load of your code

#177
post #27

There are so many similarities between writing code and writing English. - Thinking of paragraphs as functions with one purpose - keeping sentences short to reduce load on working memory and increase comprehension - create visual breaks to help the reader by grouping common stuff together as mini-functions - reduce intimidation factor of reading by removing convoluted stuff - remove cognitive noise (dead code, unnece…

I agree with everything you said. As an old Perl guy, I found it hilarious that Perl has a reputation for illegibility, while I find it easier to read than most Java, because in Perl I can express my intent, and in Java it's buried in the noise. One cognitive problem I've not yet found a good solution to: So I have a high level routine to, say, sort the items in a display. Said sorting has some cascading effects, so…

Make them separate functions each with their own local state or use namespacing. The problem sounds like too much state in a single algorithm. Break it down into subalgorithms each with their own state.

Re: How to reduce the cognitive load of your code

#178

I didn't appreciate how much of a difference it would make until I tried it, but now I know that one of the best ways of making code more comprehensible is to eliminate any questions about interactions between components by using a language with referential transparency. The results of functions should be determined solely by the values of their arguments, with no contamination by shared state and no side effects.

In other words, a pure function. https://en.wikipedia.org/wiki/Pure_function

In mathematical words, a function.

Re: How to reduce the cognitive load of your code

#179
post #43
post #19

Earlier quoted context omitted.

Most of the bad code was made by very productive developers.

This leads to the question what 'productive' really means. If a productive programmer writes a lot of code that isn't maintainable at all, can you really call that person productive? Maybe... but the poor sob tasked with maintaining the code later, will certainly not be called productive. Maybe productivity should not be regarded isolated from other metrics and/or certain style-considerations.

What is the true measure of productivity? If you include things like maintenance and other developers' time are they really being productive? There's individual productivity and team productivity. Also a quick one time job is different than something that needs to be maintained. Everything is relative to the goals.

Re: How to reduce the cognitive load of your code

#180

Earlier quoted context omitted.

In my experience, most bad code is written by dogmatic cargo cult programmers that are more interested in writing code that adheres to their pet development philosophy or framework instead of programming to solve a problem in the simplest way possible.

A fashionable framework on your CV will get you an interview, while claiming that the code was simple won't. It's as immoral as objective reality is.

That's quite poetic. But I assume you mean "amoral"?
Post reply on HN