Safely handling destructive loops


Collections abound everywhere in the real world and loops are very common in programming. A simple loop is shown below:

var arr = [1,2,3,4];

for(var i = 0, len = arr.length; i < len; i++) {
    console.log(arr[i]);
}

//Output
1,2,3,4

Destructive loops

Simple loops can be boring, after all, why not have the collection change during a looping operation for more fun? Won’t happen? Believe me it does, have run into such at least twice.

An example scenario involves collections of listeners (say for example in a pub-sub implementation). Ideally, you want to go through all the listeners and invoke them. However it is possible a listener can either directly or indirectly remove itself while the loop is processing. For example, it might call a destroy function on some object which in turn leads to a unsubscribe call.

When this happens, it’s all chaos. Funny things happen or even worse – bugs.

Suddenly, the loop invariants are all wrong and you get funny results and/or errors (most likely errors). Let’s take an example:

function createListenerArray(arr) {
   for(var i = 0; i < 4; i++) {
       arr.push(function(i) {
           console.log(i);
           if(i === 2) {
               arr.splice(i, 1);
           }
       });
   }

   return arr;
}

The createListener function pushes 4 functions onto the array reference it gets. One of these functions (the third one) will remove itself from the array once invoked. To make tracking things easier, each function will log its index to the console.

var arr = [];
createListenerArray(arr);
for(var i = 0, len = arr.length; i < len; i++) {
    arr[i](i);
}

0
1
2
//TypeError: arr[i] is not a function

Oops! Blows up…

The loop was proceeding smoothly until it got to the function at index 2. Invoking that function changed the array by removing the corresponding entry from the array. Thus the valid length of the array decreased from 4 to 3.

The next step of the loop tried to access the element at index 3; however that index is now an invalid position since the element at index 3 got moved to index 2 when the array shrunk. arr[3] is undefined and invoking undefined as a function leads to the TypeError.

Imagine the ripple effect this can cause in larger arrays

Let’s try forEach.

var arr = [];
createListenerArray(arr);

arr.forEach(function(val, i){
    val(i);
});

0
1
2
undefined

This is not the desired result but on the bright side, at least there were no Exceptions. So what other approaches exist?

1. Clone

One way is to create a clone of the array to provide a validation checker before invocations as shown below.

var arr = [];
createListenerArray(arr);
var clone = arr.slice(0);

for(var i = 0, len = clone.length; i < len; i++) {
    if(arr.indexOf(clone[i]) > -1) {
        clone[i](i);
    }
}
//
0
1
2
3

This guarantees that the functions would always exist; to verify, we can re-run the snippet again to prove that the value at index 2 is now gone.

for(var i = 0, len = clone.length; i < len; i++) {
if(arr.indexOf(clone[i]) > -1) {
        clone[i](i);
    }
}

//Output
0
1
3

2. Count down

Cloning can lead to new issues with memory allocation and garbage collection. There is another approach that is cleaner, doesn’t require cloning and should not leave danglers around.

The fix relies on understanding the true cause of the looping issue. The problem occurs because the removal of a loop element affects unprocessed elements in the loop (by changing the array length).

We can circumvent this by counting down from right to left – if an element removes itself, the unprocessed elements to the left are not affected since their indices are still valid (compare to the left-to-right count-up approach).

Now, even if a function should remove itself, things are still alright, since its index would be removed and not be valid anymore.

let arr = [];
createListenerArray(arr);

for(var i = arr.length - 1; i >= 0; i--) {
    arr[i](i);
}

//Output
3
2
1
0

console.log(arr.length);
//3

Neat! Now, this is another reason to use utils like _.forEachRight.

Liked this trick? Let me know your thoughts.

Advertisements

Advice for aspiring programmers


I have made a couple of mistakes over the years and wanted to share those pitfalls so upcoming programmers know what to avoid and what works.

1. Focus

You can’t do everything – I don’t think it is possible for one person to simultaneously be a pro at writing high quality code, network engineering, computer hardware and machine learning.

Some years ago, a much younger and naive me wanted to do everything in software engineering, use several operating systems and know enough about network engineering. Did I succeed at that? No, I just diluted my efforts and wasted loads of time (was fun though…).

Laser-like focus is essential as the field of computing is extremely wide. Decide the field you are interested in, narrow down a learning path and get your hands dirty. For example, if you choose software engineering, you’ll have to select one of three tiers: web/mobile/desktop. Once decided, just work on completing a sample project. The more projects you have under your belt, the better you become and the more learning you do.

2. Dedication

You probably won’t become good enough in one or two years. That learn * in 24 hours book? Gives you a feel for what the language syntax is but there is more than that to mastery. You need to learn language idioms, problem analysis and clean architectural design.

This take time – a lot of time: Norvig put it at 10 years; just like mastery in any other field. It is a long haul so set your mind at it and you should hopefully start seeing results in about 5 years.

3. Consistency

Little drops of water consistently dripping on the same spot can wear down rocks.

The rush of excitement you feel at the beginning is eventually going to wane. Once it becomes a dreary old routine, what will keep you going at it? Consistency and habits can compound in surprising ways.

