Sunday, July 11, 2010

Javascript functions - Part 3

In this post, I am going to experiment with a few more ways of invoking functions in javascript. In my previous post Javascript functions - Part 2 I elaborated on a few ways in which functions can be called.

Unlike many other languages, javascript functions are more than just functions. They are objects as well. And since functions, being an object, can have more functions defined for them, javascript allows us to have two pretty useful functions that can be used to call functions.

Every function in javascript can be called by its name and passing parameters. However, the context in which a function is being called can be different everytime.

What? Context? Now where did that come into the picture?

Well, if i were to define the context, I'd say that its nothing but the value of the 'this' in the function that is being executed. Seems pretty simple eh?

But somehow, the value of 'this' is not as easily grasped while programming in javascript. This is because 'this' is not your usual 'this' that you see in other languages like Java. For someone like me who has been meddling with hard code oops concepts, the way in which 'this' was being used in the javascript was pretty elusive in the beginning.

I am not going to be talking much about 'this' in today's post, however, there is something that we need to know before we can check out the the 2 new ways in which functions can be invoked in javascript.

'this' is something that you must know! < insert wicked laughter here >

Whenever a function is being invoked in javascript, and there is no object who is the invoker of the function, the window object is considered to be the default invoker.
Also, when defining objects that are not members of other objects, the objects are considered to be members of the default object - the window object.

Well, the above two lines are pretty simple. But lets see how these simple little things can make the behavior of code unpredictable when programming if you are not careful with your code.

Lets assume we have the following function defined in our script

var v={a:10};
  v.fun4=function(){
   alert("fun4 "+ this);
   fun5();
  }

function fun5(){
   alert("fun5" + this);
  }

v.fun4();


What I have done here is pretty simple. I created an object 'v' with a property 'a' and a function fun4(). fun4() alerts a message and then calls fun5(). Run this code and see what happens. As you see, the first alert indicates that the value of the 'this' keyword in the function fun4 is the object(in our case it is 'v'. You can check it by printing the value of v.a). But the second alert indicates that the value of 'this' is not the object v, but instead it is the default window object.

If you are not familiar with javascript, you might be perplexed, maybe just for a while, before the concept actually begins to reveal itself.

As you see, during the declaration of the function fun5(), it is not declared as a function of any object. Hence, this function is implicitly a function of the window object. Functions declared on the window object are global and can be called by any other function, which is exactly what our fun4() does. Hence, the default context of the function fun5() is the window object, which is the value of our 'this' keyword.

But what if you want the value of 'this' to be the object 'v' in fun5? What do you do?
Well, if you are thinking that you can simply replace the line fun5() with this.fun5(), that, my friend, is simply not gonna work. That's because, the function fun5() is not a function of the 'this' object in fun4().


However, there is a way to do it. The call() and apply() functions in javascript can be used to aid us in exactly this sort of scenario. these functions are used to set the context of the function, which is thereby reflected in the value of the 'this' keyword of the function.

In the following piece of code, we are going to declare 2 more functions on our object 'v'. And 2 global functions on the window object.

v.fun6() invokes global function fun7() using the call() function.

v.fun8() invokes global function fun9() using the apply() function.

v.fun6=function(){
   alert("fun6 "+ this);
   fun7.call(this,'ryan');
  }
  
  function fun7(arg){
   alert("fun7" + this + " arg : "+ arg);
  }
  
  v.fun8=function(){
   alert("fun8 "+ this);
   fun9.apply(this,['ryan']);
  }
  
  function fun9(arg){
   alert("fun9" + this + " arg : "+ arg);
  }
  
  v.fun6();
  v.fun8();


As it can be seen, the global functions also receive a parameter. The syntax of call() and apply() are quite similar. The first argument of both these functions is used as the context in which the actual function is to be called.

The call() method can have many arguments after the first argument such that each argument becomes the argument to be passed to the actual function.

The second argument of the apply() function takes an array of values that are to be passed as arguments to the actual function.

Run the code and see for yourself, how the value of the 'this' keyword is now appropriately being used in the global functions.

One implication of this sort of technique is that you can have a number of global functions, each of which does a single common task. And you can have several objects, belonging to different classes that call these global function using their own context, thereby reducing the redundancy of existing functionality.

That's all for now. We shall do some more experiments in the next post. :>

Happy Programming :)
Signing Off
Ryan

Saturday, July 3, 2010

The Observer Pattern

In today's post, I am going to discuss about the observer pattern. This is one of the most widely used patterns in most J2EE applications. I say this because of the inherent simplicity of this pattern and the the fact that it is highly possible that you are already implementing this pattern without actually being aware of it! This is something that certainly cannot be said about other patterns like the Visitor or the Factory pattern.

As I always do, this time as well, i am going to elaborate the usage of this pattern in a fictional - game like situation.

