Tuesday, July 26, 2011

Exploring CoffeeScript Part 4 - Objects and Classes

For this blog post, we’re going to continue our journey through the wonderful world of CoffeeScript, exploring objects and classes.

Also make sure to check out the previous installments:

Objects

Most of us have know how the object literal notation looks like using plain old JavaScript. Here’s a simple example:

var podcast = {
    title: 'Astronomy Cast',
    description: 'A fact-based journey through the galaxy.',
    details: {
        homepage: 'http://www.astronomycast.com',
        rss: 'http://www.astronomycast.com/feed/',
        atom: 'http://www.astronomycast.com/feed/atom/'    
    },
    
    toString: function() {
       return 'Title: ' + this.title;
    }
};

Lets have a look at how define the exact same object using CoffeeScript.

podcast =
    title: 'Astronomy Cast'
    description: 'A fact-based journey through the galaxy.'
    details:
        homepage: 'http://www.astronomycast.com'
        rss: 'http://www.astronomycast.com/feed/'
        atom: 'http://www.astronomycast.com/feed/atom/'
    
    toString: ->
       return "Title: " + @title

As you can see, the CoffeeScript equivalent involves less overhead which naturally results in a more compact syntax. For object literals we don't have to provide curly braces and commas, taking full advantage of significant whitespace.

In this basic example, we directly assign values for the different properties which is not very common. Suppose that we want to create podcast objects by calling a factory method specifying the necessary parameter values:

createPodcast = (title, description, homepage, rss, atom) ->
    title: title
    description: description
    details: 
        homepage: homepage
        rss: rss
        atom: atom    
        
    toString: -> return "Title: " + @title    

title = 'Astronomy Cast'
description = 'A fact-based journey through the galaxy.'
homepage = 'http://www.astronomycast.com'
rss = 'http://www.astronomycast.com/feed/'
atom = 'http://www.astronomycast.com/feed/atom/'

podcast = createPodcast title, description, homepage, rss, atom

console.log podcast
console.log podcast.toString()

Again, CoffeeScript can save us some typing here as we don’t need to provide both the property name and the corresponding variable name if they are both the same. In this case we can rely on conventions to create a new podcast object.

createPodcast = (title, description, homepage, rss, atom) ->
    {   
        title
        description
        details: {
            homepage
            rss
            atom
        } 
        
        toString: -> return "Title: " + @title    
    }

Note that we need to specify curly braces for both the resulting podcast object as for the nested details object because otherwise we’ll get some parser errors. Either way, CoffeeScript gets the most out of every keystroke :-).

Classes

JavaScript is not a ‘classical’ language but a prototypal object language. There are several JavaScript libraries out there that have made an attempt to bring some form of class like syntax into the language. It’s my personal belief that by fully embracing the prototypical nature of JavaScript that we can gain the true benefits of this great language. However I do recognize that a class like syntax can save us from the syntactical and mental burden that is often seen with prototypical inheritance in JavaScript. Again, CoffeeScript is here to save the day.

By providing a class-style syntax, CoffeeScript effectively provides us with a useful abstraction on top of JavaScript’s prototype capabilities, also applying all the well-known best practices in the process. This enables us to write code that is much more concise and therefore also more clear while still taking advantage of the benefits of the JavaScript object model.

Let’s talk code, shall we?

class Medium
    constructor: (@name) ->
    
    # Prototype method
    download: (episode) ->
        console.log 'Downloading ' + episode + ' of ' + @name
    
    # Static method
    @play: (episode, name) ->
        console.log 'Playing ' + episode + ' of ' + name         
        
    playOn: -> 
        console.log 'unknown'    
                
        
class Podcast extends Medium
    constructor: (name, @description) ->
        super name
                
    listen: -> 
        console.log 'Listening to ' + @name
    
    playOn: ->
        console.log 'iPod'
        
        
class Screencast extends Medium
    constructor: (name, @description, @author) ->
        super name
        
    watch: ->
        console.log 'Watching ' + @name
        
    playOn: ->
        console.log 'iPad'

Here we have three classes. Both the Podcast and the Screencast class derive from the Medium class using the extends keyword. First have a look at the constructor functions. CoffeeScript lets us define dedicated functions that will be executed upon instantiation. Notice the shorthand syntax for property initialization. Instead of constructor: (name) –> @name = name we can simply use the equivalent constructor: (@name). This shorthand will also work for normal functions outside of classes. Remember, every keystroke counts! The constructor functions of the derived classes invoke the constructor of the base class by simply calling super, which translates into a call to an ancestor method of the same name.

