Общо показвания

октомври 17, 2012

Closure compiler and the adverse effect of using types for optimizations

This is more of a note and less a fully featured post. Just a quick reminder that one should not use types for optimizations if one is not actually providing the types. This way one will not spend almost 30 minutes battling with a code compiled with debug options (and thus extremely ugly) just to figure out why the the code is not working as expected even thou one has followed all the rules of the compiler.

Type optimization is a great addition to the compiler and indeed produces smaller code. So small that it is actually not existing.

So next time you want to have a nice and tidy compiled code, do not forget that you should not just write the code and test it as source and then, just to see how it goes so far as compiled entity, run it with advanced mode and type optimization. You should first write the types. It is easy.

октомври 10, 2012

TypeScript (almost a week later or why you should not jump to it yet!)

I have played with the language and guess what... it is not so brilliant as one is lead to believe initially. As with many new products you start to discover the multitude of technical gaffes only after you use it for a while.

First of all I should tell that I rewrote a real world module used in production and proven to work with a) RequireJS and b) Closure tools, the later being fully annotated and all types discovered and identified correctly.

Now, in TypeScript, there are several severe problems for OOP and one of those is evident only if you use chain-able APIs. You know those, where you write almost 300 character lines of methods being invoked one after the other.

Lets see a simple example:

class Base {
  m() { return this; };
}

class Derived1 extends Base {
  m1() {};
}

class Derived2 extends Base {
   m2() {};
}

class Derived3 extends Derived1 {
  m() { return new Derived2(); }
}