Lets imagine we are playing a horror game. Yea, this time i pick a horror game instead of the good ol FPS!

First, lets begin with a somewhat formal introduction to the pattern.

As the name suggests, the Observer pattern is basically used to associate an object A with a group of other objects that observe any changes in the properties of the object A, and perform some very critical, earth shattering tasks, based upon the change made to the properties of the object A.

Well, its like another way of talking about the event - event listener, model of programming.

There are primarily three major concerns in the Observer pattern.
1) The object being observed - The Observable object.
2) The objects that observe the observable object - The Observer objects.
3) A way to associate and invoke the Observable object with the Observers - The Delegate function.

To be concise - Observer Objects Observe Observable Objects.
That's 5 O's in one sentence!

There two are styles of implementing the Observer pattern - The Push model and The Pull model. These two models differ in the way in which the Observers and the Delegate function are designed. The observable object remains the same. I will elaborate both of these models later in the post and also discuss the pros and cons of both the techniques.

However, now its time to play some game.

The protagonist of our horror game features a very bold player named ScoobyDoo.
So, we create a basic player class with three instance variables :
name, xCoordnate, yCoordinate. Here is the class definition.

public class Player {
    
    private String name;
    private Integer xCooridinate;
    private Integer yCooridinate;

    public Integer getxCooridinate() {
        return xCooridinate;
    }

    public Integer getyCooridinate() {
        return yCooridinate;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void moveForward(Integer steps){
        xCooridinate+=steps;
    }

    public void moveBackward(Integer steps){
        xCooridinate-=steps;
    }

    public void jump(Integer height){
        yCooridinate+=height;
    }

    public void fallTo(Integer height){
        yCooridinate=height;
    }
}

I have also added a function that allows the player to move forward and jump(i.e. move upward) and vice versa. These will be used to manipulate the xCoordinate and yCoordinate properties of our our Player.

Now, I don't think a game can be made scary without proper lighting and sound effects. But what makes a game scary is the appropriate timing of these effects.

Lets assume a scene where ScoobyDoo enters an empty room. As of now, the lights are bright and shining. The xCoordinate and yCoordinate of the player are initialized to 0 when the player enters the room.

Now what we want is that when ScoobyDoo is right in the middle of the room, i.e. approximately 10 steps into the room, the lights should suddenly begin to flicker.


Not only that, but we also want a scary sound to start playing in case ScoobDoo tries to act smart and tries to jump up to run out of the room.

Yea, it might sound as if I am being so mean by trying to scare the shit out of this dog, but hey, i am not to blame. I bet this dog would get scared of the sound of his own fart as well!

Okey, back to work.

What we need is a way to observe the coordinates of ScoobyDoo in the room and take appropriate actions when his coordinates cross a certain threshold.

So, here, the Observable object is the Player.

Before we begin we need to define a few interfaces that will be used to generically use and handle Observers and Observables.

Lets see the definition of these interface first.

public interface Observable {
    public void notifyObservers();
    public void addObserver(Observer o);
    public void removeObserver(Observer o);
}


public interface Observer {
    public void update(Object o);
}


Lets create Observers.

public class SoundEffectController implements Observer{

    private boolean isSoundPlaying = false;

    public void playSound(){
        System.out.println("Play an eerie sound");
        isSoundPlaying = true;
    }

    public void update(Object o) {
        if(o instanceof Integer){
            Integer yCoordiante = (Integer)o;
            if(yCoordiante>0 && isSoundPlaying== false){
                playSound();
            }
        }
    }

}



public class LightEffectController  implements Observer{

    private boolean isLightFlickering = false;

    public void flickerLights(){
        System.out.println("Flicker the lights");
        isLightFlickering = true;
    }

    public void update(Object o) {
        if(o instanceof Integer){
            Integer xCoordiante = (Integer)o;
            if(xCoordiante>10 && isLightFlickering==false){
                flickerLights();
            }
        }
    }

}


As you see, there are two observers. The SoundEffectController, and the LightEffectController.

The SoundEffectController is class that manages the sound effects of the room. The light effect controller is a class that manages the lighting effects of the room.

Now, what we need is a way to associate these observers with the events with which they are interested- the change in the xCoordinate and yCoordinate of the Player. This is where the delegate function comes into the picture.

The delegate functions's primary purpose is to pass on control to all the interested Observers upon the occurrence of any event in the Observable object. This is the core function in the observer pattern. It is this function that allows you to have 2 flavors of the Observer pattern. We will first see the Push Model of the observer pattern.

The delegate function is defined in the Observable object. In order to make the delegate function do useful things, the methods that cause a change in the properties of the object, need to invoke the delegate function. Also, the Observable class needs to maintain a list of observers.

In the Push model, the delegate function iterates over each of these observers and passes the relevant information to the Observer. The following code demonstrates the new implementation of the player class using the push model.
And now, here is the new definition of the Player class which now implements the Observable interface.

public class Player implements Observable{
    
