Tuesday, March 11, 2014

Traceur is Awesome! ... but still a little Painful

Disclaimer: Bleeding-edge stuff


Be mindful of the date this was written, this is liable to change!


What is Traceur?


Traceur is a ECMAScript 6 to ECMAScript 5 (current JavaScript) transpiler. Basically, it allows you to use "JavaScript Next" features in today's browsers. Since both Angular "2.0" and Ember "2.0" are targeting ES6, if figured it's prudent to dive in and try this stuff out as soon as possible.


Using Traceur from HTML



This is simple enough, really. You just include `traceur.js` and Traceur's `bootstrap.js` in your HTML file, then put any ES6 code in a script tag where type="text/traceuer" or type="module" and it "just works"



"Off-Line" Compiling supports Source Maps



Traceur supports "off-line" compiling, and most importantly, it supports source maps. I need my source maps. I work on very large apps and anything that can assist my debugging is a must-have. Particularly when we're talking transpiled-then-minified codebases.


Grunt-Traceur



Grunt is a mainstay of JavaScript builds, so it's the first thing I tried:  grunt-traceur. It compiles things fine, but currently, it would not output source maps... That's a no-go for me.


Gulp-Traceur



Next up... the new hotness, Gulp. Look! There's a package for this already! gulp-traceur! But alas, it's not much different than grunt-traceur. Currently it lacks documentation, and I couldn't get it to output source maps.


Tracer from the Command line



The current Traceur documentation has information about "off-line compiling" from the command-line using a `traceur.sh` shell script. A quick search of the repo, however, revealed this was ancient information. There is no `traceur.sh`.

Fortunately, I know my way around some Node, and I quickly realized there was a globally installable `traceur` command available as an npm package!

1. Install Traceur globally with npm

You need to make sure Node.JS is installed... then run this from the command line:


npm install -g traceur
traceur --version
# -> traceur@0.0.28PS


2. Basic compile


After my excitement because I felt like I was making progress, I decided to give a basic compile a go:

traceur --out .\output\compiled.js  --script .\src\original.js

And it compiled! ... but no source maps.

3. Compile with Source Map output


So now what? A quick look at `traceur --help` showed a flag `traceur --longhelp`. After I got done chuckling a little at that, I had a look... There were two flags --source-maps and --sourcemap. So I tried them out... --sourcemap worked.

traceur --out .\output\compiled.js  --script .\src\original.js --sourcemap


Now I finally have a tool, albiet not the easiest tool to use, that will compile ES6 and output a source map.

4. Compile many files into one output file with source map output



What about multiple files? For that you can just include multiple files in the `--script` flag. I wasn't able to get the available `--dir` flag to work with source maps.

The following will compile many source files into one output file and produce a sourcemap:

traceur --out .\output\compiled.js  --script .\src\file1.js  .\src\file2.js --sourcemap


Awesome tool, but a little hard to get into a workflow




After fiddling with this for a while, I have to say I really like Traceur for what it is, however, the tooling around it is still lacking enough that I'm not sure I can squeeze it into a robust workflow quite yet. It has some really great advantages over other transpiled languages, because you're (in theory) future-proofing your development a little for whenever browsers finally implement ES6 natively by default. Some browsers such as Firefox and Chrome already support ES6, however you need to manually that support, so it's still a better bet for most projects just to transpile to ES5 for now.

In the end, the biggest problem is just robust task-runner support for something like Grunt or Gulp. The current modules that exist don't seem to have "official buy-in" and aren't very well documented or supported in my opinion.

Thursday, February 20, 2014

Yet Another Conway's Game of Life in Plain JavaScript

I know it's overdone


Really, really overdone... but it sure is fun to play with.  I was doing some "katas" (I actually hate that term for coding, but whatever), putting together a BinaryTree in JavaScript, and I thought... "Hey! I should do that Game of Life thing like everyone else does!"  But I decided to do it with plain ol' JavaScript.  JQuery is overkill for something this small, I think.

Anyhow, without further ado... Here's yet another Game of Life in JavaScript... All in JSFiddle so the code can be played with. And now I should go to bed and consider doing something more productive with my time tomorrow night.

Sunday, February 9, 2014

Ubuntu Beginner Pain: Installing Java 7

Motivation


I found I had to do this because I was having difficulty installing JetBrains' WebStorm on Ubuntu. In fairness I'm an Ubuntu neophyte. My exposure to Linux is generally small tasks done in a terminal on servers.


Mistake: Just Installing Oracle Java


The first thing I tried to do was just install Oracle Java. This would complete, but I would still have the wrong version of Java when I typed java -version in Terminal. This confused me for hours. I googled, and googled, and found about 20 different solutions that didn't work.  Finally ran into one answer that gave me a clue (I need to dig up the link, sorry). OpenJRE was gunking things up.


OpenJRE on Ubuntu


Ubuntu comes with OpenJRE stuff installed on it by default. I'm not at all sure what "OpenJRE" is or why it exists. It seems to be some sort of licensing issue deal were Oracle had a disagreement with Ubuntu and some weird new Java baby was born.

