Live data from Hacker News

Push Ifs Up and Fors Down

matklad.github.io

161–170 of 209 posts

Re: Push Ifs Up and Fors Down

#161

Earlier quoted context omitted.

If you are explicitly calling authenticate() for each api, you’re doing it “wrong”. At that point you want implied authentication not explicit authentication. Why not move it to some middleware that gets called in every api call?

Because then you are calling middleware_caching_auth_broker() from 37 places instead of authenticate(). Just the name has changed, not the 37.

> Because then you are calling middleware_caching_auth_broker() from 37 places

No you aren't. You aren't really calling it from anywhere. The framework you're using, which you aren't writing, is calling the registered middleware.

The topic here is complexity for the code structure because it's called from 37 different places. A registered middleware doesn't run into that issue because it doesn't get called anywhere that "code structure complexity" matters.

Your reasoning is isomorphic to "I'm calling a bit shift millions of times because I have written some code in a programming language." Technically true but not what we're talking about here.

Re: Push Ifs Up and Fors Down

#162
post #134
post #105

Earlier quoted context omitted.

Can I float an adjacent model? Classes are nouns, functions are verbs.

And then at some point someone shows you how Classes can be verbs, and functions can be nouns, and your brain hurts for a while. You overuse that paradigm for a while, and eventually learn to find the appropriate balance of ideas.

Example: Object Algebra pattern represents data types ("nouns") as functions.

Re: Push Ifs Up and Fors Down

#163

In my field (server programming) readability trumps them all. Nested g() and h() can be much better if they are even just 1% easier to understand. No one cares about a few extra CPU cycles, because we don't write system or database code.

I will admit it is probably just some internal biasing from some unknown origin, but I always tend to think of server programming as a part of systems programming. To your mind, what keeps it out of the systems programming umbrella? I am not super certain about how programmers in your area break up the constituent parts of a server’s code, so maybe I’m thinking more along the lines of the ‘framework’/libraries your code is executing within.

Is this more of a ‘server programming is not systems programming because we are just implementing the logic of what gets served’ vs. my assumption that server programming includes the how does the server connect to the world, cache things, handle resource allocation, and distribute/parallelize the computations required to serve data back to the user?

Re: Push Ifs Up and Fors Down

#164
post #161

Earlier quoted context omitted.

Because then you are calling middleware_caching_auth_broker() from 37 places instead of authenticate(). Just the name has changed, not the 37.

> Because then you are calling middleware_caching_auth_broker() from 37 places No you aren't. You aren't really calling it from anywhere. The framework you're using, which you aren't writing, is calling the registered middleware. The topic here is complexity for the code structure because it's called from 37 different places. A registered middleware doesn't run into that issue because it doesn't get called anywhere t…

That sounds like the programming equivalent to thinking that food just comes from the grocery store.

Re: Push Ifs Up and Fors Down

#165

My weird mental model: You have a tree of possible states/program flow. Conditions prune the tree. Prune the tree as early as possible so that you have to do work on fewer branches. Don’t meticulously evaluate and potentially prune every single branch, only to find you have to prune the whole limb anyways. Or even weirder: conditionals are about figuring out what work doesn’t need to be done. Loops are the “work.” Ul…

it's not that weird, this taken to its logical conclusion is effectively prolog's execution model

Re: Push Ifs Up and Fors Down

#166

Earlier quoted context omitted.

If the function is called from 37 places, you need to refactor your code, but to answer your question on that point: it depends. DRY feels like the right answer, but I think we'd have to review an actual code example to decide. On examples where you're talking about a library function, I think you have to accept that as a library you're in a special place: you're on an ownership boundary. Data is moving across domain…

Pray tell, how many places is appropriate to call the same function? Is 5 too many? How about 6? When I hit 7, I have to refactor everything, right?

This only applies to a situation where you have a function that requires dynamic checks for preconditions. I would suggest that such a function (or how it's being used) is likely a blight already, but tolerable with very few call sites. In which case checking at the call site is the right move. And as you continue to abuse the function perhaps the code duplication will prompt you to reconsider what you are doing.

Re: Push Ifs Up and Fors Down

#167

Earlier quoted context omitted.

If the function is called from 37 places, you need to refactor your code, but to answer your question on that point: it depends. DRY feels like the right answer, but I think we'd have to review an actual code example to decide. On examples where you're talking about a library function, I think you have to accept that as a library you're in a special place: you're on an ownership boundary. Data is moving across domain…

Pray tell, how many places is appropriate to call the same function? Is 5 too many? How about 6? When I hit 7, I have to refactor everything, right?

You don't need an explicit rule, you just need to be smarter than than the average mid-curve tries-too-hard-to-feel-right hn poster and realize when you're repeating a calling convention too much.

Re: Push Ifs Up and Fors Down

#168
post #9

Earlier quoted context omitted.

The way to solve this is to split decisions from execution and that’s a notion I got from our old pal Bertrand Meyer. if (weShouldDoThis()) { doThis(); } It complements or is part of functional core imperative shell. All those checks being separate makes them easy to test, and if you care about complexity you can break out a function per clause in the check.

Functions should decide or act, not both.

This just moves decisions from inside of functions to the call site. At which point, there's more that can go wrong, since you're calling a function much more than it's single definition.

Re: Push Ifs Up and Fors Down

#169
post #70

Earlier quoted context omitted.

You can't shove every single assumption into the type system...

You can and should put as many as you can there https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-va... If instead of validating that someone has sent you a phone number in one spot and then passing along a string, you can as easily have a function construct an UncheckedPhoneNumber. You can choose to only construct VerifiedPhoneNumbers if the user has gone through a code check. Both would allow you to pluck a…

Yep! I have seen so much pushed into a type system that in the end there was hardly any code needed to do validation or scaffolding… to the point where it felt magical

Re: Push Ifs Up and Fors Down

#170

> If there’s an if condition inside a function, consider if it could be moved to the caller instead This idle conjecture is too rife with counterexamples. - If the function is called from 37 places, should they all repeat the if statement? - What if the function is getaddrinfo , or EnterCriticalSection ; do we push an if out to the users of the API? I think that we can only think about this transformation for interna…

> If the function is called from 37 places, should they all repeat the if statement?

the idea here is probably that in this case we might be able to split our function into two implementing true and false branches and then call them from 21 and 16 places respectively

Post reply on HN