Live data from Hacker News

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

seeinglogic.com

291–300 of 383 posts

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

#291

Earlier quoted context omitted.

Everything you said is true for both of our programs, the only difference is whether or not it's hidden behind function calls you can't see and don't have access to. You don't really think that functional languages aren't appending things, using temp vars, and using conditional logic behind the scenes, do you? What do you think ".filter(node => !node.isHidden)" does? It's nothing but a for loop and a conditional by a…

> the only difference is whether or not it's hidden behind function calls you can't see and don't have access to. You "can't see and don't have access to" `if`, `range`, or `append` but somehow you don't find this a problem at all. I wonder why not? > You don't really think that functional languages aren't appending things, using temp vars, and using conditional logic behind the scenes, do you? By this metric all lan…

> 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 appending to an array. You have no idea what performance regressions are happening in ANY line of FP code, and on top of that, most FP languages are dead-set on "immutability" which simply means creating copies of objects wherever you possibly can... (instead of thinking about when it makes sense and how to be performant about it)

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

#292
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…

FWIW, I'm plenty familiar with functional programming and iterator chains, and I still think for loops often beat them--not only from a "visual noise" perspective, but because complex iterator chains are harder to read than equivalent for loops (particularly when you have to deal with errors-as-values and short circuiting or other patterns) and for simple tasks iterator chains might be marginally simpler but the absolute complexity of the task is so low that a for loop is fine.

> But you should be familiar enough that you stop randomly badmouthing map and filter like you have some sort of anti-functional-programming Tourette's syndrome.

I've been moderated for saying much tamer, FYI.

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

#293

Earlier quoted context omitted.

There is just no way that reasonable people consider this to be clearer. One certainly might be more familiar with this approach, but it is less clear by a long shot. You've added a temp variable for the result, manual appending to that temp variable (which introduces a performance regression from having to periodically grow the array), loop variables, unused variables, multiple layers of nesting, and conditional log…

Everything you said is true for both of our programs, the only difference is whether or not it's hidden behind function calls you can't see and don't have access to. You don't really think that functional languages aren't appending things, using temp vars, and using conditional logic behind the scenes, do you? What do you think ".filter(node => !node.isHidden)" does? It's nothing but a for loop and a conditional by a…

> Everything you said is true for both of our programs, the only difference is whether or not it's hidden behind function calls you can't see and don't have access to.

This is a key difference between imperative programming and other paradigms.

> You don't really think that functional languages aren't appending things, using temp vars, and using conditional logic behind the scenes, do you?

A key concept in a FP approach is Referential Transparency[0]. Here, this concept is relevant in that however FP constructs do what they do "under the hood" is immaterial to collaborators. All that matters is if, for some function/method `f(x)`, it is given the same value for `x`, `f(x)` will produce the same result without observable side effects.

> What do you think ".filter(node => !node.isHidden)" does?

Depending on the language, apply a predicate to a value in a container, which could be a "traditional" collection (List, Set, etc.), an optional type (cardinality of 0 or 1), a future, an I/O operation, a ...

> It's nothing but a for loop and a conditional by another name and wrapped in an awkward, unwieldy package.

There is something to be said for the value of using appropriate abstractions. If not, then we would still be writing COBOL.

0 - https://en.wikipedia.org/wiki/Referential_transparency

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

#294
post #275

Earlier quoted context omitted.

There’s a difference between simplifying a concept and stating it plainly. I use this analogy a lot. Code can be like a novel, a short story, or a poem. A short story has to get to the point pretty quickly. A poem has to be even more so, but it relies either on shared context or extensive unpacking to be understood. It’s beautiful but not functional. And there are a bunch of us short story writers who just want to ge…

I see where you are coming from but that's unnecessarily hostile. > There’s a difference between simplifying a concept and stating it plainly. You are right, but they are not mutually exclusive. The analogy you used with novel, short story, and poem/haiku also doesn't demonstrate your point: it's not like you can compress any novel into a short story, let alone a poem. If you're into games, try equating AAA-quality 3…

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 with that.

A software developer has one audience and they don’t get to chose it. You and I write for our coworkers. If they don’t like it we have three choices. We can leave, we can change, or we can gaslight our coworkers that our code is just fine and they are the problem.

