My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.
Showing posts with label JSLint. Show all posts
Showing posts with label JSLint. Show all posts

Saturday, May 28, 2011

My Last Comments On JSLint

Preface

I have been working with many teams and I have used JSLint on daily basis. This post is not about the tool itself, neither against Douglas work, this post is about developers often too religious about this tool.
Finally, if you follow this blog you have already read tons of other reasons to think rather than "suffer silently this tool".
It's my last post about it and I hope "it will not hurt your feelings".


Seriously guys, it's not that I think JSLint is all bad, but I cannot stop thinking it's simply an effect.
The more I hear or read about developers being so religious about this tool, the more I feel to blame it.
I am pretty sure Douglas will hate me for this post but I really hope he will read it 'till the end.

Douglas Talk At Falsy Values

Both me and big Doug were there, me for a workshop and Mr D. for his speech.
"Surprisingly" Mr Crockford talked about JSLint (again?!) and why it's so good.
While many hints for newcomers are absolutely a must know, many others are absolutely inconsistent for senior JavaScript developers.
There is a particular slide and a particular sentence Douglas said there:
... write code the way it's meant for the language ...

Above sentence was related to variables declaration, showing behind something similar to this classic example:

(function () {
// never executed
if (false) {
var something = 123;
}
}());

As all of us know, and if not we should, the reason JSLint would like to have all variables defined on top of the function is that no matter which condition, for or while loop, we have at some point, the parser will pre-consider all var in the same scope as local scope variables available since the very beginning.

(function () {
// there is no "var" in this scope
alert(something);
// throws "Can't find variable: something"
if (false) {
// eventually global in ES3 and ES5 with no strict
something = 123;
}
}());

The moment we define a variable local, even if we never reach that line, that variable is available for the whole scope, got it?

(function () {
alert(something);
// undefined and no errors
if (false) {
var something = 123;
}
}());

Good, now ...

JSLint Inconsistencies

Since the previous point is clear to everybody, I wonder if it's clear that function declaration has even more precedence than variables.

(function () {
alert(something);
// the function declared later on

function something() {
return 123;
}
}());

This is not true for function expressions, where the result will still be the same obtained with variables:

(function () {
alert(something);
// undefined and no errors

var something = function() {
return 123;
};
}());

Accordingly, function declaration is referenced on top of everything, variables included!
So why on bloody earth this piece of code does not pass JSLint?

var something = (function () {

// top reference available ever
// function declaration
function something() {
return oneTwoThree;
}

// second references available in this scope
// local scope variable
var oneTwoThree = 123;

// return the local function call
return something();

}());

Try by yourself the result:

Error:
Implied global: oneTwoThree 5

Unused variable: oneTwoThree 1 'something'

---------------------------------

Global something

1 'something'()
Unused oneTwoThree
Complexity 1

4 something()
Global oneTwoThree
Complexity 1

I can bet the amount of bullshit I can read in latter result is a shame for Douglas Crockford in first person, isn't it?

Not Only Inconsistencies

Another part covered by Doug speech was the with statement ... here summarize:

... somebody (n.d. I guess me) may argue that the with statement may be useful in certain situations, but since it is always ambiguous and there is nothing that could not be done without it, the with statement should disappear from JavaScript ....
... and this is what happened.
If we try "use strict"; activation in most recent browsers we can spot that the with statement is not allowed anymore, "thanks"!

A Tool To Rule Them All

It was actually a colleague of mine asking Douglas this question (or what I got about it) :

... so, you are saying that JS developers have no discipline, but don't you think that "dictating discipline" is not such easy task as well? ...
I honestly do not remember the answer but I am sure Douglas provided a proper one ... anyway ... what I do believe is that every developer has is own style, as long as syntax and readability are not too much compromised.
If we use this tool thinking our code will improve any how we are first of all acting like machines plus we are not considering a "little detail" ...

Your Team Does Not Know JavaScript

Precisely! I know this is hard to face, but in 11 years of JavaScript programming I have never found a reason to have such tool that changes allowed programming language syntax defined by specifications ... fucking read them and stop winging! (and pardon my french)
In few words, I have never had a single problem to understand any other piece of JavaScript code written by any possible developer out there but when I had a problem, and at the beginning of whatever programming language we all have, I have investigated, studied, and finally understood, what was going on in that piece of code and what was missing from my JS knowledge about it.
Surely I did not blame the other developer, since if we would like to be monkeys on daily basis, of course we should use as many tools as possible that throw warnings even if the piece of code we wrote is absolutely correct, and we still have my precedent example few paragraph before as proof ...
On the other hand, if we would like to master our JavaScript knowledge there is no way a piece of code that perfectly works could be screwed up because of JSLint.