Instance methods and properties can be defined exactly the same way as we saw earlier when we discussed objects. Obviously, these can only be used after we create an instance of a class.

podcast = new Podcast('Astronomy Cast', 'A fact-based journey through the galaxy.')
podcast.download 'the first episode'
podcast.listen()

screencast = new Screencast('RailsCasts', 'Ruby on Rails Screencasts', 'Ryan Bates')
screencast.download 'the 267th episode'
screencast.watch()

But we can also have static methods and properties. These cannot be invoked on instances of a class but only directly on the class object itself.

# Static method
@play: (episode, name) ->
    console.log 'Playing ' + episode + ' of ' + name

...

# Object #<Podcast> has no method play
podcast.play 'the first episode'

Medium.play('the third episode', 'Hardcore History')
Podcast.play('the fourth episode', 'Astronomy Cast')

We’ve already used the shorthand syntax here. We could also use the following notation for defining this static method:

# Static method
this.play: (episode, name) ->
    console.log 'Playing ' + episode + ' of ' + name

Remember from the previous post that CoffeeScript uses the ‘@’ symbol to alias this. Every keystroke counts!

One of the key tenets of object-oriented programming using a classical language is polymorphism. Don’t worry, CoffeeScript got this covered as well.

play = (medium) ->
    medium.playOn()

play(podcast);       # Outputs 'iPod'
play(screencast);    # Outputs 'iPad'

Here we have a function that takes in a Medium object and simply invokes the playOn() function. The playOn() functions of the derived classes will be invoked and not the one defined in the base class. 

In the previous post we mentioned that we can reuse methods from other objects using the call()/apply() methods defined on the prototype of Function. This can also be done when we’re using classes in CoffeeScript.

class PodcastStub
    constructor: ->
        @name = 'some funcky stub podcast'
        
podcastStub = new PodcastStub()
podcast.listen.apply podcastStub    # Outputs 'Listening to some funcky stub podcast'

We can use the hash rocket operator (or fat arrow) to prevent this behavior if we want. By using => instead of –> we can define a function to the current value of this.

class ContextSafePodcast extends Medium
    constructor: (name, @description) ->
        super name
                
    listen: => 
        console.log 'Listening to ' + @name
    
    playOn: ->
        console.log 'iPod'

contextSafePodcast = new ContextSafePodcast('Astronomy Cast',
                                            'A fact-based journey through the galaxy.')
contextSafePodcast.listen.apply podcastStub    # Outputs 'Listening to Astronomy Cast'

I’ll round of this post by showing you the equivalent JavaScript code for the small class hierarchy shown in our example.

var Medium, Podcast, Screencast;
var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
function ctor() { this.constructor = child; }
ctor.prototype = parent.prototype;
child.prototype = new ctor;
child.__super__ = parent.prototype;
return child;
};

Medium = (function() {
function Medium(name) {
  this.name = name;
}
Medium.prototype.download = function(episode) {
  return console.log('Downloading ' + episode + ' of ' + this.name);
};
Medium.play = function(episode, name) {
  return console.log('Playing ' + episode + ' of ' + name);
};
Medium.prototype.playOn = function() {
  return console.log('unknown');
};
return Medium;
})();

Podcast = (function() {
__extends(Podcast, Medium);
function Podcast(name, description) {
  this.description = description;
  Podcast.__super__.constructor.call(this, name);
}
Podcast.prototype.listen = function() {
  return console.log('Listening to ' + this.name);
};
Podcast.prototype.playOn = function() {
  return console.log('iPod');
};
return Podcast;
})();

Screencast = (function() {
__extends(Screencast, Medium);
function Screencast(name, description, author) {
  this.description = description;
  this.author = author;
  Screencast.__super__.constructor.call(this, name);
}
Screencast.prototype.watch = function() {
  return console.log('Watching ' + this.name);
};
Screencast.prototype.playOn = function() {
  return console.log('iPad');
};
return Screencast;
})();

Did I mention that every keystroke counts? ;-)

Until next time.

Wednesday, July 13, 2011

Exploring CoffeeScript Part 3 - More on Functions

For this blog post we’re going to continue where we previously left off, talking a bit more about functions in CoffeeScript. Let’s get things started by talking a bit about function scope.

Function scope

Like Ruby, CoffeeScript uses lexical scope. This means that a variable that is declared inside a function is invisible to outside code. From there on, a variable lives inside the scope in which a value is assigned to it without being able to be redeclared. Because we don't have access to the var keyword, we can't simply declare a variable and use it in a different scope without assigning a value to it.

Consider the following code:

someFunction = -> podcast = 'Hardcore history'