Two things to notice: Base has a method called m and it returns the 'this' object, which as we know is special and is always pointing to the context in which the function/method is called. Second: Derived1 class extends Base and introduces a new method m1, which returns nothing (in TypeScript - void, in JavaScript undefined.

Would you like to assume what will the following code do?:

(new Derived1()).m().m1();

Well. it spills out an error: The property 'm1' does not exist on value of type 'Base'.

Analyzing the code is is pretty obvious what is happening: the compiler does not understand what is 'this' when the invocation is encountered. It figures out that the type is Derived1, then searches for method m on it, it does not find one, looks it up in the immediate parent, finds it, checks its return type and ... 'boom', it does not know what is 'this' anymore. Is it possible that Microsoft do not know anything about context in invocation or is it a bug?

Reading the related thread in the codeplex discussion board it is pretty clear to me that the people currently playing with the language have never ever heard of JavaScript compilation, AST and tree shaking and type inference and whole program compilation. It is also pretty obvious that the fragmentation of the JS library world does not help.

Lets try another example:

class Base {
  m() { return this; };
}

class Derived1 extends Base {
  m1() {};
}

class A {
  another(){
    return this;
  }
}

var a = new A();
var b = new Derived1();

a.another.call(b).m1();

As it might magically seems, this example works! How is this possible? Well, it is not magic, if we take a look at the definition of Function.prototype.call it is defined as returning 'any' and this is the correct declaration (because of course it can return anything). Here is the thing: the compiler should still be able to understand what is going on. Lets analyze this a bit: method of class A is called in the context of an instance of class Derived1. Lets look what is the return statement of that method: 'this' - s keyword in JavaScript and TypeScript. So if it is 'this' the return type should be the context in which it was called, right? Why is the compiler not able to determine that and instead rely on the declaration?

I will tell you why: because it was not designed to be able to do such complex tree walking. And it is okay, maybe the authors have different objectives. But what I think we should have is a language/compiler that can do this kind of things! Whole application compilation is what will really assure all your types are correct, not compiling small parts and then hoping that the type system will still work - it will not.

On the mentioned thread there was a proposition to have the _this keyword replace the fact that the compiler is not smart enough to know the type of the context of invocation. It might be true, while I do not agree, it is up to the designers of the language. But imagine this (as they promote the VisualStudio plugin): You have the code above and after you typed (new Derived1()). you get the completion and you select m() and then you get:

(new Derived1()).m().

and at this stage you get no meaningful completion, because the typescript service does not know what is the type of the result anymore. So now tell me, how useful is that?

Of course this is not really a show stopped, people seem to like it a lot, I also like the syntax for the modules and classes, kind of like the fact that you have your type definitions next to the variables, much more elegant than having Java like annotations. Unfortunately the type system reader seem to either be in its infancy or have different objectives than the ones I consider important, which makes the language not so attractive to me. There are things to be fixed, a lots of bugs have been narrowed down in the last week and I am sure the tool will mature, but the advanced features some developers are looking for (for example a robust type system as in Closure tools) are not there. Too bad, I really liked the syntax.

Good luck to Microsoft and I will make sure to check the language in 6 months. Unfortunately it seems the community will be driving the development and knowing the variety of styles and requirement I don't believe something coherent and useful will come out of it in the long run.

октомври 07, 2012

TypeScript and the JavaScript developers

This is going to be a rant of a king and is not related to the 3 part series dedicated to TypeScript.

I happen to like TypeScript a lot. It is typed (I lived with types in JavaScript for a long time, Closure tools anyone?) and I like short, clear syntax and tools that can work with it. Closure tools are awesome, but hard to learn and hard to use, internally Google have attempted to make the syntax more bearable, but then what happens is that their own tools work inconsistently with it (gjslint does not understand scoped code and thus does not provide useful information in that case, the compiler works just fine however).

TypeScript in the other hand is pretty easy to get on for the average JavaScript developer. Unfortunately the average JavaScript developer seem to be in love with patterns that are mostly used in jquery and do not understand basic concepts of the language, and still they are interested in this new language. At least this is my impression from the questions/suggestions asked on the forum on Microsoft's page.

This is in sync with the opinion of some of the 'gurus' of the JavaScript land: too many JavaScript developers, too few good ones.

Not to be too skeptical, but I don't see the regular jquery user benefit from type checking, they are in more for the auto completion. Not that this is bad... just strange, as it works without type checking as well...

As a person coming from Closure tools I am in LOVE with TypeScript. I wonder what do other find in it? While people still argue how useful type checks are in JavaScript, for me it is no longer "IF" I should do type checking, but "HOW" do I do it easier for me.

октомври 05, 2012

TypeSciprt vs. Closure Library/Compiler

This post will take a look at the user experience with the closure tools versus the experience with TypeScript.

This is part 3 of 3 parts post. Part 1 is here, part 2 is here.

Because there is a compiler involved and because everyone out there is speeding up on comparing TypeScript to Dart, Clojure, C# and whatever there is I wanted to point out one thing very important that no one seem to notice:

JavaScript is TypeScript. All valid JavaScript is valid TypeScript. This puts the new language way out of the niche of Dart, Coffee Script or whatever language is out there that compiles to JavaScript. The closest thing that there is IMO is Closure library + compiler.

I will elaborate a bit on that: Closure library is all valid JavaScript: it can work in the browser just as it is. Because you can put pure JavaScript in TypeScript same is at least in a fringe case valid for TypeScript. Most people compare the closure compiler to other option in simple optimization case: however the library and the compiler were created to be used in advanced mode, which mandates very special subset of JavaScript to be used in the source js files in order for the output to work as intended. That is: closure library is a subset of JavaScript while TypeScript is a superset of the language.

If you can remember a few years ago the closure tools and especially the library were received very badly in the JavaScript community: well established names in the community were on the fast track to reject it. I particularly remember the notes of the RaphaelJS creator on how bad the closure library was, how little the creators understand JavaScript working and so on, even for loops were used as example on how they should not be used. Of course today we all know that the library should never be used without advanced optimization and that making micro optimization on loop constructs where the loop body is 10000 slowed than the slower loop construct you can imagine is pretty stupid, but back in the days the big names of the open source JavaScript development movement were there to "explain it for us".

I mentioned this because today I see pretty much the same story: the well established names in the javaScript world (at least some of theme) were fast enough to give their verdict on the new language just because it does not coincide with their established work flow.

Well, a few years ago those people were wrong and even though closure tools were never  widely accepted or used, they remain one of the best in the business. No compiler or minifier can beat the closure compiler in advanced mode. Of course the requirement for the input remains and is clearly a big leap for any JavaScript developer, but the benefits are very clear and if small size is what you are looking for this is the place to go.

Lots and lots of big products have been built with other tools of course and they work well too. The thing is that the tools were offered for free and almost no one put enough effort to figure out how and when should it be used. The developers were angry that they have to write their code following specific patterns and the learning curve for the components that were ready to use was huge. It still can be for new comers. The main complain was the style and lack of expressiveness because of the limited number of allowed patterns.

Strangely today the same developers are limited more than ever: most of the MVC frameworks are very opinionated about the code style and patterns that can be used, also most are not interchangeable, if you start with one product it is not such an easy task to switch to another, not really. So it is basically the same thing, I for example have never used AngularJS. Today I wanted to try to make something with it, well... I had 2 hours free time. Guess what - I could not complete anything in two hours. Maybe I am a slow learner, maybe it is not for me, whatever it is, the thing is you have to give it time.

Now back on TypeScript. Because of the automatic type inferring and because it does not actually contains any code/library the learning curve is very little, epsecially if you have already dealt with module patterns, inheritance, classes in JavaScript, public/private/protected methods and types. I will translate that for you:

If you have used closure tools before, TypeScript will be very refreshing and intuitive tool for you.


Yes, it does not provide the utilities closure has, yes, it cannot strip unused code, but it seems that the community is not interested in the later, even advanced projects like uglifyJS is not aiming to clear unused members because "it is not safe" for every type of code style. Yes, it is not. But is very beneficial. Anyways, unlimited by the patterns of closure library and compiler but still having static types and easy to follow annotations, having interfaces that can be checked at compile time, having sort of 'exports' (defined in the case of TypeScript) is very familiar to any closure developer.

Like in closure tools, you have to go through a build step before you can check your changes in the browser. In the case of closure tools, this is only when you change a namespace or require a new one, you need to recalculate the dependencies. In the case of TypeScript it is true even if you change a single letter, because the file that is loaded in the browser is not the one you are editing. I believe it will not take long for this to be overcomes like it was for closure with tools like closure-script and plovr.

Unlike closure, you have source maps that work right now, not that you will needed it much, unless you are using the TypeScript preferred module pattern, because the generated JavaScript matches very closely the source.

Unlike closure the generated code is not obfuscated nor minified. However there are plenty of tools that will do that for you. Unfortunately the generated code is not compatible with the closure compiler in advanced mode and you will always need to load the full of your libraries if you happen to create them with TypeScript. The good news is that modern JS engines tend to not construct everything in the memory, there is something called lazy parsing, which I do not pretend to understand very well, but basically it says that if a part of your code is never used, it is never interpreted as well, except the first time when checking for code validity. Maybe this will solve some of the issues with downloading several megabytes of code and the caching will solve the rest? I have no idea, but the thing is that we see almost then megabytes of scripts being now part of a single application. The fact the developers tend to use patterns that are easy on the eyes and skills but hog on system memory is entirely different problem.

I find it easier to express complex constructs in TypeScript than in Closure, however the small number of people already interested in the language pointed out that it lacks some important types (for promises, deferred etc.) I believe those will be resolved in the next few months.

The language is still in Alpha! You have to know that. Also it tried to follow ES6, which probably means that if it changes the language might change as well. But it is a fun toy as well, especially if your mind set is polluted by the closure tools and you are constantly thinking about types and interfaces and static methods of classes.

So the verdict in my case (me being not really an acknowledged expert, but still with years of experience in large scale projects) is that TypeScript looks very promising and I will definitely enjoy working with it. Hopefully there will be a standard DOM library soon and hopefully widget library later as well. I also hope that it will be possible to construct a compiler that will be able to strip unused symbols to make it possible to developer large and well featured libraries without fighting for every byte.

A few words about the compiler and auto completion in other editors: last night post established that the completion and compilation can work entirely in the browser and this is true: open the play ground app and disconnect from the internet - everything will continue working: the completion service is available in the browser offline simply interpreting your code and using the main definition file (lib.d.ts). This really means it can be accomplished in IDEs like Cloud9 which already work in the browser anyway. Please please please do something about it, because I really don't like VisualStudio2012 and I dont even own a Window machine.

TypeScript Part2: AMD and CommonJS

This is the second part of three part post dedicated to the developer's experience with the TypeScript language, created and released as open source by Microsoft.

Part 1 is here.

AMD modules.

The compiler supports producing AMD compatible modules out of your code. However one need to specifically target the currently circulating module systems when coding, which is fairly simple: just avoid the module keyword and mark the exports with the export keyword. This is slightly counter-intuitive, but if you know about this feature in advance no mistakes will be made. So to sum it up and clarify I will make a real world example and define the smjs api interface present on the stb devices:


interface Smjs {
  initapi();
  set_json_handler(hanlder: string);
  jsoncmd(command: string);
}

class esmjs implements Smjs {
  initapi() {}
  set_json_handler(handler) {}
  jsoncmd(srt){}
};

export var smjs = new esmjs();

Then I compile it with the following command:
tsc --module amd mymodule.ts
and the result is then:
define(["require", "exports"], function(require, exports) {
    var esmjs = (function () {
        function esmjs() { }
        esmjs.prototype.initapi = function () {
        };
        esmjs.prototype.set_json_handler = function (handler) {
        };
        esmjs.prototype.jsoncmd = function (srt) {
        };
        return esmjs;
    })();    
    ; ;
    exports.smjs = new esmjs();
})

This will allow me to basically define my module as amd without having to write my amd boilerplate. How about required modules? It is as simple as stateing them with an import module pattern:

import myname = module('path/to/module');

The resulting code will entirely compatible, as if you typed it in the amd pattern.
There is one thing to mind however: the compiler does not understand the requirejs config options and will always traverse the paths in simple mode (i.e. as if you have not set any config on requirejs regarding paths). In the opinion of some folks using rjs this makes it impossible to use TypeScript in a real requirejs projects. However this is not my opinion, because the compiler does not try to do everything for the module loader, instead it simply provides means to allow code completion and basic checks on your module, so instead of really providing the code for the third party modules that you do not want to include in the base path of your *.ts scripts, provide the definition files instead. More details and examples can be found by browsing the example projects constructed with typescript on their website.

Producing commonJS module is similar: even without specifying the
--module
directive the compiler will output commonJS style code when it encounters the
export
keyword. The same module above will look like this:
var esmjs = (function () {
    function esmjs() { }
    esmjs.prototype.initapi = function () {
    };
    esmjs.prototype.set_json_handler = function (handler) {
    };
    esmjs.prototype.jsoncmd = function (srt) {
    };
    return esmjs;
})();
; ;
exports.smjs = new esmjs();
(Dont know why the extra semicolons though)

One interesting aspect of all this is that is you reference moduleA from moduleB, the compiler looks for it in order to make all possible checks on your code, so if you do not really have the required module (i.e. A) you should at least provide the definitions for it. With the AMD/CommonJS module pattern it is even easier as you only will provide the exports from the module, which is often a very simple, stripped interface (modules provide better implementation hiding, right?).

Another catch is how you define the referenced modules in AMD/CommonJS module definitions in TypeScript: in TypeScript module you do it by using reference comments, however in AMD/CommonJS you do it with import. You can of course use imports in TypeScript modules as well, but in a slightly different meaning. You can learn more about this in the video posted on their web site.

One note: if you tend to require lots and lots of modules that are not written in TypeScript and you do not want to spend time writing definition files it is probably better for you to not bother with TypeScript. Module migration from AMD to commonJS and from CommonJS to AMD can be achieved with other tools anyway.

In my research I found it more compelling to use the modules for nodejs projects, because there are so much npm modules each and every one of them with different interface. What would be really great is if the npm modules provide definition only and if possible with commends. This could easily lead to a tool that is able to generate documentation from definition files, which will be a double win: a) you can use TypeScript or JavaScript to develop your npm module, then you deploy the JavaScript and the definition file. It can be used both by an IDE and by a documentation tool. On the consumer of the module side same can be applied: if the consuming developer uses TypeScript he gets to use the definition file for auto completion and for documentation, if JavaScript is the preferred technology then still the definition file can be of great help on understanding the API instead of reading lots of documentation, sometimes not that well written and sometimes completely missing.