Assuming you are 1% better each day; after a year; you’ll be about 37 times better. Conversely, if you lose 1% everyday, then after a year you’ll be 0.02 of what you were. This is an extreme example but …

Small incremental progress over a long period of time leads to big increases. For example, a developer that dedicates 25 minutes daily to improving his skills would have spent ~183 hours honing his skills after a year. That’s nearly a month of intense study time. Can you study intensely for one month without burning out?

Can’t afford the 25 mins a day? How many minutes do you spend daily on Facebook? Multiply that by 365 to see where your time is going… Oh.. add in some more hours for games, TV and Twitter too. You see little things add up quickly over long periods of time.

Now once you are consistent, what’s the next step?

4. Seek mastery before moving on

Now that you have focus, the next obvious step is to stick to a path. Frameworks pop up every second in software development but hopping around from one framework to another is ill-advised: you would likely end up as a jack of all frameworks and master of none. I agree and encourage exploratory learning but jumping on every fad bandwagon is going to get you nowhere. Rather, make a strategic choice, stick to it and commit to learning it deeply.

Does this make you less marketable? Afterall, you want to be that guy who knows how to write code in 10,000 languages. Mastering a few increases your worth – you can now charge people more for expertise in your domain. Think of it this way, if you want a dining table masterpiece, what kind of carpenter would you prefer? One that specializes in dining tables or a generalist?

5. Learn the fundamentals

I can’t emphasize this enough. Let’s take a story: EmberJS and AngularJS brought about widespread adoption of 2-way binding across UI interfaces and this in turn triggered the proposal for object.observe as a JavaScript language method. More recently, the new path has been reactive programming and virtual DOM, eliminating the need for observables. You guessed it, object.observe got retired from the language. Now, a counter example, Dijkstra’s algorithm has been around since 1956 and it is still in use after 60 years! Can you beat that?

You have to know algorithms, data structures, operating system fundamentals, caching, Mathematics, etc. These concepts are language agnostic and provide a solid bases for solving new problems. That cool functional reactive somersaulting framework you are harping about today? It may be gone in 10 years. Fundamental CS knowledge? Evergreen, safe investment.

6. Be Humble

There are two things you should keep in mind:

  • There would always be a programmer better than you
  • You probably overestimate your skills

Do you disagree with me? Check out your ranking on the programmer skills matrix. Next, read Micheal Church’s excellent adders analogy. Unless you are already at 2.5+, there is no need to brag about your skills. Instead, quitely keep pushing the limits and some day you hopefully would earn bragging rights.

Humility is a great characteristic to have – there are a ton of things you do not know and need to know. And it takes time to reach the levels others have reached. Even if you think you are a rockstar, people generally appreciate a humble confident programmer who doesn’t rub his ‘magnificence’ into their faces all the time.

Need a yardstick to measure your progress? Periodically check back on both lists to track your progress.

7. Learn how to communicate

Most of software engineering is not about writing code – a large amount of time is spent discussing projects, evaluating designs and interacting with customers. The ability to clearly convey thoughts is one most programmers lack and it is a clear differentiator.

Being able to express yourself means you can get help with problems because you can explain them to others, it also means you can convince people to join your open source project or even adopt your architectural design. All these come from being able to sell yourself and your thoughts.

Communication is not limited to speech only though, writing well is another part. Want to improve? Write more, speak more, volunteer to be a spokesperson – practice makes perfect.

8. Get a mentor & be visible

Stand on the shoulders of giants to see farther. You need to avoid making pitiable mistakes if you can, accelerate your growth and ensure you are on the right path. Great mentors help you grow, introduce you to their networks and provide insightful feedback. They have a lot of experience which you don’t.

Don’t hide under a rock! People should know you for what you do!! Would you buy Microsoft Word if you never heard of it? Seek out peers in the community, interact with them and share ideas. Help one another grow and help influence the community. Being visible makes it easier to find mentors, jobs or even new freelance opportunities. Don’t want to go out? Then create a blog, comment on blogs, release software on Github or participate in fora.

9. Be open

No, your favorite language/IDE/tool is not the best thing since bread and butter. It has its own flaws and strengths.

You can have pretty strong opinions on anything, for example, favorite languages. However what you shouldn’t do is get so tied to some language that you refuse to try out any other language. There would always be situations where your favorite tool doesn’t cut it; in such scenarios, find the best tool and deploy it.

A Toyota Camry can probably carry logs of wood but you are better off moving such with a heavy freight truck.

I used to think I understood recursion until I read SICP; I was forced to write programs without resorting to variables and suddenly, simple toy programs became quite challenging. Exposure to various tools will empower you with various problem solving approaches. This is always a good thing since software engineering is all about solving the right problems.

10. Startups can be overglorified

I think most times, the start-up concept is overglorified – it involves a lot of work, huge risk and great rewards on success. However, the idea that once you make that awesome piece of software, it’ll automatically sell itself is mostly false. That rarely happens.

