Refactoring Mock Couch

So I’m working on a boilerplate and website that relies on an Apache CouchDB database. The site boilerplate, site, and database all work pretty well, but I want to use some CI/CD tools to run testing.

I have a couple of options open to me such as using configuration management to set up the whole environment, using Docker for key pieces of the environment, or finding some libraries that mock some of my required components, like CouchDB. After looking into what I would have to learn in order to implement each of them, I ended up deciding that for the near-term just going with mocking libraries would be the easiest.

Table of Contents

Why refactor this? Where did this idea come from?

Since the site is using Redis for the cookie store, we’re using the excellent redis-mock for that. Almost entirely based on the hilarious logo for it (not actually true), we quickly decided on mock-couch to mock our CouchDB. There was one problem though: the current version of mock-couch doesn’t run with NodeJS 8.x.

So I decided to refactor it in order to bring the packages up-to-date, hopefully get it working with current versions of NodeJS, and take advantage of newer language features.

I forked it a few months ago and have been working on it on-and-off here, under the update-packages branch. After I’m done I’m going to submit it back to the original author to see if he’ll accept my PR for this. If he doesn’t we’ll see where this goes from there. Maybe I’ll continue development as a new package if the merge request is declined?

Error Analysis

When I was initally trying to use this package, it always immediately threw a bunch errors. I was able to trace the errors back and found an open issue that was related. I think that it’s mostly being caused by an older version of restify and the spdy package that it relies on. A subsequent commenter on that issue discovered that this problem is found only with NodeJS > 7.x, so that means my NodeJS 8.x project is impacted. So far, that commmenter’s pull request has not been merged in even though it’s a fairly minor change.

Why not stop if somebody already made a Pull Request for your problem?

Because I think there are some other benefits to a deeper refactor in this case.

Case in point: the ramda package has evolved very much since the version this was written for and current versions of ramda actually break this package. Sure, that older version works, but this package also has reliance on it in ways that don’t simplify the code, and in some cases make it more complex for developers unfamiliar with ramda. In fact, I found that in many cases the vanilla JavaScript solution was easier to read and understand than the ramda implementation. This holds most true for the uses of ramda’s Compose() function.

Abuse of ramda.Compose()

ramda.Compose() lets you chain a bunch of function calls together, each one putting its outputs into the next one’s input. Except it’s inverted. Which isn’t intuitive at all! You end up having to read UP the page in order to understand how the code block flows.

This might be acceptable if some very complex things were going on, but most of what was going on could easily be solved with plain Array methods.

Package Linting

The package as written uses jslint, which is great. However I kind of prefer eslint and (in my opinion) the better tooling and configuration that it comes with. So jslint has been replaced with eslint.

Things that I’m leaving alone… for now.

For the moment, this is using jasmine tests. I somewhat prefer mocha, but I want to leave jasmine in place at least until I’m once again passing all tests after the refactor. Maybe at that point I’ll replace it with mocha.

I’m also leaving grunt in place as the task runner. It isn’t a very complex gruntfile at this point, so it may ultimately not be needed. I could probably replace grunt with just npm scripts with how simple they are.

Working on the code

Since I really wanted this to be totally up-to-date I started off by doing an npm update. This updated all of the packages to their most current versions and this is where I discovered the breaking changes that more modern versions of ramda introduce. I left everything in place as it was for the moment.

eslint --fix did a ton of work in whipping all of this code into shape. After it’s initial pass to fix things that are pretty straightforward I then loaded everything in /lib into my vim buffers and started working through the remaining lint errors.

As I went along I also tried to update the broken ramda code, but time after time I discovered that what was going on in the ramda calls was pretty basic stuff that could quite easily be done using vanilla JavaScript, often with Array methods. So after replacing a couple of ramda calls with vanilla equivalents I did a quick peak at all of the other places using ramda and discovered that pretty much all of them were trivial replacements, and there were only a couple of instances where I would have to go a bit beyond “trivial” to convert things to vanilla JS. So I came to the conclusion that ramda wasn’t really needed and removed it from the package dependencies.

With that out of the way I continued working through all of the buffered files, fixing linting errors and replacing now-defunct ramda calls with vanilla JS.

Working on the tests

Once again eslint --fix was a lifesaver here. It fixed a bunch of formatting issues in the tests, and the remaining ones were pretty simple to deal with. Mostly things like using destructuring, having individual let and const assignments instead of chaining assignments with commas, implementing arrow functions for unnamed functions, stuff like that.

Running the tests

This is where I’m at now. It isn’t as bad as I was thinking it would be. Roughly 50% of the tests are passing, which means that I probably just made some goofy errors in a couple of key places as I was converting away from ramda. I’m about to get into that now.

Wrapping up

Once I finish up getting all of the tests to pass I’ll update with a new post, sumbit the merge request and see where this goes after that. At the very least I’ll be able to make use of it for my purposes, so definitely looking forward to that.

Jeremy Jackson
Software Engineering and Data Science