As of AMD, the reality of most projects is as follow: you pull up like 10 different pieces of libraries and framework parts and almost none of them is AMD compatible, then you spend a few days tweaking the shims for those to be loaded as they require and then you start writing your application code "as modules" in hope that those can be reused in other parts of your application or (hail Mary) in another project, the later of course is happening like... never. At the end you have a well defined modular code of course, but you have do many dependencies in each of those modules that you figure out you will never be able to use just one or two modules from this project because they will pull up at least 10 times mode dependencies. Because it is application logic code. One thing you can easily do is plug new features in such partitioned code, which is not a small win, but it does not pay back that much when you think of it.

Enough on my opinions on the module patterns in use.

The fact is if you use AMD and/or CommonJS TypeScript can support your code easily and you do not need to rewrite your existing code to TypeScript to benefit it, you only need the definitions.

Part 3 will take a look at a how TypeScript compares to Closure Tools.

октомври 04, 2012

TypeScript (by Microsoft)

The last few days the news was all over the Internet: Microsoft has released a preview of a new superset of JavaScript.

I decided that I should give it a try, especially after reading materials on the internal situation in Microsoft vs. the same in Google. It is not a secret, that I have not been using Microsoft technologies for 12-13 years. What good comes out of Redmond, right? Or at least that is the mantra most of Linux and OSX users swear by.