The saddening part however is that most of us do not know how to deliver good software, talk less of selling software. Yet, they want to run the business. Imagine you handing over a truck on the highway to an unqualified driver who barely knows the ropes. What’s that? A recipe for a crash right? Yup, then why do we do the same with startups?

Software is typically not the critical part of most businesses, rather meeting the user’s need is. You need to learn how to write software first, then learn about business and entrepreneurship – creating a MVP, build-measure-learn cycles, customer interactions, acquisition funnels, maintenance and support, delivery pipelines, execution and meeting competitors. Now, you know this, you can see the bigger picture – the software is not the goal. The business is the goal – the best piece of software that no one uses is a failure.

There is nothing bad with working in an established shop for some time to learn the ropes, creating connections and learning how business is run. You can even start testing the waters and at least you have a safe cushion if things go south.

And that’s it! Did I miss out on anything? Do share your thoughts in the comments or follow me on Twitter.

Code complete != ship ready


I used to work for a team where whenever an engineer said he was done, the next question would invariably be are you ‘done done‘?

Do you find yourself always under-estimating the amount of time needed to complete some software project? Does it take more time than what you planned? Or do you say you are done but need to change just one small feature.

Accurate estimation is difficult but again an unclear definition of what done means also contributes to this. So what does done mean?

Checklists and Processes

Boeing introduced preflight checklists in 1935 after a prototype crash killed two pilots. Investigations revealed that they had forgotten to carry out a critical step before takeoff. Thus, the fix was to introduce a preflight checklist to avoid this (they learnt from the mistake and became better for it).

A catastrophic software failure can have disastrous outcomes – it is expensive, can harm (imagine if embedded car software were to fail), and is bad PR for the company (how many security breaches have you heard of in recent times?).

So, do we need such heavy formal checklists for software development? Some companies require standardized processes while others don’t. However, it is always good to have a mental model of the various stages of the software shipping pipeline.

Here is a checklist to guide you through the various phases of done; you can now know which stage you are at any given point in time.

1. Code complete

You have written the code (and hopefully added unit tests) but have not done any deep testing. This is what most developers erroneously refer to as done. No, code complete does not mean done. It is the first milestone in a long journey.

Always have tests for code completion

2. Test complete

Thorough exploratory testing of the feature has been carried out. This covers extreme conditions, edge cases and load/performance scenarios.

It’s an exercise in futility to attempt to find all bugs and exercise all possible code paths. Rather, the goal of testing is to reduce the chances of a user finding a glaring simple-to-discover error that should have been found earlier. It also surfaces other issues (e.g usability, security holes etc.) that might have been latent.

Every discovered bug should ideally be fixed and a unit test added to prevent future regressions. However, not all bugs are fixable (and those turn into features…). Early knowledge of these issues enable developers to proactively prepare mitigation plans, workarounds and also notify users.

If you don’t have dedicated testers (they are worth their weight in gold and very good); you  can use James Whittaker’s testing tours method to get some fun while doing this and also ensure a good coverage.

3. Integration complete

You have completed the various isolated features, written unit tests and also done exploratory testing. You have a high confidence in each of the individual features however your components work exactly like the similitude below:

So get to it and do integration of all the disparate components and ensure that things still work as they should. More testing, more discussions with collaborating software engineers and maybe some more glue code.

Why do I keep emphasizing on testing? Have you ever had a bad experience with some software? It’s nearly always a quality issue.

4. Ship ready

This is the cross your t’s and dot your i’s moment; verify that the code solves the problem, issues discovered during testing have been fixed and components have been integrated. Code complete, test complete and integration complete? Great, time to ship.

Some organizations enforce strict limits on some parameters like performance, security, reliability and compliance. If so, you should do another pass to ensure that your software meets these criteria.

The product owner / customer likes the software and viola! Your software piece rolls out like a new car off the production line.

5. Shipped (maintenance ready)

Software is never done. When it is shipped, customers would start using it in ways you never imagined and will find issues. Some can be petty – for example, can you change move this button by 0.2 pixels? While others would be pretty serious stuff.

In maintenance mode, the software already exists but there are new bugs to fix, new feature extensions to make and behavioural modifications to make.

And when you think it’s all done, then maybe it’s time to release a new version. Start at number 1 again.

Enjoyed this post? Follow me on Twitter or subscribe for weekly posts. No spam for sure.

Related Posts

  1. The Myth of Perfect Software
  2. The Effective Programmer – 3 tips to maximize impact

JavaScript’s Function.prototype.bind


The bind function allows you to set the context with which a function will execute. It takes in a ‘context object and returns a new function which has its context set to the passed in object. The variadic method, which exists on all function objects, provides a workaround for the annoying and elusive ‘this’ context issue in JavaScript.

As web developers; we all nearly need to create references to object methods at some time or the other. The annoying thing is that the original context is uusally lost when we need it most! Let’s see how bind can help in these scenarios.

var obj = {
    val: 10,
    getVal: function () {
         return this.val;
    }
};

obj.getVal();
//10

var valGetter = obj.getVal;
valGetter();
//undefined

