Live data from Hacker News

How to reduce the cognitive load of your code

chrismm.com

221–230 of 239 posts

Re: How to reduce the cognitive load of your code

#221
post #197

Earlier quoted context omitted.

I was having this dilemma on my walk home. I try to write good idiomatic Django code, and know how to make it efficient in the ways described in Two Scoops (a book about Django best practices). I have inherited an app, parts of which are exactly the opposite of Django best practices (thin models fat controllers being the most obvious one - the application's documentation says that's the philosophy , while Django enco…

I think the best practice is to just refactor the bits that you need to touch. At a minimum avoid leaving them worse, and in an ideal world leave each piece you touch better for your having looked at it.

Thats my plan, assuming i get the chance to.

Re: How to reduce the cognitive load of your code

#222
post #203

Earlier quoted context omitted.

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

If your stripping boilerplate then your operating on different things. Which seems more readable?

  SortGuiElement(){junk; SortUserNames(); junk;}
  SortUserNames(){junk;}
vs.

  SortNames(){junk; sortNames() junk;}
  sortNames(){junk;}
It might seem obvious and the code might be identical, but I see the second case very frequently in other peoples code.

Re: How to reduce the cognitive load of your code

#223
post #206

Earlier quoted context omitted.

Unit tests tell you what that small thing you did ages ago was meant to do, and what it does in different circumstances. If you have the discipline to thoroughly test your code(and the knowhow to not write brittle tests), it can really pay off.

>If you have the discipline to thoroughly test your code This isn't the issue. I, and I suspect many others, simply don't have time to thoroughly test code. It's the age-old issue of "Business doesn't rely on good code. It relies on delivering the product of that code." Up until the ship is both on fire and sinking - nobody cares about sailing a good ship. They'll settle for the shoddy lake boat and ride it out as lo…

I believe even in the short term, tested code gets done faster than non tested code, simply because you tend to waste so little time in trivial mistakes when you test. But it takes time to get to that point, and you don't get to practice testing because it's a new thing and learning it takes time you simply don't have, it looks like it will slow you down.

Re: How to reduce the cognitive load of your code

#224

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.

Think we all got different experiences there. My main problems have been with people who insist on just churning out features in the most straightforward way without doing any kind of upfront thinking. You end up with reams of copy past coding, code duplication and so much code that it is very hard to keep track of what is going on. Like e.g. if you are parsing a file, and it is complicated you can save a lot of time…

I am jealous of you. It is fairly straightforward to clean up quickly written, first version code. (In fact, this is probably the best way to develop, if you don't shirk the responsibility to refactor it yourself.) But if you have an over-architected, obfuscated mess, where do you even start? You should appreciate your fellow developers more. Maybe buy them a fruit basket or something?

Re: How to reduce the cognitive load of your code

#225
post #222

Earlier quoted context omitted.

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

If your stripping boilerplate then your operating on different things. Which seems more readable? SortGuiElement(){junk; SortUserNames(); junk;} SortUserNames(){junk;} vs. SortNames(){junk; sortNames() junk;} sortNames(){junk;} It might seem obvious and the code might be identical, but I see the second case very frequently in other peoples code.

Re-using an identifier with just a case difference is criminal.

You want:

  SortNames(){junk; SortNamesImpl(); junk;}
  sortNames(){junk;}
or whatever: SortNamesGuts(), InternalSortNames(), DoSortNames(), LowLevelSortNames(). Anything but just flipping the case of a letter or two in the "SortNames" identifier.

Re: How to reduce the cognitive load of your code

#226
post #143
post #71

Earlier quoted context omitted.

> Now I belive that most bad code out thare is made by overworked and tired programmers in a rush to deliver something that works. I would agree. But I think putting up with those conditions is a different sort of laziness, and agreeing to produce garbage is a different sort of incompetence. Looking back on the times I've done that myself, I deeply regret it. Programmers have a lot more power to shape process than th…

While we do have a good amount of power, they still have the ultimate power in that they write the checks.

If that's how you measure power, the ultimate power is in the hands of the customers, as they're the ones footing the bill.

And a given check only has power over you to the extent that you let it. Most programmers will have little trouble finding a job if they have good professional networks or are otherwise willing to work at having options. If you are confident that a just-as-good job is easily available, you can be much braver in the one you have.

Re: How to reduce the cognitive load of your code

#227
post #215

Earlier quoted context omitted.

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.

I guess I didn't think about people using C/++ and Java together regularly.

Re: How to reduce the cognitive load of your code

#228
post #222

Earlier quoted context omitted.

If your stripping boilerplate then your operating on different things. Which seems more readable? SortGuiElement(){junk; SortUserNames(); junk;} SortUserNames(){junk;} vs. SortNames(){junk; sortNames() junk;} sortNames(){junk;} It might seem obvious and the code might be identical, but I see the second case very frequently in other peoples code.

Re-using an identifier with just a case difference is criminal. You want: SortNames(){junk; SortNamesImpl(); junk;} sortNames(){junk;} or whatever: SortNamesGuts(), InternalSortNames(), DoSortNames(), LowLevelSortNames(). Anything but just flipping the case of a letter or two in the "SortNames" identifier.

I agree that reusing the same name with different capitalization is bad, but I have seen this from several developers across many different teams and several languages. These same people often have Foo(x){junk; Foo(x,y,z); more junk;} sure if it's a pass though that's fine but if you have 10 foo('s) that all have internal logic then please come up with some actual names.

Amway IMO, SortNames() and Internal/Do/LowLevel/SortNames() are almost as bad because just looking at the names it's not obvious what's going on. Yes, visually they look different which helps and consistency can make things even more readable. But, even just SortNamesHappyPath() gives some idea of what's going on.

Re: How to reduce the cognitive load of your code

#229

Earlier quoted context omitted.

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

> Not sure what you mean by separating lines from rows.

It's the example Joe Spolsky used on the blog post about prefixes that everybody keeps pointing to. He showed code that worked on rows and columns (not lines, sorry) on a table, using prefixes to avoid mixing them.

Haskell types do support this use, but you'll have to declare both types as Integral and Numeric, with the resulting boiterplate. I'm not sure exactly how to solve this, maybe a way to "lift" typeclasses out of a newtype declaration would be general enough. It is probably possible to do with template Haskell, but that is already outside of the language.

That Scala library is interesting, although it looks like lots of the work is done at run time. Also, it looks like Haskell is able to do it [1]. (It's a recurring theme of mine, to complain that something can not be done on Haskell, just to discover somebody that did it.)

[1] http://hackage.haskell.org/package/dimensional

Re: How to reduce the cognitive load of your code

#230
post #59

Like often with this kind of article it barely scratches the surface. "null != variable" will confuse people is downright silly. People confused by this won't have an inkling of what any non-hello-world program does. The rest has some validity, but it focuses on syntax and programming in the very small. It might take a bit of effort, but I can make sense of a tangled function (that's not an excuse to code sloppily th…

I agree that big, deep stuff like architecture and abstractions can be daunting, but I wouldn't be quick to dismiss style and formatting as mere nitpicks. Code clutter can have an outsize effect downwind of those who create it. A codebase is like a home. We all have to live in it. Architecture and abstractions are like the furniture and appliances. Code formatting and syntax are the nicknacks, paper bills, decoration…

Oh yes, I agree. But it's a shame it's all people ever talk about, when there's this much bigger thing that looms beneath the surface.
Post reply on HN