Wednesday, September 10, 2014

Stop using thiz, that, and self...

Quite often, I come across code that needs to keep track of "this" while still calling inner functions or callbacks. In each case, "this" has been reassigned to some other variable to keep a handle on it. See below:

userObj.getExtraData = function (cb) {
  var that = this;
  getAsyncData(function (data) {
    that.extraData = data;
    cb();
  });
};

userObj.getExtraData(function () {
  console.log(userObj.extraData);
});


You can get rid of those pesky variables (thiz, that, self, _this, whatever) by just using Function.prototype.bind like so:

userObj.getExtraData = function (cb) {
  getAsyncData(function (data) {
    this.extraData = data;
    cb();
  }.bind(this));
};

userObj.getExtraData(function () {
  console.log(userObj.extraData);
});


Huzzah!! We've got "this" back!

Edit:

The new ES6 syntax makes this a lot easier with big arrow syntax. It gives you a shorthand for writing functions while auto-binding your context. This:

(data) => {
   // do stuff
}

Is equivalent to this:

function (data) {
 // do stuff
}.bind(this);

Hence, the example turns into:

userObj.getExtraData = function (cb) { 
  getAsyncData((data) => { 
    this.extraData = data; 
    cb(); 
  });
}; 

userObj.getExtraData(function () { 
  console.log(userObj.extraData); 
});

Thursday, September 4, 2014

Don't make promises

Wrapping promises with promises to return promises that were already promises

When I first began to understand the value that promises could be to my code, I immediately began to misuse them.  I would create a deferred and resolve it like this:

function getData() {
  var deferred = $q.defer();
  $http.get('http://some.url.com/data')
    .success(function(data) {
      deferred.resolve(data);
    })
    .error(function(data) {
      deferred.reject(data);
    });
  return deferred.promise;
}


Then it occurred to me that $http returns a promise. So the above code was equivalent to (but slower than) this:

function getData() {
  return $http.get('http://some.url.com/data');
}


That example used the Angular.js $q promise implementation, but the same code works with all of the other major promises implementations.

Dealing with callbacks

Once I figured out that I could just return the promise, I realized that the only time I needed to create promises was when I was dealing with libraries like request, nano, fs, etc. Then I discovered bluebird's promisify and promisifyAll. Bluebird's promisifyAll creates functions that return promises instead of calling callbacks for almost any library. Here is an example with request:

var Promise = require('bluebird');
var _request = require('request');
var request = Promise.promisifyAll(_request);

exports.getData() {
  return request.getAsync('http://some.url.com/data')
    .then(sanitizeData)
    .catch(logAndRethrow);
}


Don't make promises

So now there is almost no reason to make a promise. Library authors and dumb setTimeout examples aside, creating promises should be extremely rare.

What is DevOps

This post isn't to point out bad or good coding practices, but to help us think about how we can better leverage the DevOps practices we have been putting in place.

DevOps is both a role and a process.  It's a way of organizing your team and sharing responsibilities in order to produce higher quality software, faster.

DevOps, while a portmanteau of 'development' and 'operations', does not mean 'development operations'.  Rather, it represents a blending of the traditionally separate processes of software development and IT operations.  

As a methodology, DevOps means some fundamental changes to how traditional (and even agile) software teams work.  In a sense, every team member becomes a DevOps engineer, if not in title.  Developers must own their code from creation to production, no more "throwing it over the wall" to QA and SysOps.

As a role, DevOps takes responsibility for everything that happens from when the developer writes his code, through the deployment and operation of software in a production environment.  This includes: 
  • quality assurance and testing activities
  • creating and maintaining the build environments
  • managing dev, test, and staging lanes
  • deploying, monitoring, and maintaining in production
So, in practice what does this mean?


Testing

Since the developer owns his code from inception to production, he is responsible for testing it and guaranteeing it will work in a production environment.  This usually means providing valuable unit tests, as well as functional and integration level testing, both manually and through automation. A DevOps engineer supports this testing in many ways:
  • Providing a robust automation framework
  • Being a "second set of eyes" for functional testing
  • Assisting with adding automation tests
  • Ensuring all needed testing happens, regardless of who does the testing
  • Stress and performance testing
  • Other types of system level tests when necessary (security, etc.)
It's important to note that while a DevOps engineer may take on a lot of the testing that a developer does not have time to focus on, this should not be done without the developers participation.  Being aware of what is being tested and how, and what the results are, is how the developers best improve their code and even their coding skills.


Build Management

A DevOps engineer is responsible for creating and maintaining a build environment that provides:
  • Continuous integration, including automation that can run automatically and inform the developer if their new code broke anything.
  • Continuous deploy to test and stage environments, including additional automation tests where appropriate.
  • Continuous deploy to production, including feedback to the development team on how their new release compares to other releases through environment monitoring.

SysOps

DevOps becomes responsible for managing and monitoring the production environment to guarantee uptime and provide performance and statistical reporting for the application.  This should be provided continually as feedback to the development team.


Development

DevOps engineers also participate in the software development process. Primarily this is focused on library support and building the necessary pieces to support testing, continuous integration/deployment, monitoring, security, etc. This relieves the pressure from other developers, allowing them to focus on customer requirements.

However, the purpose of using DevOps methodologies is to maximize team velocity.  So, when all of the items discussed above are handled, or when priorities dictate, a DevOps engineer can participate in feature development.


Team Organization

DevOps is a separate discipline from development, and is usually managed separately and deployed to software teams as needed, but it is important that they be considered as a member of a development team as integral as any other developer.  They collaborate closely with all the developers and participate in meetings and discussions such as scrum, planning meetings, and customer requirements discussions.


Summary

While the DevOps engineer takes primary responsibility for the items above, the primary principle is that the team as a whole is responsible for the entire lifecycle of their product. DevOps engineers can participate in development tasks, and developers can participate in DevOps tasks.

The end goal is to create an environment where a project development team can operate self-sufficiently, without relying on outside groups.  This means a given team will never need to wait for the availability of another group's time, or jockey for priority position with other competing projects.  This eliminates dead time in the product lifecycle and keeps the team producing at maximum capacity during every phase of development.  It also means the team is always available to respond to customer demands as quickly and efficiently as possible.