Either way, I want "real" Java, not whatever this is.... so let's get rid of it.


Answer: First remove OpenJRE, then install Oracle Java!


Here are the commands I ran to fix up Java on my machine. Annotated:

Wednesday, November 27, 2013

Common Git Tasks - So I Don't Forget Them

The title speaks for itself. I spend a lot of time hopping between three different source control systems: TFS (eww), SVN and Git.  As such sometimes my brain gets a little fried remembering some of the sequences to enter in Git to do common tasks. I really should script them out, but I'm going to write them down here so I don't forget them.

Yes I know this has been done 1000 times, but I haven't done it and this is an exercise to help me remember certain things. Also, I hope people correct me and/or this helps others.

Note: Anywhere I mention "GitHub" below I really mean "remote repository". It's just that I feel most people that are new to this stuff will be searching for "GitHub"




Checking in existing code to a new GitHub repository


Create the GitHub repo on their website from your account page. Be sure to add a .gitignore to exclude any directories or files you don't want to commit! In a prompt change directory to the root of your code folder then enter:

# initialize local repository
git init

# add all files to git tracking
git add .

# commit the tracked files to local repository
git commit -m "initial commit"

# connect to the remote repository
git remote add origin https://github.com/blesh/some-project.git

# sync remote and local
git pull origin master

# push files to remote
git push origin master



Get a project from existing GitHub repository


Change directory to the directory you want to be the parent of your project directory. Do not create a new directory for your project, Git will do that for you.

# clone the master branch to initialize your project and local repo
git clone https://github.com/blesh/some-project.git

# change to that project directory
cd some-project

# [OPTIONAL] switch to the branch you care about
git checkout somebranchname



Basic pull from GitHub


# usually you're on the master branch,
# otherwise swap "master" for your branch name.
git pull origin master

# sometimes you want to pull from a specific branch
# so switch to that branch locally
git checkout branchname

# then pull it from the remote
git pull origin branchname



Basic push up to GitHub


It's important to sync first with a pull!

# make sure you've added untracked files
git add .

# commit changes locally
git commit -m "commit message here"

# sync with remote
git pull origin master

# you might have to merge some changes at this point
# if so, generally it will involve editing the actual files
# and following the prompts in the console.

# now push your changes up to the remote
git push origin master



Overwriting all local changes with remote files from GitHub


So this one I've found will very depending on whether or not you have multiple branches you care about. This is also one where the difference between git pull and git fetch counts. For one thing, as of this writing git fetch as an --all flag you can use to pull down all remotes (branches and all), for another thing, pull will merge your files where fetch will not.

#get all files from all remotes without merging
git fetch -all

#reset your local to HEAD
git reset -hard origin/master

#remove all untracked files and directories
git clean -f -d

#[OPTIONAL] you might need reset and clean for other branches you've work on.
git checkout otherbranch
git reset -hard origin/otherbranch
git clean -f -d



Updating a forked repository from the original


When you've forked someone else's code, and you'd like to update it to the latest code base, you're going to need to rebase from an "upstream".

# add the upstream remote repository
# in this case we're naming it "upstream", but you can name it whatever you choose.
git remote add upstream https://github.com/angular/angular.js.git

# fetch all files from all branches from the upstream repository
git fetch upstream

# switch to the branch you're working on
git checkout master

# rebase to replay all of the deltas from your previous commits on top
# of the files you just pulled down with the fetch.
git rebase upstream/master

# push your changes back up to your own remote fork
# the -f flag is to force the push and ignore checks and make sure
# that the remote doesn't have issues reconciling which deltas to trust
git push -f origin master

Changing a tag name


If you need to rename a tag, you need to add a new tag where the old tag was, then delete the old one

git tag newtag oldtag
git tag -d oldtag

Inserting a change at a past commit


When you need to make a change at a prior commit in your history and propagate that change throughout. I've found you don't always have to rebase. It seems like this solution is a lot more kosher as well. Basically, you create a copy of master, then reset the master back to the point where you want to make the change. Make the change and commit it, then merge the copy back on top of your change.

# checkout the branch you need to change
git checkout master

# make a copy of it on a new branch
git branch master_copy

# rewind the branch to the commit you'd like to insert
# a change after where [commit] is a commit # or a tag:
git reset --hard [commit]

# (make your changes here)
# and commit them:
git commit -am "changes have been made"

# now merge your copy back on top of your change
git merge master_copy

# clean up the copy
git branch -d master_copy

Monday, November 11, 2013

Quick 3D Pong Game With Three.JS

I was playing around with Three.js on Plunker last Friday and whipped up a silly little Pong Game.

I put a few notes in the readme, but please feel free to play with and/or alter the code. Just show me what you did if you do anything cool!