Early JavaScript Days

When Douglas Crockford was still promoting JavaScript all over the world, nobody had any idea what he was talking about ... well, now we all have.
This bloody language is absolutely everywhere and those "feeling cool" Java developers that still think JS is a toy are regretting 50% of their studies because they just don't get it ... that's why projects like GWT exists: developers that think JavaScript is a toy, write Java that is gonna be translated into Javascript ... and this is how powerful and flexible JavaScript is.
In these days, and surely before, we truly need discipline and a lot of hints since as lazy developers we could not spend half a day reading ECMAScript 3rd Edition specs ... isn't it?
In these days, and for these developers, of course JSLint has to be there, they don't know what they are doing but hey, at least they are willing to learn something more from this tool (and most likely behind a syntax translator such GWT is, created to do not throw JSLint warnings ...) .
As demonstrated before, this is not enough.
Java skills into JavaScript language are similar to me pretendng to have Alex Martelli knowledge using Visual Basic 6 on daily basis ... I hope you know what I mean ...
As summary, if you think you can move knowledge from another programming language without deeply understanding the new one pretending you come from "something better" you are half way trough your own failure.
At the end of the day it may not matters, as long as the next point is clear for everybody.

TDD And Unit Tests Are The Only "Safer Way"

Yeah you read it right ... there is no way our JavaScript code is gonna be any safer because of JSLint or whatever JS validation tool: no fucking way!
If we think that === rather than == is all we need to be safe, without understanding why we may be safer or why we may do something simply redundant without considering cases where we want to ==, we have never been so wrong.
Unit Tests, and more Unit Tests on top of Unit Tests are the only answer to our code quality!
It does not matter how we write routines as long as real Senior Developers can understand it, simply asking more if they really don't, and as long as all our possible implementation cases have been considered.
If we are those kind of "my code pass JSLint, my code is better and safer and cleaner" develoeprs, we are simply demonstrating how much we still have to learn about programming.
I don't know any other language that religious or with need of these kind of "natural programming code evaluation tools" and we all know JavaSscript is not the first programming language ever, neither the last one.
If it's about some common code convention we don't need JSLint, we simply need a bloody wiki/web/infrastructure page able to explain it so that somebody else could eventually blame it the moment he's flexible enough to understand meant edge cases.
This is what I have answered as well during my workshop when somebody asked me what I think about JSLint, while the whole post is the reason I did not even start arguments or questions after Douglas speech, and the reason I will never do it.
We all have our style, Douglas has his own one, and I am happy for him he is that consistent.
Should I be a Douglas Crockford clone on daily basis? Hell no, since as I have said: I know WTF I am writing and why

Tuesday, February 16, 2010

JSLint: The Bad Part

Every programming language has somehow defined its own standard to write code. To be honest, as long as code is readable, clear, and indented when and if necessary, I think we do not need so many "code style guides" and, even worst, sometimes these "code standards" let us learn less about the programming language itself, helping if we are beginners, sometimes simply annoying if we are professionals.

Disclaimer

This post aim is absolutely not the one to blame one of my favorite JS gurus, this post is to inform developers about more possibilities against imperfect automation we'll probably always find in whatever excellent spec we are dealing with. This post is about flexibility and nothing else!

JSLint And Code Quality

Wehn Mr D says something, Mr D is 99.9% right about what he is saying ... he clearly represents what we can define a Guru without maybe or perhaps but he, as everybody else here, is still a programmer, and we all know that every programmer has its own style if we go down into details.
Mr D programming style has been historically summarized in this Code Conventions for the JavaScript Programming Language page.
All those practices are basically what we can find out about our code using a well known and widely adopted parser: JSLint, The JavaScript Code Quality Tool.
I write JavaScript and ActionScript (based over the same standard) since about 2001 and generally speaking, as experienced developer, I trust what I meant to do, and rarely what an automation tool supposes to teach me about the language.
This is like studying remembering rules rather than being able to understand them, something surely academical, nothing able to let us explore and discover new or better solutions ... we are stuck in those rules, but are we machines? Are we Mr D code style clones?
This post is about few inconsistent points regarding JavaScript Code Quality, with all due respect for somebody that simply tried to give us hints!

Indentation

