With Each Step Forward, Microsoft Takes Two Back
Today I was browsing a Microsoft published document on creating ASP.NET Web Pages using the Razor Syntax and to my surprise I found this gem on page 65.
@{
var db = Database.OpenFile("SmallBakery.sdf");
var selectQueryString = "SELECT * FROM Products ORDER BY Name";
}
<!DOCTYPE html>
<html>
<head>
<title>Small Bakery Products</title>
<style>
h1 {font-size: 14px;}
table, th, td {
border: solid 1px #bbbbbb;
border-collapse:collapse;
padding:2px;
}
</style>
</head>
<body>
<h1>Small Bakery Products</h1>
<table>
<thead>
<tr>
<th>Id</th>
<th>Product</th>
<th>Description</th>
<th>Price</th>
</tr>
</thead>
<tbody>
@foreach (var row in db.Query(selectQueryString)){
<tr>
<td>@row.Id</td>
<td>@row.Name</td>
<td>@row.Description</td>
<td>@row.Price</td>
</tr>
}
</tbody>
</table>
</body>
</html>
In case you missed it here is the meat of the problem I have with this example:
@{
var db = Database.OpenFile("SmallBakery.sdf");
var selectQueryString = "SELECT * FROM Products ORDER BY Name";
}
This is in direct relation with Microsoft’s latest attempt to make programming easier for bad software developers. Ayende probably put it best in his article entitled “Microsoft.Data and Positioning” when he said:
If Microsoft thinks that they can get the market for bad developers, good for them. But that needs to be highly segmented. It should be clear that going with that route is leading you to a walled garden and that writing real apps this way is not good. The best comparison I can think of is Access apps in the 90s. There was a clear separation between “just wanna write some forms over data app over the weekend” and “I want to build a real application”. When you built an app in Access, you had very clear idea about the limitations of the application, and you knew that if you wanted something more, it would be a complete re-write.
That was a good thing, because it meant that you could do the quick & dirty things, but when things got messy, you knew that you had to make the jump.
The problem with things like Microsoft.Data is that there is no such line in the sand. And when you call it “Microsoft.*” you give it a seal of approval for everything. And when you have a piece of code that is explicitly designed to support bad coding practices, it is like peeing in the pool. If there is only one pool, it is going to affect everyone. There wouldn’t be nearly as much objection if it was called WebMatrix.Data, because that would clearly put it in someone else’s pool, and it that turn into a putrid swamp, I don’t really care.
I know proponents of this approach are going to say, it’s only an example to give a quick demonstration of how the Razor syntax works, and no good developer would take this seriously. But I don’t know what land Microsoft lives in, because in my land examples like this are seen by both good developers and bad developers a like and examples like this quickly turn in to production apps. Bad developers have the same deadlines as good programmers do, and bad developers don’t have the same forethought about the pains that come from bad coding practices, so they are more apt to take the example at face value and look at it as a good example of how they should be programming coming from Microsoft itself.
And don’t even get me started about handling your post back logic in the same page, and then doing an insert into the database that is found on page 68.
@{
var db = Database.OpenFile("SmallBakery.sdf");
var Name = Request["Name"];
var Description = Request["Description"];
var Price = Request["Price"];
if (IsPost) {
// Read product name.
Name = Request["Name"];
if (Name.IsEmpty()) {
Validation.AddFieldError("Name", "Product name is required.");
}
// Read product description.
Description = Request["Description"];
if (Description.IsEmpty()) {
Validation.AddFieldError("Description", "Product description is required.");
}
// Read product price
Price = Request["Price"];
if (Price.IsEmpty()) {
Validation.AddFieldError("Price", "Product price is required.");
}
// Define the insert query. The values to assign to the
// columns in the Products table are defined as parameters
// with the VALUES keyword.
if(Validation.Success) {
var insertQuery = "INSERT INTO Products (Name, Description, Price) VALUES (@0, @1, @2)";
db.Execute(insertQuery, Name, Description, Price);
// Display the page that lists products.
Response.Redirect(@Href("~/ListProducts"));
}
}
}
I shouldn’t have to explain what is wrong with this. This is the way that PHP 3 and classic ASP developers use to construct pages over 10 years ago, which by the way is no longer recommended practice for either language. PHP 5 now has classes and a couple very well accepted MVC frameworks, classic ASP is all but gone, and Ruby, with Ruby on Rails which is an MVC framework, has most of the mind share of dynamic languages at the time of writing this.
So why is Microsoft continuing to target PHP 3 users, when they should be targeting PHP 5 and Ruby on Rails users for the mind share of rapid application development? I am calling on Microsoft to take this abomination of a document down, and just put up a simple Razor syntax language reference at the very least, and at the very most gut this document and create a document that doesn’t perpetuate bad software development practices and becoming a shining star to software developers and not a rusty anchor.
Performance Optimizations Made By Microsoft, Google, and Yahoo JavaScript Minimizers
In my first post about JavaScript compression and the different levels supported by the three major competitors in the JavaScript minimization, obfuscation, and optimization tools space. I the article I discussed which tool provided the best compression in regards to the resulting byte count. And found that Google took the over all crown with Microsoft following very closely behind. A comment posted on that article by Eric J. Smith of Code Smith, provided a nice lead in to my second article in this series, he posted this comment:
So if you haven’t guessed it yet by the title and then by Eric’s comment this post is going to be on the optimizations provided by the tools. So lets get started…
Setup
Back in October I saw an interesting article on this same subject comparing Yahoo and Microsoft on site called Ajaxian. But at the time Microsoft AJAX Minimizer was only on RC6, and as of this article is at version 1.1, so somethings have changed and I wanted to provide a more relevant comparison which included Google too. I borrowed Ajaxian’s code they used to test the different tools for my own experiment in this article.
function notCalled(text) {
alert(text);
}
/**
* @license comment
*/
var o = (function(){
var o = {};
var b = "on";
var c = "on" + b + "mouse";
var d = c + 1000 + "on";
var x = o[d];
/*!
important comment
*/
var i = 1000;
o["on" + "click"] = function(){};
o["on" + "mouse" + "over"] =
o["on" + "mouse" + "out"] =
o["on" + "mouse" + "move"] = o["on" + "click"];
o["on" + "click"] = o["on" + "click"];
if(i)
i++
;
return o
})();
The above code is designed to test many different aspects of optimization. Including:
- Code that is not called from anywhere.
- Preservation of Licenses, Copy Rights, and any other important comments.
- Frequently used string literal combination.
- Understanding of logic, to remove repeated and unnecessary dynamic access.
- Number compression. (changing 1000 to 1e3)
- Get rid of the gibberish variables at the beginning of the function that serve no purpose.
Simple Compression
First things first lets just see how each of them handle simple compression, with out any optimizations enabled on each tool. I did that by running the following:
# Ajax Minifier ajaxmin.exe test.js -o output.js # YUI Compressor java -jar yuicompressor-2.4.2.jar --nomunge --preserve-semi --disable-optimizations -o output.js test.js # Google Closure java -jar compiler.jar --compilation_level WHITESPACE_ONLY --js test.js
Above produces the following output
// Ajax Minifier
function notCalled(text){alert(text)}var o=function(){var o={},b="on",c="on"+b+"mouse",d=c+1e3+"on",x=o[d],i=1e3;o["onclick"]=function(){};o["onmouseover"]=o["onmouseout"]=o["onmousemove"]=o["onclick"];o["onclick"]=o["onclick"];if(i)i++;return o}()
// YUI Compressor
function notCalled(text){alert(text);}var o=(function(){var o={};var b="on";var c="on"+b+"mouse";var d=c+1000+"on";var x=o[d];
/*
important comment
*/
var i=1000;o["on"+"click"]=function(){};o["on"+"mouse"+"over"]=o["on"+"mouse"+"out"]=o["on"+"mouse"+"move"]=o["on"+"click"];o["on"+"click"]=o["on"+"click"];if(i){i++;}return o;})();
// Google Closure
/*
comment
*/
function notCalled(text){alert(text)}var o=function(){var o={};var b="on";var c="on"+b+"mouse";var d=c+1E3+"on";var x=o[d];var i=1E3;o["on"+"click"]=function(){};o["on"+"mouse"+"over"]=o["on"+"mouse"+"out"]=o["on"+"mouse"+"move"]=o["on"+"click"];o["on"+"click"]=o["on"+"click"];if(i)i++;return o}();
Some interesting things I noticed about the above code is:
- Yahoo was the only tool who preserved the “*!” comment block and Google was the only one who preserved the “**” comment block.
- Google and Microsoft both changed the number 1000 into 1e3.
- Microsoft combined the strings together, that were next to each other.
- Yahoo added some extra parentheses, around the if(i)i++; statement.
Simple Optimization
Next we are going to look at some basic optimizations made by each tool. I again did that by running the following:
# Ajax Minifier ajaxmin.exe -h test.js -o output.js # YUI Compressor java -jar yuicompressor-2.4.2.jar -o output.js test.js # Google Closure java -jar compiler.jar --compilation_level SIMPLE_OPTIMIZATIONS --js test.js
Above produces the following output
// Ajax Minifier
function notCalled(a){alert(a)}var o=function(){var a={},c="on",d="on"+c+"mouse",e=d+1e3+"on",f=a[e],b=1e3;a["onclick"]=function(){};a["onmouseover"]=a["onmouseout"]=a["onmousemove"]=a["onclick"];a["onclick"]=a["onclick"];if(b)b++;return a}()
// YUI Compressor
function notCalled(a){alert(a)}var o=(function(){var h={};var e="on";var j="on"+e+"mouse";var g=j+1000+"on";var a=h[g];
/*
important comment
*/
var f=1000;h.onclick=function(){};h.onmouseover=h.onmouseout=h.onmousemove=h.onclick;h.onclick=h.onclick;if(f){f++}return h})();
// Google Closure
/*
comment
*/
function notCalled(a){alert(a)}var o=function(){var a={},b=1E3;a.onclick=function(){};a.onmouseover=a.onmouseout=a.onmousemove=a.onclick;a.onclick=a.onclick;b&&b++;return a}();
Some interesting things to note about this new code is:
- Yahoo and Google still keep their respective comment blocks.
- Google and Microsoft both still changed the number 1000 into 1e3.
- Google and Yahoo show a better understanding of the code by changing the dynamic event hash mappings in to actual bound properties. Microsoft still only combines the strings together.
- All of the tools obfuscated the variable names.
- Microsoft and Google both combined the three variables at the beginning of the method in to a one statement.
- Anybody notice the optimization that Google did b&&b++ instead of if(b)b++, this shows a really good understanding of the code.
- On the other had Yahoo added some extra parentheses, again, around the if(i)i++ statement, but dropped the extra semi-colon.
- Google was the only one who got rid of the gibberish variables at the beginning of the function that served no purpose.
Best Optimizations
Next we are going to check out the best possible combination of options for each tool to produce the most optimized code. We will produce this with the following:
# Ajax Minifier ajaxmin.exe -hc test.js -o output.js # YUI Compressor java -jar yuicompressor-2.4.2.jar -o output.js test.js # Google Closure java -jar compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --js test.js
You may have noticed that we are using the same commands for Yahoo, this is on purpose, because Yahoo really doesn’t have a simple state the compares to the other tools.
The following output was produced
// Ajax Minifier
function notCalled(a){alert(a)}var o=function(){var d="click",c="mouse",a="on",b={},f=a,g=a+f+c,h=g+1e3+a,i=b[h],e=1e3;b[a+d]=function(){};b[a+c+"over"]=b[a+c+"out"]=b[a+c+"move"]=b[a+d];b[a+d]=b[a+d];if(e)e++;return b}()
// YUI Compressor
function notCalled(a){alert(a)}var o=(function(){var h={};var e="on";var j="on"+e+"mouse";var g=j+1000+"on";var a=h[g];
/*
important comment
*/
var f=1000;h.onclick=function(){};h.onmouseover=h.onmouseout=h.onmousemove=h.onclick;h.onclick=h.onclick;if(f){f++}return h})();
// Google Closure
/*
comment
*/
(function(){var a={},b=1E3;a.onclick=function(){};a.onmouseover=a.onmouseout=a.onmousemove=a.onclick;a.onclick=a.onclick;b&&b++;return a})();
Some interesting things to note about this code is:
- Yahoo and Google still keep their respective comment blocks.
- Google and Microsoft both still changed the number 1000 into 1e3.
- Google and Yahoo still show a better understanding of the code by changing the dynamic event hash mappings in to actual bound properties.
- Microsoft combined the “click”, “mouse” and “on” strings in to variables that are concatenated together in the variables and event references.
- All of the tools still obfuscated the variable names.
- Microsoft and Google still both combined the three variables at the beginning of the method in to a one statement.
- Google still kept the b&&b++ instead of if(b)b++.
- Yahoo added some extra parentheses, again, around the if(i)i++ statement, but dropped the extra semi-colon.
- Google still was the only one who got rid of the gibberish variables at the beginning of the function that served no purpose.
- Google removed the notCalled function, since it was not being used in this script file. This is good and bad, because if you referenced this from the outside, then this will cause problems when you try to use it.
Final Word
Even though Google ADVANCED_OPTIMIZATIONS scored the highest and Microsoft with –hc turned on scored second on my last post. I think Google with SIMPLE_OPTIMIZATIONS turned on is my current favorite for providing a good balance between optimization, compression, and compatibility with the original version. Closely followed by Yahoo with out any configuration options turned off. These two placed #3 and #5, respectively, in my previous post.
Even though Google with ADVANCED_OPTIMIZATIONS, did the best overall, it still scares me a little for the following reasons that I mentioned last time:
There are a couple things that should be noted about Google Closure with Advanced Options, which may not make the most beneficial option for you to choose when you are trying to minify your files.
- Removal of Code You Want to Keep
- Inconsistent Property Names
- Compiling Two Portions of Code Separately
- Broken References between Compiled and Uncompiled Code
Here are the files that resulted from the above testing:
- test.js
- microsoft.js
- microsoft-h.js
- microsoft-hc.js
- yahoo-all.js
- yahoo.js
- google-w.js
- google-s.js
- google-a.js
So which of the following optimizations do you feel the most comfortable with?


