Month: March 2014
== compiles to the strict equality operator
===, making it impossible to use the dangerous loose equality operator.
Now, if the event function needs to be expanded, one would logically think it could be changed like this.
However, that doesn’t compile. You have to drop the comma or move it onto the next line, before
How about something like
func1 1, func2 2, 3? Does 3 get passed to the first or second function? I still frequently forget one place where parenthesis are not optional, leading to unexpected behaviour. The statement
x = f -> f looks like it should assign x to the identity function, but it doesn’t. Instead, x is assigned the result of calling f with a function of no arguments returning f. Or how about this,
a + b adds a and b while
a +b calls a with the argument
+b. There are lots of other examples of ambiguous and confusing syntax in CoffeeScript. For more examples, check out My Take on CoffeeScript by Ruoyu Sun and this Gist from Tom Dale.
Readable, Think Again
Ambiguous code is only one part of what makes CoffeeScript difficult to read. Everything is an expression (returns a value) and it has lots of control flow and operator aliases. All of which encourages very English sentence like code. However, that often makes the code less readable, not more. The human mind is good at understanding logic in symbols; English is not good at expression logic. As an example, consider the line
eat food for food in foods when food isnt 'chocolate' from the CoffeeScript tutorial. The declaration of what food is occurs in the middle of the line and doesn’t even look like a variable declaration. Furthermore, until you finish reading the line it isn’t clear which foods will be eaten. That code could easily be worse if
unless eat is undefined was added to the end, making the whole line conditional. One wouldn’t realize it was conditional until reading the end. Imagine if the expression before the
for had been a complex multi-line method call with logic in it. Ryan Florence digs deeper into these issues in his post A Case Against Using CoffeeScript. Suffice it to say, many of the features added to CoffeeScript with the intent of making it “readable” actually have the opposite effect.
To see how this would happen, imagine you are in a hurry to implement the next feature. Unbeknownst to you, the following code is near the bottom of the file you are about to modify.
Now, near the top of a code file you add these lines. So that the file is now.
Did you catch the error? Originally,
lastValue was local to the
innocent function, but now it is global to the file and the
innocent function actually modifies it. We now have a bug waiting to happen when someone calls
innocent then checks the value of
lastValue. Keep in mind there could be multiple screens of code between these two code segments.
Not Far Enough
typeof to something that was more useful, for example the
typeOf() function recommend by Douglas Crockford.
Classes Are an Illusion
new keyword or to make everything a factory function.
CoffeeScript has a
this keyword. When creating a class you can’t help but feel that
this should refer to the class everywhere within the body of the class. That is what it would mean for something to be a class. But the actual semantics of
this are unchanged. For example, if you declare a class with methods using
Car is a class, one expects
I’m starting a new web application project, and I’ve decided to use Ember.js. That will enable me to provide users a slick single-page app experience. Since I am a .NET web developer by training, I plan to use C# and ASP.NET Web API as my server technologies. I could use tools like Lineman.js or Grunt to manage and package my client-side code. Instead, I’d like to use the Visual Studio toolchain, because it provides a lot of great tools for web application development. Since I already know Visual Studio, there will be almost no learning curve for me. I’m not trying to argue this is the right choice. I’m just trying to share a little about what it takes to make it work with Ember.js. Early on, I realized that I would want to bundle and minify all my scripts and templates. I’ve chosen the Cassette library for this which provides “asset bundling for .NET web apps”. Here is how I made it work with Ember.js, but first, why did I choose Cassette?
Why not ASP.NET Web Optimization
Ever since Microsoft released the ASP.NET Web Optimization framework, now available as a NuGet package, it has been the default choice on the .NET platform for bundling and minification of scripts and css. Indeed, I initially started with it. However, I quickly ran into a number of issues with it, all of which were made more challenging by the lack of documentation.
More serious than that, ASP.NET Web Optimization provides no support for compiling or embedding templates. In the official EmberJS template from Microsoft they use a beta version third party extension to provide template compilation for Ember.js and provide a 117 line class for embedding templates outside the the web optimization framework. The third party library appears to be abandoned, with 8 months since the last commit and still in beta as of March, 2014. Even with all that, the EmberJS template’s solution doesn’t switch between embedding and compiling based on whether the web optimization library is in debug mode, leading to possible problems.
The Cassette library preceded Microsoft’s ASP.NET Web Optimization library and is arguably the primary alternative to it. If your familiar with how Web Optimization approaches bundling it may take a while to become accustomed to the Cassette approach. They use the term “bundle” somewhat differently, which is confusing when you are first learning. I recommend you read the “Getting Started” and “Assets and Bundles” sections of the Cassette v1 docs before switching and reading the the v2 docs. Those sections of the v1 docs explain basic concepts not explained in the v2 docs. Until I read them, Cassette wasn’t making any sense to me.
The main difference between the approaches is around what a bundle is. In the Web Optimization library, a bundle is a group of files that will be minified and combined into a single file. Referencing that bundle is including a reference to the combined file. Whereas, in Cassette a bundle is more like a group of files that work as a single dependency. Meaning that you would never want one file out of the bundle separate from another. Referencing bundles is then stating what the page’s dependencies are. The bundles are then minified and combined into three separate files for css, scripts and templates. For templates, Cassette supports the idea of embedding the templates rather than loading them from a separate file.
At the top of your cshtml page you reference any individual assets or bundles the page depends on:
Then in the page body, you indicate where the html to include scripts, templates and style sheets should be rendered. This will then group the dependencies by type and, depending on whether Cassette is in debug or production mode, output either debug friendly assets or minified, compressed, cached, versioned assets.
Cassette is a powerful library with many more features and options. Be sure to check out the documentation for the details. Additionally, the author of Cassette has created NuGet packages for drop in support for Less, Sass, CoffeeScript, TypeScript and more. One of those NuGet packages is for pre-compiling Mustache Templates using Hogan.js. Unfortunately, this doesn’t work for Ember.js, because it needs its own template compiler due to the
set methods on Ember models. Never the less, we’ll see that all is not lost.
Configuring and Referencing an HtmlTemplateBundle
Setting up a bundle in Cassette for all your templates is very easy. Don’t install the Cassette.Hogan NuGet package since it doesn’t work with Ember.js. I choose to put all my templates in the
app/templates folder following the example in the EmberJS template from Microsoft. The template uses the extension
hbs for Handlebars templates, however I choose to use the also common extension
handlebars, because it was more explicit. Since all the templates are in one directory, creating a bundle was an easy addition to my Cassette bundle configuration.
To reference the templates from my application page only required adding
Bundles.Reference("app/templates"); to my bundle references. The templates were then automatically embedded in the page inside script blocks in place of the
@Bundles.RenderTemplates() call right before the close body tag.
Giving Templates a “data-template-name”
There were some problems with the embedded templates at this point. The script blocks were being generated with an
id attribute based on the path of the template file and the type attribute was set to “text/html” instead of “text/x-handlebars”. While there is some confusion over this, I believe that the
data-template-name attribute is the preferred way of identifying your ember templates, rather than the
id attribute. The reason is that nested route templates have names separated with ‘/’, but it is not valid to have the ‘/’ character in an html id. Fortunatly, Cassette is based around a very flexible pipeline model, making it easy to customize. After reading some of the documentation, poking around the source and reading some some code from the Cassette.Hogan package, I came up with a simple solution.
Cassette allows the bundle pipeline for any bundle type to be easily modified by implementing the
IBundlePipelineModifier<T> where T : Bundle interface. All bundle pipeline modifiers are picked up automatically. Fixing the issues was almost as simple as setting the content type of the html template pipeline and swapping out the implementation of how templates were wrapped in a script block.
WrapTemplatesInEmberScriptElements class is basically the same as the old
WrapHtmlTemplatesInScriptElements with the
id= replaced by
If you try the above code with version 2.4.1 or prior of Cassette, you’ll get an exception when it’s not in debug mode. I didn’t notice this issue until a week after writing the code above when I deployed to the test environment. The switch between production and debug mode can be confusing in Cassette, because it isn’t your first thought when something works on the developers machine but not the deployment environment. It took me at least an hour to track down the problem. In production mode the exception you get is
KeyNotFoundException from deep inside Cassette around bundle cache code. Turns out that setting the content type to
"text/x-handlebars" causes Cassette to not know what extension to give the cache file. That seems to be poor design choice to me, but essentially the fix is that
"text/x-handlebars" needs to be added to a list of known content types. I have submitted a pull request to do this, that will hopefully be accepted soon, so this won’t be a problem in future versions. Until then, you can work around this by adding the following hack to the beginning of your
With that, my Ember.js templates where embedded correctly into the page and developers could begin work with a clean separation of the templates into individual files. Obviously, before production release I would like to be able to enable compiled templates when Cassette is not in debug mode, but that challenge can wait for another day.
I guarantee you that Apple and Microsoft (and Opera and Mozilla, but the first two are enough) will never embed the Dart VM.
Still not statically typed
dynamic type that a mix of dynamic and static typing can be interesting and useful. A language showing another way of mixing the two with dynamic as the default would be very interesting. Unfortunately, that isn’t what Dart is. Dart is a dynamic language, plain and simple. Type checking is just a jsHint style suggestion that something might be wrong. What’s the use of a type declaration if it doesn’t mean the value will actually be of that type?
To dig deeper, check out Why Dart is not the language of the future by Rafaël Garcia-Suarez.
Not the Answer