Live data from Hacker News

How to reduce the cognitive load of your code

chrismm.com

211–220 of 239 posts

Re: How to reduce the cognitive load of your code

#211

Earlier quoted context omitted.

When you're really good, you learn to FIX IT NOW while also not making a hack. Your code becomes flexible enough to handle that kind of change.

You can't anticipate every emergency change required to the codebase. Sure, you can make some intelligent predictions about certain points in the code and encapsulate possible changes but it's impossible in the general case. Trying to code to future possible requirements is often far more harmful because of over-abstraction than occasionally having to perform a quick hack and then fix it later.

Yeah. It's a balance between "build as little 'framework code' as possible;" and "build the framework as you go."

I say 'framework code' but it could be called structural code, or glue code or something, too.

Re: How to reduce the cognitive load of your code

#212

Earlier quoted context omitted.

When you're really good, you learn to FIX IT NOW while also not making a hack. Your code becomes flexible enough to handle that kind of change.

I'm not that good to pull that off with other people's code. :-)

Nah, you're good enough. If the code is bad, change your goal to "make it better than it was when I got here." That's something you can do.

Re: How to reduce the cognitive load of your code

#213
post #135

Earlier quoted context omitted.

When you're really good, you learn to FIX IT NOW while also not making a hack. Your code becomes flexible enough to handle that kind of change.

That's assuming it's your code. Most of the time it's not your code. While one would hope that the rest of the team writes flexible code as well, that's not always the case.

Then settle for making the code better than it was when you started working on it.

Re: How to reduce the cognitive load of your code

#214
post #203

Earlier quoted context omitted.

The problem is that the validateSortDisplayItems is some sort of public function. The caller doesn't care about the validation, only that the items are sorted. All kinds of functions everywhere validate their arguments; that doesn't deserve to be in their name.

The question is why you need a helper function? IMO, public functions are a special case and your generally better off using different naming schemes for internal and external functions. Granted, if it's pure pass-through then reusing the name is a non issue. Foo(x){foo(x);} is not confusing. Foo(x){junk; foo(x);} is. One option is Foo(x){validateForFoo; ValidedFoo(x);} Alternatively for private functions JunkFoo(x){…

The computation represented by "foo" could actually not be contributing any new semantics to "foo". It could just be some boiler plate that is needed to extract and isolate various resources out of context "x", so that these pieces can then be passed to the low-level "foo", which knows nothing of the aggregate "x". "junk" could be some locking an dunlocking, or debugging, or preparing the display in some way or whatever.

If someone wants to know how to name the low-level helper which does the real work and the interface over it, we just have to take it for granted that the separation is necessary and that it makes sense for either function to have the name "displaySortedItems" or whatever.

Re: How to reduce the cognitive load of your code

#215
post #84

Earlier quoted context omitted.

It's the difference between, say, length(foo) and foo.length() - any difference in cognitive load should be lost in the noise next to "this variable can be null". And given most languages in use today use = to mean assignment instead of equality, it's hardly "no reason".

Except if you do if(foo = null){} it won't compile in java which is exactly what you want to happen. So using it in java is just cognitive load and provides 0 benefits.

Habits are hard to break. Switching back and forth between habits leads to mistakes. There's a trade-off here. I'm not going to say one is definitely worth it vs. the other, but if we pretend the disadvantages of one option don't exist, we lose the ability to make appropriate judgements.

Re: How to reduce the cognitive load of your code

#216
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…

A convention I've seen in Java libraries and that I'm fond of is:

  public sort() {
    preconds()
    try {
      doSort()
    } catch (ex) {
      handle(ex)
    }
    postconds()
  }

  private doSort() throws Exception {
    // core impl
  }

Re: How to reduce the cognitive load of your code

#217

Earlier quoted context omitted.

In modern type systems (Haskell, etc.) you can define a new type that wraps an existing type with zero runtime cost. In Haskell you could write newtype UnsafeString = Unsafe String (UnsafeString is the name of the type. Unsafe is the constructor you use to create an UnsafeString from the String). With this and other techniques you can lift these characteristics of you data into the type system, which is IME much more…

I don't think the Haskell typing system is powerful enough for completely replacing prefix labels. Marking something unsafe is a best case scenario. Separating lines from rows would require a huge amount of boiterplate to preserve the numeric operations, and one still can not create a library that will check something like: let l = 5 :: Meter w = 4 :: Newton in l * w :: Joule

Representing constraints in the type system is always an engineering tradeoff---how much type level machinery do you want to build vs the effort required to build that?

Not sure what you mean by separating lines from rows. In the example you give of computing with units, I've seen examples of such systems in Scala (e.g. http://www.squants.com/) and F# comes with something built-in for this (IIUC). You might be interested in checking them out; it's quite neat.

Re: How to reduce the cognitive load of your code

#218
post #180

Earlier quoted context omitted.

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"?

Being a pessimist I consider it immoral.

Re: How to reduce the cognitive load of your code

#219
post #86

Not sure I can say I always write clean code but when I do, in non-trivial cases, I often start to write a comment, delete it and replace the code I wrote with something that does not need a comment... I suppose it only works for people who (think they) know(s) what good code looks like, but (I think) it works as a good guiding principle (for me).

This is one of my guiding principles too. If I find myself wanting to comment the code to make it clearer or understandable, I refactor the code.

The one time I let comments slide is when they document unexpected and unavoidable behavior that I can't fix in code. For example working with an inconsistent data set and having to add some convoluted code because what is a string in 95% of the rows might parse as a tuple in the remaining lines, so I need to account for that. This is so that I, or the next guy, knows why the code was written as such and won't go off trying to fix it.

Re: How to reduce the cognitive load of your code

#220

one programming style that i think makes things worse is the "how many calls can i make on a single line" programming style. MyObjecter.GetObjectRelatativeThingy(ThingyHolder.WhatsMything(IndexKeeper.Get(), OtherWhatsIt.BuildOther( MoonCheese.Intensify(true))) It's probably a result of the letterbox effect of widescreen monitors and IDEs with horizontal toolbars and status bars. Is there anything wrong with expanding…

I like Raymond Hettinger's idea of one concept per line. Sometimes that means having two or even three functions on a single line, sometimes one.
Post reply on HN