Well, it turns out Microsoft have learned and they are indeed able to produce high quality. I have talked previously about the TV interface and the fact that is uses no library at all and uses everything available in webkit. Well it turns out it works without any changes in Internet Explorer 10! So yeah, tehy have learned!

Now about the new language.

The last few months I have been working extensively with closure tools and I can honestly say that while it is very interesting and big and well designed product, it is a subset of the original language in so many ways, that it is like you have to learn to think in javascript anew.  It dictates memory saving rules and design patterns, but on top of that it dictates constructs that a very small minority of JavaScript developers would appreciate. Its pluses and minuses are not the topic here, however I will use it to compare to TypeScript.

The history, the aims and directions for the language you can get from the official web site and slightly reinterpreted from all news about it. Here I will be talking more about it from developer's point of view.

First of all, it provides the class, interface and module constructs on top of a type system. Nothing new here, however the module system seem to confuse most of the developers, judging from the forums. The beauty I see in it is that it can output modules in both commonJS and AMD format. This means that you can indeed write your logic once and make it work in node and browser without using any wrapping or boilerplate code! This is really really great. I have read about similar capabilities, but most of the time it was converting from one to the other or involved writing boilerplate code.

The module pattern TypeScript authors decided to use is a well known and kind of "used and dismissed" one: self invoking function wrapping. The reason it is not widely used I believe is that it leaves the developer managing dependencies manually. There was no sane way to manage a project with hundreds of files this way.

