Saturday, March 30, 2013

Hiding implementation details

Introduction

I started to  seriously consider javascript as a development language three years ago when I tried to implement a card game simulator (the pokemon one). You will find some running code here: PokeMul. The project is not really finished nor over but a Flash version of the game has been officially released and it outblooms my own realisation (Pokemon TCG).This is why I decided to focus on putting in common tools and technics that could be reused in other projects.

I have been impressed by jQuery which offers a rich, comprehensive and widely accepted API and my goal is to achieve the same kind of success (let be optimistic). More seriously, I already learned a lot by doing this, I hope this would be helpful to someone.


Before going any further, I make the assumption that you are familiar with the javascript language  and some of its "advanced" concepts (objects, prototype, closure...).
If not, I highly advise you to go to this well documented learning site: Codeacademy.

Most of the libraries you would find on the net are delivered into a single javascript file (for instance: jquery.js). Once loaded and evaluated in your HTML page, it extends the execution context with its own API.
Very often, those libraries own a hidden part that contains the implementation details. For instance, some variables are kept as caches to store information. The same way, some methods - known only by the library developpers - are used to put in common some code.

My research is to know how I can control what is exposed or not.

Demonstration

I created a page to demonstrate the different ways to declare things and how they appear in the global context: demonstration. Don't hesitate to use "view source" on the page to see how it is coded.

How does it work?


The starting point is to enumerate all the members of the global context to check what becomes available to the user of a library.

As this enumeration is done several times, everything is stored in an object (used like a dictionary). It allows me to see what is different between two consecutive calls.

// Maintain the known properties inside a global map var members = { _count: 0 }; // The following are "known" because declared below (they are not 'counted') members[ "members" ] = 0; members[ "echo" ] = 0; members[ "enumMembers" ] = 0; members[ "addInclude" ] = 0; The enumeration function itself uses the for ... in syntax to enumerate members. By default, this is used to enumerate the global object.

You will also notice the use of an addInclude function that is capable of dynamically inserting a script tag and wait for the loading to be done (based on the jQuery implementation). This will be detailled later.

What does it demonstrate?

In the first example, you see that the global variable isItPrivate1 appears before its has been declared. This is inherant to javascript which declares the function and variables before executing the code.

On the contrary, by dividing the script tag in two parts, the second example shows that you can control when the variable will be declared: isItPrivate2 appears only on the third enumeration.

In any case, both examples are not relevant because they don't demonstrate the use of a separate javascript file.

I created the third example to show that if you declare variables in an external javascript file, it is merged with the current context once the script is loaded. It means that if the library needs to use global variables the developper has to control their visibility: it has to be done differently.

I wanted to see how jQuery extends the context, so I loaded it. As a result, only two new members are inserted in the global context: $ (the famous jQuery shortcut) and jQuery.
On the other hand, enumerating the jQuery object content shows lots of members that are not necessarily the ones documented.

Finally, by creating a closure, the last example demonstrates how an object can be declared to expose a function that uses a variable that is not in the current context:


(function(){ var isItPrivate4 = "Yes!"; this[ "example4" ] = { isItPublic4: function(){ return isItPrivate4; } }; })(); This will be the preferred solution to develop the library.

To conclude

I am not pretending that everything above is crystal clear and this would probably require more redacting to be understandable (do not hesitate to comment). My goal is to explain how I selected the implementation and why: by limiting the visibility of what is exposed by the library, I can significantly reduce the size of the context (and that is really helpful when you debug) and secure the code by creating variables that are not modifiable outside of the library.

Monday, March 25, 2013

The three W

As this is the first message of this new blog, I felt it was necessary to explain the three W: Who, What and Why.
I won't detail too much the Who: I started programming early and my first "workstation" was an 8 bit home computer that Santa brought me at the age of 8. Since this first hardware, I have tried Basic (many different ones), Assembly (several ones), C, C++, Pascal and other languages. Naturally, I became a software developper but not only: I have been quickly involved in other responsibilites where programming was not the only required skill. Also, I should mention that english is not my native language so... please excuse any mistake I may do.
The content of this blog (What) is mostly related to my developments and the thinking behind these developments: this is why you will find articles related to Javascript and the current things I am trying to achieve. I started a project some time ago which had some good feedback but I quickly realized that I needed to formalize some concepts in order to progress efficiently to a scalable software.
Finally, the Why: I have recently been told that I was a little egotistic. I can't deny that I like to share my ideas and enjoy implementing them. However, I try to keep an eye on what's going on and I like to hear feedback that help me to progress. I can't predict if I will have any kind of success - and this is not what I am looking for - but I would like to share my thoughts and get feedback about them.

This being said, I will try to post as often as possible in order to show you my progress and take into accounts all the comments (... if any ...).

Have a good reading,
- Arnaud