Tuesday, 9 February 2016

Easy Singletons with CommonJS

Bye bye, singleton wiring and getInstance()!

CommonJS has a nice way of automatically creating singletons out of your modules. It's all in how you write your modules and what you export from them. No more hideous getInstance methods that drowns out the actual purpose of the module, sweet! If that's what you want, of course. If not, the behaviour might be a bit confusing... :)

CommonJS and Browserify

To be able to use the same syntax in your browser javascripts as you do in node, using CommonJS-modules with an exports-statement, you have to use a tool like Browserify or Webpack. I'm sure there are others out there too, but these are the ones I'm familiar with. Browserify is very easy to setup for small private projects. I'll try to walk you through it.

Project structure

The structure of this little project is the simplest possible: A source-folder containing Index.html and three js-files. Main.js is the entry point for the javascript source files and uses the colourFetcher.js and colourRepository.js to fetch and display colours. What we want to do is use Browserify to bundle up all the js-dependencies into one file that we can include in Index.html.

Install Browserify

You can find more info about Browserify on browserify.org. You need node on your machine, and then it's a cakewalk to install it:

In your root folder, create a package.json file if you don't already have one. This is done by running the command npm init in the terminal and answering the questions.

Install Browserify by running npm install browserify --save-dev in the terminal. This will install the package and add the dependency to the devDependencies-section of your package.json.

