Tuesday, February 11, 2014

Object Oriented Programming in JavaScript (Part 1)

There is been a while since my last post, I've been occupied studying for my exams mainly, also, this semester, my teams in two class projects decided to take vacations, and I ended up with extra load. Anyways, my experience was good, because the projects were really interesting, one was about secure communications via SSL, between an Educational Grades Submission System and the other was about Cacti, a Network Monitoring Tool that allows you to draw beautiful graphics about almost everything that can be extracted via shell scripting! All my semesters in the university tend to show me, that the Team factor is the most important part of any software project.

This post will be about Object Oriented Programming in JavaScript: Classes and Encapsulation, since my first experience with JavaScript I always felt like there were thousand ways to achieve a task due to the high flexibility of the language, although with expertise and some knowledge, it's in fact possible to work with JavaScript in an Object Oriented way.

Because of this, I think that is fundamental for every JavaScript Programmer to learn, how to program in this language in an OO way. 

Just in case you are really asking the question "Why is that? What's wrong with function foo(){ alert('bar'); } in my code? It works!", well the direct answer is, it depends, and it depends on the lifetime of you code, if you wrote that function for a website that will be active just for a weekend event, then your code is great, don't bother improving it. 

But if your code is suppose to be read, modified or even fixed by others, you will want to improve your code, or that or you will endup taking lunch alone :) , while your colleagues will be pissed at you because of the time they took to understand your code logic. Please notice that, master the fundamentals of what OO defends is just like for example, UML, why learn UML? It's boring as hell, It's a pain to do it well, and again, It's boring. And the key answer to that is, we interact with people and it's important that all speak or know how to speak in the same language.

The Concept of Object Oriented Programming, is made of 3 fundamental key concepts:
  • Encapsulation;
  • Inheritance;
  • Polimorphism.

I will show you, how to achieve each of this key concepts, in a series of articles, being this about Classes and Encapsulation.

The first think you need to know is how to create a class:

/* class Book */
function Book(){
   ...
}

Hey, stop! But function is analog to a method in OO programming right? Well, if you're writing a function Book with the objective of using it together with the operator new then function should be read as class, this is one of the reasons why you should master OO programming in JavaScript  (P.S: comments are very important too, always comment your code)!

Now, creating a full class with methods, constructors and everything:

/* class Book */
function Book(){
   /* private variables */
   var _name,
       _description,
       _isbn,
       _authors;

   /* get/set/property for field 'name' */
   this.getName = function(){ return _name; }
   this.setName = function(name){ _name = name; }

   /* get/set/property for field 'description' */
   this.getDescription = function(){ return _description; }
   this.setDescription = function(desc){ _description = desc; }

   /* get/set/property for field 'isbn' */
   this.getISBN = function(){ return _isbn; }
   this.setName = function(isbn){ _isbn = isbn; }

   /* get/set/property for field 'authors' */
   this.getAuthors = function(){ return _authors; }
   this.addAuthor = function(author){ _authors.push(author); }

   //constructor-code
   //read bellow (will talk about this)
   _authors = [];
}
In the code above you can see that we have private fields prefixed with "_", this is just a code convention, the reason why they are private is because they are declared as var fieldname inside of the function Book, so their scope is limited to the code running inside function Book.

Also you can see that we have methods declared like this this.methodname = function(){}, so this type of methods are called privileged methods, because they are methods that have access to private variables.

We have a constructor too, see the comments in the end of our function Book? All the code inside the function Book is the constructor, by convention, we can put constructor specific code in the end of the function Book, although at the end of this article you will see the right way to do it.

By the way, have I said that functions in javascript have a context of their own and they are are all seen as objects? No? Well, let me use the code above, the code above as a problem, what will happen if we call the keyword this, inside of the function getAuthors? let's say... like this this._authors? What will happen, is an undefined exception, because in the context of the anonymous function defined in the this.getAuthors, _authors is not defined.

What? Yes, it's true, this happens because of something I haven't told you before, function(){ } is an anonymous function, and this inside of it is referring to the anonymous function, not the function Book. We will see later how to handle this.

Now a class with a good constructor:

/* class Book */
function Book(){
   /* private variables */
   var _name,
       _description,
       _isbn,
       _authors;
   
   (function Book_(){
      _authors = [];
   }).apply(this, arguments);
   
   /* get/set/property for field 'name' */
   this.getName = function(){ return _name; }
   this.setName = function(name){ _name = name; }
   
   /* get/set/property for field 'description' */
   this.getDescription = function(){ return _description; }
   this.setDescription = function(desc){ _description = desc; }
   
   /* get/set/property for field 'isbn' */
   this.getISBN = function(){ return _isbn; }
   this.setName = function(isbn){ _isbn = isbn; }

   /* get/set/property for field 'authors' */
   this.getAuthors = function(){ return _authors; }
   this.addAuthor = function(author){ _authors.push(author); }
}