(Also, don't judge the code, I was sandboxing for kicks, :P haha)

Monday, October 21, 2013

Angular JS - you probably shouldn't use $watch in your controllers.

The problem with $watch isn’t so much that it doesn’t work. It definitely works. The problems are two-fold:
  1. It’s hard/hackish to test effectively.
  2. It’s inefficient.

Inefficiency: Adding complexity to your $digest

As I discussed in my other post, a $digest must occur to update the view from the model or the model from the view. This happens in Angular with great frequency. Whenever a digest occurs you it must evaluate all of your registered $watches. To make matters worse, whatever is altering that value you’re $watching, probably already has a $watch associated to it or an $apply you can leverage to update your value in your view.

Bad: $watch a value changed by user input

What do I mean? Suppose you had some sort of input that was changing a value you were watching:
<input type="text" ng-model="foo"/>
And in your controller you were watching foo for some reason so you could update some other value:
$scope.$watch('foo', function (val){
    switch(val) {
        if(val === 'test') {
            $scope.bar = 'foo is testing me';
            } else if (val === 'blah') {
                $scope.bar = 'foo seems indifferent';
            } else {
                $scope.bar = 'I do not understand foo';
        }
   }
});
and what would the test around this look like? UGLY.
$scope.foo = 'test';
$scope.$apply(); //don't forget the magic step!
expect($scope.bar).toBe('foo is testing me'); //makes sense right? 


Better: Use ng-change

Here we can simplify this greatly by just leveraging ng-change on the <input/>:
<input type="text" ng-model="foo" ng-change="updateBar(foo)"/>
In our controller we’d have a a nice, easy to read, easy to test function:
$scope.updateBar = function(foo) {
    if(val === 'test') {
        scope.bar = 'foo is testing me';
    } else if (val === 'blah') {
        $scope.bar = 'foo seems indifferent';
    } else {
            $scope.bar = 'I do not understand foo';
    }
};
And our test is much clearer and cleaner:
$scope.updateBar('test');
expect($scope.bar).toBe('foo is testing me');

Bad: Use $watch to update a value after [some event here]

In this case you might be doing something like getting a value via Ajax, and you think, “Man, $watches are SWEET, I’m going to use one of these bad boys to watch my value”:
app.controller('WidgetCtrl', function($scope, widgetService) {
    $scope.$watch('widgets', function(val) {
        var count = (val && val.length ? val.length : 0);
        $scope.theCountSays = count + ', ' + count + ' widgets! ah! ah!';
    });

    $scope.updateWidgets = function(widgets) {
        $scope.widgets = result;
    };

    $scope.getWidgets = function() {
        widgetService.get().then($scope.updateWidgets);
    };
});
Now look! theCountSays is updated automagically! Isn’t that awesome? No, I say. No it is not.
Look at our test related to it:
$scope.widgets = [1,2,3,4,5];
$scope.$apply(); //Weee! magic!
expect($scope.theCountSays).toBe(5);


Better: Use the event that triggered the change to update your value!

This is really the case for every single use of $watch in a controller… if you need to update something, update it when you need to, not in some catch all $watch.
app.controller('WidgetCtrl', function($scope, widgetService) {
    $scope.updateWidgets = function(widgets) {
       $scope.widgets = result;
       var count = (val && val.length ? val.length : 0);
       $scope.theCountSays = count + ', ' + count + ' widgets! ah! ah!';
    };

    $scope.getWidgets = function() {
        widgetService.get().then($scope.updateWidgets);
    };
});
and the tests are clear again:
$scope.updateWidgets([1,2,3,4,5]);
expect($scope.theCountSays).toBe(5);


Conclusion: Watches are almost never really necessary in a controller.

I realize the examples I gave above are contrived, but I’m happy to take on more specific examples. In the end, the only thing you need to remember when trying to avoid watches is: “What is triggering the change I’m worried about?” and subscribe to that. $watch is really meant to facilitate two-way binding between the model and the DOM as part of constructing directives.

Wednesday, August 28, 2013

Pseudo-Random Number Generation (Seeded) in JavaScript

What, no seed on Math.random()? But I could've sworn...

I was faced with a situation where I wanted to produce random numbers from a seeded generator in JavaScript, and I noticed (strangely for the first time) that Math.random() is a random number generator, but not a pseudo-random number generator (PRNG). The problem I was trying to solve is that I wanted to create random numbers, but I wanted to be able to recreate the same series of random numbers.


The Mersenne Twister

So I hit the Googles, and immediately came across this post on StackOverflow that had a few solutions for PRNG. The post suggested that Mersenne Twister was one of the better algorithms for PRNG, but didn't really offer up code for that in JavaScript. So I Googled further and found that there was a JavaScript implemenation of Messente Twister, but I didn't like it, really. No offense meant to the original authors, but it seemed to be a port of a C or C++ implementation straight to JavaScript, and was a little bulky and not factored out enough for me.


TL;DR: I made an open source Mersenne Twister implementation in JavaScript

It's here on GitHub, hopefully someone else finds it useful. The goal was to keep it concise and compact.

What does it do? It produces evenly distributed random integers between 0 and 4,294,967,296 (aka 0x100000000) from a seeded generator.

BTW: If anyone is an expert in cryptography or mathematics please review my implementation.