Showing posts with label oop. Show all posts
Showing posts with label oop. Show all posts

Saturday, February 23, 2008

Javascript : Creating a queue system part 2 :OOP way

In the last entry, we have seen what was a queue and how to implement it in javascript, in a procedural way. We also noticed that we were limited in our possible use of the program as multiple queues were not possible. We will see how moving from procedural to object oriented approach will allow us to deal with multiple queues in a simple way.

Reviewing the queue code


Before we go OOP, let's review the code first:
var q      = [];
var paused = false;

function queue() {
    for(var i=0;i < arguments.length;i++)
       q.push(arguments[i]);
}
function dequeue() {
     if(!empty()) q.pop();
}
function next() {
     if(empty()) return;
     if(paused)   return;
     q.shift()();
}
function empty() {
     if(q.length==0) return true;
     return false;
}
function clear() {
    q=[];
}

//application aware flush function:
//update the div with the length of the queue

function updateDIV(delay) {

 function delayed() {
   document.getElementById('queued').innerHTML+=q.length;
   next();
 }
 setTimeout(delayed,delay);
}
function flush(delay) {
 updateDIV(delay);
}
You can always read the firt part to get a better understanding of this code.

Limits of the above code


The main drawback of this programming style is that we hold our main data, the queue array and the pause flag, in the gobal space. Therefore we cannot create several queue with the above code.
The main advantage of putting everything in the global space is that the code is straight forward:
queue(function(){updateDIV(300)},function() {updateDIV(500)},function(updateDIV(450)));
dequeue();
next();
paused=true;
flush();
As you can see, we don't really have to care about the queue array, we just let the program deal with it for us. Now, let's see how we can try to implement multiple queues.

Multiple queues, the procedural way

In order to deal with multiple queues, we first need to allow multiple queue container.
Therefore, we need to change our global queue as being a parameter of the function:
function queue(q) {
    for(var i=1;i < arguments.length;i++)
       q.push(arguments[i]);
    return q;
}
function dequeue(q) {
     if(!empty()) q.pop();
     return q;
}
function next(q) {
     if(empty(q)) return q;
     q.shift()();
     return q;
}
function empty(q) {
     if(q.length==0) return true;
     return false;
}
function clear(q) {
    q=[]; 
    return q;
}

//application aware flush function:
//update the div with the length of the queue

function updateDIV(q,delay) {

 function delayed() {
   document.getElementById('queued').innerHTML+=q.length;
   next(q);
 }
 setTimeout(delayed,delay);
}
function flush(q,delay) {
 updateDIV(q,delay);
}
huummmm, as you can see, this is a little bit trickier...
I have dropped the paused flag in order to keep thing simple.
Let's see how we can use the above code:
var q1=[];
var q2=[];

q1= queue(q1,function(){updateDIV(q1,300)},function() {q1,updateDIV(500)},function(q1,updateDIV(450)));
q1= dequeue(q1);
q1 = next(q1);
flush(q1);

q2= queue(q2,function(){updateDIV(q2,300)},function() {q2,updateDIV(500)},function(q2,updateDIV(450)));
q2= dequeue(q2);
q2 = next(q2);
flush(q2);
Hummmm,,,
This is starting to be very hard!
Before, as we only had one and only one queue, we didn't have to care about which queue we were working on.
Now that we can have several queues, we need to indicate each time on which queue we are working to the function and we need to get back the queue to stay sync with the application...
in other words, this is a real pain in the butt!
Why is it that hard?
Could we simplify this??
Yes, we can, thanks to an object oriented approach!

The object oriented approach of the queue


So why the code get so difficult to write and certainly, in a long run, to maintain??
Because we are thinking in a procedural way:

We have functions that work on a particular data.


By thinking this way, we need to specify what is the data to the functions.
Depending on what you want to do, a procedural approach will be revealant, don't think that it is a wrong way of doing things (even if hardcore oop programmer will claim that even a if else statement is devil,,,just forget about them!!)

