Live data from Hacker News

Writing good code: how to reduce the cognitive load of your code

chrismm.com

31–40 of 187 posts

Re: Writing good code: how to reduce the cognitive load of your code

#31

I like code that reads like a Dick & Jane book ("See Dick. See Jane. See Dick run. See Jane run."). However, it appears to be trendy to write insanely difficult to read code. To use the analogy, Shakespearean code. Instead of one line of code doing one thing the developers will write a ton of functionality into one line of code by using fluent and method chaining. As someone reviewing the code I have to keep this men…

I hear you. I don't like method chaining either. Instead of

    window.FindCanvasForObject(obj).Color(RED).MoveTo(10,30).LineTo(50,20). ...
I much prefer:

    o = window.FindCanvasForObject(obj)
    o.Color(RED);
    o.MoveTo(10,30);
    o.LineTo(50,20);
(Where, in C++ I would enclose this inside a { curly block } to give o the right type and make it local, and in Python I would add a "del o" at the end; and yes, I reuse 'o' to mean 'object' in these cases as much as possible, occasionally having "ox" and "oy" when I have x and y objects to deal with simultaneously).

I think it provides the fluency of method chaining with the readability of "standard" code, but this style seems to get scorn from both the chaining-loving people and the chaining-hating people. Oh well, different strokes etc.

Re: Writing good code: how to reduce the cognitive load of your code

#32
post #26

Earlier quoted context omitted.

I also don't understand this, nothing wrong about Yoda conditions and I don't understand the 'cognitive load' argument since the condition is just as readable. And: Visual Studio 2015 does not warn in the case of "if (a = 5)", not even at the highest warning level, only the VS2015 static code analyser catches this.

It also probably shouldn't (warn) if(Foo* a = GetAFoo()) { /* Do something with a non-null foo */ } is perfectly valid code.

Depends on the language, C# won't allow that, if's don't accept null, they accept bool.

Re: Writing good code: how to reduce the cognitive load of your code

#34
Whenever I read articles like this and the ensuing discussion that follows, I'm reminded of this quote from Dijkstra:

Don't blame me for the fact that competent programming, as I view it as an intellectual possibility, will be too difficult for "the average programmer" — you must not fall into the trap of rejecting a surgical technique because it is beyond the capabilities of the barber in his shop around the corner.

Dijkstra (1975) Comments at a Symposium

Whenever I read code written in the "so boring it cannot fail" camp I get exhausted. This code is inherently procedural and rolls itself into a giant ball of mud -- composition is difficult to achieve so as requirements change the code accrues more loops and conditionals until it is nearly incomprehensible.

It might start out neat and clean but rarely will it stay that way.

Good, non-leaky abstractions are key. This can even be achieved with procedural code but I think functional programming techniques like pure functions, immutable values, and a sound type system help a great deal... even at the expense of the initial "cognitive load," it takes to learn how to employ these tools.

Re: Writing good code: how to reduce the cognitive load of your code

#35
post #31

I like code that reads like a Dick & Jane book ("See Dick. See Jane. See Dick run. See Jane run."). However, it appears to be trendy to write insanely difficult to read code. To use the analogy, Shakespearean code. Instead of one line of code doing one thing the developers will write a ton of functionality into one line of code by using fluent and method chaining. As someone reviewing the code I have to keep this men…

I hear you. I don't like method chaining either. Instead of window.FindCanvasForObject(obj).Color(RED).MoveTo(10,30).LineTo(50,20). ... I much prefer: o = window.FindCanvasForObject(obj) o.Color(RED); o.MoveTo(10,30); o.LineTo(50,20); (Where, in C++ I would enclose this inside a { curly block } to give o the right type and make it local, and in Python I would add a "del o" at the end; and yes, I reuse 'o' to mean 'ob…

How about:

   window
     .FindCanvasForObject(obj)
     .Color(RED)
     .MoveTo(10, 30)
     .LineTo(50, 20)
This avoids the repetition of the local variable name, while still making it clear what's being called on the object.

Re: Writing good code: how to reduce the cognitive load of your code

#36
Hire programmers who can read.

Lines like "Don’t use tools that are still too hard to get a grip on" are code for 'your team will get discouraged if they have to do any homework at all to understand your project'. If that's true, how do you expect them to understand the business requirements?

Every large project has embedded tools and legacy tricks so the author is implicitly saying 'don't let projects scale'.

Simplicity is hard to achieve, and people who can't understand complex code can't write simple code.

If a book hits you on the head and makes a hollow sound, it may not be the fault of the book.

Re: Writing good code: how to reduce the cognitive load of your code

#37
post #30

Earlier quoted context omitted.

I can't up-vote this enough. As someone that started doing development in the late 80's, I find this style of coding to be infuriating. It completely destroys the ability to map lines of code directly to function calls without resorting to manual coding rules that require that each .function() be on a separate line, and makes debugging way harder than it needs to be. And, for what purpose ? To avoid a local, temporar…