var boundValGetter = valGetter.bind(obj);
boundValGetter();
//10

Function Signature

Function.bind(thisObj, arg1, arg2,…)

thisObj refers to the new context for the function. However if the newly returned function is used as a constructor (i.e. called using the new operator), the this context will be a new empty object as expected.

arg1, arg2,… are extra parameters that are prepended to the list of arguments that the newly bound function is called with. Assuming you declare two arguments in the original bind call and then pass three new arguments to the returned bound function, then the two original bound arguments appear before the three newly passed in arguments.

var fn = function () {};
var bound = fn.bind(window, 1,2);

#equivalent forms
bound(3);
fn.call(window, 1,2,3)

If the bound function is invoked as a constructor, then the bound arguments are still passed on.

Uses

The most common application would be to avoid the use of the ‘that = this’ pattern in JavaScript. This is especially the case when you need to pass in context to event handlers, use anonymous functions or do something similar.

var ordExample = {
     log : function () {
           console.log('logger called');
     },
     asyncCall : function (callback) {
          //...
          callback();
     },
     useAsync : function () {
          var that = this;
          this.asyncCall(function () {
               that.log();
          });
     }
}

//Bind form
var bindExample = {
     log : function () {
          console.log('logger called');
     },
     asyncCall : function (callback) {
          //...
          callback();
     },
     useAsync : function () {
          this.asyncCall(function () {
               this.log();
          }.bind(this));
     }
}

ordExample.useAsync();
//logger called
bindExample.useAsync();
//logger called

As seen from the example above, we can use this in all sort of scenarios – from timers, Ajax callback handlers, event handlers, custom objects etc.

Issues

You cannot unbind after binding a function; anytime you call the Function.prototype.bind, you get a new function which has its ‘this’ context already prefixed to the pre-supplied value.

var fn = function () {};
console.log(fn.bind(this)===fn.bind(this));
//false

Ben Cowboy Alman has written a Function.protoype.unbind polyfill here.

The other issue is that there is some overhead with using bind; it adds some overhead and is not as optimal as using the ‘this = that‘ approach (variable vs function). Here is a jsperf run for four various bind styles.

So that’s it; now go bind some functions.

Defining JavaScript Functions


There are many ways to create functions in JavaScript; some styles are quite popular e.g. the function declaration and function expression while others are not.

//function samples
function declaration () {};
var funcExpression = function () {};
var namedFuncExpression = function named() {};
var fnConstructor = new Function ();

All approaches create a Function object however there are a couple of differences under the hood. Lets take a peek…

1. Function Declaration

The function declaration pattern is one of the most common patterns.


function fn () {
    //function body
}

Once a function is defined using the declaration format; it can be used anywhere in the enclosing scope even before the function body. Confusing? It’s all about hoisting.

2. Function Expressions

Functions are first class objects in JavaScript, thus it is possible to have expressions that evaluate to function values; such expressions are appropriately termed function expressions.

Creating a function expression is easy: just declare a function where the parser expects an expression and it automatically becomes a function expression. This includes assignments to variables and/or object properties, placing functions between parentheses (the grouping operator can only contain expressions),or after a unary operator (e.g. !, +, – etc).

//anonymous function expressions
var fnExpr = function () {};

(function fnExpr2() {} );

!function fnExpr3() {}

Function expressions can be named or anonymous; named function expressions (NFE) expose a function name that is available inside the function body but not outside it. See the snippet below:

var namedFuncExpression = function named() {
    return named.name;
};

named();
//ReferenceError, named is not defined

namedFuncExpression();
//returns "named"

NFEs help to make debugging nicer (we all know how frustrating it is to keep seeing ‘anonymous’ functions in the debugger). It might also come in handy when you need to retrieve a function name by calling toString() or make recursive functions (although the variable name will also serve the same purpose).

Function expressions are essential to achieve functional programming concepts like currying and partial application in JavaScript.

3. Function Constructor

The last way is to use the function constructor, this constructs a function object and returns it.

There are a few things to note while using this approach: created functions can only access variables in the global scope or in their own scope and it is no possible to create closures. Moreover, the use of the function constructor is slower since the function body has to be parsed every time it is called. And there are potential risks from malicious agents.

var add = new Function('a','b', 'return a + b');

add(1,2);
//3

var glbFoo = "global";
function scope() {
  var scpFoo = "scoped";,
   scop=Function('console.log(typeof scpFoo)'),
   glob=Function('console.log(typeof glbFoo)');

   scop();
   glob();
}

scope();
//logs undefined
//logs string

The parameters to the function are passed in first and then the function body (as a string) is passed in as the last parameter and viola! the function object is returned. The new keyword is optional; it still works without the new.

4. Function expression vs Function declaration

Function declarations and their bodies get hoisted to the top of the scope (no matter where they appear – top, bottom or middle) and are thus available through the scope. However for function expressions, the variable declaration is hoisted while the assignment to the function body only happens at runtime. See the example below:

declared();
//logs declared
function declared () {
    console.log('declared');
}