So how should we think the problem?
If we change our way of thinking, we can move to the following:

We have a particular data that possesses,has different methods.

And that's all!
Instead of thinking of different individual functions that work on a particular data, we need to think that we have a particular data that share, have particular functions/methods.
By simply inversing the first axiom,the subject of the action, we will be able to have the easyness of a global variable and the power of multiple data, ie, multiple queues.

The object in OOP


So, that's nice, we have inversed the problem and so what??
When we created our queue, we had a queue container, a queue pause flag and functions that work on the data.
If you remember the first approach, we first created our queue container, our pause flag and then called the different functions that were all working on the same data, the global queue and global pause flag.
Using an object approach, we are just going to allow to create several queue container and flag, each hold within a box, an object. Therefore each object will have it's own internal state of the data.
Come to think of it, if you have two identical TVs, one in your living room, one in your room.
If you turn on the TV in your living room, the one in your room is not going to start and hopefully.
You have two objects and each of them although they do the same thing, have their own state of information, their own data.
We are going to learn how to create TVs!!

Understanding the queue in a OOP way


Let's see how we will write the code in a OOP way:
var q1 = new Queue();
q1.queue(function(){updateDIV(300)},function() {updateDIV(500)},function(updateDIV(450)));
q1.dequeue();
q1.next();
q1.flush();

var q2 = new Queue();
q2.queue(function(){updateDIV(300)},function() {updateDIV(500)},function(updateDIV(450)));
q2.dequeue();
q2.next();
q2.flush();

If you remember the procedural approach with only one global variable, you will see that is very similar, but remember:
We do not have functions that work on a particular data.
We have a set of data that has some particular functions to work on.
The main, main difference is the following line:
var q1 = new Queue();
In the procedural way, we add:
var q1 = [];
var paused=false;
hum ??
But where did you write the line defining the paused flag in the OOP way??
In fact, remember, we are working with a set of data that we enclose in a box, an object.
Whene we write 'new Queue()', in the background we have created an object that has a queue container, an array, and a paused flag set to false!
If you have your TV on and that you change of channels, you don't expect your TV in your room to change of channel too, right?
Here it is the same thing, we have turned on our queue, set our initial state of information (an empty queue, a paused flag to false) and get an image back, in fact, an object holding all this information.
If you have never done OOP until now, you need to know that the return value is not a string or an array, it is what we call an object, which is yet an other structure of data.
We are lucky because in javascript creating an object is the same has using an hash, or associative array!
So we get back an hash that holds the following info:
var q1 = new Queue();
q1.toSource(); //=> {  queue:[],  paused:false };
But this hash is a little bit different from a simple hash.
If you buy exactly the same TV in a store, they will share exactly the same properties, the same features but if you need to repair one of them, you need to have a way to differentiate them, this can be a code barre or a client code.
Therefore, when you create a new object in javascript, you will get back a hash, that contains the name of the object, here Queue and obviously a particular memory address.
So when you do the following:
var q1 = new Queue();
var q2 = new Queue();
var q3 = new Queue();
You are creating each time a new Queue hash that has a particular memory address with their own state of the information.

And what the heck with the rest of the code????
var q1 = new Queue();
q1.queue(function(){updateDIV(300)},function() {updateDIV(500)},function(updateDIV(450)));
q1.dequeue();
q1.next();
q1.flush();
How can we call functions on the q1 variable??
Again, remember, we do not have functions that work on a particular data, we have a set of data that has some functions.
In a OOP language, we don't refer to functions but to methods.
Each new queue container array and paused flag are not variables but properties.
Properties are state, methods are actions.
A human being has the following property : 2 legs, 2 eyes, a mouth, 2 ears,etc. And a human being has the following methods, actions : run, walk, speak, sleep,etc. Sleeping being my favorite action of all!

So we have initialised our particular set of data, hold in an object called q1 and each time you will be calling methods (actions) on it, the methods will be working on the data of this object!
So with OOP, we can create has many queues as we want, we do not have to care about passing the queue array around or the paused flag around, everything is held within the object, within each object.
That's why our code is easier to write in the end because we do not have to deal with the state of the information, the object is doing it for us!!