If you want to explore the options available, just type browserify in the terminal and take it from there. What we want to do now is just take all js-files in the src-folder and bundle them into a bundle.js-file placed in a public-folder. Just create a new folder named public under src and in the terminal, run browserify src/*.js -o src/public/bundle.js -d. The first part of the command is the glob-pattern for the files to bundle, the -o is the output location and -d stands for debug and means source maps will be generated. We probably don't want to have to remember this command, so change the script-section in package.json to look like this:
"scripts": {
  "start": "browserify src/*.js -o src/public/bundle.js -d"
}
Now you can handily run the site with the command npm start instead and add the bundle.js as the js-source for your index.html.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Singleton</title>
    <script src="public/bundle.js"></script>
</head>
<body>
</body>
</html>

Add Watchify

To add a nice watch-function that immediately re-bundles your files when they're modified, install Watchify with npm install watchify. Modify your package.json again with:
"scripts": {
  "start": "browserify src/*.js -o src/public/bundle.js -d 
     && watchify src/*.js -o src/public/bundle.js -d -v"
}
This will run browserify immediately followed by watchify with the verbose setting on (-v).

Back to the singleton issue

Now, we should have a nice environment up and running for trying out the quirks and wonders of CommonJS. For instance module caching. So let's create some code. First colourRepository.js:
var colourRepository = function () {
    var colours = {
        magenta: "#FF00FF",
        palegreen: "#98FB98",
        chocolate: "#D2691E",
    };

    var list = function (callback, message) {
        if (!message)
            message = "from repo";
        callback(colours, message);
    };

    console.log("new colourrepo");

    return {
        list: list
    };
};
module.exports = colourRepository;
ColourRepository.js just sets up a list of colours and passes them along into the callback function provided by the caller. If there's a message it gets sent back to the callback too, otherwise we add one.

Next up, colourFetcher.js, that requires colourRepository as a dependency and calls it:
var colourRepo = require("./colourRepository")();

var colourFetcher = function() {
    var list = function(callback) {
        colourRepo.list(callback, "from fetcher");
    };

    return {
        list: list
    };
};
module.exports = colourFetcher;
And last, main.js, that requires both of the modules and therefore fetches colour in two different ways:
var colourRepo = require("./colourRepository")();
var colourFetcher = require("./colourFetcher")();

colourRepo.list(listColours);
colourFetcher.list(listColours);

function listColours(colours, message) {
    console.log(message);
    for (var colour in colours) {
        console.log(colours[colour] + '=' + colour);
    }
}
If we run this code, we notice that the console logs "new colourrepo" twice. Once when the repo is required in main.js and once when it's required from colourFetcher.js. This is because we're exporting colourRepository as a function. When we require it, we call the function at the same time using var colourRepo = require("./colourRepository")();. No caching, no singleton.

So, what if we change the code in a couple of places? Instead of exporting a function in colourRepository.js, we change the last line to module.exports = colourRepository();. The exports-statement now returns the called function when the module is loaded. When we require the module in main.js and colourFetcher.js, we can now remove the call to that function: var colourRepo = require("./colourRepository");. As the code is run, the console only logs "new colourrepo" once, and with the tiniest of effort we've turned our colour repository into a singleton. :)

Summary

Modules in CommonJS are cached after the first time they're loaded. This means that require("colourRepository") will return the same object everywhere, if it is resolved by the same file. If this is not the wanted behaviour, the exports-statement of the CommonJS-module should return a function instead, and the calling script must call that function.

Thursday, 4 February 2016

Writing a pure javascript repository pattern

My javascripting needs work!

I suffer from javascriptus horribilis. I don't know why all my knowledge of object oriented programming and patterns disappear when I write javascript. It feels like I'm coding myself into a corner all the time. But I'm trying to improve. One step was to try and mix a bit of factory and repository thinking into my javascripts. Don't you just feel the weight of the Gang of Four-book sweeping in by now?


Basic train of thought

So the idea is this; think layers in javascript. That sounds like a very non-hipster thing I guess, stiff and overly complicated, but if we think 'components' or 'modules' instead it gets more hip by the minute. What I wanted to do was basically:
  • The calling component calls a repository, with a callback to trigger when the data returns.
  • A repository factory provides the available repositories to the calling component.
  • The repository exposes public methods for CRUD, provides data from some source and calls the callback provided from the calling component. Whether the source is static content, an external service or whatnot is not important, and the calling component doesn't have to know anything about that.
Code is available on Github. I like the Node-way of requiring modules, so I use Browserify to be able to write my code in commonjs-style.


A CRUD Repository

Let's start with creating a basic User Repository, userRepository.js.
var userRepository = function() {

    var get = function(id, callback) {
        callback();
    };

    var list = function(callback) {
        callback();
    };

    var save = function(user, callback) {
        callback();
    };

    return {
        get: get,
        list: list,
        save: save
    };
};

module.exports = userRepository();
The code executes when it is required (module.exports = userRepository()) and the methods get, list and save are exposed. Now we can require and call the repository from our main.js file:
var userRepo = require("./userRepository");
userRepo.get(1, getUser);

function getUser() {
    console.log("got the user");
}
This code requires the user repository and assigns it to the variable userRepo. Now we can call the get-method and send along the callback function that we want the user repository to execute when the data is fetched. For now, the callback just logs a message.


Implementing the CRUD-methods

Now, what the repo actually does can of course be whatever. Fetch data from an array in the repo, from external or internal services or from text files. I just fake a service by fetching the content of a json-file, users.json.
[
  { "id":1, "name":"User Number One" },
  { "id":2, "name":"User Number Two" },
  { "id":3, "name":"User Number Three" },
  { "id":4, "name":"User Number Four" }
]
To fetch these, I want to make an Ajax-call using a promise. Granted, promise is not a standard in for example IE, but there are nice polyfillers out there that will do the trick. The nice thing about promises is that you can chain methods together and the catch-clause catches errors in all of the then-clauses. In userRepository.js I extend my get-implementation to this:
var get = function(id, callback) {
    ajax.makeRequest('GET', 'users.json')
        .then(function (data) {
            var users = JSON.parse(data);
            var user = users.filter(function(user) {
                return user.id === id;
            });
            if (user.length > 0)
                user = user[0];
            callback(user);
        })
        .catch(function (err) {
            console.error('Ouch, there was an error!', 
            err.statusText);
        });
};
I make a request to users.json and when the promise is resolved and returns, I parse the data, filters the users by id and returns the correct user. Yeah, not the most efficient way to get a user, agreed, but it's there to show that there's a middle layer between the actual ajax-request and the component needing the data. :)

When the user is filtered and ready, the callback is executed, sending along the user. The ajax-component being used in the repo looks like this, but it's outside the scope here and really not important:
var ajax = function () {

    var createParams = function (params) {
        if (params && typeof params === 'object') {
            params = Object.keys(params).map(function (key) {
                return encodeURIComponent(key) + '=' 
                  + encodeURIComponent(params[key]);
            }).join('&');
        }
        return params;
    };

    var makeRequest = function (method, url, params) {
        return new Promise(function (resolve, reject) {
            var xhr = new XMLHttpRequest();
            xhr.open(method, url);
            xhr.onload = function () {
                if (this.status >= 200 && this.status < 300) {
                    resolve(xhr.response);
                }
                else {
                    reject({
                        status: this.status,
                        statusText: xhr.statusText
                    })
                }
            };
            xhr.onerror = function () {
                reject({
                    status: this.status,
                    statusText: xhr.statusText
                });
            };
            if (params) {
                params = xhr.params = createParams(params);
            }
            xhr.send(params);
        });
    };

    return {
        makeRequest: makeRequest
    }
};

module.exports = ajax();


A repository factory, just because factories are cool

After writing all possible repositories, the code in main.js looks quite nice. Lots of different repositories being required and assigned to variables though.
var dom = require("./domManager");
var userRepo = require("./userRepository");
var catRepo = require("./catRepository");
var colourRepo = require("./colourRepository");

userRepo.list(listUsers);
catRepo.list(listCats);
colourRepo.list(listColours);
colourRepo.get("magenta", showColour);

function listUsers(users) {
  users.forEach(function(user) {
      dom(".userList").addListItem(user.name, user.id);
  });
}

function listCats(cats) {
  var catsWithImages = cats.filter(function(cat) {
      return "image" in cat;
  });

  catsWithImages.forEach(function(cat) {
      dom(".catList").addHtml(
       "<div><img src='"+cat.image+"'></div>"
      );
  });
}

function listColours(cols) {
  for (var col in cols) {
      dom(".colourList").addHtml(
       "<div><b style='color:"+cols[col]+"'>"+col+"</b></div>"
      );
  }
}

function showColour(hex) {
  dom(".bestColour").element.style.backgroundColor = hex;
}
The repository factory to the rescue! Easy-breezy repositoryFactory.js takes care of the plumming:
var repositoryFactory = function() {
    var repos = this;
    var repositories = [
      {name: "users", source: require("./userRepository")},
      {name: "cats", source: require("./catRepository")},
      {name: "colours", source: require("./colourRepository")}
    ];

    repositories.forEach(function(repo) {
       repos[repo.name] = repo.source;
    });
};

module.exports = new repositoryFactory();
The factory contains an array with all available repositories. When it is required, it loops through the repos in the array, requires all of them and assigns them to properties on 'this'. Since they execute when they are required, they're all exposing their public methods and are ready to be used. Neat and tidy. And now we can do this in main.js:
var repos = require("./repositoryFactory");

repos.users.list(listUsers);
repos.cats.list(listCats);
repos.colours.list(listColours);
repos.colours.get("magenta", showColour);