Trying Out JavaScript v.Next

Tuesday, April 10, 2012 by K. Scott Allen
2 comments

ECMAScript Harmony is the future of JavaScript, and something you can experiment with using the stable builds of Chrome (my machine is currently running 18.0.1025.152 m, but that is subject to change at any minute).

The first step is going into chrome://flags, and flipping the "Enable Experimental JavaScript" bit.

Enabling Experimental JavaScript in Chrome

I'm looking forward to let and proxies.

Let

You might know that the JavaScript we use today has only function scope and global scope. There is no block scope, and the following test will pass without any difficulty (x is scoped to the doWork function, not the block inside the conditional).

test("there is no block scope", function () {
    "use strict";    

    var doWork = function() {
        
        if(true)
        {
            var x = 3;
        }
        return x;
    };

    var result = doWork();
    strictEqual(result, 3);
});

 

Change the code to use the new let keyword, and the behavior is dramatically different (the return statement in doWork will throw an exception).

test("let has block scope", function () {
    "use strict";

    var error;
    var doWork = function() {
        
        if(true)
        {
            let x = 3;
        }
        return x;
    };

    try {
        var result = doWork();    
    }
    catch(ex) {
        error = ex;
    }

    strictEqual(error.name, "ReferenceError");

});

Proxies

Proxies will give JavaScript method_missing and interception / call trap capabilities. I can imagine the data-binding and MVVM frameworks being much less intrusive if they fully embrace proxies.  In fact, I can see proxies solving all sorts of problems from data-binding to DOM inconsistencies.

test("Use a proxy", function() {

    var p = Proxy.create({
                get: function(proxy, name) {
                    return "You read " + name;
                }
            });

    var result = p.fooBar;

    strictEqual(result, "You read fooBar");
});
Now we just need to wait until this code isn't considered "experimental"...

A Refactoring Experiment

Monday, April 9, 2012 by K. Scott Allen
10 comments

obfuscated codeSoon I'll be giving a group of developers some code and asking them to do some refactoring.

The bad news is the code is hard to read. Some might say it's intentionally obfuscated, but let's not assume malice right away.

The good news is there are six working unit tests for the code.

There are two goals to the exercise. One goal is to give developers an opportunity to practice refactoring (a Kata, if you will). The way I'd attack the code is to start with some renaming operations, then extract some methods, then perhaps break down the one big class or eliminate a switch statement using patterns. There is no perfect answer.

The larger goal is to convince anyone not entirely sold on the benefit of automated tests how tests can empower them to work with, experiment with, and change existing code - even code they don't completely understand. Although this code was intentionally obfuscated, it's not unlike walking into the code for a complex domain the first time and not understanding why a wurgled customer can blargsmack on Tuesdays if they hold a vorkenhosen status. All domains are nonsense at the start.

If you want to try it too, the code is on github.

The Bar Is Even Higher Now

Thursday, April 5, 2012 by K. Scott Allen
7 comments

It's been just over 8 years since Michael Feathers wrote "The Bar Is Higher Now".

I don't care how good you think your design is. If I can't walk in and write a test for an arbitrary method of yours in five minutes its not as good as you think it is, and whether you know it or not, you're paying a price for it.

continuous delivery

It's fascinating to talk to IT professionals from companies around the world and realize what a wide range of workflows are in place. In some shops there are very few automated tests, no automated deployments, and 30 page manuals with instructions for setting up a developer workstation to reach the point where you can begin to work on an application.

On the other side of the gulf there is Amazon (a deployment every 11.6 seconds), Etsy (a new developer commits to production on day 1), and Flickr (they deployed 97 times this week (scroll to the bottom)).

The rapid feedback cycles and agility gained through ruthless automation are a strategic advantage for those companies. I also suspect the developers are happier and far more productive compared to the companies where 20 people are on-call at 4am waiting to help with a new deployment that's been 10 months in the making.

Perhaps the new bar to reach for is this:

If I can't walk in and commit to production on day 1, then you are not as good as you think you are, and you are paying a price for it.

Interesting goal, don't you think?

jQuery UI Autocomplete and Automatic Form Submit

Wednesday, April 4, 2012 by K. Scott Allen
4 comments