Now when the function Book is instantiated, all the code inside of it, will be executed, and when the code (function Book_(){  }).apply(this, arguments) is called, what will happen is that, the function Book_ will be called with the arguments passed to the class Book! The variable arguments exists in every javascript function and represents an array of the parameters passed to it, so for example if you call some function like this foo(a,b,c,d,e), arguments will be [a,b,c,d,e].

The this in the apply function makes the this keyword inside Book_ point to the Book function instead, which is more useful since the this of the Book_ function is pretty much useless.

This means that now we can do this var x = this.getName(); inside of the constructor Book_, you need to use this to access getName the same way you need to do it in Java or C#, this is, you use it or you don't, it's your choice, what we need to ensure is that, if one decides to use this inside Book_, the this will work as supposed in an OO language, instead of introducing a bug.

After all of this, you may be asking, ok, we have private fields (variables), but what about private methods? How can we specify a public interface for our classes? Well, I will explain it with an example:

When we do :

var book = new Book();

The book variable holds and instance of Book, where you can call, all the members defined inside of Book's constructor using this.something = ...  .

To create private methods you use Nested Functions, which are functions declared inside of Book constructor:

/* class Book */
function Book()
{
   /**
    * Private Fields (private)
    */

   var _name,
       _description,
       _isbn,
       _authors,
       _rating;

   /**
    * Public Fields (public)
    */
   
   this.imageURL = 'http://google.com?q=images';
    
   /**
    * Constructor
    */   

   (function Book_(){
      _authors = [];
      _rating = 5;
   }).apply(this, arguments);

   
   /**
    * Private Methods (private)
    */

   function getAmazonBookImage(){
       //some ajax request ($.ajax or $.json)       
   }

   function getAmazonBookInfo(){
       //some ajax request ($.ajax or $.json)
   }


   /**
    * Privileged Methods - Methods with access to private scope.
    */

   /* get/set/property for field 'name' */
   this.getName = function(){ return _name; }
   this.setName = function(name){ _name = name; }
   
   /* get/set/property for field 'description' */
   this.getDescription = function(){ return _description; }
   this.setDescription = function(desc){ _description = desc; }
   
   /* get/set/property for field 'isbn' */
   this.getISBN = function(){ return _isbn; }
   this.setName = function(isbn){ _isbn = isbn; }

   /* get/set/property for field 'authors' */
   this.getAuthors = function(){ return _authors; }
   this.addAuthor = function(author){ _authors.push(author); }
};

/**
 * Public Methods of Book
 */
Book.prototype = {
    getRating: function(){
        return this.imageURL;
    }
};

//little example
var book = new Book();
alert(book.getRating());


Some thoughts of all of this I have talked about, that you should have in mind:
  • The public methods declared in prototype will be available in all instances of Book, and they occupy space in memory just one time, this is, all methods of Book declared via prototype will be created from it. While this is good in terms of memory, the only drawback is that, public methods will not have access to private scope (variables/methods).
  • To declare functions that have access to the private scope, you must declare them from within the constructor code using this keyword. This kind of methods are called privileged methods, because they are public and have access to the private scope. The drawbacks are that you must be careful using the this keyword inside of this methods, because they are declared using anonymous functions this.getName = function(){ //this, in here refers to this function! }, and the other drawback, probably the biggest is that, for each instance of Book you will be using extra memory for each one of the private and privileged methods you declared, remember that everything in JavaScript except for variables of the 3 primitive types is an object. This means that functions are also an object.
  • This as the potencial to use more memory than other approaches, so it should only be used when you require true private members. This approach is also hard to subclass when using inheritance (I will talk about this in another article). The new inherited class will not have access to any of the superclass private methods or attributes.
    We often listen that "Inheritance breaks Encapsulation", because the subclasses have access to the superclass protected methods and attributes, in javascript this is not true.

For the unexperienced and even for the experience javascript can be tricky to understand sometimes, but once you find a convention it becomes easier to program good and maintainable programs. 

Although for many corporations can be hard to ensure that all programmers handle JavaScript the same way, so I advise you to take a look at CoffeeScript. Whether to use it or not, my opinion is that it's depends on, what's the lifetime of your code? How many code is involved? ...

So this article talked about classes and encapsulation in JavaScript and how you can create private/public members in a Class, I hope you liked it.

Next time, I'll write about other approaches on how to handle JavaScript Encapsulation, Closures,
followed by Inheritance and Polymorphism, stay tuned.