Push everything down for better code readability printInvoice(invoice, options) // is much better than if(printerReady){ if(printerHasInk){ if(printerHasPaper){ if(invoiceFormatIsPortrait){ : The same can be said of loops printInvoices(invoices) // much better than for(invoice of invoices){ printInvoice(invoice) } At the end, while code readability is extremely important, encapsulation is much more important, so mix…
Push Ifs Up and Fors Down
181–190 of 209 posts
Re: Push Ifs Up and Fors Down
#182> 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, 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…
I'm guessing you mean something else, or do you feel useful functions can't be called many times in the same program?
Re: Push Ifs Up and Fors Down
#183Earlier 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.
Like how the phrase “to boldly go where no man has gone before” will bring out pendants.
Re: Push Ifs Up and Fors Down
#184Related: Within a function, I'm a fan of early bail out. While this goes against the usual advice of having the positive branch first, if the positive branch is sufficiently large you avoid having most of the function indented.
Re: Push Ifs Up and Fors Down
#185Related: Within a function, I'm a fan of early bail out. While this goes against the usual advice of having the positive branch first, if the positive branch is sufficiently large you avoid having most of the function indented.
> having positive branching first This is advice I've never seen or received. It's always been the latter, exit early, etc. Languages like Swift even encode this into a feature, a la if guards.
Negative first makes else-branches double negative which reads weird, eg. if !userExists {…} else {…}
Re: Push Ifs Up and Fors Down
#186Re: Push Ifs Up and Fors Down
#187Earlier quoted context omitted.
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.
Writing code is like writing though. None of these ideas for structuring code are the be all and end all of coding. Things evolve, sometimes old idea are good, sometimes new. Like how the phrase “to boldly go where no man has gone before” will bring out pendants.
Re: Push Ifs Up and Fors Down
#188Earlier quoted context omitted.
It sounds like self-inflicted boilerplate to me.
If you were going to write the tests anyway, the additional boilerplate for splitting it up and doing a wrapper isn’t so bad (in C at least, maybe it is worse for some language).
Re: Push Ifs Up and Fors Down
#189Earlier quoted context omitted.
> a database object exists, and creating it if not. Imagine your filesystem or database library either doesn't have an upsert function to do this for you, or else you can't use it because you want some special behaviour for new records (like writing the current timestamp or a running total, or adding an entry to a log file, or something). This is why databases have transactions. > simple example where you're checking…
Sure, I agree that a transaction should be used here (in the database example at least). But that's orthogonal to my point, or maybe even in favour of it: doesn't a transaction necessitate keeping the conditional close to the effect? It's a perfect example of what I'm trying to say, how do you make sure the conditional happens in the same transaction as the effect, while simultaneously trying to push the conditional…
Your transaction needs to encompass all of those operations, not just parts of it.
Re: Push Ifs Up and Fors Down
#190Earlier quoted context omitted.
If you were going to write the tests anyway, the additional boilerplate for splitting it up and doing a wrapper isn’t so bad (in C at least, maybe it is worse for some language).
When you say "isn't so bad", is it just a manner of speech or is it actually a little bad (but it is a compromise?)?
* I wasn’t around long enough to see if there was a hidden maintenance cost
* It was a very thoughtfully designed library in an already-well-understood domain so it wasn’t like we were going to need to change the arguments a ton
* It was explicitly a library designed to be used as a library from the get-go, so there was a clear distinction of which functions should be user-visible.
I think I would find it annoying if I was doing exploratory programming and expected to change the arguments often. But, in that case, maybe it is too early to start checking user inputs anyway.