expressed();
//logs TypeError: undefined is not a function

var expressed = function () {
    console.log('expressed ');
}
expressed();
//logs expressed

5. Spot the difference? Identifying function expressions and declarations in code

Differentiating between function expressions and declarations can be tricky. According to the ECMAscript specification, function declarations must have an identifier. If functions without identifiers are unequivocally function expressions, how do we distinguish between a function declaration and a named function expression?

Function declarations are only allowed as sourceElements of scripts or functions. They cannot appear in nested blocks because blocks are  only allowed to contain statements and not sourceElements. Expressions on the other hand are expressions… :)

//source element examples
var a = 0;
function b () {};
if (false) {
    //nested, not source element
    var c = 0;
    function d () {};
}

//function declaration
function foo() {
    //another declaration
    function bar() {};

    if(true) {
        //function expression because
        //it is not a source element
        function baz() {};
    }

    //function expression
    //expressions expected after unary operator
    !function bng () {};
};

6. Finally…

Still reading? Here are some more examples of queer ways to create functions. Don’t do this at home/work/live/staging/etc.

var f = function (str) {
    alert(str);
};
eval('f("eval")');
//alerts eval

setTimeout('f("timeout")',1000);
//alerts timeout after a sec
};

Remember, don’t do this on live servers…

Did you enjoy this post? Here are a couple more interesting posts:

1. The JavaScript Function
2. Three Important JavaScript Concepts
3. A peek into JavaScript’s Array.prototype.map and jQuery.map

Update

Brilliant explanation of the difference between function and Function by Peter van der Zee:

“The `Function` is a global object and a function value, which generates a new function when called. You create new local variables named `Function` but not with `function` “

Three Important JavaScript Concepts


Statements and Expressions

The MDN documentation defines JavaScript expressions as any valid unit of code that resolves to a value.

a = 1;
3 + 4;

The first expression has value 1 which is then assigned to variable a while the second has value 7 which is not assigned to anything.

Since expressions evaluate to values (numbers, strings, functions etc), they can be substituted anywhere these values are expected. Programmers just have to ensure expressions resolve to expected values because of JavaScript’s weak typing.

Consider the following simple statement:

var x = "statement";

This is a statement and not an expression. Statements do something while expressions evaluate to values.

Dr. Axel has an excellent post which differentiates both: “you can use expressions where statements are expected (these are called expression statements) however you cannot use a statement where an expression (i.e. something that evaluates to a value) is expected”.

To simplify; you cannot use the statement above as a condition for an if branch (which expects an expression or value).

Variable Scope

Scope determines the lifetime of variables and where they can be used. Most programming languages have block scope, i.e. variables only exist within enclosing blocks (usually delimited by braces). However, JavaScript has other ideas… Check the code snippet below.

function JSBlockScope() {
    var noBlockScope = "BlockScope";
    if(true) {
        var noBlockScope = "FuncScope";
    }
    console.log(noBlockScope);
};

JSBlockScope();
//logs FuncScope

The output is “FuncScope”! Surprised? Block scope implies that declarations inside blocks do not overwrite external variables. JavaScript has function scope and consequently noBlockScope gets overwritten to ‘FuncScope’.

Function scope also means that variables declared inside functions are only available inside those functions, once the function exits, the variables are inaccessible anymore (well, unless you use closures…).

function scopeCheck() {
    var functionScope = "inside Func";
    console.log(functionScope);
};

scopeCheck();
//logs inside Func

console.log(functionScope);
//ReferenceError: functionScope is
// not defined

The functionScope variable defined inside the scopeCheck function only exists inside the body of the function.

Variables are first looked up in the current scope (i.e. the enclosing function), if not found, then the interpreter continues walking up enclosing scopes until it gets to the global scope. If the variable is not defined still; then the well-known “ReferenceError: variable is not defined” error occurs.

Hoisting

JavaScript has this weird but fascinating concept called hoisting. All variable declarations are hoisted – every variable gets declared immediately even though their values might not be set immediately.

function hoisting() {
    console.log(hoistedVar);
    var hoistedVar = "hoisted!";
    console.log(hoistedVar);
}

hoisting();
//logs undefined
//hoisted!

Explanation

Confused? Well what happens is that all declarations are hoisted to the top before any code execution begins. The above code is totally similar to the one below:

function hoisting() {
    var hoistedVar; //undefined
    console.log(hoistedVar);
    hoistedVar = "hoisted!";
    console.log(hoistedVar);
}

hoisting();
//logs undefined
//logs hoisted!

The log statements show ‘undefined’ since this is the default value for uninitialized JavaScript variables. If they weren’t hoisted, the interpreter would have thrown a ReferenceError. 

Hoisting also applies to functions (JavaScript functions are values afterall…) however there is a subtle difference between function declarations and expressions. Function declarations get hoisted to the top and are immediately available within the scope while function expressions are only declared and not hoisted (much like the same case for variables above). 

function isFunc(fn) {
    var isFn = (typeof fn === 'function');
    console.log(isFn);
}