podcast = 'Astronomy cast'
someFunction()

console.log podcast        # This outputs 'Astronomy cast'

The output might come as a surprise to you, but it actually makes a lot of sense. A variable that is declared inside an inner scope cannot shadow a variable with the same name that is declared in an outer scope. I highly recommend that you avoid reusing variable names as shown by this example.

Function context

In JavaScript, the this keyword inside a function does not necessarily point to the object for which the function is declared. The object that is referenced by this depends on how the function is called. The same applies to CoffeeScript as well, only it uses the '@' symbol for denoting the this keyword in JavaScript. Let’s look at a couple of scenarios.

download = (podcast) -> 
    @podcast = podcast
    console.log @podcast    # This outputs 'Astronomy Cast'
    console.log @           # This outputs all properties of the global object
    
download 'Astronomy Cast'

Compiling this down to JavaScript results in the following code:

var download;
download = function(podcast) {
    this.podcast = podcast;
    console.log(this.podcast);
    return console.log(this);
};

download('Astronomy Cast');

As you can see, @podcast is the shorthand notation for this.podcast in JavaScript. For this example, this references the global object. Let’s have a look at another scenario.

Podcast = () ->
    @name = 'Astronomy Cast'
    @download = (episode) ->
        console.log 'Downloading ' + episode + ' of ' + @name
    return @

# Outputs 'Downloading the first episode of Astronomy Cast'
podcast = new Podcast
podcast.download 'the first episode'

This results in the following JavaScript code:

var Podcast, podcast;

Podcast = function() {
    this.name = 'Astronomy Cast';
    this.download = function(episode) {
        return console.log('Downloading ' + episode + ' of ' + this.name);
    };
    return this;
};

podcast = new Podcast;
podcast.download('the first episode');

When calling a constructor function using the new operator, this references the new object being created. We've also explicitly added 'return @' in order to return the new object. Otherwise the function assigned to the download property is implicitly returned. Let’s move on to the next case.

podcast = 
    name: 'Astronomy Cast'
    download: (episode) ->
        console.log 'Downloading ' + episode + ' of ' + @name 

otherPodcast = 
    name: 'Hardcore History'

# Outputs 'Downloading the first episode of Hardcore History'
podcast.download.apply otherPodcast, ['the first episode']        

Compiling this to JavaScript results into the following code:

var otherPodcast, podcast;
podcast = {
    name: 'Astronomy Cast',
    download: function(episode) {
        return console.log('Downloading ' + episode + ' of ' + this.name);
    }
};

otherPodcast = {
    name: 'Hardcore History'
};

podcast.download.apply(otherPodcast, ['the first episode']);

As I already mentioned in a previous blog post, we can reuse methods from other objects using the call()/apply() methods defined on the prototype of Function. In this example we reuse the download function in the context of the otherPodcast object. This means that this now references otherPodcast instead of the podcast object. Let’s dive into the final and most common scenario.

podcast = 
    name: 'Astronomy Cast'
    download: (episode) ->
        console.log 'Downloading ' + episode + ' of ' + @name 
        
# Outputs 'Downloading the first episode of Astronomy Cast'
podcast.download('the first episode')

The equivalent JavaScript code looks like this:

var podcast;
podcast = {
    name: 'Astronomy Cast',
    download: function(episode) {
        return console.log('Downloading ' + episode + ' of ' + this.name);
    }
};

podcast.download('the first episode');

Here this simply references the current object to which the executing function belongs to.

Function binding

Going over these different scenarios regarding the function context, it might be useful to be able to define a function that binds to the current value of this. In CoffeeScript we can use the => symbol instead of –> to accomplish just that. Let’s look at the code example from the CoffeeScript website.

Account = (customer, cart) ->
  @customer = customer
  @cart = cart

  $('.shopping_cart').bind 'click', (event) =>
    @customer.purchase @cart

This is especially helpful for event callbacks. The reason you might want to consider the ‘fat arrow’ in this case is that callbacks are executed in the context of the element, i.e. this references the element. When you want to keep this equal to the local context, without doing the self = this dance, then ‘fat arrows’ are the way to go.

Splats

Splats enable us to easily take a variable number of parameters in a function. JavaScript has a similar construct with the arguments object that is available in every function. But the major downside of the arguments object is that it lacks the semantics of an array which makes it pretty cumbersome to use. With splats, CoffeeScript provides us with a much better way to deal with a varying number of parameters. 

download = (name, episodes..., epilogue) ->
    console.log 'Downloading ' + episodes.join(', ') + ' of ' + name;
    console.log epilogue