It’s the latter I’ve seen too much of, and even if you’re not a victim of it you’re allowed to be incensed for those who are. In fact you’re obligated to do so.

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

#295
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…

And in a real functional language like F#...

  let authorsOfLongBooks = 
    books
    |> Seq.filter (fun book -> book.pageCount > 1000)
    |> Seq.map (fun book -> book.author)
    |> Seq.distinct
...you can set breakpoints anywhere in the pipeline!

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

#296
post #284

Earlier quoted context omitted.

Build up and debug the chain as you work in an environment like Jupyter. No need to create variables. Just run the code and verify that the current step works. Then, proceed to the next. Then, put the chain in a function. If you want to be nice, put a .loc as the first step to explicitly list all of the input columns. Drop another .loc as the last step to validate the output columns. (This also serves as a test and d…

> 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`.

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

#297

Earlier quoted context omitted.

Folks don't seem to have a problem when SQL does it. Only when code like Pandas does it...

Hi Matt! I've observed this phenomenon as well. When the SQL and Pandas examples are isomorphic except for shallow syntactic differences, the root cause of the complaint must either be: * that the judgment was emotional rather than substantive * or that the syntactic differences (dots and parens) actually matter

Folks really like their intermediate dataframes... for "debugging".

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

#298
post #54

There is a (large, I believe) aspect of good code that is fundamentally qualitative & almost literary. This annoys a lot of computer programmers (and academics) who are inclined to the mathematical mindset and want quantitative answers instead. I love dostoyevsky and wodehouse, both wrote very well, but also very differently. While I don't think coding is quite that open a playing field, I have worked on good code ba…

I 100% agree with this. One of the best compliments I ever got (regarding programming) was from one of my principal engineers who said something along the lines of "your code reads like a story". He meant he could open a code file I had written, read from top to bottom and follow the 'narrative' in an easy way, because of how I'd ordered functions, but also how I created declarative implementations that would 'talk'…

I had a similar experience. I was a lead on a project where the client sent a functional expert to literally (at times) watch over my shoulder as I worked. He got very frustrated after a few weeks, seeing little in the way of code being laid down. He even complained to the project manager. That's because this was a complicated manufacturing system, and I was absorbing the necessary rules for it and designing it... a process that involved mostly sitting and thinking.

When I decided on the final design and basically barfed all the code out in a matter of days, I walked this guy (a non-programmer) through the code. He then wrote my manager a letter declaring it to be the "most beautiful code he had ever seen." I still have the Post-It she left in my cube telling me that.

I have little tolerance for untidy code, and also overly-clever syntax that wastes the reader's time trying to unravel it.

And now we have languages building more inconsistent and obscure syntax in as special-case options, wasting more time. Specifically I'm thinking about Swift; where, if the last parameter in a function call is a closure, it's a "trailing" closure and you can just ignore the function signature and plop the whole closure right there AFTER the closing parenthesis. Why?https://www.hackingwithswift.com/sixty/6/5/trailing-closure-...

This is just one example, and yeah... you can get used to it. But in this example, the language has undermined PARENTHESES, a notation that is almost universally understood to enclose things. When something that basic is out the window, you're dealing with language designers who lack an appreciation for human communication.

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

#299
post #290
post #157

Earlier quoted context omitted.

SELECT DISTINCT author FROM books WHERE pageCount > 1000;

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 SQL, you push the entire query down into the database engine and expose it to the query optimizer. And SQL is actually supported by many, many systems. And it's what people have been writing for 40+ years.

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

#300
post #61

My pet peeve: function getOddness4(n: number): if (n % 2 === 0): return "Even"; return "Odd"; While it is shorter, I prefer vastly prefer this one: function getOddness2(n: number): if (n % 2 === 0): return "Even"; else: return "Odd"; Reason: getOddness4 gives some sense of asymmetry, whereas "Even" and "Odd" are symmetric choices. getOddness2 is in that respect straightforward.

function getOddness(n: number): return (n % 2 === 0) ? "Even" : "Odd"; Lowest boilerplate makes it the most readable. If working in a language with the ternary operator it ought to be easily recognized!

[deleted]
Post reply on HN