Hacker News new | ask | show | jobs
by UglyToad 1067 days ago
It feels like their calculation missed 2 crucial confounders, stack depth and type tracking.

1) Stack depth. In their refactored example if I truly want to understand the code I need to now store everything I was thinking about in the current function and jump to their new `is_paid_today` function, then into each of the 3 dependent functions, I'd say as finger in the air type estimates each stack frame should add 2 * depth and then some multiplier for breadth or something. This is why I prefer big functions like the initial state read from top to bottom with no indirection, abstraction or surprises where reasonable. (curly braces wouldn't go amiss to give visual indicators of scope...) This is completely counter to 'clean code' dogma but clean code dogma is... bad.

2) Type tracking. To reignite this holy war if I have to track the type information mentally then I'd say every parameter and variable has an additional +1 working memory overhead. What is employee, what is employee_database, what is `is_end_of_month` and where on earth is it coming from? Try as I might I just cannot understand people who onboard to big codebases without type hints at least, y'all are a different breed, you should work as like super-rememberers.

2 comments

Stack depth isn’t an issue for me typically. I assume the function is named correctly and the operation it represents is the operation needed at this point. If I find errors (why did we “getLighterColor” and from the resulting object expect to find a fruit name?), then I investigate the called function to see if it really does stuff a banana into a color and ask its author “wat?” And that’s because the contents of a function the current code depends on should be correct based on its name.

Type tracking though, oh yes. How many times have I been debugging old JS code where someone forgot or misunderstood that this date is a string and not a Date.

I think while the name things correctly principle is nice and good to aspire to like anything at the intersection of people doing the right thing and natural language there's a bunch of places it doesn't work.

I'm usually reading code for 2 purposes. First, to understand the code and the domain. If this is the case I want to see how the code handles paid weekly versus monthly. Is it possible it's not accounting for fortnightly (biweekly) payments? If we were to account for that how would it slot in. How does `is_end_of_month` or week account for federal holidays, etc?

Secondly, to fix it. Something has gone wrong or some assumption has become outdated. The call is coming from inside the house. Nothing is to be trusted. This is most of my work to be honest, spelunking into code and trying to solve the mystery in which case I'm not going to take the current name-as-written to be factual and need to include the function call in my logical model of the code under investigation.

That's not to say I disagree entirely. Like all things in software it's a balance and you don't want to define getting a lighter color everywhere you need to use it, eventually you want to have a function that just wraps it. But over-eager splitting out of functions also incurs a working memory cost and it's striking the balance between the stack depth and memory overhead of the single function. Since the article's working memory model incurs no cost per stack frame I don't think it's well designed to encourage careful thought on this trade-off.

I'm with you here: can't do stack depth for anything. When I code complicated things I'll quite often stack them up as inline blocks and separate the blocks with 'begin filter Hi' and then 'end filter Hi' 'begin filter Mid' and so on. I'll be able to process it easier if I can see where similar things are repeating themselves. Basically, heresy :)

The thing people don't often get is that when I code it's to a purpose other than making the code. So I'm thinking about quite a few things outside of the code that's making those things happen with the samples I'm working with, and the stuff not related to how it's coded is typically a lot more important.

Hence, my stack is always going to be catastrophically, tragically pitiful, unless the thing I'm working on is quite useless :) and in that case, why am I bothering to code at all?