Re-ordering Objects in a List

In an old version of an app I wrote, I had a list of objects which were in a specific order. I wrote the app to operate using a REST API, so when you changed one of the objects, the client sent a PUT request to the server with the new data for that object and the change was made.

This worked very well for everything except then I got into a bind trying to figure out how to change the order of the objects in the list.

The way I did it back then was… not the greatest. I assigned a property to each object called order which was the index of that object in the list. When the user moves an object, the client sends a PUT request to the server telling it the new value of order. So if you moved the object at position 5 to position 2, my app would ask to change that object to have an order of 2.

Sounds easy enough. But wait, there’s already an object with the order of 2. What do we do with that? So we have to move it down to 3. In fact, we have to move all of the objects below that down one index, up until we get to the old index (because we don’t want to move the object with the order of 6).

That’s a lot of work (and a lot of changed models), especially for long lists. It’s also an entirely different operation if you’re moving objects down the list versus moving objects up the list (you have to update the objects in the reverse direction). And to make it extra-hard, my code needed to perform this complex operation twice: once on the client before we sent the data (since the data sent to the server was mirrored on the client), and once on the server.

Recently I was going over this code again and I saw what amounted to a pretty big mess that I was sure could be done differently. I started thinking of a deck of playing cards, and how easy it is to just move one card from one place in the deck to another. How simple! Could I achieve the same simplicity here?

My first realization was that there’s already a type of object in programming languages that handles re-ordering very efficiently, just like a deck of cards: the humble Array.

I was so fixated before on the idea that each object had to have an order property, that I missed what may otherwise have been obvious. When I re-order something, I’m really re-ordering the whole list, which is just like re-ordering an Array.

By removing the order property from each object on the client, I no longer need to update each object when the order changes; the objects simply have different places in the Array. Then I just send the whole new array back to the server (actually just the IDs of the objects) and the server updates its version of the list as well.

I’m sure this is not a new idea, but it was new to me, and it’s saved me a lot of work. It just goes to show how we evolve as developers over the years and how it’s probably always worth going back over old code.

ES2015 module re-exports

Today’s episode of TIL (“Today I Learned”) is:

Did you know you can re-export modules in ES2015 (aka: ES6, aka: new JavaScript)? That is, you can import a module and export it again all in one line of code. Why would you want to do this?

Well, first you need to know about the way importing directories works. If you write import foo from './foo', the JavaScript engine will look for either a file named ./foo.js or a directory named ./foo. If the latter is found, it will assume the directory is a node (npm) module and look inside for a package.json to determine what file to include. If there is no package.json, it will default to loading ./foo/index.js.

Sometimes I have a file I’ve been importing, like user.js, containing a default model and a validation function:

export default { firstName: 'Big', lastName: McLargeHuge' }
export function validateUser( user ) {
  if ( user.firstName && user.lastName ) {
    return true
  }
  return false
}

In the rest of my code, I load it like this:

import user from './user'
import { validateUser } from './user'

Then later I decide I actually want to split up the code inside user.js into multiple files, all related to users. Let’s say I want to add a new file for validation of user data. In that case, I can move user.js to ./user/index.js and add the file ./user/validation.js.

Here’s ./user/index.js:

export default { firstName: 'Big', lastName: McLargeHuge' }

And here’s ./user/validation.js

export function validateUser( user ) {
  if ( user.firstName && user.lastName ) {
    return true
  }
  return false
}

That works well! Now in the rest of my code I can load things like so:

import user from './user'
import { validateUser } from './user/validation'

But wouldn’t it be nice to be able to get the validateUser function from the user module without needing to know the internal structure of that module? Here’s where we can use re-exports.

By adding this line to my ./user/index.js, I can import and export my validation code in one shot: export { validateUser } from './validation' (or even easier, export * from './validation').

Let’s take this one step further. I don’t want to have that re-export dirtying up my user model file. Let’s move my default user module into its own file, ./user/main.js:

export default { firstName: 'Big', lastName: McLargeHuge' }

We’ll just re-export that too. (We just need to do one tricky thing in order to re-export a default, we have to write export {default as default}). So now the ./user/index.js looks like this:

export { default as default } from './main'
export * from './validation'

Magic! Now in the rest of my code, I can just write:

import user from `./user`
import { validateUser } from './user'

And yet the code for both of those is in entirely separate files!