To get you started, I'd like to compare my problems regarding `if = ` with yours. This assumes you aren't the kind of lunatic to actually assign a constant inside of an if's condition. 1. I can't articulate exactly why, but that should totally be flipped. The constant should be on the right side! `if(3.17 == possiblyPi)` would make me seriously question the author's motives. 2. It's personal preference, but in almost…

Sorry, I should have made it clear that what I posted was pseudo-code, so just assume that = is equivalent to == or whatever in the target language.

1) Yes, my issue was the constant being on the left side. I've seen it done a few times, and I'm sure it's probably just a "I did it that way when I first started and it stuck" or something similar, but it just never looks right to me. I just want to scream "But, you're comparing the variable !!!!". :-)

2) Constants are useful when there are going to be gaps in the values (message dispatch codes), but yeah, I also agree here - enums are always the way to go, if you can do it. Switches are also great, but can be problematic at times due to the way that they aren't always implemented in a consistent manner among various languages with respect to fall-through and breaks.

Re: Writing good code: how to reduce the cognitive load of your code

#38
post #31

I like code that reads like a Dick & Jane book ("See Dick. See Jane. See Dick run. See Jane run."). However, it appears to be trendy to write insanely difficult to read code. To use the analogy, Shakespearean code. Instead of one line of code doing one thing the developers will write a ton of functionality into one line of code by using fluent and method chaining. As someone reviewing the code I have to keep this men…

I hear you. I don't like method chaining either. Instead of window.FindCanvasForObject(obj).Color(RED).MoveTo(10,30).LineTo(50,20). ... I much prefer: o = window.FindCanvasForObject(obj) o.Color(RED); o.MoveTo(10,30); o.LineTo(50,20); (Where, in C++ I would enclose this inside a { curly block } to give o the right type and make it local, and in Python I would add a "del o" at the end; and yes, I reuse 'o' to mean 'ob…

Just to nitpick, those aren't quite equivalent. The second should be:

    o = window.FindCanvasForObject(obj);
    o = o.Color(RED);
    o = o.MoveTo(10,30);
    o = o.LineTo(50,20);
Which leaves more room for error in the general case - if the API gives you a new object each time, and you fail to assign it every time (or say you have multiple and get the letters mixed up, or you do this rarely and forget), you lose some of the config. It can be fairly easily missed in code reviews. When it's all chained together, there's only one possible interpretation if it compiles and only has one assignment.

But I can see where you're coming from. Chains can be abused rather horrifically. IMO part of that is because it's hard to make helper functions, e.g.:

    window.FindCanvasForObject(obj).Color(RED).MoveTo(10,30).LineTo(50,20)
    
    # plus
    def move_line(thing, start, end):
      return thing.MoveTo(start).LineTo(end)
    
    # leads to
    move_line(window.FindCanvasForObject(obj).Color(RED), (10, 30), (50, 20))
It breaks the straightforward left-to-right interpretation. So instead, people just make the chain longer and longer, forever.

(not as much of a problem with a language with open classes, but modifying existing classes for ad-hoc helpers is usually frowned upon too.)

Re: Writing good code: how to reduce the cognitive load of your code

#39
post #30

Earlier quoted context omitted.

I can't up-vote this enough. As someone that started doing development in the late 80's, I find this style of coding to be infuriating. It completely destroys the ability to map lines of code directly to function calls without resorting to manual coding rules that require that each .function() be on a separate line, and makes debugging way harder than it needs to be. And, for what purpose ? To avoid a local, temporar…

To get you started, I'd like to compare my problems regarding `if = ` with yours. This assumes you aren't the kind of lunatic to actually assign a constant inside of an if's condition. 1. I can't articulate exactly why, but that should totally be flipped. The constant should be on the right side! `if(3.17 == possiblyPi)` would make me seriously question the author's motives. 2. It's personal preference, but in almost…

I can't articulate exactly why, but that should totally be flipped.

Should it? If you accidentally use an assignment operator (eg = ) instead of a comparison (eg === )[1] with the constant on the left your code will throw an exception, which is what you want. If you put the variable on the left and accidentally use an assignment then you'll overwrite the variable with the constant value and return true, consequently executing whatever is in the block of code that the comparison is supposed to be checking for. You don't want to do that. That could be really bad.

[1] If you use == then you are bad and wrong.

Re: Writing good code: how to reduce the cognitive load of your code

#40

Whenever I read articles like this and the ensuing discussion that follows, I'm reminded of this quote from Dijkstra: Don't blame me for the fact that competent programming, as I view it as an intellectual possibility, will be too difficult for "the average programmer" — you must not fall into the trap of rejecting a surgical technique because it is beyond the capabilities of the barber in his shop around the corner.…

Meh. I think you're overshooting the runway a bit here.

I'm a functional coder and I like the idea of reducing cognitive load. The procedural guys use it in a different fashion but if you're writing code you can't understand after walking away for a few months and coming back? You're doing something wrong.

I don't think that relates to the abstraction or composability of your solution style. I find good naming, decomposition, and re-composition allows me to take things that don't matter and put them in a utility library somewhere. Then I'm left with a small number of new symbols and configurations that's easy enough to grok coming in cold. There are plenty of FP guys that don't do this. Hell if I'd want to maintain their code.

Post reply on HN