Most active commenters
  • hinkley(3)

←back to thread

1457 points nromiun | 11 comments | | HN request time: 1.144s | source | bottom
1. alphazard ◴[] No.45078066[source]
The bit about "smart developer quirks" looks suspiciously like the author only understands code that they have written, or is in a specific style that they recognize. That's not the biggest driver behind cognitive load.

Reducing cognitive load comes from the code that you don't have to read. Boundaries between components with strong guarantees let you reason about a large amount of code without ever reading it. Making a change (which the article uses as a benchmark) is done in terms of these clear APIs instead of with all the degrees of freedom available in the codebase.

If you are using small crisp API boundaries to break up the system, "smart developer quirks" don't really matter very much. They are visible in the volume, but not in the surface area.

replies(5): >>45078114 #>>45078206 #>>45078208 #>>45078237 #>>45078727 #
2. hinkley ◴[] No.45078114[source]
I learned pretty early on that people get really tired of optimization of code that is directly in the call stack they have to breakpoint in. Later on I clocked some of that as code smells pulling attention and analysis time during debug work.

But the trick I found is that if you can extract a function for only the part of the code you’re optimizing/improving, and then make your change in a single commit, two things happen. One, it’s off the code path, so out of site, out of mind. Two, people are more forgiving of code changes they don’t like but can roll back by reverting a single commit. That breaks down a bit with PRs, since they tend to think of the code as a single commit. But the crisp boundaries still matter a lot.

replies(1): >>45078153 #
3. srcreigh ◴[] No.45078153[source]
What do you mean about “people get really tired of optimization of code that is directly in the call stack they have to breakpoint in”? What’s the context where everybody else is using breakpoints?
replies(2): >>45078321 #>>45078363 #
4. djmips ◴[] No.45078206[source]
https://news.ycombinator.com/newsguidelines.html

"Please respond to the strongest plausible interpretation of what someone says, not a weaker one that's easier to criticize. Assume good faith."

5. zakirullin ◴[] No.45078208[source]
Having a clear and minimalistic API doesn't mean that the underlying code is easy to understand. It's good when things just work and you can use an API, but most of the time you have to dig whatever is under the rug.
replies(1): >>45079415 #
6. SickOfItAll ◴[] No.45078237[source]
It’s simple, but developers are generally terrible at it, especially the ones who are ‘smart’: Aim to think in terms of contracts and interfaces, not implementation. I don’t want to know what’s in your black box in order to understand how it works; if you make me read your code, you’ve done it wrong.
7. nycdotnet ◴[] No.45078321{3}[source]
In some software platforms, the tooling makes it really easy to use a debugger to see what’s happening, so it’s common for everyone on the team to use them all the time.

The comment you’re responding to mentioned pulling code into a function. As an example, if there’s a clever algorithm or technique that optimizes a particular calculation, it’s fine to write code more for the machine to be fast than the human to read as long as it’s tidy in a function that a dev using a debugger can just step over or out of.

replies(1): >>45078367 #
8. hinkley ◴[] No.45078363{3}[source]
Anything that is more complex than the simplest thing that can work, needs to be out in leaf node functions any time that is remotely possible, if you want to remain popular with your coworkers. It is, I believe, part of the calculus of “premature optimization” nobody wants to have to think about complex code when looking for other bugs. Kernighan’s Law also informs on this topic.

There are code improvements that improve legibility, correctness, and performance. There are ones that improve two of those three qualities. You can use those pretty much anywhere and people will pick a reason to like the code you modified in such a manner.

But if you put “clever” code high in the call graph, get ready for grumbling from all corners. If it happens to be near where legitimate bugs tend to live, get ready for a lot of it.

I would probably also add that this advice goes hand in glove with Functional Core, Imperative Shell. The surface area for unintended consequences in pure code is much tighter, so people won’t have to scan as much code to narrow down the source of a strange interaction because there aren’t interactions to be strange. I don’t need to look at code that has a single responsibility that is orthogonal to the problem I’m researching. Until or unless I become desperate because nothing else has worked so far.

9. hinkley ◴[] No.45078367{4}[source]
More succinct than I managed.
10. zmmmmm ◴[] No.45078727[source]
> If you are using small crisp API boundaries to break up the system, "smart developer quirks" don't really matter very much

To me this is the upside of the microservices concept. Of course, true microservices take it way too far. But once you tell two teams they can only talk to each other with APIs and make them use tooling that properly defines what those are (schemas etc) .... all of a sudden they are forced to draw those boundaries well and then stick to them. And they get really conservative about changing them and think hard about what the definitions should be up front. It's sort of perversely sticking technical friction in at the points where you want there to be natural conservatism around change.

11. alphazard ◴[] No.45079415[source]
> Having a clear and minimalistic API doesn't mean that the underlying code is easy to understand.

Doesn't need to be. The API tells me what it does, hopefully there is a test suite to assure me. I can add to the test suite if I have a question, or want to lock in a behavior.

When it's a third party library, everyone assumes it's supposed to work? but when it's a system in the same repository, all of a sudden all bets are off, and you need to understand it fully to get anything done?

> It's good when things just work and you can use an API, but most of the time you have to dig whatever is under the rug.

If most changes require simultaneously changing multiple areas of the code, such that changing one system implies changing every other system with roughly equal probability, then it's not well designed.

I don't know what else to tell you. It's going to be hard to iterate or maintain that system, in part because it requires a high cognitive load. None of the code in such a system provides any cognitive leverage. You can't rule out, or infer behavior of a large amount of code, by reading a small amount.

If such a system is important, then part of the strategy has to be to improve the architecture.