We had a nice group of participants with a wide range of kills and knowledge and we covered (roughly) multiple aspects of testing JavaScript apps. I had fun and we were busy during the workshop which is a good sign. Please if you were in the workshop give us some feedback using the comments in this post apart from the form that SkillsMatter will send to you, it will be very appreciated and will help us improve.

Big thank you to Jenny for her invaluable help and support before and during the workshop. And to Tony Bruce and SkillsMatter for organizing this great two days of networking and workshops. It's fantastic to visit London from time to time and meet so many fascinating people.

There is no magic in programming languages. The fact that they are formal languages makes them deterministic. For every behaviour there is a reason. For every error there is a logical cause.

Before googling for an odd error message, try to understand what the interpreter means. This is the fastest way to solve the problem.

I often see developers wondering why a certain test throws an error, whilst reading several times the production code, without really understand what's the meaning of the error. Wrong approach, one must know what the interpreter is saying before searching for the cause. It may be an error in the test itself!

The same error message may be expressed in a different manner by different browsers and other JavaScript interpreters like Node. This fact emphasizes the need for understanding what are they talking about.

In order to understand JavaScript error messages one must understand
what's the meaning of "undefined". Undefined is a special value.

var x; // We are declaring a varible, whose value is undefined

In this case we say that variable "x" is undefined, is the type of the variable:

typeof(x); // prints out the string "undefined" (as a string!).

The value of a variable is undefined until it's assigned a concrete
value:

var x = 5; // x is a Number

var x = function(){}; // x is a Function

var x = {}; // x is an Object

var x = true; // x is a boolean

var x = undefined; // x is undefined

Now let's review errors containing the word "undefined" in the message:

TypeError: undefined is not a function (Google Chrome)

The interpreter says that something used as a function, is not a function actually, it's an undefined variable. Why does the interpreter assumes it's a function? Because there are braces after a name. When there is an open parenthesis right after a name, the interpreter determines that name is a function according to the grammar of the language. It's exactly like the question mark at the end of a sentence in English, we assume the sentence must be a question because of the mark at the end. The writer of the function was probably expecting the variable to be a function at that point but given some defect, it's not. This is how to reproduce the error:

var x; // x is undefined.

x(); // and... undefined is not a function, is just undefined!

TypeError: Cannot read property 'length' of undefined (Google Chrome)

The error says there is a property named "length". A property is a member of an object. The interpreter assumes that "length" must be a property of an object because there is a dot preceding it. Properties are accessed with a dot:

var obj = {propA: 123, propB: 456}; // an object with 2 properties

var val1 = obj.propA; // reading property (123)

var val2 = obj.propB; // reading property (456)

The error message says that the variable at the left of the "length" property is undefined, that is, the object is not actually an object, it's actually the undefined value. This is the way to reproduce the error:

var obj; // obj is undefined

obj.length; // trying to create or reference a property in an undefined value, raises an error.

If the "property" is accessed to set it a value, the error message will be slightly different:

TypeError: Cannot call method 'trigger' of undefined (Google Chrome)

This one is similar to the previous. It says "of undefined" expresses the sense of belonging. It must be related to an object. This time it's a method, not a property. It assumes that it must be a method because there are braces after "trigger". The error means that the value of the variable at the left hand side of the dot, is undefined:

var obj;

obj.trigger(); // trying to reference a method in an undefined value, raises error.

Node.js produces slightly different messages for the same errors:

var x; // variable x is undefined

x(); // TypeError: Property 'x' of object #<Object> is not a functio

In JavaScript everything happens within a certain environment. When the variable is defined out of any function its scope is global. In the case of the browser, the global environment is the "window" object. In the case of node, it's the "global" object:

var x = 5;

window.x; // 5 in the browser, error in node

global.x; // 5 in node, error in browse

Node makes this fact explicit in the error messages.

TypeError: Property 'x' of object #<Object> is not a function (Node.js)

As there is not dot preceeding the "x", we know it's talking about
the "global" object. As we are using braces after "x", node assumes
it must be a function. Notice that it doesn't reveal the value of "x", which is undefined, it just says that "x" is not a function. So it would raise the same error if "x" was a number.

At the time of this writing, Firefox behaves a bit similar with regards to the value of the variable:

TypeError: x is not a function (Mozilla Firefox)

var x;

x(); // TypeError: x is not a function

ReferenceError: x is not defined

I find this message a bit unfortunate. I would prefer "x is not declared" or "x does not exists". Because "not defined" seems to be the same as "undefined" but it's not. This error happens when the variable has not been declared but it's value is being accessed:

By pairing with a wide variety of other programmers, I've noticed that the programmer's memory has an important impact on the productivity. In order to be agile searching for code blocks within a file, we must remember the structure of the code, be familiar with the code geography. We should have a mental map of the file that we can handle in our heads, so as to remember whether certain block is located near the top, near the middle or at the bottom of the file. When the file is too big or the developer doesn't make an effort to build the mental map, he starts using the IDE's search feature to navigate everywhere, even when the code block is present in the current screen. Searching for code blocks with the IDE all the time, stops the flow and thus reduces productivity. The focus goes away. Well, this is what I've seen and I've experimented whilst pairing.

Different people have different memory capacity, the trick is to be aware of your capacity and manage it accordingly. If you can't handle files longer than 300 lines of code, then keep your files below that size. When you find yourself using Ctrl+F to search for a function name often, consider splitting the file into several ones. The same applies for packages, modules, namespaces... try to group artifacts so that you can handle a mental model that contains all you need to work on the task or feature at hand.

Coding requires a lot of concentration and all the attention that we can put on ourselves to improve our own process day after day. Every coding session is an opportunity to learn and improve. Specially when you pair and get immediate feedback from your pair.

I believe this has a relationship with developer's preferred font size. The bigger the monitors are, the smaller I see people's fonts. I need a magnifier to be able to read to code sometimes, I always have to ask them to enlarge the font. Smaller fonts means more lines in every screen but anyway, most people work with horrible mountains of legacy code and it doesn't fit in even 5 screens!