Hacker News new | ask | show | jobs
by nahname 3280 days ago
>To reduce cognitive load, I want to be able to read a function/method without having to think about where some variable comes from.

To reduce cognitive load for me, I should be able to treat the function/method as a black box. Care about what it receives, care about what it returns, don't care about how it goes about accomplishing it.

>When I read the code above, my first question is: How is config.Pi defined?

That line really hammers home the difference. I trust the previous author, the test suite and ultimately, the project. Programmers seem to fall into two camps. Those that need to know details to understand a method and those that need to know the contract to understand a method.

5 comments

I think there is an implied context here that the author didn't do a good job of communicating. Usually I will also assume the function does what it says when I use it in code I'm writing.

But what happens when I'm debugging a problem in code I may or may not have written myself? Or when I'm debugging code that I wrote so long ago that I no longer remember all the details. That's when I need to be able to follow the code in the function I'm consuming. You are right that when you are consuming code it's good when you can treat that code as a black box. But that's not actually where I spend the most time as a developer. I spend far more time reading code I don't have full state about and trying to figure why something is broken.

Pi was probably a bad example here since we are conditioned to think of it as a constant. But there are similar uses in code where a function is doing bad things and it's not clear why because you didn't realize the function had an undeclared input from global mutable state. I think that is what the author was trying to say in his post.

> To reduce cognitive load for me, I should be able to treat the function/method as a black box. Care about what it receives, care about what it returns, don't care about how it goes about accomplishing it.

I couldn't agree more.

This was the massive reason I loved Go when I switched from Node. My cognitive load was massive in Node, because I could not trust a function just by looking at it. Did it return a value? Did it take a callback? Did it return a promise? etc. I always had to have the documentation up. Now with Go, not only is the function signature easily accessible from Code (due to the static nature of it), but most things return values. Async doesn't propagate in an almost sinister way, like it does in JS.

In fact, I'm switching back to JavaScript due to needing to write some ReactNative stuff, and I'm having PTSD of sorts. React & Redux are great, I love them, but they're designed quite synchronously. Async just piles on another layer of complexity, for such a simple task.

Anyway, I'm diverging a bit, apologies.

Typescript and as mentioned below Flow are good solutions to this problem. Add appropriate linting to force types to be defined on methods and you just hover over (or however you prefer to open a method definition window) and get a breakdown of types that you can click to go to if you need further definition.
You might wanna give Flow [0] a try. I think the default ReactNative tools include support out of the box.

[0] https://flow.org

> I trust the previous author, the test suite and ultimately, the project.

I agree with your first point (functions should abstract some things away), but I disagree here. I feel like this falls into a "let's just not do stupid things" category of stuff that we just can't achieve. If people didn't make mistakes, we wouldn't need tests or monitoring.

I trust people but that doesn't mean I assume everything they do will be flawless. What if you're working on this project and you're debugging an issue where the function's not working right?

Or, what if you want to change how the function works? Pi is admittedly a poor example of this but the general concept is sound I think.

> Programmers seem to fall into two camps. Those that need to know details to understand a method and those that need to know the contract to understand a method.

A user of a software module shouldn't need to know the details of a function, but readability is much more for other engineers working on the codebase than it is for users of the codebase.

> Programmers seem to fall into two camps. Those that need to know details to understand a method and those that need to know the contract to understand a method.

This is an interesting observation. I seem to fall into the former category, but I'm not sure if that's a side effect of working with proprietary codebases that have less than stellar interfaces.

When stuff ultimately goes sideways, I value being able to relatively quickly reason about the flow without firing up a debugger. Information hiding cuts both ways.

Even if you don't trust the previous author, you can still use your "go to definition" shortcut and see the real thing: who is it who is coding one file at a time?

You shouldn't be considering the implementation details every time you want calculate the circumference. Even that pi is involved is WAY more information than the caller needs to know. And if you are debugging you need to know where to look for the answer, not the answer itself.