prettyprint

Wednesday 30 January 2013

How to write maintainable javascript (or die trying) part I

I think I finally got it! After years of doing experiments I finally found the secret formula for maintainable javascript. I would like to share it, as well as invite you to peer review it.

(Edit from 2014 Meanwhile my coding style dramatically evolved from this, I'm keeping this post here more as a legacy reference)

When I began working with JavaScript The first thing I did was learning jQuery and watch the David Crawford's video Javascript the Good Parts. Afterwards I started a project which was a Ganttchart web app. If you dare to inspect it you will see the most messy JavaScript ever written. Meanwhile I kept working on doing other front end stuff, never dropping jQuery but always trying to improve my code style.

I don't want to bug you with the full story so I'll just cut to the chase. Following are the issues that most commonly occur when developing front end stuff: (This article addresses some of them)
- Declaring lots of loose functions/variables in the same scope.
- Repeatedly querying the DOM for the same thing
- Overuse of JavaScript closures
- Cross dependencies everywhere
- Using the DOM as a place holder to store variables and states
- Doing mega selector chains in jQuery

Each one of these issues has a reason to exist, otherwise they would not happen. Remarkably when you find code that has one, you will easily find signs of the others. Typically declaring lots of loose functions is the first code smell. You can argue that you have them only doing a stateless thing in the interface like:
function selectFriends(firstName){ 
    $('div.friend').each(function(i,e){
        var names = $(e).attr('data-name').split(); 
        $(e).toggleClass(‘selected’, names[0]==firstName); 
    }); 
}

function removeFriends(firstName){ 
    $('div.friend').each(function(i,e){ 
        var names = $(e).attr('data-name').split(); 
        if(names[0]==firstName){ 
           $(e).remove(); 
        } 
    }); 
}

If you only have the first function, I will not complain that you should encapsulate it. But the moment you start adding more functionality things will get messy.

Lets Identify the main issues present in that code:
- Every time we want to select or remove friends we are querying the DOM
- Both functions are dependent on the string “div.friend”, so if you want to change this you would have to edit it everywhere. Imagine if you have many references… on different files!
- Duplicate code.

To address these issues, it is always a good idea to use a map, after all JavaScript is all about maps. So why not run some code before these functions are called, which should build a simple data structure to store our references? As we are only doing operations on the first name we can use those as keys. Afterwards we can then store a reference to the DOM as the paired value. As names are not unique lets use a list of DOM references, so we can store multiple ones.

With this in mind we can now refractor the above code into:
var friendNames = {};

$('div.friend').each(function(i,e){ 
    var name = $(e).attr('data-name').split(); 
    if (!friendNames[name[0]]){ 
        friendNames[name[0]] = [$(e)]; 
    } else { 
        friendNames[name[0]].push($(e)); 
    } 
});

function selectFriends(firstName){ 
    for(var i=0; i < friendNames[firstName].length; i++){ 
        friendNames[firstName][i].addClass('selected'); 
    } 
}

function removeFriends(firstName){ 
    for(var i=0; i < friendNames[firstName].length; i++){ 
        friendNames[firstName][i].remove(); 
    } 
    friendNames[firstName] = []; 
}

In this new code we are no longer querying the DOM every time we want to select or remove a friend. The logic behind each function is also much clearer.

But a new issue arises: we are still writing all the code in the global scope, which isn't nice. So we should encapsulate it into an object which explicitly dictates its functionality. I like to use singletons for interface controllers that specifically handle a single functionality in the interface. To do that I store a reference to itself in its prototype.

So our object would look like this:
function FriendHandler(){ 
    if(FriendHandler.prototype.singleton){ 
        return FriendHandler.prototype.singleton; 
    }

    if(!(this instanceOf FriendHandler)){
        return new FriendHandler();
    }

    FriendHandler.prototype.singleton = this;

    var NODES       = { friends : $('div.friends') },
        friendNames = {};

    NODES.friends.each(function(i,e){ 
        var name = $(e).attr('data-name').split(); 
        if (!friendNames[name[0]]){ 
            friendNames[name[0]] = [$(e)]; 
        } else { 
            friendNames[name[0]].push($(e)); 
        } 
    });

    this.selectFriends = function(firstName){ 
        for(var i=0; i < friendNames[firstName].length; i++){ 
            friendNames[firstName][i].addClass('selected'); 
        } 
    };

    this.removeFriends = function(firstName){ 
        for(var i=0; i < friendNames[firstName].length; i++){ 
            friendNames[firstName][i].remove(); 
        } 
        friendNames[firstName] = []; 
    };

    return this;
}

We now have a nice object with public functions which anyone can easily understand. Any coder who reads FriendHandler().selectFriends(‘Jonh’); will easily follow the logic flow and quickly understand what is happening. On a side note a friend of mine, to whom I requested a review of this article, made this cool jsFiddle with an example of the code above.





Some details:

In this last code there are still some issues, one of them is: what happens if new html shows up? It's very common to have an ajax call appending new friends. Then our object would contain an inconsistent representation of the DOM, in both the NODES.friends and in the friendNames map.

To solve the first problem, which consists in the jQuery object representing old HTML entries. This representation could contain elements which are no longer present in the DOM and miss new ones which where added later. I created a small jQuery plugin, so small that it fits in a gist on github (link), to allow easy updating of jQuery elements stored in variables. With this plugin we just need to call update() to have the an updated version of the DOM without having to run the selector again.
    NODES.friends.update();
Know that we know of a way to update the jQuery object which we have stored, it is only a matter of creating a function to update our map. We can this way add the following to our object:
function _update(){
    friendNames = {};

    NODES.friends.update().each(function(i,e){ 
        var name = $(e).attr('data-name').split(); 
        if (!friendNames[name[0]]){ 
            friendNames[name[0]] = [$(e)]; 
        } else { 
            friendNames[name[0]].push($(e)); 
        } 
    });
}

this.update = function(){
  _update();
};


I hope you have found this article both useful and enjoyable. I will eventually write part II where I want expose how to write event subscription systems based on Observers. Thank you for reading and if you have any questions or feed back please leave a comment and I'll be glad to reply.

Wednesday 2 January 2013

The status of real estate investment in Portugal

Many of you look at countries under bailout, such as Portugal, and think that now is the time to make real estate investment in these countries. The real interjection to this idea is both a yes and a no. I have been for the past years interested in buying something myself. But with this being a lifelong investment and with a computer science background I wanted to be as pragmatic as possible. So I started my market research, where I ended up studying macroeconomics and financial markets as well. I would now like to share the results and conclusions with anyone who may find them useful.

To properly understand the Portuguese real estate, we should take into consideration that buying a house or apartment has always been the favourite investment of the general population. It is also important to know that unlike other western European countries, Portugal has a very high amount of emigrants. Lots of Portuguese live outside of the country where they work in higher return jobs piling up money for when they eventually return.

Traditionally the emigration scenario leads to “power buyers” who are able to buy one or more homes without requiring credit. These return after they retire or if the macroeconomic environment improves. It is well known that Portugal is currently in a deep recession, which encourages the opposite! Every month thousands of Portuguese leave the country, many of them highly skilled and trained workers. The first negative variable rests here, if they would stay in Portugal, these workers would drive economic growth and would have the best salaries the country has to offer, making them the ideal home buyers.

Another two interesting factors are the severe aging of Portuguese population during a burst of a real estate bubble. The active workers which could invest in homes are either already paying one or having their salaries shrunk to a point where they hardly have any available disposable income. While their counterparts, the young ones, are either unemployed, paid poorly or leaving the country. If this is associated to the housing market burst it can be easily seen that the aggregate supply highly exceeds the aggregate demand. Leading to thousands of unsold homes all over the country, which leads to higher competition and declining prices.

It is not possible to talk about real estate investment without also analysing the renting opportunities of owning a home. And to properly do this we should first look at risk factors and investment yield. A low risk investment normally has a full return on investment of around 20 years which is represented by an averaged 4% annual yield on the total value of the initial investment. At the moment a home being rented has the same or lower yield after you consider extra costs, such has maintenance, real estate tax and other expenses. The risk also increases if you consider the dangers of renting to a bad person, which might severely damage your property.

People normally say “so what? You can still sell your home for more money than you bought it”. This is sometimes true, but this also applies to all other investments you do: stock, debt, precious metals, you name it. If the aggregate demand doesn’t increase it is more likely you will sell it for the same price you bought it than to score a huge profit out of your sale.

On the other hand if you wish to buy an extra home for vacations in one of Portugal great beaches, the power to negotiate is on the side of those with money. And there are very good opportunities with people getting desperate to sell properties in order to get some cash or free themselves from debt. Banks doing massive auctions and even the state is selling properties with a success rate of only 12%.

All this will lead to a decline (i'm not taking inflation into account here) in real estate prices during the next years until it stabilizes. So there is still a long road until the prices stop dropping, and with an average selling time frame of 14 months you can find really good businesses if you are patient. But don’t expect to quickly monetize your investment if you are buying solely to get the yield and profit from it.