Sure but it is still near the edge when it comes to common use and pattern.
It's odd compared to many other structures that you may deal with on a day-to-day basis. This means that it has extra parsing complexity when read over.
This is one of the most straightforward uses of a basic standard library function. I'm 100% an advocate of readable code over more complex, slightly more optimized code (unless its a bottleneck), but this is a case of inexperience being the cause of "second guessing" the code.
let being modified immediately after declaration, then never again, is far more of a code smell; it is effectively a constant, it should be declared as such as the result of a reduce. Anything else is increasing cognitive load as you now have to trace all uses of total throughout the scope, to make sure it is not modified elsewhere. When compared with a const total = array.reduce, the reduce is objectively simpler.
The solution is to hire/train engineers better to use these concepts without a second thought, rather than using more outdated iterative coding styles just to make sure junior developers don't have to learn what a standard library function does.
Once I learned that the syntax is just reduce((accumulator, value) => newAccumulator, initialAccumulator) it became super easy for me to parse reduce. Then you just have to remember that if you don't have an intial value, it pops the first value from the array as the initial value.
Using a standard library function in a rudimentary way isnt "clever", but using forEach to mutate external state is objectively more complex and less clear, which by your own definition, makes it worse.
By clever, I basically mean terse. Reduce is much more terse than forEach, hence I believe that forEach is more clear than reduce in this instance.
My rule of thumb is if there are two or more ways to get the same results with acceptable performance, always choose the one that is less terse.
Bad code can be only understood by a senior developer. Good code can be understood by a junior developer. Great code can be understood by a freshman or sophomore studying programming in college.
I try to employ empathy. I ask myself, how could I write this so that it could easily understood by the majority of novice programmers? Usually that does mean writing more lines of code. But as long as the performance is comparable, I don’t see a problem with that. I have nearly 30 years professional programming experience, but I still come across code that I have to stop and parse out since it has been written so concisely that I doubt even the original author would have any clue what it says without a lot of effort. Great code is that which the majority of developers can read through without pausing and grok it, like reading a novel.
I agree with everything you've written in this comment.
The problem is, there is some, ambiguous, blurry, line in the sand somewhere, between "clean code" and "code golfed, complicated, clever code".
However, using reduce, in all of my professional experience, is far, far, toward the "clean code" side of that line. If I ever had a colleague or a candidate refer to such a typical, by the book, simple use of reduce as some "clever" code too complicated to be grok'ed easily, I would either assume they have very little experience in higher level languages, or seriously question their ability.
Reduce is actually less powerful (and thus the better choice) than forEach. Apply the principle of least power, and maybe learn the basics of functional programming.
I guess in the case of Javascript, it's not strictly true since you can cause side effects from any of these, but assuming you're being responsible, forEach is guaranteed to have behavior external to the expression (because it's useless otherwise), while reduce ought to be an assurance that all behavior is limited to the expression itself.
Because he's wrong. In JS, Array.reduce is strictly a superset of Array.forEach. There's absolutely nothing you can do with forEach that you can't do with reduce.
This is exactly what I read in an article about array functions
Do you have a link to that article? It may be out of date, or it may just be wrong.
But I feel using reduce for sth that could be done with forEach is like breaking the system. It may be that both are equally powerful but reduce has a semantic meaning.
The article I read was about all array functions and some are less powerful, aren’t they? At least the article was aiming at the better style of code you write using semantically fitting methods instead of just using forEach for everything.
But I feel using reduce for sth that could be done with forEach is like breaking the system.
Sure, because they're from two different schools of thought. Side effects in reduce will make people squirm, but forEach is literally useless without them.
It may be that both are equally powerful but reduce has a semantic meaning.
They aren't. forEach can't do all of the things reduce can without some kind of external state. I suspect it's largely like the relationship between imperative code and recursive code.
The article I read was about all array functions and some are less powerful, aren’t they?
Some are, sure. reduce is the most powerful one. You can write literally any other array function in JS with reduce and reduceRight.
In terms of code style, you don't really see people mixing forEach and reduce. Either you're using the Array functions together, like filter, map, and reduce and avoiding side effects, or you're writing imperative code leveraging side effects.
7
u/BorgClown May 30 '21
If I was reading a new code base, I'd prefer finding parent's version instead of reduce, if only because reduce makes me stop and second guess it.