function isUndef(fn) {
    var ntDef = (typeof fn === 'undefined');
    console.log(ntDef);
}

function funcHoisting() {
    isUndef(declaredFn); //false
    isUndef(hoistedFn);  //true

    function declaredFn () {};
    var hoistedFn = function () {};

    isFunc(declaredFn); //true
    isFunc(hoistedFn);  //true
}

funcHoisting();

Declaring variables at the top of functions helps to avoid hoisting surprises.

Conclusion

I was going to write about function expressions vs declarations, however I believe these three JavaScript concepts would significantly make it easier to understand that topic. Insha Allaah I’ll publish the function expression vs declaration post next.

Meanwhile, here are some other posts you might like:

1. The JavaScript Function
2. A peek into JavaScript’s Array.prototype.map and jQuery.map
3. Programming Language Type Systems I

A peek into JavaScript’s Array.prototype.map and jQuery.map


The map function comes from JavaScript’s functional programming roots: it applies a function to every array element and returns a new array of the results without mutating the original array. So lets look at the native JS and jQuery map implementations.

Array.prototype.map

The signature for the native JS implementation is:

array.map(callback, thisObject)

The callback is the transforming function that changes elements of array into new elements while thisObject will be this inside the callback (some cool applications exist). Most browsers allow Array.protototype.map  (support got added in JavaScript 1.6) however a few browsers still do not.

jQuery’s map

The signature for the jQuery implementation is:

$.map(array, callback, arg)

The array and callback parameters mean the same as above while the arg parameter allows you to send in extra arguments into the function ( I still haven’t found a use for this yet).  Unfortunately this inside the callback refers to the Global object (Window); if you need to get around this, you can wrap the callback in a $.proxy  call.

What’s the Callback?

The callback function is triadic in both implementations; the three parameters being the array element, the element’s index and the entire array (why this is needed still puzzles me).

jQuery callback example

var numbers = [1,2,3,4],
 squareNumbers = function (number) {
     return number * number;
 },
 squares = $.map(numbers, squareNumbers);

console.log(squares);//logs [1,4,9,16]

Array.prototype.map callback example

var numbers = [1,2,3,4],
    squares = numbers.map(squareNumbers);

console.log(squares);//logs [1,4,9,16]

Using element indices

If the element indices matter to you, take it into consideration the subtle differences between both implementations.

jQuery example

The jQuery’s map method will always return a flattened array which does not contain null/undefined values.

var numbers = [1,2,3,4],
    getAllEvenIndices = function(number, indexInArray){
        if(indexInArray % 2 === 0) return number
    },
    evenIndexedNumbers = $.map(numbers, getAllEvenIndices);

console.log(evenIndexedNumbers); //logs [1,3]

Native JS map example

The native implementation does not filter out undefined values.

var numbers = [1,2,3,4],
    evenIndexedNumbers = numbers.map(getAllEvenIndices);

console.log(evenIndexedNumbers);
//logs [1, undefined, 3, undefined]

Can I use Objects?

Surprisingly yes! You can call the jQuery.Map function on an object, for example, you have a JSON payload coming in from the server and you want an array of the values or keys, it is simple and easy to do this:

var payload = { id : 1, username : "xyz", points : 10}
    retrieveKeys = function (value, key) {
        return key;
    },
    payloadKeys = $.map(payload, retrieveKeys);

console.log(payloadKeys);//logs ["id", "username", "points"]

I don’t know of any simple way to do this using the native JS Array.prototype.map (I don’t know if it is even possible, maybe with some JS kung-fu. :) ).

So why use jQuery’s array.map if the JS language supports it implicitly? Here are a couple of reasons: the jQuery version strips off both undefined and null values, will work fine in all browsers (IE7 + IE8 do not have native support). But you can always write a polyfill too…

Here’s a puzzler: what would the snippet below return?

var result = $.map ([[1,2], [3,6]], function(elem) {
    return elem;
})

Did you enjoy this post? Check out my other posts on JS, JS Events and JS functional Programing.

Becoming a Professional Programmer


1. Deliver when you commit

It is extremely bad for your reputation to fail to meet up to your words; if you can’t deliver, please say no or find an alternative way out. How would you feel if an artisan disappoints you for no good reason? I bet you’ll probably never do business with them again.

So before you commit to anything (boring bug fixing, dreary testing or documentation), please make sure you’ll deliver or else do not commit.

2. Stay up to date

Do you know design patterns? Development methodologies? The latest fad in software development? Don’t neglect learning else you’ll wake up one day and realize that you are writing COBOL (OK, this is an exaggeration but you sure do get the hint). Staying up to date is your responsibility and no one else’s.

Dedicate time to make sure you know your field very well, ideally it should be time off work and gains should be measurable. While you are at it, please remember not to burn out, create time for fun things too.

Some employers actually make this easy by training employees or providing libraries – if you are lucky enough to have this, please take full advantage of this :); otherwise, there are tons of free stuff on the Internet that you can leverage – blogs, newsletters etc.

3. Be responsible

