Live data from Hacker News

What makes code hard to read: Visual patterns of complexity (2023)

seeinglogic.com

341–350 of 383 posts

Re: What makes code hard to read: Visual patterns of complexity (2023)

#341

Earlier quoted context omitted.

> it could build up a set internally, it could use a hashmap, or any one of a million other approaches. It can even probe the size of the array to pick the performance-optimal approach. I don't have to care. Well, this is probably why functional programming doesn't see a lot of real use in production environments. Usually, you actually do have to care. Talk about noticing a performance regression because I was simply…

I consider an abstraction to be a good abstraction if I don't need to care for its internal workings all the time - whether that's some build step in the CI, or the usage of data structures from simple string s to advanced Cuckoo filter s and beyond. Even Python uses a Bloom filter with operations on strings internally AFAIK. Correctness and maintainability trumps performance most of the time, and map , filter and im…

> Correctness and maintainability trumps performance

Great, please make all the software even slower than it already is. I am overjoyed to have to purchase several new laptops a decade because they become e-waste purely due to the degradation of software performance. It is beyond ridiculous that to FP programmers daring to mutate variables or fine-tune a for loop is an exceptional scenario that you don't do "unless you have to" and which requires "knowing what you're doing". Do you know what you're doing? How can you be a software engineer and think that for loops are too difficult of a construct, and that you need something higher-level and more abstract to feel safe? It's insane. Utterly insane. Perhaps even the root of all evil, Code Golf manifested as religion.

Re: What makes code hard to read: Visual patterns of complexity (2023)

#342
post #109

> Chaining together map/reduce/filter and other functional programming constructs (lambdas, iterators, comprehensions) may be concise, but long/multiple chains hurt readability This is not at all implied by anything else in the article. This feels like a common "I'm unfamiliar with it so it's bad" gripe that the author just sneaked in. Once you become a little familiar with it, it's usually far easier to both read an…

I think, an explicit type would make it even easier to grok:

  ISet authorsOfLongBooks =
    books
    .filter(book => book.pageCount > 1000)
    .map(book => book.author)
    .distinct()
    .toHashset()
Or whatever the equivalent for ISet is in the respective language. Or IReadonlySet if the set should be immutable.

Re: What makes code hard to read: Visual patterns of complexity (2023)

#343
post #316

Earlier quoted context omitted.

This comment seems unnecessarily mean-spirited... perhaps I just feel that way because I'm the person on the other end of it! I agree the code you have there is very readable, but it's not really an example of what that sentence you quoted is referencing... However I didn't spell out exactly what I meant, so please allow me to clarify. For me, roughly 5 calls in a chain is where things begin to become harder to read,…

To me the functional style is much more easy to parse as well. Maybe the lesson is that familiarity can be highly subjective. I for example prefer a well chosen one-liner list comprehension in python over a loop with temporary variables and nested if statements most of the time. That is because usually people who use the list comprehension do not program it with side effects, so I know this block of code, once unders…

> Maybe the lesson is that familiarity can be highly subjective.

Over the years I've come to firmly believe that readability is highly subjective. And familiarity is a key contributor to that, but not the only one. There are other factors that I've found highly correlate with various personality traits and other preferences. In other words, people shouldn't make claims that one pattern is objectively more readable than another. Ever.

I've reached the point where anyone who claims some style is "more readable" without adding "to me" I just start to tune out. There's very little objective truth to be had here.

What should one do? If on a team and you're the outlier, suck it up and conform. If you're on a team and someone else is the outlier? Try to convince them to suck it up and conform. If you're on a new team? Work empathetically with your teammates to understand what the happy medium style should be.

Re: What makes code hard to read: Visual patterns of complexity (2023)

#344
I think a lot about code readability a lot. I agree with most of this except the names part and shorthand constructs. Especially for the latter, it's unfair to make a comparison with the wrong operator. The example in general is a bit weird. I think a better one is `if (myObj !== null) myObj = someOtherObj`. A very common pattern for which js now has a nullish coalescing assignment you can use insteal (`myObject ??= somOtherObj`) or there's also ||=. These sacrifice some readability upfront due to them being "uncommon" operators and the code might be harder to read for someone whose never seen it, but is so much easier to read once you get used to it. There is of course, always a trade off. Using a lot of .? to access properties can be code smell, but also sometimes very helpful, as the alternative would expand into a lot of code.

Regarding names, I think the suggestions are a bit in conflict, as often to avoid variable shadowing you have to do stuff like name things node, _node, node2. I try to have distinct names, but I'd rather the shadowing in those cases where it's hard. As for i, and j. I don't like them, but they're such conventions it's hard to avoid them. I always try to use them only once, and assign the variable I need: `item = obj[i][j]` if possible.

Re: What makes code hard to read: Visual patterns of complexity (2023)

#345
post #308

Earlier quoted context omitted.

What is "long"?

Are you really confused when people don't think 3 operations constitutes "long"? I would guess anyone with half a brain would agree 3 operations is not long, maybe 5 or 6 and you will have many people agreeing, and above that most.

[deleted]

Re: What makes code hard to read: Visual patterns of complexity (2023)

#346
post #60
post #58