The unit of indentation is four spaces. Use of tabs should be avoided because there still is not a standard for the placement of tabstops
While size always matters, since to move 1Gb or 600Mb in a network still makes a big difference, I wonder what's wrong with just two spaces. The monospace font we all use to write code on daily basis is "large enough", and while 2 spaces rather than 4 are extremely easy to spot, 4 spaces are absolutely ambiguous.
How many times we had to check via cursor if some other editor placed a tab rather than 4 spaces there? Ambiguity is something that does not match at all with the concept of Code Quality, am I wrong?
Finally, while everybody in this world has always used innerHTML due its better performances against the DOM, Mr D. tells us that tabs are not defined as a standard ... have we never heard something like de facto standard?
Specially in a unicode based language as JavaScript is, where tabs are indeed replaced by "\t" even in Mr D JSON specs, how can we think about whatever JavaScript IDE or Engine unable to understand tabs? Let's avoid them, but still, at least let's replace them with something that does NOT occupy exactly the same space!

Variable Declarations

All variables should be declared before used. JavaScript does not require this, but doing so makes the program easier to read and makes it easier to detect undeclared variables that may become implied globals.
OK, got the point, minifier or munger will take care about this so it could make sense. Now, everything is fine to me, as long as I don't read the next immediate point:
The var statements should be the first statements in the function body.
... are we serious here?
So, if var declaration is the first thing I should do, why on earth I should spend 10 times my time to write semiclons and var again?

// first thing to do
var a = 1;
var b = 2;
var c = 3;
var d = {};

// AGAINST
var a = 1, b = 2, c = 3,
d = {}
;

Faster to type, easier to read, I can even group blocks of variable declaration to define different types (primitive first, object after, undefined later if necessary) and thanks to indentation, the precedent point, I must be an idiot to do not understand what the hell I wrote. Is it just me?
I prefer to perfectly know the difference between comma and semicolon and these two buttons are in a different place, there is NO WAY I coul dmake a mistake unless I don't know the difference ... but in that case I guess we have another problem, I know nothing about JS!
Furthermore, something kinda hilarious to me:
Implied global variables should never be used.
OK, assuming for whatever reason we don't consider global functions references/variables, we should forget:
  • undefined
  • window
  • navigator
  • document
  • Math
  • jQuery (dollar $ is global baby!)
  • everything else that supposed to be reached on the global scope
I may have misunderstood this point so I do hope for some clarification, but again, the difference between a local scoped variable and a global one should be clear to everybody since JSLint cannot solve anything, and I'll show you later.

Function Declarations