You must unconditionally know HOW and WHY your code works; and when testers find a bug, accept it as your doing graciouslyThis also applies to inherited code – no one wants to know if the code is spaghetti (with some onions and meat included) or written in Japanese. Once you inherit the code, it automatically becomes your code and it’s up to you to know how it works, what it does and how to fix/extend it.

If you are stuck with such bad code, why not try cleaning it up slowly? Every time you open the file, just make a tiny improvement (please no new bugs).

4. Know the domain

Most developers feel that users are not ‘smart’ enough to understand the intricacies of software development. Software development is complex but so are financial accounting, quantum physics , economics and a whole slew of other fields.

Imagine two developers working on a financial accounting product, the first writes software based on the requirements alone while the second makes a conscious effort to learn more about financial accounting. Who do you think will write better software and communicate more lucidly? Who will understand the problems, issues and challenges better?

Admittedly, it is more work trying to understand accounting (or any other field) but in the long run, it’ll pay off because you’ll write code in the problem domain. This also gives you the chance to contribute meaningfully to the project, proffer advice and analyze the competition. Who knows, it could open the door to new opportunities.

5. Work consciously

Most times we do things because we are accustomed to having things work that way – in coding, code design or requirements gathering. Ideally, we should always be thinking of our work – it should not just be the same ol’ thing all the time.

There are things to try, new (and probably better/more efficient) ways to write code and arcane language features to explore. Always keep asking these questions – why am I doing this? What am I doing now? Is there a better way to do this? It applies to everything – coding, design, maintenance and even meetings! Yes, meetings! :)

Did you enjoy this piece? Maybe you’ll also like becoming a better programmer and 5 things I learnt from Code Complete 2.

5 things I learnt from Code Complete 2


My yearning to read Code Complete started early in 2012 – I came across the book in the MASDAR library. Most of it didn’t make sense to me then but I made a mental note to return to it. Alhamdulilah I eventually got a copy of the book around August 2012 but I couldn’t bring myself to read it because of the many pages. Instead I read a couple of smaller books.  I finally stumbled upon goodreads this year and it helped to revive my long-lost book-reading habits.

I made a simple rule – I would make sure I read for about 30 mins everyday: no more no less; I wasn’t bothered about how long it would take or my reading speed, all I cared about was my consistency and understanding of the concepts. I finally finished the book about five months later (sounds like eternity huh?). The book is a little on the verbose side however I learnt a lot – I mean a REAL LOT – and here are my top five lessons from it.

1. Comments might actually imply bad code

It was surprising for me to learn that code with LOTS of comments might actually be bad code, strange huh? Yeah you’re right! Heavily commented code actually implies that the underlying codebase is abstruse and not self-documenting. Ideally code should be simple, straightforward and not need heavily commented

Moreover if comments are not updated when the original code changes, then they’ll become misleading which is even worse than having no comments at all. If you have excessive comments; maybe you should do a review and rework your code. Trust me, most times you’ll end up with cleaner code… OK,  well hopefully :).

Oh, and for those times you write ‘rocket science’ code (aka impossible to simplify), please save future maintainers the stress and do add comments.

2. Project Management

I think one of the most difficult aspects of the software development profession is getting requirements right. Customer perceptions always change and most times people do not even know WHAT they WANT and when they finally do, they want it delivered last week :).

I picked up a couple of ways on how to make this a pleasurable acceptable experience for everyone involved – from developers to project managers to clients. Learn how to say no, estimate project times and methodologies.

3. Leveling up as a programmer

I especially love the ‘Program into your language, Not in it’ quote. Programmers should NOT be limited by the languages or tools they use. If a language does not have a highly desired feature (e.g. asserts, exceptions etc), there is nothing stopping you from implementing your own such features.

Another important point I picked up was the continuous need to consciously improve the quality of my development process. I always get the urge to write quick dirty fixes to problems and the instant gratification of ‘working’ code fuels this bad habit. No, don’t give in! Resist the urge, fight it and crush it! Try to go the extra mile every time you code, that’s the way to grow.

I admit that writing ‘beautiful code’ takes more time and effort however the future savings far outweigh the immediate gains of bad fixes. What is the use of writing quick code in 2 hours and then spending 12 hours to maintain it? It would have been better to spend 6 hours to get it all right.

I once spent about two days trying to get a really critical function to work, I could have written it very quickly (< 2 hours) in sub-optimal ways however it would not have been reusable or flexible or neat.

4. Code is written to be maintained!

I have known for some time that duplicated code is bad and I finally got to really understand why; the issue is with maintenance. Assuming there are three replicated instances of the same code block; if a new programmer updates only one and forgets to update the others, then ‘miracles’ will happen during execution and it is going to be extremely difficult to find the issue.

It is also good to create config files that allow you to make platform-wide changes easily ( I use this a lot now); it makes code much more flexible and you do not really need to dive into some ‘evil’ forest to make changes.

Finally deleting code is a good idea – strange? The smaller the codebase, the fewer the chances of mistakes happening and the smaller the number of things you have to worry about. :)

5.  The importance of planning and design

