Live data from Hacker News

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

chrismm.com

71–80 of 187 posts

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

#71
post #43
post #39

Earlier quoted context omitted.

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…

Good point. I've been writing a lot of coffeescript recently, and the `is` operator insulates me from that whole situation. re [1] - javascript isn't the only language == isn't bad and wrong everywhere!

Ok, this explains a lot.

What you are seeing is people taking specific C codying styles into other languages. This is a cargo-cult style and probably in detriment of your code base.

On the other hand, it makes perfect sense in a C code base. The purpose of this is to transform a semantic error into a syntactic error. In C, both this expressions are legal but semantics is different:

if (A == B) //Compare B to A, decide on boolean result

if (A = B) //Assign B to A, then cast B's type //into a boolean value (non-zero true, //zero false) and decide on that.

In theory, it should be possible to identify every instance of A=B, but then it is hard to tell if it is a typo or the actual intention of the original programmer. If you compound this with the tendency to write complicated code, you find monstrousities like this one:

if (!A & B = C == D || E == F = G)

I am sure there's a language lawyer that can tell you for sure that the above means. I, on the other hand, can only be sure that this will compile as long as B and F are L-values.

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

#72

Earlier quoted context omitted.

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.

But on what object? The fact that calling .MoveTo(10, 30) would return the same object it has been called on, and not, for example, a handle to created movement animation, is not exactly obvious. Modern pattern of methods which just return the objects that they've been called on, by default seems to be very trendy, but I fail to see how is it helpful.

Er... on the window, as the indentation and API tells you.

It may be "not exactly obvious" to you, but having been doing GUI programming for a long time, this makes complete sense to me. It is also, of course, a matter of personal style and preference.

(Aside: some friends tell me, a vi user, that the way Emacs works is obvious. I disagree, but then, I don't use it).

And as for "modern"... I've been using this since C++ gained references.

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

#73

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…

When learning C in college, I was specifically taught to use CONTSTANT == variable. Accidentally omitting a '=' is common and putting the constant on the left side ensured the compiler would catch the mistake.

I would argue that by using CONSTANT == variable, you are reducing the cognitive load of the compiler, but increasing the cognitive load of the human reading the code (who has to mentally flip the expression around). I think the original article intended to say the same thing.

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

#74
post #73

Earlier quoted context omitted.

When learning C in college, I was specifically taught to use CONTSTANT == variable. Accidentally omitting a '=' is common and putting the constant on the left side ensured the compiler would catch the mistake.

I would argue that by using CONSTANT == variable, you are reducing the cognitive load of the compiler, but increasing the cognitive load of the human reading the code (who has to mentally flip the expression around). I think the original article intended to say the same thing.

Thats just what you're familiar with.

I find it perfectly natural to read "if 5 == x:" without having to flip it around.

(And it's not about "cognitive load" on the compiler, it's about fail to error not fail to silent success.)

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

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

This is much easier to debug. You can look at the state after each step.

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

#76
post #29

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 love chaining, but one verb per line. Instead of something like Me.getFish.skin.debone.flour.salt.fry.eat It would be something like Me.getFish .skin .debone .flour .salt .fry .eat I find this more readable than doing it without chaining like this: fish = Me.getFish fish.skin fish.debone fish.flour fish.salt fish.fry Me.eat(fish)

I find the version without chaining easier to debug.

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

#77
post #73

Earlier quoted context omitted.

I would argue that by using CONSTANT == variable, you are reducing the cognitive load of the compiler, but increasing the cognitive load of the human reading the code (who has to mentally flip the expression around). I think the original article intended to say the same thing.

Thats just what you're familiar with. I find it perfectly natural to read "if 5 == x:" without having to flip it around. (And it's not about "cognitive load" on the compiler, it's about fail to error not fail to silent success.)

Agreed. I think the key here is that consistent exposure over time to patterns reduces cognitive load through "chunking".

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

#78
post #60

Code Complete is an old book now. Is it still good advice? In my new project I see a lot of code like below. I hate it but I'm not sure if I'm old fashioned or correct in thinking it should be 4 or five lines. Should I reject a code review for stuff like this? return (HadoopSummary)ScopeCoordinator.getInstance().findObject(Scope.getFirst(), new Path (SCOPE_PATH.split("\\.")));

I still hear recommendations for Code Complete so I assume it's still useful, but haven't read it myself. A somewhat old book I like is Working Effectively With Legacy Code, I think its main premise and prescriptions can help a lot of codebases out there even if not all of them, especially those in functional languages. (Namely, your codebase will be better the more you get it under test and the more you leverage OOP design principles.)

Your code snippet looks like normal Java code to me. :) Not great that it's so common but it's at least not unusual... Being one line or more lines for that piece of code doesn't really matter to me but I'd prefer the single line in this case: I'm viewing it in an IDE, I've got more than 80 columns, and the pieces of syntax are easy enough to spot I don't need vertical cues. (Unfortunately rainbow parens still seem to be a minority preference.)

My own quick context-free review of that: is it testable in junit? Can you substitute a mock (without using something like PowerMockito) for ScopeCoordinator.getInstance() and for Scope.getFirst()? May be better to make the instance a member variable that you can mock by just passing a different one in the constructor. Why is it Scope.getFirst(), unless this method is explicitly about finding the first of something so it's clear in context? For the 'new Path(SCOPE_PATH.split("\\."))' part, that looks like it's going to be the same every time and not dependent on any runtime code so why not make it a static member? (Or an instance member you can mock, or maybe the enclosing method can take a Path as an optional param with the default being the static one.) Can the design be redone to avoid the type conversion or is it too late?

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

#79

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.…

We've been refactoring and decoupling code for decades in imperative coding styles. I think one of the problems we have as a community of programmers is the concept that it must end up in a ball of mud. Almost all of our extant systems are developed in imperative style. The system I work on today is many orders of magnitude larger than the systems I first learned on and yet it is dramatically easier to write useful code. That's because over time, we have extracted and polished functionality into useful and unambiguous pieces.

Back when I was a young programmer it was often said, "If you don't have time to get it right the first time, how on earth will you have time to do it again?". To me, this concept is why we get into the ball of mud. It will happen to you no matter what style of programming you choose, because you can't get it "right" the first time. You don't know what "right" is. Because we resist the rework/refactoring, we build balls of mud. We even blame it on the people before us "who got it wrong" (which is easy to do because average attrition is about 2 years and they've likely left the company).

I like functional style as much as the next programmer (well, probably more than most in fact), but FP isn't going to save you in this instance. The only way to maintain high levels of productivity in projects is ruthless rework in the face of changing requirements.

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

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

I disagree. You've created a variable for no reason. I hate having more variables than needed. I have to worry about things like its scope, its mutability, anywhere else it might be used, etc etc. It's pointless to me.

Like another poster below, I do agree you should spread that out over a few lines though:

    window
        .FindCanvasForObject(obj)
        .Color(RED)
        .MoveTo(10,30)
        .LineTo(50,20)
Post reply on HN