I agree lmost everything about this chapter, but there are surely a couple of inconsistencies here as well.
There should be no space between the name of a function and the ( (left parenthesis) of its parameter list. There should be one space between the ) (right parenthesis) and the { (left curly brace) that begins the statement body.
...
If a function literal is anonymous, there should be one space between the word function and the ( (left parenthesis). If the space is omited, then it can appear that the function's name is function, which is an incorrect reading.
Let me guess: if there is a name, there must be a space to identify the name, if there is no name, the must a space as well? A function called function which is a reserved word?
I am sure Mr D has much more experience than me, but I wonder if that guy that wrote function function() {} has been fired, is in the Daily WTF website, it is part of the shenanigans group, or if it is still working beside Mr D ... in few words, how can be no space and a bracket ambiguous?

var f = function(){};
I want to honestly know who is that programmer able to confuse above code ... please write a comment with your name and your company, I will send you a Congratulation You Are Doing Wrong card ... I'll pay for it!!!
Same is for the space after the right parenthesis, as if an argument could accept brackets so that we could be confused about the beginning of the function body, isn't it?
Some bad code there in this chapter as well, which let me think truly weird stuff:

walkTheDOM(document.body, function (node) {
var a; // array of class names
var c = node.className; // the node's classname
var i; // loop counter results.
if (c) {
a = c.split(' ');
for (i = 0; i < a.length; i += 1) {
...

So we have to declare every variable at the beginning, included variable used for loops, the i, so the day engines will implement a let statement we'll have to rewrite the whole application?

var collection = (function () {
var keys = [], values = [];

return {
....

wait a second, consistency anybody? How come the next paragraph uses a natural assignment as that one while the Code Quality is to do not use it?

Names

Names should be formed from the 26 upper and lower case letters (A .. Z, a .. z), the 10 digits (0 .. 9), and _ (underbar). Avoid use of international characters because they may not read well or be understood everywhere. Do not use $ (dollar sign) or \ (backslash) in names.
I am not sure if Prototype and jQuery guys shouted something like: epic fail but I kinda laughed when I read it. It must be said that these practices are older than recent framework, and this is why I have talked about do not explore code potentials at the beginning of this post.
Do not use _ (underbar) as the first character of a name. It is sometimes used to indicate privacy, but it does not actually provide privacy. If privacy is important, use the forms that provide private members. Avoid conventions that demonstrate a lack of competence.
So if I got it right, if we identify private variables inside a closure, where these variable actualy are private, we should not identify them as private so we can mess up with arguments, local public variables (remember cached vars?) and everything else ... ambiguous!

Statements

Labels
Statement labels are optional. Only these statements should be labeled: while, do, for, switch.
...
continue Statement
Avoid use of the continue statement. It tends to obscure the control flow of the function.

Labels are fine, continue, which is basically an implicit label similar to goto: nextloopstep should be avoided. But as far as I read the return statement able to break whatever function in whatever point has no hints about being only at the end of the function bosy as is for ANSI-C programmers?

Block Scope

In JavaScript blocks do not have scope. Only functions have scope. Do not use blocks except as required by the compound statements.

with (document) {
body.innerHTML = "is this a scope?";
}
Never mind, somebody in ES5 strict specs decided that with statement is dangerous ...

=== and !== Operators.

It is almost always better to use the === and !== operators. The == and != operators do type coercion. In particular, do not use == to compare against falsy values.
This is the most annoying point ever. As a JavaScript developer, I suppose to perfectly know the difference between == and ===. It's like asking PHP or Ruby people to avoid usage of single quoted strings because double quoted are all they need ... does it make any sense?

// thanks lord null is falsy as undefined is
null == undefined; // true
null == false; // false
null == 0; // false
null == ""; // false
null == []; // false
null === null; // true, this is not NaN

In few words, as I have said already before, null is == only with null and undefined, which means we can avoid completely redundant code such:

// Mr D way
if (v !== null && v !== undefined) {
// v is not null neither undefined
}

// thanks JavaScript
if (v != null) {
// v is not null neither undefined
}

Moreover, since undefined is a variable it can be redefined somewhere else so that the second check could easily fail ... and where is security in this case?

// somewhere else ..
undefined = {what:ever};


// Mr D way
if (v !== null && v !== undefined) {
// this is never gonna happen AS EXPECTED
}

Please Mr D whatever you think about this post, think more about that silly warning in JSLint: it's TOO ANNOYING!!!
One last example about ==, the only way to implicitly call a valueOf if redefined:

if ({valueOf: function(){return !this.falsy;}} == true) {
// hooray, we have more power to deal with!
}


eval is Evil

The eval function is the most misused feature of JavaScript. Avoid it.
eval has aliases. Do not use the Function constructor. Do not pass strings to setTimeout or setInterval.

aliases? It seems to me that eval is misunderstood as well since there is no alias fr eval. This function may be evil specially because it is able to bring the current scope inside the evaluated string.
Function and setWhaatever do not suffer this problem, these global function always ignore external scope.
Moreover, it is thanks to Function that we can create ad-hoc, runtime, extremely performer functions thanks to dynamic access to static resolution:

function createKickAssPerformancesCallback(objname, case, stuff, other) {
return Function(objname, "return " + [objname, case, stuff, other].join("."));
}

Where exactly is the eval here and why we should avoid such powerful feature when we are doing everything correct?

Unit Test IS The Solution

If we think we are safe because of JSLint we are wrong. If we think we cannot do mistakes because of JSLint we are again wrong. JSLint could help, as long as we understand every single warning or error and we are able to ignore them, otherwise it won't make our code any better, neither more performance killer, surely not safe.
There are so many checks in JSLint that somebody could simply rely in this tool and nothing else and this, for the last time, is wrong!
Next part of the post is about a couple of examples, please feel free to ask more or comment if something is not clear, thanks.

JSLint: The Bad Part

All these tests are about possibly correct warnings, often useless on daily basis code. Please note all codes have been tested via The Good Parts options and without them.

Conditional Expressions

I twitted few days ago about this gotcha. An expression to me does not necessary require brackets, specially it does not require brackets when it is already inside brackets.

"use strict";
var lastValidArgument;
function A(b) {
// I mean it!!!
if (lastValidArgument = b) {
return "OK";
}
}

Somebody told me that if we put extra brackets, as JSLint suggests, it measn that we meant that assignment, rather than a possible missed equal.
First of all, if == is discouraged in favor of === how can be possible developer forgot to press the bloody equal sign three times? It does not matter, the inconsistency here is that if I properly compare there two variables leaving there brackets, theoretically there to let me understand I am doing an assignment rather than comparing vars, nothing happens:

"use strict";
var lastValidArgument;
function A(b) {
if ((lastValidArgument === b)) {
return "OK";
}
}

I would have expected a warning such: Doode, what the hell are you doing here? You have superflous brackets around! ... nothing, inconsistent in both cases, imho.

Unused variable

A proper syntax analyzer is truly able to understand if inside a whole scope, we used a variable as we meant to do. Unfortunately, here we have a totally useless warning/error about an extremely silly, but possible, operation. To avoid the error:

"use strict";
(function () {
var u;
// we forgot to assign the "u" var
// how can this if remove such error from this scope?
if (u) {
}
}());

Agreed, u has been used, but why on earth I have no warnings about a completely pointless if? As far as I understand, variables are truly well monitored ... this requires an improvement ... or remove the Unused variable check since in this case it does not change anything.

Pattern to avoid global scope pollution

The new operator is powerful, but it could be omitted and JSLint knows this pretty well! We, as developers, are able to modify behaviors, using functions duality to understand what's going on. Example:

"use strict";
function A() {
if (!(this instanceof A)) {
return new A();
}
}

// always true
A() instanceof A;
new A() instanceof A;

Cool, isn't it?
Problem at line 7 character 9: Missing 'new' prefix when invoking a constructor.
How nice, thanks JSLint!

Look behind without look forward

More about new, who said this requires parenthesis? As soon as I write new I am obviously trying to create an instance. Since the constructor will be exactely the one referenced after, and since after this operation there will be a semicolon, a comma, a bracket (return without semicolon), how can it be possibly a problem for JavaScript?

var a = new A;

If I don't need arguments, I feel kinda an idiot to specify parenthesis ... maybe it's just my PHP background, isn't it?

class A {}
$a = new A; // OK
$b = 'A';
$a = new $b; // still ok
$a = new $b(); // WTF, $b is a string

// oh wait ...
$b = 'str_repeat';
$b('right', 2); // rightright


Strictly Compared

I have already talked about null and == feature, now let's see how dangerous can be JSLint sugestion:

"use strict";
function pow(num, radix) {
return Math.pow(num, radix === null || radix === undefined ? 2 : radix);
}

// somewhere else, since not only eval is evil
[].sort.call(null)["undefined"] = 123;

Above code will both pass JSLint and always fail the check || radix === undefined since undefined will be 123 primitive.
You know what this mean? Unless we do not define an undefined local scope variable for each function (the most boring coding style ever, imho) we should simply avoid === undefined checks, these are both unsafe, these slow down code execution since undefined is global and requires scope resolution, and these are a waste of bytes

function pow(num, radix) {
return Math.pow(num, radix == null ? 2 : radix);
}

That's it, there is no value that could mess up that check: undefined, null, or a number, 0 included!

Nothing bad in this code

This is the best way I know to create a singleton, or a prototype, to have a private scope as well, shadowing the runtime constructor:

"use strict";
var Singleton = new function () {
// private function (or method)
function _setValue(value) {
// lots of stuff here
_value = value;
}
var _value;
this.get = function () {
return _value;
};
this.set = function (value) {
if (!_value) {
_setValue(value);
}
};
this.constructor = Object;
};

Here we have a Jackpot:
Error:
Problem at line 4 character 14: Unexpected dangling '_' in '_setValue'.
Problem at line 6 character 9: Unexpected dangling '_' in '_value'.
Problem at line 6 character 9: '_value' is not defined.
Problem at line 8 character 9: Unexpected dangling '_' in '_value'.
Problem at line 10 character 16: Unexpected dangling '_' in '_value'.
Problem at line 13 character 14: Unexpected dangling '_' in '_value'.
Problem at line 14 character 13: Unexpected dangling '_' in '_setValue'.
Problem at line 2 character 17: Weird construction. Delete 'new'.
Problem at line 18 character 2: Missing '()' invoking a constructor.

We can nullify the Singleton variable itself, but still nobody else can have access to that scope. This is what I call a variable or method private, and I mean it!
Underscore is perfect as first character, since it helps us to understand a "protected method/property", which is never truly protected, and a real private method/property, shared across instances if it's a variable, usable as private method if called via a public one.
The best one ever, in any ase is:Weird construction. Delete 'new'. ... Weird what? A lambda based language cannot create runtime via lambdas instances?

Conclusion

I hope this post will help both Mr D. and developers, the first guru to improve JSLint syntax checks, while latter people to understand errors, being able sometimes to completely ignore them.
I am looking forward for some feedback or, even better, something I did not consider or some example able to demonstrate or underline my points, thanks for reading.