Do not just rush into code, think carefully about the design, how to create re-usable components, how to properly name variables and ensure that code is clean and can be easily extended in the future.

I also adopted the Pseudocode Programming Process (PPP) which has saved me a lot of trouble with coding and design; this is how it works: you write pseudocode of what you want to do and how you are going to go about it – I normally just create a list of numbered steps – then you think through your plan and validate all assumptions.

Afterwards coding should be a breeze and even better, the pseudocode (assuming you leave it in the code) can be converted into cool comments. This approach also helps you to prevent second guessing when you get to tricky situations because you already went through the scenario in the past and wrote it out.

I noticed remarkable changes when I stopped diving into code without thinking. For example, I was able to re-use some  of my existing code to create an admin dashboard in just about 120 minutes; I bet I would have had to start from the scratch otherwise.

Final Thoughts

The size of the book and its verbosity still, Code Complete 2 is a great book and all programmers should read it – you will learn a lot and know what habits to drop.

If you also find it too difficult to understand, put it away for some time and make sure you return to it in about six months. The following quote explains this best:

If you’re a beginning programmer you won’t understand a lot of the material, and if you are experienced, the book will only confirm what you already know. Robert Harvey

The Art of Debugging


I recently wasted a lot of time while attempting to use the amazing Dropzonejs image uploader. I left out a function call in an overloaded function and this broke every subsequent call. More annoyingly, I could not pinpoint the cause of the error as Dropzone was failing silently.

Close to giving up, I decided to give it one more attempt and went to my sandbox – I create a safe area in all my projects for doing ‘risky’ stuff. Starting afresh there, I was amazed to see that everything worked fine. A close comparison of the code samples revealed the bug’s origin – the left out function call. I double-checked to confirm this and that was all about it. Sadly, the documentation does not mention that a failure to call done() in the accept function will break the code silently.

Programmers usually spend a lot of time debugging and it can be a painful experience;  some feel like tearing out their hair in exasperation, smashing their poor computers or even believing that their computers really ‘hate’ them! :)

Actually computers do not hate people and the operating system is not conjuring bugs – the most likely reason is buggy code. Here are a couple of tips on debugging; hopefully these will help to reduce time spent, frustration and annoyance levels.

The Inefficient Way of Debugging: Trial-by-Error

Random guesses? Print statements littered around? Fast fixes that ‘appear’ to work? Do these ring a bell? Welcome to the bad bad way of debugging.

This approach is fraught with a gazillion issues. The worst being the potential introduction of new bugs into the codebase. Lucky bug discoveries offer little learning opportunities and it might be difficult to reuse knowledge gained from such fixes in the future.  Also, such run-of-the-mill fixes tend to be inelegant and stand out like a sore thumb when compared to earlier designs and architecture.

The Efficient Ways of Debugging

1. The very first thing is to create a list of the likely causes of the bug; this usually involves thinking deeply about loopholes and design flaws. Studying program error dumps and buggy behaviour might also help.

2. Go through the list while eliminating disproved hypotheses. Once a likely cause is found, a verification needs to be carried out; this can be as simple as proving that the bug appears only when that cause is activated.

3. Don’t just rush to write a fix – I bet you would not want your ‘super-fix’ to mutate into a monster ‘bug’. Think deeply about the bug and what potential ripple effects a fix could have. Also think about how the proposed fix would work, how it blends into the system’s architecture and possible design impacts.

4. Yes, you got it!! Go ahead and squash that bug! Yuck – I dislike bugs.

5. Not finished yet, you need to go through your code armed with your newly acquired bug-terminating powers. Find and ruthlessly sanitize code likely to suffer from such bugs. Rinse and repeat – always leave code in a cleaner state than before.

Extreme Approaches: When the Efficient Ways Fail

You might apply all the above and still be stuck in a rut; this might occur if you have extra-terrestrial bugs (quite popular in multi-threaded environments).

6. Total examination

The brute force approach is bound to work insha Allaah although it involves painstaking work. You go through the code thoroughly (a debugger should come in handy); this might involve examining all execution paths if possible and trying to pinpoint the issue. Hard work…

7. Start afresh

When everything fails, why not throw out the old code and write it again?

Some other tips

6. Very important, set a time limit

Do not spend 3 days hours trying to fix a bug if you can re-implement the same feature in 2 hours. If you are sure you can rewrite a bug-free version of some buggy code, go ahead with a rewrite and spare yourself the trouble. Time counts.

7 Learn to use tools

Debuggers, memory examination tools and profilers. They will help point out to what might be causing the issue. I once had a really really nasty bug while using jQueryUI, the bug only showed up on a particular browser and only when the page was accessed over the local network; otherwise all was fine.

I eventually had to use a profiler after several failed debugging attempts, I  then discovered that a function was being called several hundred times. Bug case solved!

8. Discuss with a buddy

Find a programmer / buddy to discuss with, discussing your ideas with someone will help you to find design gaps and flawed assumptions; you might be surprised that you get the error spot on without any contribution from your buddy.

Now go ahead and eliminate some bugs :).