Shoutout to the pipe operator in R. The code equivalent of "and then." It helps to unnest functions and put each action on one line. I know R is more for stats and data, but I just think it's neat.

Yes, dplyr pipes are wonderful. Also, for the same reason, I find JavaScript list comprehensions cleaner than those in Python - as in the former it is possible to chain maps and filters. Also, now there is a new pipe syntax in SQL, that adds a lot to readability.

I just wanted to point out that, apart from dplyr/magrittr, R introduced a native pipe operator (|>) a few years ago.

Re: What makes code hard to read: Visual patterns of complexity (2023)

#347
post #109

> Chaining together map/reduce/filter and other functional programming constructs (lambdas, iterators, comprehensions) may be concise, but long/multiple chains hurt readability This is not at all implied by anything else in the article. This feels like a common "I'm unfamiliar with it so it's bad" gripe that the author just sneaked in. Once you become a little familiar with it, it's usually far easier to both read an…

This comment seems unnecessarily mean-spirited... perhaps I just feel that way because I'm the person on the other end of it! I agree the code you have there is very readable, but it's not really an example of what that sentence you quoted is referencing... However I didn't spell out exactly what I meant, so please allow me to clarify. For me, roughly 5 calls in a chain is where things begin to become harder to read,…

Agreed —

seeinglogic's article made me think of a 3rd option:

1. Sorta long functional chain where the type changes partway through 2. Use temp variables 3. (New option) Use comments

(Here's funcA from seeinglogic's article, but I added 3 comments)

    function funcC(graph) {
      return 
        // target node
        graph.nodes(`node[name = ${name}]`)
          // neighbor nodes
          .connected()
          .nodes()
          // visible names
          .not('.hidden')
          .data('name');
     }


Compare to funcB which uses temp variables:

    function funcB(graph) {
      const targetNode = graph.nodes(`node[name = ${name}]`)
      const neighborNodes = targetNode.connected().nodes();
      const visibleNames = neighborNodes.not('.hidden').data('name')

      return visibleNames;
    }
For me the commented version is easier to read and audit and it also feels safer for some reason, but I'm not how subjective that is.

Re: What makes code hard to read: Visual patterns of complexity (2023)

#348
post #307

Earlier quoted context omitted.

If you think people only get upset about things for their own self interest, then I wonder what you think about social justice. You have a Texas Sharpshooter Fallacy in your logic. A novelist is successful if they reach an audience. Once they find it, if they stick with it they will be successful. If they’re lucky then they might switch up genres without alienating their existing readers. But not everyone gets away w…

> If you think people only get upset about things for their own self interest, then I wonder what you think about social justice. That's a gross mischaracterization of what I said. If anything, I'd be really concerned if you think what you're doing is akin to "social justice", and being hostile to others is justified in the name of "social justice". > You have a Texas Sharpshooter Fallacy in your logic. That doesn't…

>> You have a Texas Sharpshooter Fallacy in your logic.

> That doesn't even make any sense.

Well that explains the long response but that’s the gist right there.

Sharpshooter fires bullets at a barn and then paints a target on the spot with the most holes. That’s how creative writing usually works, unless you’re a paid columnist and even then it’s partially true.

I think you’re mistaking using swear words with hostility. Not everyone has veins popping out of their foreheads when they call a bullshit situation bullshit.

Re: What makes code hard to read: Visual patterns of complexity (2023)

#349
post #299
post #290

Earlier quoted context omitted.

In fairness, if this was in a relational data store, the same code as above would probably look more like... SELECT DISTINCT authors.some_field FROM books JOIN authors ON books.author_id = authors.author_id WHERE books.pageCount > 1000 And if you wanted to grab the entire authors record (like the code does) you'd probably need some more complexity in there: SELECT * FROM authors WHERE author_id IN ( SELECT DISTINCT a…

The last one is better as: SELECT * FROM authors WHERE author_id IN (SELECT author_id FROM books WHERE pageCount > 1000); But I think you're missing the point. The functional/procedural style of writing is sequentialized and potentially slow. It's not transactional, doesn't handle partial failure, isn't parallelizable (without heavy lifting from the language-- maybe LINQ can do this? but definitely not in Java). With…

agreed on the revised SQL!

But I don't think I missed the point, the original text talks about measuring complexity as a function of operators, operands, and nested code. The true one to one mapping is more complex than the original comment I replied to

Re: What makes code hard to read: Visual patterns of complexity (2023)

#350
post #284

Earlier quoted context omitted.

> Build up and debug the chain as you work in an environment like Jupyter. > Just run the code and verify that the current step works. Then, proceed to the next. Yes, it's not debuggable/"viewable" without cut/paste/commenting out lines, once it's constructed.

If it is breakpoints you are concerned about, you can set a breakpoint on a method in the chain and inspect `self`.

Most languages don't expose the internal of map to set a breakpoint, so you're left with individual entities. But yes, there are tricks you can use to make it work, although most require more complex conditional/sequential breakpoints. In your method breakpoint example, you would need to set a chained breakpoint, as in "don't break until this other breakpoint above the chain has been hit", otherwise the breakpoint in the method won't be "spatially" relevant to the code you're debugging.
Post reply on HN