# Outputs 'Downloading the first, the second, and third episode of Astronomy Cast'
#          'What a hoot!'
download('Astronomy Cast', 'the first', 'the second', 'and third episode', 
         'What a hoot!')

This boils down to the following (nasty) JavaScript code:

var download;
var __slice = Array.prototype.slice;

download = function() {
    var epilogue, episodes, name, _i;
    name = arguments[0], 
    episodes = 3 <= arguments.length ? 
        __slice.call(arguments, 1, _i = arguments.length - 1) 
      : (_i = 1, []), epilogue = arguments[_i++];
    
    console.log('Downloading ' + episodes.join(', ') + ' of ' + name);
    return console.log(epilogue);
};
download('Astronomy Cast', 'the first', 'the second', 'and third episode', 
         'What a hoot!');

As you can see, splats don't have to be defined at the end of the parameter list. For this example, the first and last value get to be assigned to the regular parameters after which the remaining values in the middle of the list get assigned to the splat parameter. When we only specify two values, then these will be used for the regular parameters while the splat parameter will be null.

The values for the regular parameters get to be assigned first after which the remaining values all get to be passed to the splat parameter. This also implies that there can be only a single splat parameter for a given function definition.

Splats are not only available for function definitions, but also for calling functions as well. 

download = (name, episode, epilogue) ->
    console.log 'Downloading ' + episode + ' of ' + name;
    console.log epilogue

# Outputs 'Downloading the first episode of Astronomy Cast'
#          'What a hoot!'
arguments = ['Astronomy Cast', 'the first episode', 'What a hoot!']
download(arguments...)

This simply boils down to calling the apply() method of the download function in the resulting JavaScript code:

var download;
download = function(name, episode, epilogue) {
    console.log('Downloading ' + episode + ' of ' + name);
    return console.log(epilogue);
};

arguments = ['Astronomy Cast', 'the first episode', 'What a hoot!'];
download.apply(null, arguments);

No doubt that CoffeeScript brings a lot of goodness to the table when it comes to functions. But there’s also a lot more. Stay tuned for the next couple of blog posts.

Until next time.

Tuesday, July 05, 2011

Taking Baby Steps with Node.js – Don’t Block The Event Loop

< The list of previous installments can be found here. >

The basic premise of Node.js is that all I/O operations are expensive. That is why all I/O should be carried out asynchronously, at least according to the philosophy behind Node.js. What this basically boils down to is that we need to specify a callback function or bind to one or more events in order to get the outcome for a particular I/O related function that we want to execute. This means that things like file access, database operations, communication over HTTP, TCP or UDP, etc. … don’t block the main execution of a Node.js application.

One of the components that lies at the heart of Node.js is the event loop. This is basically a component that processes a queue of events and invokes an associated callback for each of these events. Tom Hughes-Croucher provides a very nice explanation in this article where he provides an analogy between the event loop in Node.js and a mail man:

To our event-loop postman, each letter is an event. He has a stack of events to deliver in order. For each letter (event) the postman gets, he walks to the route to deliver the letter. The route is the callback function assigned to that event (sometimes more than one). However, critically, since our mailman only has a single set of legs, he can only walk a single code path at once.

 

image

Since the event loop is running on a single thread, it is very important that we do not block it’s execution by doing heavy computations in callback functions or synchronous I/O. Going over a large collection of values/objects or performing time-consuming computations in a callback function prevents the event loop from further processing other events in the queue.

Doing synchronous I/O is also a bad thing for the same obvious reason that it blocks the event loop. There are a couple of synchronous I/O functions available in the Node.js built-in API. A few of these are exported by the file system (fs) module (the ones that end with …Sync). I strongly advise you to stay away from these functions.

There’s one synchronous, pseudo-global function that you probably have to use in any Node.js application besides the typical “hello world” example, and that is the require function. By executing the require function we can load another module into the process of our application. This means that the content of the corresponding JavaScript file for a requested module is read from disk. By caching this JavaScript content, Node.js ensures that such an expensive synchronous read doesn’t happen more than once when the require function is issued multiple times for the same module. Because we typically make a call to the require function at the beginning of a module, executing this synchronous function only affects the startup time of our application. Make sure that you do not call the require function inside a callback. In this scenario, the event loop is blocked until the requested JavaScript file is loaded from disk (unless the requested module is already in the cache, but don’t count on it).

The event loop that is baked into Node.js is a wonderful thing when building real-time applications. But it can turn into a nightmare when holding on to the paradigms of synchronous I/O. Node.js stands for asynchronous I/O and the event loop is the pumping heart that makes it happen.

Until next time.