    private String name;
    private Integer xCooridinate;
    private Integer yCooridinate;

    private List observers ;

    public Player(String name) {
        this.name = name;
        this.observers=new ArrayList();
    }


    public Integer getxCooridinate() {
        return xCooridinate;
    }

    public Integer getyCooridinate() {
        return yCooridinate;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void moveForward(Integer steps){
        xCooridinate+=steps;
        notifyObservers();
    }

    public void moveBackward(Integer steps){
        xCooridinate-=steps;
        notifyObservers();
    }

    public void jump(Integer height){
        yCooridinate+=height;
        notifyObservers();
    }

    public void fallTo(Integer height){
        yCooridinate=height;
        notifyObservers();
    }

    //This is the core function that delegates the change in the state of the
    //Observable object to the observers
    public void notifyObservers() {
        for(Observer o:observers){
            if(o instanceof SoundEffectController){
                o.update(yCooridinate);
            }
            else{
                if(o instanceof LightEffectController){
                    o.update(xCooridinate);
                }
            }
        }
    }

    public void addObserver(Observer o) {
        this.observers.add(o);
    }

    public void removeObserver(Observer o) {
        this.observers.remove(o);
    }
}


Here is the Main class.

public class Main {
    public static void main(String[] args){
        Player myDog = new Player("ScoobyDoo");

        myDog.addObserver(new SoundEffectController());
        myDog.addObserver(new LightEffectController());

        myDog.moveForward(2);
        System.out.println("Nothing yet.");
        myDog.moveForward(3);
        System.out.println("Nothing yet.");

        myDog.moveForward(7);
        
        myDog.jump(3);
        
    }
}


On running the main program, you get the following output.

Nothing yet.
Nothing yet.
Flicker the lights
Play an eerie sound


As is seen in the above code, it is clearly evident that the delegate function - notifyObservers() is invoking a particular function on an Observer to notify it of the changes in state. On close examination, you would notice that the delegate function is not as flexible as we want it to be. This is because, the delegate needs to be aware of the data that each observer is interested in listening to, thereby making the delegate function a tad more complex than it should be. As time progresses and more observers want to be notified of the changes in the Observable object, the delegate function becomes more convoluted as it needs to be aware of the requirements of each type of observer. For example, there may be 'n' number of observers interested in the change in the x coordinate of the player, while there may be 'm' number of observers that may be interested in the change of 'y' coordinate of the player. There might also be 'l' number of observers that may be interested in both the x and y coordinate of the player. The problem certainly becomes harder to solve as the variety and number of observers increases with time.


This is where the pull model comes to the rescue. In the pull model, the delegate function sends the Observable object itself to the Observers. It then becomes the observer's responsibility to extract the the information in which they are interested, from the Observable object. In our case, this can be implemented as follows.

Change the code in notifyObservers() in the Player class to the following


public void notifyObservers() {
        for(Observer o:observers){
                o.update(this);
        }
    }


Change the update function in SoundEffectControler to the following

public void update(Object o) {
        if(o instanceof Player){
            Player p = (Player)o;
            Integer yCoordiante = p.getyCooridinate();
            if(yCoordiante>0 && isSoundPlaying== false){
                playSound();
            }
        }
    }


Change the update function in LightEffectController to the following

public void update(Object o) {
        if(o instanceof Player){
            Player p = (Player)o;
            Integer xCoordiante = p.getxCooridinate();
            if(xCoordiante>10 && isLightFlickering==false){
                flickerLights();
            }
        }
    }


On running the main program, you get the following output.

Nothing yet.
Nothing yet.
Flicker the lights
Play an eerie sound


As you can see from the above code, the complexity has now shifted from the delegate function to the Observer classes. It is now the Observer's responsibility to take extract the information and also perform typecasting to identify the object with which it is being notified.

When you decide to implement the observer pattern, you keep in mind a few things. The push model works great in areas where you have several components that build up a system, and some of these components act as observers to many different types of Observable objects. In this case, you would prefer to provide only a specific portion of information to the observer instead of the entire Observable object. This would greatly increase the decoupling of your Observer components from the Observable components thereby giving you the chance to use the same observer across multiple objects.

The pull model works great if your Observable object is already in place and you are designing components around this Observable object. If there are many observers, and each observer depends of different combinations of the properties of the Observable object. In this case, since the components are being designed with only a particular Observable class in mind, shifting the complexity to the Observer classes seems like a good idea. Each observer would extract the relevant information from a Observable perform necessary actions.

As is the case with all design pattern, the way you choose to implement it depends on multiple factors. Understanding how a particular implementation will impact your solution should be the key concern in deciding upon a particular implementation.


Happy Programming :)
Signing Off
Ryan