Array.reduce considered harmful?
Tags: javascript, craft
Published: 2021-06-14 14:53:41

---
title: Array.reduce considered harmful?
published: true
description: People have been complaining about Array reduce, are they right?
tags: javascript,craft
//cover_image: https://direct_url_to_image.jpg
---

These past few weeks I've seen some stirrings on Twitter about how people should avoid using [`Array.prototype.reduce`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce) mainly around the fact it's difficult to read. At first I thought it was rubbish and that it wasn't difficult at all. The more I thought about it I realised that I've been writing JavaScript for years. I've led teams and projects, I've also been the guy that people come to for help with their JS. I'm an _experienced_ developer. 

What I was missing from my initial dismissal of the tweets versus `reduce` was **empathy**. I'll come back to that. 


When I first came across `reduce` it took a while for it to stick in my brain, I studied it and practiced it and eventually I had the muscle memory to bend code to my will using reduce.

...but that's the crux of the issue isn't it? It took time and focus to understand. 

Writing software is challenging enough - especially in large codebases where dragons are lurking around every corner - without fighting to understand the basic language. 

## My brain on reduce (at first)
Here's my inner dialogue when I first started coming across `reduce`:
```js
// Okay so we're going to do something here
// It takes data as an argument and returns something
function doSomething(data){
// Nice a one liner this should be simple

// So I'm guessing 'data' is an array, I know that reduce is for arrays. (TypeScript helps with this!)

// Wait what is acc? What is curr?
// Nice argument names doofus.
// acc + curr.val, okay so is it concatenating strings? 
// Oh theres a second argument to reduce 
// *reads MDN docs*
// Oh that's the initial value
// Sweet so it's just calculating a total
// So on first pass acc = 0
// Ahh and then for each element of data we add the elements `val` property
	return data.reduce((acc, curr) => acc + curr.val, 0)
}
```

That's for a simple `reduce`, this is the primary example that's given on when to use reduce. `reduce` is good for other stuff such as grouping data for a given key or combining `map` and `filter` in a single iteration:

```js
const activeIds = items
.filter((item) => item.active === true)
.map((item) => item.id)


const activeIds = items.reduce((result, item) => {
  if(!item.active) return result;
  return [...result, item.id]
}, [])
```

The filter + map loops over items twice whereas reduce does it once. However, tell me which of the above snippets is the easiest to read? It's filter + map, yes if you're familiar with reduce and your muscle memory kicked in it's not so bad. When we're building software we want to be focused on the business logic and adding features, not wasting focus deciphering language features. 

## Empathy

There's the common quote that's used: 
> Code is read much more than it is written.

This is 100% true.
1. You write some code
2. It works
3. You ship it
4. Time passes
5. Requirements change
6. You or some other poor soul needs to update the code
7. They study it and all code around it
8. They decide if this is the place the change needs to be made
9. They make the change

Repeat as many times as requirements change or bugs are fixed. Most of the time spent in that process is reading and understanding. 

Now imagine someone on your team less experienced at JavaScript or software development in general comes along and not only do they need to understand the requirements of the task, but also break down the language. They won't have the muscle memory that you do. 

So tell me why is: 
```js
function calculateTotalValue(data){
  return data.reduce((result, item) => result + item.val, 0)
}
```
better than this:

```js
function calculateTotalValue(data){
  let sum = 0;
  // This could also easily be a straight up for loop
  for(let item of data){
    sum += i.val;
  } 
  return sum;
}
```

Anyone can read the loop, you don't get points for being succinct. This isn't code golf. 


## Performance
I _very_ briefly touched on performance when I mentioned iterating a collection just once vs `filter` + `map`. 

What if I told you that a regular for loop or a for..of loop was faster than reduce anyway? (marginally for realistic examples)

Take a look at these snippets
```js
function reduceData(data){
  return data.reduce((acc, curr) => acc + curr.val, 0)
}

function forOfData(data){
  let sum = 0;
  for(let i of data){
    sum += i.val;
  } 
  return sum;
}

function forLoopData(data){
  let sum = 0;
  for(let i = 0, len = data.length; i < len; i++){
    sum += data[i].val;
  }
  return sum;
}
```

**Result: 1000 items**
![CleanShot2021-06-14154143@2x](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3e24m9wsq3p6flt633ss.jpg)

**Result: 10,000 items**
![CleanShot2021-06-14154317@2x](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f083wbhrra6tbqzf24jv.jpg)
 

You can [view the benchmark here](https://jsben.ch/k2wtW)

Yes, these are really contrived and for realistic sample sizes it's extremely marginal. 

## Conclusion
Writing code isn't about telling a computer what to do. It's about telling other people what you want to computer to do. You don't get points for succinct code unless you're doing code golf. You don't get points for smashing out a 1 liner that takes 5 minutes to understand. 

You get points from writing readable code, your team will thank you. 

I wrote this post as a reminder to myself. I'm guilty of doing some pretty arcane stuff with `reduce` when I should reach for a simpler solution. I'm trying to be better. 
 
So, use filter+map+whatever or regular loops: 
- ✅ More readable
- ✅ Faster (marginally)
- ✅ Anyone with a basic understanding of JavaScript understands what's going on