TypeScript uses something called references: a comment at the top of the source file that declares dependencies. The declaration has two uses: 1) it allows the editor (I will talk about editor support later) to know which files to use for completion/type checking and if "output all" mode is used, those files fill be included in the build. The later will produce a single javascript file with optional source map that has the sources arranged in the correct order. This way it is able to provide a build system on its own, without depending on AMD loader.

Unfortunately most of the code out there is written using different patterns (which is why writing large application trying to compile a working system out of so many different pieces is pain in the *ss). The interesting thing about TypeScript is that is is compatible with any library because the resulting javascript is "pure" javascript. It does not expect anything from any other part of your application. You can write any code in TypeScript that depend on backbone for example. The type system can be 'boosted' much like the closure compiler type system. You just define an interface and then declare a variable that is using it. Let's see an example. In most modern browsers on the Element class you have classList property that is an object with property length and a few methods. It is not included in the lib.d.ts file (d.ts files are the way TypeScript can include type declarations only without actual implementations, much like the extern files in closure).

interface classList {
  length: number;
  contains(classname: string): bool;
  add(classname: string): void;
  item(index: number): string;
  remove(classname: string): void;
  toggle(classname: string): void;
}

interface Element {
  classList: classList;
}
This will tell the editor and the compiler about a property on all Element instances, named classList which implements the classList interface. The interface is not really defined in the browsers as I defined it here, in fact it is a DOMTokenList and one could simply complete the Element interface with classList as this:

interface Element {
  classList: DOMTokenList;
}

but I am using this as an example how one can define an interface and then attach it to an existing interface. This is possible because the interfaces are 'open' as they call them in TypeScript, which means that one can add to them from wherever needed.

If you happen to override an interface property you will get a warning.

As this simplified example shows, one can easily add types for an existing code base and then include it. In case this is done and a '*.d.ts' is included in a source file it will be considered for types but as it does not provide implementation the developer has to provide it manually (in the browser - include the javascript for the external source for example). However this covers a large portions of the web sites in the wild!

A few words about the editors. Syntax highlighting is provided for vim, emacs and Sublime Text 2. I have not tried it in vim and I have never used emacs, however sublime is working (only in OSX, interestingly it is not working under Linux, on the sublime text 2 forums there are other people with the same issue). There is already a gist providing build config for ts files in sublime text 2. I have tested this one as well, however the line/column error recognition is not working, but the build is working okay. On the demo video, presenting the language, a plugin for VisualStudio is used. If you happen to have Window 7/8 and VisualStudio, the plugin is free of charge and is working as demonstrated, meaning - it works great! Auto completion, error detection and intellisense are all great. What you might have not noticed however is that the same is available in the play ground on the website! Which means that all this intellisense, type and error checking etc is running on javascript. Hopefully it will be available soon on other editors/ides as well.

I want to say something here as well: Cloud9 IDE were the first one to congratulate themselves with "support for the language". However having syntax highlighting in the editor is not exactly language support. It would be great if they could have had the intellisense (as it was already demonstrated that it could run on javascript only) and then go out loud. Never the less, I hope they will catch up on this. They have built great platform and I think this will be a great completion to the product.

Part two will cover commonJS and AMD modules.