Conclusion


Writting the implementation code here will make the entry too long so we will see how to implement the OOP way in a third party!!
But I hope that this entry has help you understanding the difference between a procedural approach, where functions work on data and an object oriented approach where a set of data has methods.
Understanding this will allow to ease the next entry development phase!
I hope you have seen how powerful can be a OOP approach where an object can hold has many information as you want and deal with them internally without having you to care!
So keep on reading!

Sunday, February 3, 2008

Javascript - Creating a queue system part 1 : procedural way

We queue all the time : at the administration, at the supermarket, at school for lunch....
The first in the queue, will go out first and the last one, well, will be out the last. This is the basic system that many programs use to process commands,functions in a particular order, here the first in, first out order (FIFO). It can be used to create chained effects, delayed remote call to server, sending mails by bunch, etc. We'll see in this entry the underlyings of a queue!
(this is a very basic procedural approach, that will be improved in the next entry)

Example

Before we go on and dive into the coding of our queue system, let's see what we will be able to do with a simple example.
Each time you click on queue, you will add an elment in the queue.
Each time you click on dequeue, you will remove the last element in the queue.
When you click on the flush queue, all the elements are going to be called one after an other (when the last action has finished).
And pause, we'll just pause the queue!
You will see the number of element actually present in the queue each time you click on next in queue of flush queue:
So 0 means that there is nothing in the queue and 1,2,3 are the elements left in the queue:

 
queue dequeue next in queue flush queue pause clear

What do we queue?


A queue contains most of the time functions or commands that a program needs to execute in a FIFO order.
In javascript, a common use of queues are for chaining effects or even queueing remote server calls while offline or in a slow network context and that a call has failed...
It could also be used to trigger other functions when a certain signal is fired, like an event.Indeed, a queue is also the base of what could be our own event sytem triggering functions on demand!(observer pattern with subjects/ observers or publishers and subscribers).
As you can see queues can be very useful and indeed are!
Let's see the features a queue needs.

What are the queue features?



When you are queueing at the supermarket, you need to wait for the signal of the cashier to move forward.
Sometimes, you need to stop people from moving and pause them!
Sometimes, the cashier can ask you to go to an other place and get rid off you!
Sometimes, you just need to get rid off the entire queue because time is over!
Obviously, you need something that contains in the order they came in the clients.
Well, we are lucky because the container in Javascript, that keeps things in order they come is nothing more than an array!
Let's see:
var clients=[]; // or new Array();
clients.push('first in');
clients.push('second in');
clients.push('last in');
alert(clients[0]); 'first in'
alert(clients[1]); 'second in'
So as you can see, it was very easy to create the base of a queue!
We create an array and we just 'push' the clients as they come in!
the first client is in the slot 0 and the last one in the slot 1, as we only have 2 clients!
There is also a very useful function in Javascript in order to deal with arrays, it is the pop function that will just get rid off the last entry in the array:
var client= clients.pop();
alert(client); // 'last in'
alert(clients); // return in order : first in, second in
As you can see the pop get rid off the last element and send it back to us.
There is obviously the counter part of pop, that is, the shift function that gets rid off the first element in the queue:
var first = clients.shift();
alert(first); // 'first in'
alert(clients); // return : second in
So basically, we have all the 4 main ingredients required for a queue:
- a container : the array
- a way to add in order : push, adds element at the end of the array
- a way to remove the first element : shift
- a way to remove the last element : pop

when we add an element at the end of the queue, we say that we 'enqueue' or 'queue'.
when we remove the last element of the queue, we say that we 'dequeue' when we advance in the queue, which is to say, calling the first element in the queue and getting rid off it, we say that we 'advance' or that we call the 'next' in the queue.
When we call all the elements in the queue one after an other, we say that we 'flush' the queue.
In the end, we restart the queue from the beginning, we 'clear' the queue.

