Live data from Hacker News

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

chrismm.com

41–50 of 187 posts

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

#41
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.

I believe that's a declaration inside `if`. C doesn't support that, but C++ does. I believe in this case you can't actually put parenthesis around it.

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

#42
post #26

Earlier quoted context omitted.

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.

True. I was speaking of C++, which also accepts bool [0] (or more specifically, something that can be converted to a bool, which a null pointer can be [1]).

Actually [0] has a good example of when the if (Foo* a = ...) syntax is useful (dynamic cast)

[0] http://en.cppreference.com/w/cpp/language/if [1] https://ideone.com/im4uVn

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

#43
post #39
post #30

Earlier quoted context omitted.

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…

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!

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

#44

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…

This only a problem in dynamically typed languages.

Just so this is clear, in Java this pattern is very present, especially since Java 8 (Streams). Before that, there was the Builder pattern[1]. It's also present in C++/C# in the same form.

[1]: https://en.wikipedia.org/wiki/Builder_pattern

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

#45
At the risk of making too much over the section (and ranting risks in general :)) I get the sense that "Keep your personal quirks out of it" strays dangerously close to "don't learn anything new, don't encourage the team to do it either". Of course I agree with not being clever for the sake of clverness, and not going against the overall style of the team with your preferred style. But the article goes on:

"The problem is that people just want to fix their bugs and move on." Yeah, screw that, maybe if people spent some time learning better coding techniques they wouldn't have so many bugs? Take for instance this "trick":

    String blah = Optional.ofNullable(foo.bar()).map(Clz::doZap).map(OtherClz::extractZorp).map(OtherOtherClz::toString).orElse("");
The normal "just leave me alone and let me code and fix bugs and get on with life" equivalent is:

    String blah = foo.bar().doZap().extractZorp().toString();
Problem: any of those method calls can blow up with NPE, because they were written long ago by other not so careful devs and you can't simply rewrite. I see this all the time. Or a variant where foo.bar() is null-checked so they can call doZap(), but they still do (or edit it to do later) the rest of the chaining of doZap().extractZorp().toString(). When something inevitably does blow up, you get your bug to fix and then move on, but wouldn't it have been better to not have the bug in the first place?

It's not even that devs don't realize that code could blow up with a NPE, a lot of the time they do, they just don't want to do the ugly "solution" up front (that someone will end up doing when they fix the bug and move on anyway) of all the intermediary variables and if scopes checking for nulls (or a NPE exception handler in the middle of their logic) and convince themselves it probably won't ever be null. The Optional 'trick' lets them be lazy (low syntax overhead once you understand what map() and flatMap() can do) and safe.

Without even bringing up streams and lambdas, a nifty trick that appeared in Java not that long ago is the for-each syntax (which prevents all too easy to happen off-by-one errors in a loop counter). I keep up with language developments, I'm going to use new expressive capabilities in my code (when they're helpful -- again I'm on board against cleverness-for-cleverness'-sake) and anyone who has a cognitive load with it ought to learn it well enough so there is no load and we can develop more solid code. Ultimately I concede the point I've heard from Haskell or Scala advocates that as you practice all that Type power becomes less troublesome, I'm just not willing to invest the cognitive effort up front to get to that point since I think the tradeoffs aren't worth it for my use cases. The fact that I find a lot of Scala to be incomprehensible is a fact about my state of mind, not a fact about Scala or the developer who wrote the code.

In the end these aren't even huge issues. The worst bugs aren't often the result of presence/absence of good code or capabilities (security bugs are probably a big exception), they often happen before coding even begins and accumulate over time with more and more edits to a system without stepping back to see if the original design makes sense for the current system or whether we've been stapling things together. We focus too much on these small details about how it takes 30 extra seconds to parse a too-terse line of code that would have been easier to swallow if it was 5 lines and ignore the fact that we've got 30 classes for this feature (so modular and testable) that could have been done in maybe 30 terse lines of a more powerful language with perhaps some extra cognitive overhead upfront.

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

#46

Earlier quoted context omitted.

Everything is unclear until you become used to it, though. I mean, used to it, as in, you can read it without stepping yourself through the steps manually. And to a novice programmer, pretty much everything they come up against represents this. Turning five lines into one line with a reduce function sounds like a normal thing to do for experienced programmers, but to a beginner, they'll think you're a genius for poin…

You'll also find that some experienced programmers specifically turn 1 line into 5. It's the beginner that tries to create the 1 liner because they think it's genius.

One-liners are bad if they are obscure and experienced programmers know that. However I wouldn't go as far as say that experienced programmers don't use one-liners at all. As usual in programming, it's all about balancing clarity/conciseness.

For example, I find this much clearer as a one-liner (Python):

    validated_items = filter(is_validated, items)
rather than

    validated_items = []
    for item in items:
        if is_validated(item):
            validated_items.append(item)

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

#48
post #27
post #2

I don't understand the first example. if (null != variable) If this was C, it should be NULL, and it is almost always better to just write `if (variable)` to check for NULL pointers instead. If this was JavaScript, this check includes undefined too. Not sure why it didn't use triple equal. If this was just talking about placing a constant value to be compared before a more complicated expression, I really don't see a…

I'm the accidental maintainer/guardian/dungeon keeper of a bunch of scary code at work, which happily does: if (false != aBooleanVariable) I still can't parse that without stopping and thinking (and sometimes cursing the original author). To me, with booleans , this can only sanely be written: if (aBooleanVariable) Code with literals is often worse than functionally equivalent code without; literals are complexity. A…

I thought up at some point something like this:

    return (aBoolean != false) ? false : true;
So ridiculous that it made me laugh.

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

#49
post #5
post #2

I don't understand the first example. if (null != variable) If this was C, it should be NULL, and it is almost always better to just write `if (variable)` to check for NULL pointers instead. If this was JavaScript, this check includes undefined too. Not sure why it didn't use triple equal. If this was just talking about placing a constant value to be compared before a more complicated expression, I really don't see a…

To paraphrase the comment above that line, they say its purpose is to avoid accidental assignment. That's not an issue with "not equals" though, but that may just be their point. As for whether it's more readable, I'm skeptical: It may save you going through some of the condition, but I believe getting used to it would make you more likely to overlook parts of the condition. Plus, the way it reads is the opposite of…

To provide a different opinion, I'm not a fan of the macro NULL because the C spec leaves it rather open to compiler authors how to expand it. It says it must be 0, but they don't specify the type. It could be 0, 0L, (void*) 0, 0UL, 0LL, etc.

However, the spec does say that only the null pointer evaluates to false and all other points are true. So doing if(ptr) is much more well-defined than the NULL macro.

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

#50
It starts with picking the right language. Some languages help you to clarify your thoughts and some seem to do their best to obscure whatever meaning there was.

Then, after you've picked your language it's up to you, the programmer. And 'good code' to me translates into 'whatever is on the screen is enough to understand the code'.

If you have to page back-and-forth all the time between different parts of a function or between different functions or even different files then your code will be hard to maintain, hard to read and probably buggy.

So work hard on reducing scope as much as you can.

Post reply on HN