It's a common to automatically submit a form after a user selects an item from an autocomplete list. The keyword here is "select" – it will lead you to handling the select event of the jQuery UI autocomplete widget.

someInput.autocomplete({
    source: data,
    select: function () {
        form.submit();
    }
});

This code will work as long as the user selects an item using the arrow keys and keyboard. The code doesn't work if the user selects an item using the mouse (the proper value doesn't appear in the input or the form submission).

The problem is the select event seems to be designed as more of a pre-processing event. You can implement your own custom selection logic and / or cancel the default logic by returning false from the method. You can also make sure the input is populated before submitting the form.

someInput.autocomplete({
    source: data,
    select: function (event, ui) {
        $(this).val(ui.item.value);
        form.submit();
    }
});

Quacks At Work

Tuesday, April 3, 2012 by K. Scott Allen
0 comments

"The Lords of Finance" includes a story about famous economist John Maynard Keynes, who was diagnosed with a chronic cardiac condition and needed medical help*.

In 1939, he fell into the hands of a Dr. Janos Plesch, a Hungarian Jewish émigré, who, according to Keynes, was a cross between a “genius” and a “quack.” In addition to some highly unorthodox protocols—three-hour sessions of ice packs placed on the chest or Dr. Plesch jumping up and down on his patient as he lay in bed...

Quack! by mikemolJumping up and down on the patient? At least Keynes suspected his doctor was a quack, but once you realize this was only 80 years ago you also begin to realize that medicine spent dozens of centuries treating patients using blood letting and other techniques based on beliefs, faiths, and superstitions.

Overall I think software has done far more good than harm, but I do wonder how long it will take us to figure out programming once and for all, or if we ever will. A lot of our practices today are based on hard won experiences, but we all carry our own beliefs, faiths, and superstitions (and thus the opportunity for technology evangelism). 

* Fascinating book, particularly if you are interested in a human story involving macro economics, gold bullion, and fiat money.

What's Wrong With This Code? (#29)

Monday, April 2, 2012 by K. Scott Allen
12 comments

Here is some code similar to other code I've seen that has a severe bug. The Entity Framework model configuration is setup to allow optimistic concurrency checks via a movie's Version property.

public class Movie
{
    public virtual int ID { get; set; }
    public virtual string Title { get; set; }
    public byte[] Version { get; set; }
}

public class MovieDB : DbContext
{
    public DbSet<Movie> Movies { get; set; }

    protected override void OnModelCreating(
        DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Movie>()
                    .Property(p => p.Version)
                    .IsRowVersion();
        base.OnModelCreating(modelBuilder);
    }
}

During editing, the view correctly holds the row version in a hidden input.

@Html.HiddenFor(model => model.Version)

But unfortunately, the controller action accepting the edit request has a flaw. It's trying to retrieve the existing movie from the database, overwrite the entity with new values (and the previously retrieved version value), then save the entity. The idea is that if the underlying record changed, we'll see an optimistic concurrency exception because we gave the entity an old row version value.

[HttpPost]
public ActionResult Edit(int id, Movie editedMovie)
{
    if (ModelState.IsValid)
    {
        var movie = db.Movies.Find(id);
        movie.Title = editedMovie.Title;
        movie.Version = editedMovie.Version;       
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(editedMovie);
}

The update will almost never fail with an OptimisticConcurrencyException. The update will almost always overwrite the current record in the database*.

What's wrong?

Hint: the Entity Framework doesn't behave like the implementation expects.

Answer

A property marked as a RowVersion property implicitly holds a  "store-generated" value. The Entity Framework never expects an application to modify the value. When you retrieve an entity and set a computed property to a new value, you'll still see the original value sent to the database when you call SaveChanges. The Entity Framework will always use the original value loaded from the database. The correct way to save the new values is to "attach" the movie instead of using a query to retrieve values from the database.

[HttpPost]
public ActionResult Edit(Movie editedMovie)
{
    if (ModelState.IsValid)
    {
        db.Entry(editedMovie).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(editedMovie);
}

* I say "almost" because you could have a concurrency exception if the data changes between the query and the call to SaveChanges (where time is measured in milliseconds). It doesn't fail if the data changes between the Edit GET request and the POST request (where time might be measured in minutes).

by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!