The main functions


From there we can define the main elements required:
var q=[];//our queue container
var paused=false; // a boolean flag
function queue() {}
function dequeue() {}
function next() {}
function flush() {}
function clear() {}
you may also want to 'pause' the queue. We will therefore use a boolean flag too.
Now let's see the implementation, this is going to be very straightforward:
var q      = [];
var paused = false;

function queue() {
 for(var i=0;i< arguments.length;i++)
     q.push(arguments[i]);
}
function dequeue() {
    if(!empty()) q.pop();
}
function next() {
    if(empty()) return; //check that we have something in the queue
    paused=false; //if we call the next function, set to false the paused
    q.shift()(); // the same as var func = q.shift(); func();
}
function flush () {
    paused=false;
    while(!empty()) next(); //call all stored elements
}
function empty() {  //helper function
    if(q.length==0) return true;
    return false;
}
function clear() {
    q=[];
}
And here we have our basic queue system!
let's see how we can use it:
queue(function() { alert(1)},function(){ alert(2)},function(){alert(3)});
next(); // alert 1
dequeue(); // the last function, alerting 3 is removed
flush(); // call everything, here alert 2
clear(); // the queue is already empty in that case but anyway...
You can try the above code
As you can see, it works like expected but let's say that instead of alerting something we decide to update a div...
Let's take the following function:
function updateDiv(val) {
   function delayed() {
        document.getElementById('test').innerHTML+=val;
   } 
   setTimeout(delayed,500);
}
We add a timeout to simulate an application taking time to perform.
if we rewrite our example:
queue(function() { updateDiv(1)},function(){ updateDiv(2)},function(){updateDiv(3)});
flush(); // call everything
If we keep the principle of a queue, we should have each function called one after an other, try it yourself
And it doesn't work as expected!!
Well in fact, the flush function is something that we cannot build independently of the application.
Why?
Because our flush function calls each function without even knowing if the precedent one has finished!
In order to create a queue, we need to call the next function at the end of the last executed queued function. Therefore, the queue and the application needs to be related to some extend.
We should rewrite our function like this:
function updateDiv(val) {
   function delayed() {
        document.getElementById('test').innerHTML+=val;
        next();
   } 
   setTimeout(delayed,500);
}
Now, the queue is going to be processed after the end of each function, the recursive call to the next function will create our application related flush:
queue(function() { updateDiv(1)},function(){ updateDiv(2)},function(){updateDiv(3)});
next(); // call next function that will work as a flush here
Now, if you try the above code
And it works as expected!
In fact, each application should have its own flush method.
In order to create a flush function, we need to know when the function is done to move on to the next element in the queue.
But how do I stop the queue processing or just advance one element in the queue then??
Well, we just need to change the flush function and wrap the next function like so:
function advance() {
 paused=false;
 next();
 paused=true;
}
function flush() {
 paused=false;
 next();
}
So, the advance function change the pause flag to false at the beginning and set it right away to true after calling the next function. The next function will stop at the following call as the pause flag will be set to true!
On the other hand the flush function just wrap the next function that will be called by each functions in the queue!
As you can see if some elements can be true to all queues, the flushing of a queue needs to be application aware and can hardly be generalize.
If you add a function in the queue that doesn't call the next function when it is done, your queue won't work and stop there.

Conclusion


We have built here a very basic queue system that allows us to understand the underlying process of a queue.
Javascript offers everything that we need to make it very easy like arrays, push, pop, shift functions.
Obviously these functions can have some overheads that a queue implemented at lower level won't have but the cost is not that much nowadays.

But this queue system has a real huge drawback:
our container and our pause flag is in the global space and we won't be able to have several queues running at the same time!!
Therefore we will see in the next entry an other approach that allows us to create several queue entities,objects that will keep track of their own internal state of the queue.
We will be switching from a procedural approach to an object oriented approach(OOP) and therefore see some of the advantages of this technique over this one.
We will also see how to use a queue in a real context, chaining effects!