tag:blogger.com,1999:blog-69170865967828756722024-03-13T23:14:36.187+11:00Legacy to the EdgeWeb Development with Jason StoneRolaverichttp://www.blogger.com/profile/07055170854302013537noreply@blogger.comBlogger12125tag:blogger.com,1999:blog-6917086596782875672.post-49696963814646775102015-09-06T17:50:00.001+10:002015-09-08T20:55:33.594+10:00FalcorJS with AngularJS v1.x<p>
Ever since it was <a href="https://www.youtube.com/watch?v=WiO1f6h15c8">presented at ng-conf</a>, I've been excited to get my hands on Netflix's new "One Model Everywhere" data-fetching framework: <a href="http://netflix.github.io/falcor/">FalcorJS</a>. Now it's been released on the world as a Developer Preview, I wanted to show how it can be used with AngularJS v1.x.
</p>
<h2>What is FalcorJS?</h2>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgD9DMpCo7Sy4sJaorZVyIsQ8TeAWFLTYjmz9EUfMtGPsWpSQpVMmq7CvQjFw9so5r6jgaTvRlB8fBIU_0loIKSDSVE9j8i-qmyZa7lvRnJYB5DIlOIkooT92yZKVEvXP-2OGn1BqihbrA/s1600/falcor.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgD9DMpCo7Sy4sJaorZVyIsQ8TeAWFLTYjmz9EUfMtGPsWpSQpVMmq7CvQjFw9so5r6jgaTvRlB8fBIU_0loIKSDSVE9j8i-qmyZa7lvRnJYB5DIlOIkooT92yZKVEvXP-2OGn1BqihbrA/s1600/falcor.png" /></a>
</div>
<blockquote>
<i>"A JavaScript library for efficient data fetching"</i>
</blockquote>
<p>
That sums up FalcorJS pretty well.<br />
It's designed to retrieve only as much data as you need at a time by letting the view specify the values it needs, then the model can batch those requests up when it calls the server.</p>
<p>
Falcor represents your data as a big JSON '<a href="https://en.wikipedia.org/wiki/Graph_(abstract_data_type)">graph</a>', which means you can request the same data from different paths and it will use the cache from the first request.
</p>
<script src="https://gist.github.com/rolaveric/942ff651ef2a30211fd1.js"></script>
<blockquote>
<i>Sample from <a href="http://netflix.github.io/falcor/documentation/jsongraph.html">FalcorJS' JSON Graph Guide</a></i>
</blockquote>
<p>
One odd thing you will have to get used to with FalcorJS is that you only request 1 value at a time. And by "value" I mean: string, number, boolean, or null. This feels totally alien coming from... everything else, but it works because FalcorJS takes care of the efficiencies for you. Instead of having 1 request for an array of objects, which you then have to split up into 20 fields on your view - you instead make 20 requests from your view, which are automatically batched for you into 1 request.
</p>
<p>
Other mechanics that Falcor provides is functions on your JSON Graph than you can 'call()', which is good for things like creating whole new objects and transactions where you want to be sure everything is being handled in one go. Responses can also include multiple values, for situations where you're sure it's going to be required, and can specify what routes should have their cache invalidated.
</p>
<p>
The last thing to mention is that FalcorJS is built on Observables from <a href="https://github.com/Reactive-Extensions/RxJS">RxJS</a> for all it's asynchronous operations. For those unfamiliar with them, Observables and the whole <a href="http://reactivex.io/">ReactiveX API</a> are the ultimate asynchronous toolkit. Observables fill in the gaps with Promises, things like how to handle multiple values over time, and whether new 'observers' see just new values or the preceding values too. I won't go into Observables too much, but there are <a href="http://reactivex.io/">lots</a> <a href="http://reactivex.io/learnrx/">and</a> <a href="https://gist.github.com/staltz/868e7e9bc2a7b8c1f754">lots</a> of <b>excellent</b> resources online.
</p>
<h2>Using with AngularJS v1.x</h2>
<div class="separator" style="clear: both; text-align: center;"></div>
<blockquote>
<i><strong>Disclaimer:</strong> Once again, FalcorJS is in Developer Preview. So what's written here today may not work tomorrow. Check the FalcorJS <a href="http://netflix.github.io/falcor/doc/DataSource.html">API Reference</a> and <a href="https://github.com/Netflix/falcor">Github</a> if you have difficulties.</i>
</blockquote>
<p>
In this example we're going to build a UI with AngularJS v1.x that uses a <a href="http://netflix.github.io/falcor/documentation/model.html">FalcorJS Model</a> with a <a href="http://netflix.github.io/falcor/doc/HttpDataSource.html">HttpDataSource</a> pointed at our <a href="https://github.com/Netflix/falcor-express-demo">falcor-express-demo</a> and <a href="https://github.com/netflix/falcor-router-demo">falcor-router-demo</a> server.
</p>
<script src="https://gist.github.com/rolaveric/7858a9ffe37436577cb7.js"></script>
<p>
With our Model setup we can pull values from the server using <span style="font-family: Courier New, Courier, monospace;">this.model.getValue(path)</span>. It will then build the necessary <a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest">XHR</a> call and return an Observable for it's result.
</p>
<h4>The $apply problem</h4>
<p>
<i>Wait a sec... if it makes it's own XHR call, how will Angular know when to start a $digest loop?</i>
</p>
<p>
Well the usual solution in these circumstances is to use <span style="font-family: Courier New, Courier, monospace;">$scope.$apply()</span>, such as when binding to an event that's not triggered within Angular's digest loop. However we can't actually be 100% sure that we're <strong>not</strong> in the digest loop either. For example, if we're hitting cached values, all the callback functions could be called immediately. A better solution is to use <span style="font-family: Courier New, Courier, monospace;"><a href="http://www.bennadel.com/blog/2605-scope-evalasync-vs-timeout-in-angularjs.htm">$scope.$evalAsync()</a></span> which will start a new digest loop if, and only if, one is not already in progress. So any time we subscribe to an Observable, we simply need to call <span style="font-family: Courier New, Courier, monospace;">$scope.$evalAsync()</span> and we're good to go.
</p>
<script src="https://gist.github.com/rolaveric/2f1a043a8b698eecf551.js"></script>
<h4>Calling from the View</h4>
<p>
The next thing we want is to start making calls from the View rather than making it the controller's responsibility. This helps to decouple the view and the controller further (all the controller supplies is a reference to the model), and means we're only requesting as much data as we're actually using. eg. If we're showing a cut-down mobile friendly view, we don't have to pull back as much data.<br />
But how are we going to get our results onto the View? All our requests are going to return fresh Observables.
</p>
<p>
This is where the <span style="font-family: Courier New, Courier, monospace;"><a href="http://netflix.github.io/falcor/doc/Model.html#getCache">Model.getCache(path)</a></span> method comes in. It synchronously returns the value from the Model's cache. If that returns undefined, we can call <span style="font-family: Courier New, Courier, monospace;">Model.getValue(path).subscribe(_ => $scope.$evalAsync())</span> - It'll request the value and call <span style="font-family: Courier New, Courier, monospace;">$scope.$evalAsync()</span> once it returns, which means a new digest loop, which will trigger a new call, which will get a successful hit from the cache.
</p>
<script src="https://gist.github.com/rolaveric/3abce7410cb95da93446.js"></script>
<script src="https://gist.github.com/rolaveric/489562fb0d4240936231.js"></script>
<h4>Dealing with collections</h4>
<p>
Since FalcorJS doesn't support returning objects and arrays (well, <a href="http://netflix.github.io/falcor/doc/global.html#Atom">sort of</a>) we need a way to deal with collections in our data. The solution that I prefer is to generate an array of index numbers which represent a 'page range', and request the length of your collection ahead of time to set your max index.
</p>
<script src="https://gist.github.com/rolaveric/303477bb54b9ef125eb8.js"></script>
<script src="https://gist.github.com/rolaveric/c8e8e69d9fc76e59177a.js"></script>
<p>
Another thing you may be able to use is the <a href="http://netflix.github.io/falcor/doc/Model.html#deref"><span style="font-family: Courier New, Courier, monospace;">Model.deref(path)</span></a> method, passing the result to another directive that can handle resolving the Observable.
</p>
<h2>What about writing data?</h2>
<p>
Falcor comes with two primary methods for writing values: <span style="font-family: Courier New, Courier, monospace;"><a href="http://netflix.github.io/falcor/doc/Model.html#setValue">setValue(path, value)</a></span> and <span style="font-family: Courier New, Courier, monospace;"><a href="http://netflix.github.io/falcor/doc/Model.html#call">call(path, args)</a></span>.
</p>
<p>
<span style="font-family: Courier New, Courier, monospace;">setValue()</span> sets the value for a particular path, returning an Observable for the result. Integrating it with ng-model is simple using <span style="font-family: Courier New, Courier, monospace;"><a href="https://docs.angularjs.org/api/ng/directive/ngModelOptions">ng-model-options="{getterSetter: true}"</a></span>. We create a function which takes the model and the path, then returns a function which either calls <span style="font-family: Courier New, Courier, monospace;">getValue()</span> or <span style="font-family: Courier New, Courier, monospace;">setValue()</span>, depending on the number of arguments.
</p>
<script src="https://gist.github.com/rolaveric/4cbc38a8e9d057444751.js"></script>
<script src="https://gist.github.com/rolaveric/2b5e689e85e6991ac6ac.js"></script>
<p>
<span style="font-family: Courier New, Courier, monospace;">setValue()</span> is great if you want to set one value at a time. But what if you want to save the entire form at once, after you've confirmed your data is valid?<br />
This is where <span style="font-family: Courier New, Courier, monospace;">call()</span> comes in.
</p>
<p>
The <a href="http://netflix.github.io/falcor/documentation/router.html">Falcor Router</a> supports 3 different types of operations on each route: <span style="font-family: Courier New, Courier, monospace;">get</span>, <span style="font-family: Courier New, Courier, monospace;">set</span>, and <span style="font-family: Courier New, Courier, monospace;">call</span>. <span style="font-family: Courier New, Courier, monospace;">call</span> turns the route into an <a href="https://en.wikipedia.org/wiki/Remote_procedure_call">RPC</a> endpoint where you pass in arguments, which can include objects and arrays (anything that can be JSON encoded), and it returns a set of PathValues and cache invalidations for the Falcor Model to interpret.
</p>
<script src="https://gist.github.com/rolaveric/fc32a0a0a7502eacee0f.js"></script>
<h2>Summary</h2>
<p>
Once again I have to repeat: Falcor is in "Developer Preview" mode. Which means that not only is it not ready for production, but it's also only recommended for those of us who like to cut ourselves on the bleeding edge.
</p>
<p>
With that in mind: Falcor is pretty solid, and the learning curve is quite smooth. It does require rethinking your data API to fit "the falcor way", but that's a common cost with opinionated frameworks which pays back with simpler and more consistent code.
</p>
<p>
Where it really excels most is with "mostly-read/rarely-write" type applications, but you can still do write operations with `setValue()` and `calls()`. I probably wouldn't try to write any games with it (though that might be a fun exercise all the same).
</p>
<p>
I've started a <a href="https://github.com/rolaveric/angular-falcor">github repository</a> with a working example of everything I've shown here, along with a "falcor" module that encapsulates the falcor specific code.
</p>
<p>
Cheers,<br />Jason Stone
</p>Rolaverichttp://www.blogger.com/profile/07055170854302013537noreply@blogger.com0tag:blogger.com,1999:blog-6917086596782875672.post-4077661700004832632015-03-28T17:31:00.003+11:002015-03-28T17:34:26.239+11:00Tips for designing a JSON Schema<div>
<p>
I've been writing a lot of <a href="http://json-schema.org/">JSON schemas</a> lately.<br />
Some were just small API requests and responses.<br />
Some were big all encompassing documents that involves over 20 unique object types.
</p>
<p>
When I started the big ones, I went looking around the internet for some resources. What I found was plenty on how to <b>write</b> a JSON Schema (<a href="http://spacetelescope.github.io/understanding-json-schema/">This being the best one</a>), but not on how to <b>design</b> one.<br />
To contrast, there's plenty of material available on how to design relational database schemas - from blog articles to university subjects.<br />
I still managed to come up with something resembling a process, so I thought I'd share with the class in the hopes it'll help someone else.
</p>
<p>
Just a quick disclaimer: These are just my own personal findings and opinions.<br />
If you have your own findings that you think are better, by all means stick to them. Share them with the class too, if you can.
</p>
</div>
<h2>Read the '<a href="http://jsonapi.org/">JSON API</a>' standard</h2>
<div>
<p>
I cannot emphasise this point enough.<br/>
Go to <a href="http://jsonapi.org/">http://jsonapi.org/</a> and read through the documentation and examples.<br />
I'm not expecting you to implement it - especially if you're not creating JSON Schemas for a web API - but it's great example of a JSON based standard, and well worth the time to look at. I've based a lot of my own schemas off elements of it, without implementing it completely.<br />
Things like using the "id", "type", and "links" keywords.
</p>
<p>
If you do decide to implement it, take into account that it's a work in progress.<br />
In the last month they've published a release candidate which had some significant differences from the previously published versions. But the fact that they're calling it a "release candidate" says it should be pretty stable by now.
</p>
</div>
<h2>Keep a flat structure</h2>
<div>
<p>
Don't embed objects within objects within objects within objects.<br />
You're better off keeping a flat structure of one or many arrays at the top level containing objects.<br />Rather than nesting one object inside another, create a separate object in one of those arrays and link the two together - even if you're sure it's a 1-to-1 relationship for both objects.<br />
The JSON API uses a single "included" array that contains all additional objects. I personally prefer having multiple arrays that group the objects by "type" - but that's me.
</p>
<p>
You can also use the same prefix for property names, rather than creating a new embedded object.<br />
eg. {"name": {"first": "John", "last": "Smith"}} becomes {"nameFirst": "John", "nameLast": "Smith"}
</p>
<p>
<i>Why?</i>
</p>
<ul>
<li>
It means less code like this:<br />
<span style="font-family: 'Courier New', Courier, monospace;">var value = data.article && data.article.author && data.article.author.phone && data.article.author.phone.number;</span>
</li>
<li>
It simplifies things if you're marshalling and unmarshalling your JSON into and out of other data structure. eg. Classes and SQL tables.<br />
Even if you're using a NoSQL DB with NodeJS today - tomorrow you might create a new microservice in something new. Doesn't hurt to be flexible.
</li>
<li>
You have a 1-to-1 link today, but a new feature tomorrow might change that.<br />
Keeping things flat give you some extra flexibility for the future.
</li>
</ul>
<script src="https://gist.github.com/rolaveric/73036f28ff1f6fd4d901.js"></script>
</div>
<h2>Work out how relationships are defined</h2>
<div>
<p>
Even if you don't go with a flat structure, you're going to need some way to say "X relates to Y because Z" - unless you honestly plan to duplicate and embed each and every object.<br />
Take a look at <a href="http://jsonapi.org/format/#document-structure-resource-relationships">how JSON API does it</a> - the way the "links" property contains relationships, and each of those has a "linkage" object(s) with the "id" and "type" of the other object(s).<br />
You don't need to do the exact same thing. But you should be consistent throughout your entire schema.<br />
Preferably throughout all the schemas in your organisation, if you can manage it.
</p>
<p>
<i>Why?</i>
</p>
<p>
Because if you have a consistent format for defining relationship, you can write functions that will traverse those relationships for you.
</p>
<script src="https://gist.github.com/rolaveric/a2b04376f96412b1d0e8.js"></script>
</div>
<h2>New properties are cheap</h2>
<div>
<p>
Sometimes there's the temptation to reuse the same property for a slightly different purpose.<br />
Maybe you want to define an "accountType" which then gives a completely different context to the 5 other properties, and you think "I just saved myself from writing 5 new properties into the schema, for the price of 1 - woooo!"
</p>
<p>
Don't do that.
</p>
<p>
Of all the possible schema changes you could make - new properties are the cheapest.<br />
Don't make things more confusing by trying to shove square pegs into round holes.<br />
Unless you are writing super memory efficient software, where you need to squeeze every last bit from the hardware (in which case, why are you using JSON at all?) - just make a new property.
</p>
</div>
<h2>Prepare for change</h2>
<div>
<p>
No matter how hard you try, how long you work, how much you analyse and survey and workshop - there's going to be <i>something</i> you need to change in the structure of the schema.<br />
Now you can either live in constant fear of this day, or you can work out your strategy ahead of time.
</p>
<p>
Embed the version of the schema in your JSON documents and have a process in place for running migration scripts.<br />
Whether your strategy is a 'big-bang' during downtime or an ongoing background process.<br />
Just have your migration process ready.
</p>
</div>
<h2>Use "allOf" to create schema mixins</h2>
<div>
<p>
I said this wasn't about how to write a JSON Schema, just how to design it - this is the exception.
</p>
<p>
I gave the example earlier of prefixing property names rather than nesting objects - 'name' to 'firstName' and 'lastName'.<br />
But what if you have 5 different objects that need to have a 'name'?<br />
Am I supposed to duplicate that in the schema 5 times too?
</p>
<p>
No.
</p>
<p>
The JSON Schema standard defines a number of keywords that can be used to <a href="http://spacetelescope.github.io/understanding-json-schema/reference/combining.html">combine schemas</a>: "oneOf", "allOf", and "anyOf".<br />
"oneOf" is good for applying "switch" logic branching.<br />
"anyOf" is for when you're a lot more forgiving.<br />
"allOf" is great for constructing a schema from sub-schemas.<br />
For example you can create a sub-schema for an object with "nameFirst" and "nameLast" properties, and include it as part of the schema for a completely different object.
</p>
<br />
<script src="https://gist.github.com/rolaveric/01c77c5db2183fc26ffd.js"></script>
</div>
<p>
Cheers,<br />
Jason Stone
</p>
Rolaverichttp://www.blogger.com/profile/07055170854302013537noreply@blogger.com0tag:blogger.com,1999:blog-6917086596782875672.post-65468663390930367702015-01-21T22:02:00.003+11:002015-01-21T22:04:51.808+11:00Using ES6 with your AngularJS project<style type="text/css">
.monospace {
font-family: Courier New, Courier, monospace;
}
.console {
font-family: Courier New, Courier, monospace;
background-color: black;
color: white;
padding: 5px;
}
</style>
<p>
Earlier this month <a href="http://glenmaddern.com/">Glen Maddern</a> (aka. The <a href="http://geelen.github.io/x-gif/"><x-gif></a> guy) posted an article, <a href="http://glenmaddern.com/articles/javascript-in-2015">Javascript in 2015</a>, with <a href="https://www.youtube.com/watch?v=iukBMY4apvI">a YouTube video</a> giving "A brief tour of <a href="http://jspm.io/">JSPM</a>, <a href="https://github.com/systemjs/systemjs">SystemJS</a> & ES6 features".<br />
If you haven't seen it already, go take a look.
</p>
<p>
In a short time he has a front-end application written in ES6 running, with modules being loaded and transpiled (via <a href="https://github.com/google/traceur-compiler">Traceur</a>) by SystemJS. And at the end he creates a self-executing, minified bundle of that application code, including source maps.
</p>
<p>
These tools make it easy to start using ES6 now with your existing AngularJS applications - which will almost certainly be step 1 on the migration plan to Angular v2.0. Even without that, the goodies from ES6 are too good to pass up.
</p>
<p>
As a demonstration, we're going to take <a href="https://github.com/angular/angular-seed">angular-seed</a>, update it to ES6 using SystemJS, bundle the app for production with <a href="https://github.com/systemjs/builder">systemjs-builder</a>, and configure Karma to run unit tests using the <a href="https://github.com/rolaveric/karma-systemjs">karma-systemjs</a> plugin.
</p>
<h2>SystemJS Setup</h2>
<p>OK - lets get started.<br />
We're going to clone an angular-seed repo, switch to a new es6 branch, then install dependencies from npm and bower.
The dependencies for angular-seed are a bit old, so we've updated them too:</p>
<p class="console">
git clone https://github.com/angular/angular-seed.git<br/>
cd angular-seed<br/>
git checkout -b es6<br/>
npm install --save-dev systemjs-builder karma-systemjs karma#~0.12 karma-chrome-launcher karma-firefox-launcher karma-jasmine<br/>
bower install -f -S angular#1.3.x angular-route#1.3.x angular-mocks#~1.3.x system.js<br/>
</p>
<p>
Next thing we need is a config file for SystemJS: <span class="monospace">`app/system.config.js`</span>.
This is where we tell SystemJS how to find certain modules. In this case, we're going to map the module names 'angular' and 'angular-route' to their long paths:
</p>
<script src="https://gist.github.com/rolaveric/40f56ceaf000aec3acb6.js"></script>
<p>
Next we'll change <span class="monospace">`app/index-async.html`</span> to use SystemJS rather than angular-loader:
</p>
<script src="https://gist.github.com/rolaveric/f1c3841027fa7e1b4374.js"></script>
<p>
Last thing to do is add <span class="monospace">`import`</span> statements to <span class="monospace">`app/app.js`</span> to include the rest of the application, as it's what will be loaded by <span class="monospace">`System.import('app')`</span>:
</p>
<script src="https://gist.github.com/rolaveric/6e56f740eac0275397b4.js"></script>
<p>
Now if you load up <span class="monospace">`app/index-async.html`</span> using a local webserver (The one included with angular-seed start with <span class="monospace">`npm start`</span>) you should see the angular-seed application running as normal, only it's been loaded as a set of ES6 files.
</p>
<p>
This is just the bare minimum required to get existing code to ES6 using SystemJS.<br />
You can add more ES6 syntax and rearrange the modules as you like.
</p>
<p>
Here's my suggestions:
</p>
<ul>
<li>Use classes for Controllers (Controller as), Services (.service()), and Providers</li>
<li>Use ES6 modules over angular modules</li>
<li>Use arrow functions - cause they're sugary sweet!</li>
</ul>
<h2>Bundling for Production</h2>
<p>
With our SystemJS config file already in place, we only need to pass that into systemjs-builder with a slight tweak to bundle our code for production.
This is a simple node script you can run with <span class="monospace">`node bundle.js`</span> that will bundle all the modules imported by <span class="monospace">`app/app.js`</span> and output the result to <span class="monospace">`app/bundle.js`</span>:
</p>
<script src="https://gist.github.com/rolaveric/8b8b608f7ecfa1deb79a.js"></script>
<p>
And finally we change <span class="monospace">`app/index.html`</span> to include <span class="monospace">`traceur-runtime.js`</span> and the <span class="monospace">`bundle.js`</span> file we just created:
</p>
<script src="https://gist.github.com/rolaveric/1b3ed7fcd69d92ea937c.js"></script>
<h2>Unit Testing</h2>
<p>
Karma works like most a typical browser application: Load all <span class="monospace"><script/></span> tags, then start the application `onload`.
In this case, we want Karma to let SystemJS handle loading everything, then start the test runner once everything is ready. This is essentially what karma-systemjs does for us.</p>
<p>
First we need to adjust <span class="monospace">`karma.conf.js`</span>:
</p>
<script src="https://gist.github.com/rolaveric/531c8b993f625a1f690e.js"></script>
<p>
Next we update our test suites to act like ES6 modules - importing the code to be tested, along with any dependency libraries.
</p>
<script src="https://gist.github.com/rolaveric/fc8e5ba027e4a55b1675.js"></script>
<p>
Note how <span class="monospace">`module()`</span> has been changed to <span class="monospace">`angular.mock.module()`</span>.
</p>
<p>
And that's it.<br />
An existing AngularJS project converted over to using ES6 with SystemJS, with working unit tests and a means of generating bundles for production.<br />
You can find the complete code here: <a href="https://github.com/rolaveric/angular-seed/tree/es6">https://github.com/rolaveric/angular-seed/tree/es6</a>
</p>
<p>
Cheers,<br/>
Jason Stone
</p>Rolaverichttp://www.blogger.com/profile/07055170854302013537noreply@blogger.com0tag:blogger.com,1999:blog-6917086596782875672.post-66874948224230817602014-11-05T22:54:00.000+11:002014-11-05T22:54:12.736+11:00ng-europe Retrospective Part 2: RIPIn the <a href="http://legacytotheedge.blogspot.com.au/2014/10/ng-europe-retrospective-part-1-new.html">last post</a> we went through some of the new Javascript syntax that the Angular team are trialling through AtScript, a superset of TypeScript, which is a superset of ES6...<br />
<br />
In this post we'll look at what's being removed between v1.x and v2.0 - The victims from <a href="https://www.youtube.com/watch?v=gNmWybAyBHI">Igor Minar and Tobias Bosch's talk at ng-europe</a>.<br />
<br />
First, it's worth mentioning some of the great material that's come up since the last post.<br />
<ul>
<li>More videos from ng-europe have been uploaded to YouTube: <a href="https://www.youtube.com/channel/UCEGUP3TJJfMsEM_1y8iviSQ">ng-europe channel</a></li>
<li>Tero Parviainen talked about <a href="http://teropa.info/blog/2014/11/01/why-i-think-angular-2-will-still-be-angular.html">why Angular 2 will still be Angular</a>.</li>
<li>Lukas Ruebbelke gives us <a href="http://onehungrymind.com/10-things-consider-keeping-level-head-angularjs-2-0/">10 Things To Consider While Keeping a Level Head About AngularJS 2.0</a>.</li>
<li>Misko Hevery opens up discussion about the <a href="https://github.com/angular/angular/issues/133">templating syntax in Angular 2</a>.</li>
<li>Matt Asay explains <a href="http://readwrite.com/2014/10/30/angularjs-javascript-framework-web-tools-need-to-break-themselves">Why Web Tools Like AngularJS Need To Keep Breaking Themselves</a>.</li>
</ul>
And no doubt there'll be more good stuff published in the coming days. Keep an eye on #AngularJS and the AngularJS team on <a href="https://twitter.com/search?q=%23AngularJS&src=tyah">Twitter</a> and <a href="https://plus.google.com/explore/AngularJS">Google+</a>.
<br /><br />
Now then. Lets take a look at the kill list.<br />
<br />
<h2>
RIP</h2>
<div>
First, a little disclaimer: I don't know for sure what Angular v2.0 will look like.<br />
Nobody does for sure. Not even the Angular team, because they haven't finished it yet.<br />
I'm merely extrapolating from the ng-europe presentations, and what's currently available in AngularDart.<br />
<br /></div>
<h3>
Controllers</h3><br />
<div>
Controllers, as we know them, are going.<br />
This has already been trialled in AngularDart. Controllers were originally a sub-class of directives, but were eventually deprecated and then <a href="https://github.com/angular/angular.dart/commit/5f8e27659ffb0140e0c153f8cecd627df273bfd2">removed for the release of v1.0</a>.<br />
<br />
Instead you will have a way to expose the properties and methods of a class with a @Directive annotation onto your templates. Igor and Tobias' talk mentioned some of the <a href="https://docs.google.com/presentation/d/1XQP0_NTzCUcFweauLlkZpbbhNVYbYy156oD--KLmXsk/preview?usp=drive_web&sle=true&slide=id.g498be00ed_262">potential Directive subclasses</a> that will make things easier for you.<br />
<br />
The closest equivalent in v1.x I can think of would be a directive with a 'controller' and a 'controllerAs', like so:<br />
<script src="https://gist.github.com/rolaveric/bc9734c30528e0886bc3.js"></script>
</div>
<h3>
Directive Definition Object (DDO)</h3><br />
<div>
The old DDO syntax that we all know and... know, for writing directives will be gone.<br />
The heart of your directive logic will be a class, with annotations that describe how the directive will be used.<br />
<br />
Once again, to get the best idea of how this will work, <a href="https://docs.angulardart.org/#angular/angular-core-annotation">look no further than AngularDart</a>.<br />
<br /></div>
<h3>
$scope</h3><br />
<div>
Now this is an interesting one - the classic $scope object gone for good.<br />
How is that even possible?<br />
<br />
Well, $scope provides 3 main functions:<br />
<ul>
<li>exposing properties to the template</li>
<li>creating watchers</li>
<li>and handling events</li>
</ul>
<div>
The first is somewhat redundant because every control-I mean, every component class will be exposing it's public properties to the template. As though "controllerAs" had become mandatory.<br />
<br />
Watchers will be handled by their own new module: <a href="https://github.com/angular/watchtower.js/">watchtower.js</a><br />
This allows watchers to be grouped together in a way which doesn't depend on... well, anything really. But certainly not a scope hierarchy like in Angular v1.x<br />
<br />
As for events... I'm not sure.<br />
I haven't seen anything specific about events, so I can only speculate.<br />
In saying that - my money is on using the native DOM API for events, as that's how Angular v2.0 is heading for DOM manipulation.</div>
<div>
<br /></div>
<div>
Speaking of which...</div>
<div>
<br /></div>
<br />
<h3>
jqLite</h3><br />
<div>
<div>
The Angular team have found that jqLite has become too much of a performance bottleneck for them.<br />
And since Angular v2.0 is for evergreen browsers, they have no fear of relying on native implementations of the DOM API.<br />
<br />
DOM traversal is easily handled by <a href="https://developer.mozilla.org/en-US/docs/Web/API/document.querySelector">querySelector()</a> and <a href="https://developer.mozilla.org/en-US/docs/Web/API/document.querySelectorAll">querySelectorAll()</a>, events with <a href="https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener">addEventListener()</a>, and good old <a href="https://developer.mozilla.org/en-US/docs/Web/API/document.createElement">createElement()</a>, <a href="https://developer.mozilla.org/en-US/docs/Web/API/Element.setAttribute">setAttribute()</a>, and <a href="https://developer.mozilla.org/en-US/docs/Web/API/Node.appendChild">appendChild()</a> for manipulation.<br />
<br /></div>
<div>
But in the end, if you want to use jQuery, there's nothing stopping you from using it.<br />
It just won't be part of the Angular Core.</div>
</div>
</div>
<div>
<br /></div>
<h3>
angular.module</h3><br />
<div>
angular.module() has 2 somewhat overlapping jobs:<br />
<br />
<ul>
<li>Register different types of components (eg. Directives, controllers, filters, etc.)</li>
<li>and register injectables and their dependencies.</li>
</ul>
The first has been replaced by annotations, like @Directive.<br />
The second has been split into it's own module: <a href="https://github.com/angular/di.js">di.js</a><br />
<br />
The workings of di.js is pretty simple.<br />
You declare the dependencies for a class using the @Inject annotation, specifying the class for each dependency (The actual class - not just it's name as a string, like Angular v1.x does), and then create an Injector for the classes you want.<br />
Checkout the example on the di.js github: <a href="https://github.com/angular/di.js/tree/master/example/kitchen-di">kitchen-di</a><br />
<br />
The great thing about this is that it doesn't make any assumptions about your application. It's totally separated from Angular.<br />
You can even create multiple injectors, maybe one for each instance of a directive.<br />
<br />
<h3>
ng-app</h3><br />
This wasn't listed with the other tombstones, but you'll notice it was missing from <a href="https://docs.google.com/presentation/d/1XQP0_NTzCUcFweauLlkZpbbhNVYbYy156oD--KLmXsk/preview?usp=drive_web&sle=true&slide=id.g498335282_06">the slide</a> with the experimental template syntax.<br />
It's also not used by AngularDart applications.<br />
Instead they create their own application object, which you then register classes with, and then run the application. Not unlike "<a href="https://docs.angularjs.org/api/ng/function/angular.bootstrap">angular.bootstrap()</a>".<br />
I think Angular v2.0 will do something similar.</div>
<div>
<br /></div>
<h2>
Final Thoughts</h2>
<div>
These changes are about making your code less "Angular" and more "Javascript".<br />
But nothing is really set in stone yet for Angular v2.0:<br />
<blockquote class="twitter-tweet" lang="en">
Reminder that the <a href="https://twitter.com/angularjs">@angularjs</a> 2.0 announcements are a call for feedback, not a final design. We're listening to your feedback!<br />
— Brian Ford (@briantford) <a href="https://twitter.com/briantford/status/528278903857483776">October 31, 2014</a></blockquote>
<script async="" charset="utf-8" src="//platform.twitter.com/widgets.js"></script>
In my next post I'm going to make some wild assumptions about Angular v2.0 and come up with some things we can do with our v1.x code to make the transition easier.<br />
(Spoiler alert: It's going to involve ES6)</div>Rolaverichttp://www.blogger.com/profile/07055170854302013537noreply@blogger.com0tag:blogger.com,1999:blog-6917086596782875672.post-27462489715659316582014-10-31T21:48:00.001+11:002014-10-31T21:48:54.374+11:00ng-europe Retrospective Part 1: New Syntaxng-europe, the European AngularJS conference, was held last week in Paris (France - not that other Paris), and the videos from the sessions were uploaded to Youtube earlier this week:<br />
<a href="https://www.youtube.com/channel/UCEGUP3TJJfMsEM_1y8iviSQ">https://www.youtube.com/channel/UCEGUP3TJJfMsEM_1y8iviSQ</a><br />
<br />
The main topic around the conference was, to no one's surprise, AngularJS v2.0<br />
When will it be released? What will it bring? What will it break?<br />
The answers to which break down to: Soon ™; The same but faster and using future standards; And a lot less than some people are panicking about.<br />
<br />
If I were to sum up what I've seen of AngularJS v2.0: It will have <a href="http://legacytotheedge.blogspot.com.au/2014/03/angulardart-sneak-peek-at-future-of.html">everything that AngularDart got</a>, with some of the crust cut off.<br />
In fact, the Angular team have organised the source code so that they can build AngularJS and AngularDart from the <a href="https://github.com/angular/angular">same code base</a>, which is an impressive feat.<br />
<h2>
New Syntax</h2>
Wait... but how can they do that?<br />
AngularDart uses classes and type reflection to handle dependency injection, and annotations for marking classes as directives or web components.<br />
These things aren't in Javascript...<br />But they are in ES6, TypeScript, and AtScript.<br />
<br />
Confused?<br />That's where this slide comes in handy.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwxFpKgBpjWl8zoL1DYoSiiL7GvGIpK8PvVHq21zJUG4j7eR2uG32K7zor_PyLjn6np080YVmS33tolB4VUsfASy_4APxX-hbdn-UEtAz3GZUm3p4nQ29gatD6m8J9UOyXYytYwTQhz-k/s1600/atscript.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwxFpKgBpjWl8zoL1DYoSiiL7GvGIpK8PvVHq21zJUG4j7eR2uG32K7zor_PyLjn6np080YVmS33tolB4VUsfASy_4APxX-hbdn-UEtAz3GZUm3p4nQ29gatD6m8J9UOyXYytYwTQhz-k/s1600/atscript.jpg" height="345" width="400" /></a></div>
<h3>
Classes</h3>
<br />
The class syntax is being standardised in ES6.<br />
And when it's compiled down to ES5, it uses the good old Javascript prototype chain: Effective but ugly.<br />
<br />
<script src="https://gist.github.com/rolaveric/241332ae69db2628c24d.js"></script>
<h3>
Types</h3>
<div>
<br /></div>
For dependency injection to work we need to know what type of objects each dependency is. Today this is achieved by identifying dependencies with strings.<br />
For Angular v2.0, the Angular team wants to move away from this idea that everything must be registered explicitly with Angular (ie. module.factory(), module.value(), etc.) and instead just use classes. Same way it's been done for AngularDart.<br />
<br />
The trouble is that ES6 still has no syntax for declaring that a parameter should be a particular type.<br />If I want my function to only accept parameter "meep" if it came from "MyClass", then I'm going to have to do my own manual "meep instanceof MyClass" check.<br />
This is where the "name:type" syntax comes in. It provides both type assertions at runtime, and documentation.<br />
It's currently being used by TypeScript, and <a href="http://wiki.ecmascript.org/doku.php?id=strawman:types">a proposal was drafted for ES6</a>, but it looks like it will be deferred till ES7 at least.<br />
<br />
<script src="https://gist.github.com/rolaveric/8e9769f20093ceda444d.js"></script>
<br />
<h3>
Type Introspection</h3>
<br />
What TypeScript does is great for doing type checking on values, but it doesn't actually help with things like dependency injection. It's not about passing in the correct values to a function - It's about knowing what the function wants in the first place.<br />
That's where the need for type introspection (or type reflection) comes in.<br />
<br />
Looking at <a href="https://google.github.io/traceur-compiler/demo/repl.html#%2F%2F%20Options%3A%20--annotations%20--array-comprehension%20--async-functions%20--exponentiation%20--generator-comprehension%20--symbols%20--types%20%0Afunction%20fn(a%3AMyClass%2C%20b%3Astring)%20%7B%7D%0A">the code generated by traceur</a>, AtScript's solution is to attach the classes or some equivalent to the function as a property called "parameters". Simple, but effective.<br />
<script src="https://gist.github.com/rolaveric/29d0d09ef4460c90247f.js"></script>
<br />
<h3>
Annotations</h3>
<br />
The last piece is annotations. Metadata which declares something about a class or function without directly interfering with it.<br />
Annotations become a property of the function called "annotations", similar to parameters.<br />
<br />
<script src="https://gist.github.com/rolaveric/75591c7a45a38cfe8983.js"></script>
<br />
<h2>
Final Thoughts</h2>
<div>
All of these new syntaxes are going to be added to Javascript, sooner or later, and I believe they'll be a welcome addition to the language.</div>
<div>
<br />Creating class-like structures right now requires either a third-party library or some very ugly looking uses of the 'prototype' property. It's about time it got standardised.</div>
<div>
<br /></div>
<div>
Fact: Types are useful.<br />If you don't want to use them, fine. The type system is optional.</div>
<div>
But they can help stop trivial bugs, make IDEs more useful, and refactoring a lot easier.</div>
<div>
<br /></div>
<div>
And I think the way Angular uses annotations proves just how useful they can be.<br /><br /><h2>
Next Time</h2>
</div>
<div>
Next time I'm going to take a look through the things <a href="https://www.youtube.com/watch?v=gNmWybAyBHI">Igor and Tobias mentioned</a> will be killed off in Angular v2.0, and what will replace them.<br />After that I'll take a look at a few things we could do in v1.x that might make migrating to v2.0 a little less jarring.</div>
<div>
<br /></div>
<div>
Till then.</div>
<div>
<br /></div>
<div>
Cheers,</div>
<div>
Jason Stone</div>
Rolaverichttp://www.blogger.com/profile/07055170854302013537noreply@blogger.com0tag:blogger.com,1999:blog-6917086596782875672.post-24089615129950235372014-05-16T23:16:00.000+10:002014-05-16T23:37:48.532+10:00Guide to Javascript on Classic ASP<div>
<i>Disclaimer: As the title says, this is for Classic ASP with "Javascript". If your project is using Visual Basic, you may be able to glean some information from this article, but it's not written with you in mind.</i></div>
<div>
<br /></div>
I've had some recent experience with a legacy system using Javascript (technically "JScript") on Classic ASP, and the thing I found most frustrating was the lack of coherent documentation available. Despite it's <a href="http://www.w3fools.com/">reputation</a>, <a href="http://www.w3schools.com/asp/">w3schools</a> is still one of the best references available on the web.<br />
<div>
<br />
<div>
I guess this shouldn't be a surprise. It is a deprecated platform, and they don't call it "Classic" for nothing. But there are still legacy systems out there which need to be maintained. If the system is purely in <a href="http://en.wikipedia.org/wiki/Maintenance_mode">maintenance mode</a>, you can probably get along just by reading the existing code and holding your nose. But if you need to add features and make significant changes, it's worth knowing some of Classic ASP's secrets so you can take advantage of the modern Javascript ecosystem.</div>
</div>
<div>
<br /></div>
<div>
<i>Note: This is meant to be a reference for anyone who's forced to work with Classic ASP. In no way am I condoning using it by choice. But if you've got to use it - use it right.</i></div>
<div>
<br /></div>
<h2>
Javascript in Classic ASP is ECMAScript 3</h2>
<div>
<br /></div>
<div>
First thing to be aware of is that the code you're writing, at it's core, is ECMAScript 3. Another way to think of it: If your code runs in IE8 (minus the DOM API, obviously) it'll run in Classic ASP.</div>
<div>
<br /></div>
<div>
I've seen some developers approach Classic ASP code like it's some ancient writing which only the old masters knew how to interpret. It's not. There are only 6 things which are not, strictly speaking, Javascript: Request, Response, Server, Application, Session, and ASPError.</div>
<div>
Your biggest challenge is learning to live without features from ES5, or finding appropriate shims.</div>
<div>
<br /></div>
<h2>
The global scope cannot be directly manipulated</h2>
<div>
This is the biggest WTF to get your head around if you're used to coding in browsers or NodeJS. Trying to work with the global scope object as "this" will cause errors, giving developers the false impression that modern libraries won't work with Classic ASP.</div>
<div>
<br /></div>
<div>
Say you've got a third party library (like <a href="http://underscorejs.org/">UnderscoreJS</a>) that declares itself like so:</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">(function () {</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> this.myExport = {};</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">}).call(this);</span></div>
<div>
<br /></div>
<div>
If I try to run this in Classic ASP, it will throw an error.</div>
<div>
You can easily work around it, though it is somewhat tedious:</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">var surrogate = {};</span></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;">(function () {</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> this.myExport = {};</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">}).call(surrogate);</span></div>
</div>
<div>
<span style="font-family: Courier New, Courier, monospace;">var myExport = surrogate.myExport;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<h2>
Use <script src="" runat="server"> to include code without tags</h2>
<div>
<br /></div>
<div>
Most Classic ASP I know uses the <a href="http://www.w3schools.com/asp/asp_incfiles.asp">#include directive</a> provided by IIS to compose source files. The directive works by essentially pasting the entire file content into the directive location, like so:</div>
<div>
<br /></div>
<div>
include.asp:</div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><script runat="server"></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">var myInclude = {};</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"></script></span></div>
<div>
<br /></div>
<div>
main.asp:</div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><!-- #include file="include.asp" --></span></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><script runat="server"></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">var myProgram = {include: myInclude};</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"></script></span></div>
</div>
<div>
<br /></div>
<div>
Results in:</div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><script runat="server"></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">var myInclude = {};</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"></script></span></div>
</div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><script runat="server"></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">var myProgram = {include: myInclude};</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"></script></span></div>
</div>
<div>
<br /></div>
<div>
The downside to this is that you can't use any Javascript code quality tools. They'll start to parse your file, find the tags, and throw syntax errors. This prevents you from doing <a href="http://www.jshint.com/">style checks</a>, <a href="https://github.com/gotwarlost/istanbul">code coverage</a>, and <a href="https://github.com/es-analysis/plato">code metrics</a>. It can also cause headaches for editors and IDEs.</div>
<div>
<br /></div>
<div>
Instead you can use <script src="" runat="server"> to include files into your tags, just like any ".js" file into HTML:</div>
<div>
<br /></div>
<div>
include.js</div>
<div>
<span style="font-family: Courier New, Courier, monospace;">var myInclude = {};</span></div>
<div>
<br /></div>
<div>
main.asp:</div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><script src="include.js" runat="server"></script></span></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><script runat="server"></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">var myProgram = {include: myInclude};</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"></script></span></div>
</div>
<div>
<br /></div>
<div>
Using this method, there's noth... very little to stop you using the same tools enjoyed by NodeJS developers. Though you obviously need to be configure IIS so that it doesn't expose your code files as static resources.<br />
That would be bad...</div>
<div>
<br /></div>
<h2>
Code in <% %> tags is parsed before <script runat="server"></script> tags</h2>
<div>
This was a bit of a head scratcher when I first discovered it. But sure enough, code in <% %> tags executes before <script runat="server"></script> tags (<a href="http://stackoverflow.com/questions/1447822/whats-the-difference-between-and-script-language-vbscript-runat-serve">stackoverflow</a>).</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><script runat="server">Response.Write("first");</script></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><%Response.Write("second");%></span></div>
<div>
<br /></div>
<div>
Result: second, first</div>
<div>
<br /></div>
<div>
My recommendation is: Don't use <% %> tags.</div>
<div>
<br /></div>
<div>
It's too easy to create <a href="http://en.wikipedia.org/wiki/Tag_soup">tag soup</a>, and you're better off using <script src="" runat="server"> anyway for JS code tooling.</div>
<div>
<br /></div>
<h2>
Core ASP objects don't produce Javascript primitives</h2>
<div>
<span style="font-family: Courier New, Courier, monospace;">var param = Request.QueryString('param');</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">param == "test"; // true</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">param === "test"; // false</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">String(param) === "test"; true</span></div>
<div>
<br /></div>
<div>
This means you tried to call "param.substring(1)", it would throw an error saying that "substring" was undefined. So you need to make sure you wrap results from core ASP objects in String(), Number(), or Boolean() before you try to use them.</div>
<div>
<br /></div>
<div>
That about does it.</div>
<div>
To all the poor bastards out there stuck working on Classic ASP: This is for you.</div>
<div>
<a href="http://knowyourmeme.com/photos/107432-i-know-that-feel-bro"><img src="http://i2.kym-cdn.com/photos/images/original/000/107/432/i_hug_that_feel.png" height="295" width="320" /></a><br />
See more on <a href="http://knowyourmeme.com/">Know Your Meme</a></div>
<div>
<br /></div>
Rolaverichttp://www.blogger.com/profile/07055170854302013537noreply@blogger.com2tag:blogger.com,1999:blog-6917086596782875672.post-53664764528576832352014-05-16T21:11:00.002+10:002014-05-16T21:14:04.427+10:00E2E testing AngularJS with Protractor<blockquote>
<i><span style="font-family: Arial, Helvetica, sans-serif;">In the beginning, there was <a href="https://code.google.com/p/js-test-driver/">JSTestDriver</a>.</span></i><br />
<i><span style="font-family: Arial, Helvetica, sans-serif;">It was a dark time, with much wailing and gnashing of teeth.</span></i><br />
<i><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></i>
<i><span style="font-family: Arial, Helvetica, sans-serif;">Then came <a href="http://googletesting.blogspot.com.au/2012/11/testacular-spectacular-test-runner-for.html">Testacular: The spectacular test runner</a>.</span></i><br />
<i><span style="font-family: Arial, Helvetica, sans-serif;">For a time, once everyone stopped sniggering like teenagers, it was good.</span></i><br />
<i><span style="font-family: Arial, Helvetica, sans-serif;">Unit tests ran quick as lightning on any browser that could call a web page.</span></i><br />
<i><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></i>
<i><span style="font-family: Arial, Helvetica, sans-serif;">Finally, to please the squeamish who were too embarrassed to speak of Testacular to colleagues and managers, <a href="https://github.com/vojtajina">the creator</a> <a href="https://github.com/karma-runner/karma/commit/2b2044eeed2e4675afec9235430db314d46154ec">moved heaven and earth</a> to rename it <a href="http://karma-runner.github.io/">Karma</a>.</span></i><br />
<i><span style="font-family: Arial, Helvetica, sans-serif;">And it was, and still is, good.</span></i><br />
<i><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></i>
<i><span style="font-family: Arial, Helvetica, sans-serif;">But there was still unrest.</span></i><br />
<i><span style="font-family: Arial, Helvetica, sans-serif;">While unit tests were as quick as the wind, E2E (end-to-end) tests were constrained from within the Javascript VM.</span></i><br />
<i><span style="font-family: Arial, Helvetica, sans-serif;">"Free me from this reverse proxy! Treat me as though I were a real user!"</span></i><br />
<i><span style="font-family: Arial, Helvetica, sans-serif;">And thus <a href="https://github.com/angular/protractor">Protractor</a> was born.</span></i></blockquote>
<br />
*ahem*<br />
Protractor is the official E2E testing framework for AngularJS applications, working as a wrapper around <a href="https://code.google.com/p/selenium/wiki/WebDriverJs">Web Driver</a> (ie. <a href="https://code.google.com/p/selenium/wiki/FrequentlyAskedQuestions#Q:_What_is_Selenium_2.0?">Selenium 2.0</a>) which is a well established and widely used platform for writing functional test for web applications. What makes it different from Karma is that Karma acts as a reverse proxy in front of your live AngularJS code, while Web Driver accesses the browser directly. So your tests become more authentic in regards to the user's experience.<br />
<br />
One cool thing about Web Driver, which I didn't realise till recently, is that it's API is currently being drafted up as a <a href="https://dvcs.w3.org/hg/webdriver/raw-file/default/webdriver-spec.html">W3 standard</a>. We're also seeing <a href="https://www.google.com.au/search?q=Selenium+test+service">a number of services appear</a> for running your selenium tests using their VMs, which is useful for doing CI and performance testing without taking on the operational overhead yourself.<br />
<br />
Let's go!<br />
<br />
<h2>
The App</h2>
I've created <a href="https://github.com/rolaveric/protractorDemo">a simple application</a> to write tests for. So first we'll clone the application from github, install the local NodeJS modules, and then install the required bower components:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">git clone https://github.com/rolaveric/protractorDemo</span><br />
<span style="font-family: Courier New, Courier, monospace;">cd protractorDemo</span><br />
<span style="font-family: Courier New, Courier, monospace;">npm install</span><br />
<span style="font-family: Courier New, Courier, monospace;">node node_modules/bower/bin/bower install</span><br />
<br />
Now you should have a copy of the application with node modules 'bower' and 'protractor' installed, and AngularJS installed as a bower component.<br />
<br />
The application is dead simple. It has a button with the label "Click to reverse". When you click it, it (you guessed it) reverses the label. So our tests should look something like this:<br />
<ul>
<li>Load App</li>
<li>Click button</li>
<li>Assert that label is now reversed</li>
<li>Click button again</li>
<li>Assert that label is now back to normal</li>
</ul>
<h2>
Installing Selenium</h2>
<div>
Protractor comes with a utility program for installing and managing a selenium server locally: webdriver-manager<br />
Calling it with "update" will download a copy of the selenium standalone server to run.<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">node node_modules/protractor/bin/webdriver-manager update</span><br />
<h2>
Setting up for tests</h2>
First thing we need is a configuration file for protractor. It tells protractor everything it needs to know to run your tests: Where to find or how to start Selenium, where to find the web application, and where to find the tests.<br />
<br />
Since we're using webdriver-manager to run selenium server, we'll tell it the default address to find it: http://localhost:4444/wd/hub<br />
Optionally you could give it the location of the selenium server JAR file to start itself, or a set of credentials to use <a href="https://saucelabs.com/">SauceLabs</a>.<br />
<br />
The tests we'll place in "test/e2e", and <span style="font-family: Courier New, Courier, monospace;">npm start</span> spins up a local web server at "http://localhost:8000/". So the basic configuration file stored in "config/protractor.conf.js" looks like this:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">exports.config = {</span><br />
<span style="font-family: Courier New, Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>seleniumAddress: 'http://localhost:4444/wd/hub',</span><br />
<span style="font-family: Courier New, Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>specs: ['../test/e2e/*.js'],</span><br />
<span style="font-family: 'Courier New', Courier, monospace; white-space: pre;"> </span><span style="font-family: Courier New, Courier, monospace;">baseUrl: 'http://localhost:8000/'</span><br />
<span style="font-family: Courier New, Courier, monospace;">};</span><br />
<br />
There's actually a lot more you can do with the configuration file, but this is all we need to get going. Check out the <a href="https://github.com/angular/protractor/blob/master/referenceConf.js">reference config</a> in protractor's github for more options. You can do things like pass parameters to selenium, your testing framework, and even to your tests (eg. login details).<br />
<h2>
Writing tests</h2>
In "test/e2e/click.js" is a simple test for the "Click to reverse" behaviour:<br />
<br />
<script src="https://gist.github.com/rolaveric/11076098.js"></script>
The process behind writing E2E tests is pretty simple: Perform an action, get some data, then test that data. Generally each action or query also involves finding a particular element on the page, either by CSS selector, ng-model name, or template binding.<br />
<br />
First it opens the "index.html" file (which it finds relative to the baseUrl in the configuration file), finds the button by it's binding, clicks the button, then gets the button's text value and tests it. Then we click the button again, get it's text value, and test that it's changed back to normal.<br />
<br />
<h2>
Running tests</h2>
<br />
Now for the payoff - the running of the tests.<br />
<br />
First we'll start up the web and webdriver servers:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">npm start</span><br />
<span style="font-family: Courier New, Courier, monospace;">node node_modules/protractor/bin/webdriver-manager start</span><br />
<br />
Then we tell protractor to run the tests according to our configuration file:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">node node_modules/protractor/bin/protractor config/protractor.conf.js</span><br />
<br />
If everything's gone well, you should soon be rewarded with the following result:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">Finished in 2.061 seconds</span><br />
<span style="color: #274e13; font-family: Courier New, Courier, monospace;">2 tests, 2 assertions, 0 failures</span><br />
<br />
And there you have it. Webdriver tests for your AngularJS application with minimum pain. If you already have angular-scenario based tests, converting them to Protractor should be a trivial "search & replace" exercise with the right regular expressions.</div>
Rolaverichttp://www.blogger.com/profile/07055170854302013537noreply@blogger.com0tag:blogger.com,1999:blog-6917086596782875672.post-83510416304830020162014-03-30T22:16:00.002+11:002014-04-14T20:35:17.198+10:00AngularDart: The future of AngularJS?The AngularJS team have been working on a port to Dart called, naturally, <a href="https://angulardart.org/">AngularDart</a>.<br />
They've taken the opportunity to completely rewrite Angular, adding features and patterns which feel quite natural when written in Dart.<br />
At <a href="https://angulardart.org/">ng-conf</a> 2014, they talked about their intention to port these new features back into AngularJS as part of version 2.0. So I've been curious to take a look at AngularDart as a sneak peek into the future of AngularJS.<br />
<h2>
What's Dart?</h2>
<a href="https://www.dartlang.org/">Dart</a> is an open source language, backed by Google (In the same way Go is), which is designed to replace Javascript as the programming language for web browsers. It has it's own VM called Dartium, similar to V8 for Javascript, and I believe has some of the original V8 developers working on it.<br />
<br />
But since the only browser which comes with Dartium is a special build of Chromium made specifically for Dart development, the Dart SDK comes with dart2js: A <a href="http://en.wikipedia.org/wiki/Source-to-source_compiler">transpiler</a> that produces Javascript which can be used in any browser that supports ECMAScript 5.<br />
<br />
And the performance from what dart2js produces is <a href="https://www.dartlang.org/performance/">fairly impressive</a>. Though one should always take benchmarks with a grain of salt.<br />
<br />
<h3>
What makes Dart different from any other modern programming language?</h3>
<div>
<br /></div>
There are more <a href="https://github.com/jashkenas/coffee-script/wiki/List-of-languages-that-compile-to-JS">transpilers to Javascript</a> than you can poke a stick at.<br />
<br />
I think the answer is about the original purpose of the language. The purpose of Dart was to create a new language for web browsers, which requires it to have a resemblance to Javascript, so that it can interoperate with it. This is different from, say, Clojure which wasn't written specifically so it could work with Javascript; That was implemented later as <a href="https://github.com/clojure/clojurescript">ClojureScript</a>.<br />
<br />
<a href="http://coffeescript.org/">CoffeeScript</a> is probably the closest example to what Dart is trying to do. The difference is that CoffeeScript's purpose was always to be compiled down to Javascript. It was never intended to completely replace Javascript, just to smooth out it's flaws.<br />
<br />
Dart also comes with it's own tools. As well as the <a href="https://www.dartlang.org/tools/dart2js/">dart2js</a> transpiler, you've got <a href="https://www.dartlang.org/tools/pub/">pub</a> for package management (think npm and <a href="http://bower.io/">bower</a>), <a href="https://www.dartlang.org/docs/dart-up-and-running/contents/ch04-tools-dart_analyzer.html">dartanalyzer</a> for <a href="http://en.wikipedia.org/wiki/Lint_(software)">linting</a>, <a href="https://www.dartlang.org/tools/docgen/">docgen</a> for documentation generation, and <a href="https://www.dartlang.org/tools/dartfmt/">dartfmt</a> for code formatting. I'm a big fan of platform enforced formatting. It takes the decision, and therefore the argument, as far away from me as humanly possible.<br />
<br />
<h2>
First look at AngularDart</h2>
<h3>
"Hello Dart"</h3>
<div>
<br /></div>
<div>
The Dart SDK comes with Dart Editor, a customised <a href="https://www.eclipse.org/">Eclipse IDE</a>. The welcome page includes a link for an AngularDart sample (which you can find the source for at <a href="https://github.com/angular/angular.dart/tree/master/example">github.com/angular/angular.dart</a>), but it just wouldn't be as fun to have everything pre-done for us... well, not the first time, at least.</div>
<div>
<br /></div>
<div>
Go "File -> New Application", pick "Web application" and give it a name (I went with 'intro'). You'll be given some basic boilerplate: a ".dart", ".css", and ".html file, and some files used by 'pub' for package management. Click "Run" (the green 'play' button) to spin up the application in Dartium.</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEcnIWCH_LEnAQ-9u32lnoU0GCaTtboc7nYEbf2XOrdTHO6_Aoz78tA3UFuQ4BVIdBFARMagLiWuaVDFLWo_8792FJr8y-HtbCBQH8jPvl4n2UvBiHYfxAguGO-q70543CrC_sEEGXCO4/s1600/angularDart1.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEcnIWCH_LEnAQ-9u32lnoU0GCaTtboc7nYEbf2XOrdTHO6_Aoz78tA3UFuQ4BVIdBFARMagLiWuaVDFLWo_8792FJr8y-HtbCBQH8jPvl4n2UvBiHYfxAguGO-q70543CrC_sEEGXCO4/s1600/angularDart1.PNG" height="275" width="400" /></a></div>
<br />
What you should see is a simple page with the words "Click Me!" which reverse themselves when clicked.<br />
The code is pretty self-explanatory. It uses "querySelector()" to pick the element, set the text, then add an event listener which reverses the text. Next we'll change it to use AngularDart instead of the core library.<br />
<br />
<h3>
"Hello AngularDart"</h3>
</div>
<div>
<br /></div>
<div>
First thing we need is to install the AngularDart package using "pub".</div>
<div>
Open up the "pubspec.yaml" file. You should see an existing "browser: any" dependency. This means the application depends upon any (ie. latest stable) version of the "browser" package, which is a library for applications that run in a browser, as opposed to using the "io" package if you wanted to run it as a standalone application. Add "angular: any" to the dependencies and then run "pub get".</div>
<br />
Back to the code.<br />
First, lets import AngularDart and bootstrap it:<br />
<br />
<script src="https://gist.github.com/rolaveric/9848667.js"></script>
If everything has gone fine, this should have zero effect on your application. But if you start getting "The built-in library 'dart:json' is not available on Dartium.", run "pub upgrade" to fix it. It means one of the dependencies is still trying to use "dart:json" instead of "dart:convert".
<br />
<br />
Now we want to replace that click event listener with a directive. Directives in AngularDart are given a CSS selector, rather than a name plus a type restriction. However that doesn't mean they support any kind of CSS selector. You're generally restricted to an attribute or element name. So we want to change the "#sample_text_id" in the HTML to "[sample-text-id]", since we can't use the 'id' attribute:<br />
<br />
<script src="https://gist.github.com/rolaveric/9849097.js"></script>
Now to write our directive.<br />
<br />
Directives are structured differently in AngularDart. Instead of POJ objects, they're classes with an "@NgDirective" annotation. Annotations play a big part in AngularDart, and are likely going to do the same for AngularJS 2.0 (Which is causing some contention since annotations aren't part of the ES6 spec, but is supported by <a href="https://github.com/google/traceur-compiler">Traceur</a>).<br />
<br />
Another big difference with AngularDart directives is that you don't use a name and a "restrict" property to decide what elements or attributes they get triggered by. Instead you add a "selector" with a CSS selector to the annotation.<br />
<br />
And last of all we need to make sure the directive gets included in the application bootstrap process. We do this by setting our new "ReverseClickDirective" class as a type on a new module, which gets passed into the "ngBootstrap()" method call. I'll go into the Module class a bit more later.<br />
<br />
<script src="https://gist.github.com/rolaveric/9850668.js"></script>
All I've done here is a bad recreation of "ng-click", but it gives you an idea of how different AngularDart is compared to AngularJS v1.*, and how different AngularJS v2.* is likely to look.
<br />
<br />
<h2>
In depth AngularDart</h2>
<div>
So you think "hmm, that's some what interesting. Where should I go from here?".</div>
<div>
A wise man once said "Luke, read the source".<br />
The <a href="https://docs.angulardart.org/">documentation for AngularDart</a> is pretty sparse right now (understandably, since it's still in beta). So your best bet is to go straight to the source code, most of which is pretty well documented with inline comments; especially the public API.</div>
<div>
<br /></div>
<h3>
Dependency Injection</h3>
<div>
<br /></div>
<div>
In AngularDart, the DI framework has been separated from Angular into it's <a href="https://github.com/angular/di.dart">own package</a>. But it's still reference quite heavily in the Angular code, so you'll need to understand the DI framework to follow the AngularDart source code. Remember the "Module" class with it's "type" method that was passed to the "ngBootstrap" method? That was from the DI package, not from Angular.</div>
<div>
<br /></div>
<div>
Lets start with the Module class because it's really the most important class. Open up "packages/di/module.dart". Remember the "value()", "factory()", "service()", "constant()" and "provider()" module methods in AngularJS? Here they are again, but instead you have:</div>
<div>
<br /></div>
<div>
<ul>
<li><b>value(Type id, value, {Type withAnnotation, Visibility visibility})</b><br />The "value()" you know and love, but with a twist.<br />Instead of "id" being a string, it's a Type (ie. class). This makes perfect sense in Dart because it supports an (optional) type checking system with classes.<br />However, if you're not dealing with a class or you're dealing with multiple instances of the same class you can use annotations, combined with the "withAnnotation" parameter.<br /><br />The "visibility" parameter is a function which takes 2 injectors, the requesting and the defining, and returns whether or not the requesting injector has visibility of the instance created by the defining injector. This is a new DI concept for Angular which we haven't seen in AngularJS v1.*, but was hinted at by Vojta Jina in <a href="https://www.youtube.com/watch?v=_OGGsf1ZXMs">this talk at ng-conf</a>. This idea of multiple injectors which can share, or not share, certain injectables is pretty cool.</li>
<li><b>type(Type id, {Type withAnnotation, Type implementedBy, Visibility visibility})</b><br />We've seen type before when we declared our directive class during bootstrap. It's pretty much what you would expect - give it a class, and expect to get an instance of that class on injection.<br />As an added bonus, you can also specify an "implementedBy" subclass to use when the "id" class is required.</li>
<li><b>factory(Type id, FactoryFn factoryFn, {Type withAnnotation, Visibility visibility})</b><br />If you're not a fan of "new", you can use a factory function instead.<br /><br />A "FactoryFn" accepts an injector as a parameter, for loading dependencies, and returns the injectable value.</li>
<li><b>install(Module module)</b><br />Used to extend an existing module.</li>
</ul>
What about "constant()" and "provider()"?<br />
AngularDart has taken the whole "config() phase vs run() phase" concept and thrown it away, making those methods redundant. If you really need to perform extra configuration on your modules before the application starts running, then you should do it before calling "ngBootstrap()".</div>
<div>
<br /></div>
<div>
Okay, that handles registering injectables. But how do I declare dependencies?<br />
"factory()" already has this handled because it gets an instance of the injector. So it just needs to call "injector.get(MyDependency)", and away it goes.<br />
What about "type()"? Well that's the beauty of a static type system. The DI framework uses <a href="https://api.dartlang.org/apidocs/channels/stable/#dart-mirrors">reflection</a> to determine the types expected by the class constructor, and injects those in. Look at this:</div>
<br />
<script src="https://gist.github.com/rolaveric/9852538.js"></script>
<br />
<div>
That's how the DI framework works. If it's instantiated through the DI framework, then it will attempt to provide all the dependencies required by it's constructor.
<br />
<br />
<h3>
Controllers, Filters, and Directives (Oh my?)</h3>
</div>
<div>
The missing methods from our old AngularJS modules are "controller()", "filter()", and "directive()".</div>
<div>
<br /></div>
<div>
The truth is that they've already been covered by "Module.type()" because, to the DI framework, they're just classes. The way to declare them differently is to use annotations.<br />
<br />
<a href="https://github.com/angular/angular.dart/blob/master/lib/core/filter.dart">Filters</a> use an "@NgFilter(name)" annotation, where the name is how they're named in the template, and expose a "call(input, params...)" method.</div>
<div>
<br /></div>
<div>
<a href="https://github.com/angular/angular.dart/blob/master/lib/core/directive.dart#L314">Controllers</a> use an "@NgController(selector, publishAs)" annotation, which is actually a subclass of the <a href="https://github.com/angular/angular.dart/blob/master/lib/core/directive.dart#L266">@NgDirective annotation class</a>. "selector" is a CSS selector which is used to apply the controller to the HTML view. And "publishAs" is the name that the controller instance can be referenced as from the template. Remember the "ng-controller='x as y'" syntax in AngularJS? same thing. Properties from the controller instance are exposed on the view, and any dependencies declared in the constructor are injected in, including <a href="https://github.com/angular/angular.dart/blob/master/lib/core/scope.dart">Scope</a> for creating watchers and generating events.</div>
<div>
<br /></div>
<div>
I already showed you a basic directive example, but there's a lot more to be learnt. If you want to go deeper, I suggest doing the same thing as for AngularJS: Look at <a href="https://github.com/angular/angular.dart/tree/master/lib/directive">the builtin directives</a>. I also suggest looking at <a href="https://github.com/angular/angular.dart/blob/master/lib/core/directive.dart">the classes for the annotations</a> too.<br />
There's lots of interesting things, like implementing "NgAttachAware" and "NgDetachAware" to run "attach()" and "detach()" methods when scopes are first created and destroyed.</div>
<div>
<br /></div>
<h3>
Components?</h3>
<div>
There is one new feature of AngularDart which I haven't covered which is a 'component'.<br />
AngularDart components are related to <a href="http://www.w3.org/TR/components-intro/">web-components</a> and make use of the <a href="http://w3c.github.io/webcomponents/spec/shadow/">Shadow DOM</a> feature in modern browsers; Two things which I am not completely familiar with. So I'm going to leave them alone for now rather than do them a disservice through my own ignorance.</div>
<div>
<br /></div>
<h2>
Final Thoughts</h2>
<div>
First, Dart. I'm so-so about Dart.<br />
On one hand, trying to replace JavaScript with something more up to date is a noble ambition.<br />
However Dart, and it's sponsor Google, have failed to win the rest of the web over. The popular vote is in improving Javascript, rather than outright replacing it, through new standards like ES6 and ES7.<br />
What's the best path? I can't say. But the writing on the wall tells me the support for Javascript is (strangely) growing, due in no small part to the success stories being heard about NodeJS.</div>
<div>
<br /></div>
<div>
As for AngularDart, the differences from AngularJS seem to depend on 2 main features: static typing with reflection, and annotations.<br />
ES6 will introduce classes, but there's no suggestion that there will be any optional type checking added to go with it. That means we can't just pass a class or function into the DI framework as they are (at least, not post-minification). We'll still need that separate list of injectable types, but instead of strings it should be possible to use classes.<br />
Annotations on the other hand aren't mentioned in any of the ES6 specifications at all. They're an entirely separate feature which just happens to be in Dart and supported by Traceur. So if AngularJS v2.* does use annotations, we're either going to be forced to use Traceur, regardless of the browser support for ES6, or we'll have to write them by hand:</div>
<br />
<script src="https://gist.github.com/rolaveric/9853590.js"></script>
<br />
<div>
Doing them by hand isn't so bad, but it does "kill the mood" some what. The idea is to improve the syntax, but ends up making it worse.<br />
<br />
Aside from those 2 worries, I'm quite keen to see what happens with AngularJS v2.*.<br />
Now to get those last few IE8 users to upgrade...</div>
<ul>
</ul>
Rolaverichttp://www.blogger.com/profile/07055170854302013537noreply@blogger.com0tag:blogger.com,1999:blog-6917086596782875672.post-62693790627583311632014-03-11T10:30:00.000+11:002015-03-07T14:32:15.301+11:00GopherJS: Go to Javascript Transpiler<style type="text/css">a:link {text-decoration: underline;}</style>
In my <a href="http://legacytotheedge.blogspot.com.au/2014/03/adventures-into-go-by-js-developer.html">last entry</a> I talked about the idea of migrating from a legacy platform to a modern platform by implementing the new platform as a reverse proxy. That way you can keep your existing platform active while gradually migrating over to the new platform with minimal risk; No need to maintain 2 code bases, and no need to keep your new code on the shelf collecting dust until you've finished porting everything else. Then I demonstrating how you can do this using Go.<br />
<br />
Amongst the feedback from the community (For which I say, thank you to everyone who read, shared, and commented. It was much appreciated. Let no one doubt how nice the online Go community is) was the question "What about your common libraries?". It's a good point. The reverse proxy solves the problem nicely when porting code route by route. But you're likely to have some common libraries shared across multiple routes. If you've only migrated some of those routes, you're going to be dual-maintaining both an old and a new version of that library until all your routes have been ported.<br />
<br />
Maybe that's okay. Maybe you're comfortable with the pace of your migration vs the need to make maintenance changes. But if you're not in that position, you can use a <a href="http://en.wikipedia.org/wiki/Source-to-source_compiler">transpiler</a> to convert your code from the new language back to the old one. For my situation of moving from Javascript to Go, that means using <a href="https://github.com/gopherjs/gopherjs">GopherJS</a>.<br />
<br />
<h2>
GopherJS</h2>
<div>
GopherJS transpiles Go source code to Javascript, which means you can get all the development and build time advantages of Go (eg. Static type checking, built in code coverage tool, etc.) and then run it in a Javascript library like NodeJS or the browser. The creator, <a href="https://plus.google.com/+RichardMusiol">Richard Musiol</a>, has even setup a <a href="http://gopherjs.github.io/playground/">GopherJS Playground</a> so you can give it a try online and immediately execute the code in your browser. You can even use <a href="http://angularjs.org/">AngularJS</a>. In fact, that's what the playground uses, along with an AngularJS wrapper library, <a href="https://github.com/gopherjs/go-angularjs">go-angularjs</a>.</div>
<div>
<br /></div>
<div>
Naturally, there are some limitations. Like you can't run anything anything that requires cgo or anything that needs low level access to the OS (unless you build an adapter for NodeJS). Even so, it's a pretty impressive <a href="https://github.com/gopherjs/gopherjs/blob/master/doc/packages.md">list of core packages which are compatible</a>. And don't let the lack of "net/http" or "database/sql" access scare you away - you can still use existing Javascript libraries to fill those gaps, and I'm going to show you how.<br />
<br />
Another thing you need to be aware of is that GopherJS produces Javascript suitable for an ECMAScript 5 (or ES5) compliant environment. So if you're building code for an older Javascript environment, like IE8 or <a href="http://en.wikipedia.org/wiki/Windows_Script_Host">Windows Host Script</a>, you're going to need shims for at least <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys">Object.keys()</a>, <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty">Object.defineProperty()</a>, <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames">Object.getOwnPropertyNames()</a>, and the various <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays">Typed Arrays</a>.<br />
<br />
And last, you need to be aware that it's not an all access border between Go and Javascript. If you want to pass a struct with methods from Go, you need to use "<a href="http://godoc.org/github.com/gopherjs/gopherjs/js#MakeWrapper">js.MakeWrapper()</a>" to make those methods safe. Similarly, you can't implement Go interfaces with Javascript objects. You'll need an intermediary that accesses the Javascript object as a "<a href="http://godoc.org/github.com/gopherjs/gopherjs/js#Object">*js.Object</a>".<br />
<br /></div>
<div>
<h3>
What does Go look like in Javascript?</h3>
</div>
<div>
<br /></div>
<div>
First I'm going to show you what Go code looks like as Javascript. We eventually want to take an existing Javascript library and convert it to Go, so we need to know what changes (if any) we should make to our code before porting it to Go.</div>
<div>
<br />
<script src="https://gist.github.com/rolaveric/9388326.js"></script>
You can see I've created a (rather contrived) Go package called 'pet' which defines a simple 'Pet' struct type, and a factory method called 'New()'. Since 'Pet' includes a method, 'New()' uses '<a href="http://godoc.org/github.com/gopherjs/gopherjs/js#MakeWrapper">js.MakeWrapper()</a>' to make the methods safe to use in Javascript. Then in 'main' I'm importing 'pet' and the 'github.com/gopherjs/gopherjs/js' package, which gives me access to Javascript context objects like the global scope. So I attach the 'New()' factory under the namespace 'pet'.<br />
<br />
<a href="https://gist.github.com/rolaveric/9407509">Here's the result when built with GopherJS</a>.<br />
<br />
1470 LOC and 45kb, uncompressed and unminified. The bulk of which is the builtin library.<br />
It will only compile what it needs to. So if you declare types that are never used, they won't show up in the resulting code. This goes for core packages too. If I change that code so it requires "fmt", the result explodes to 12845 LOC and 624kb ("fmt" imports a LOT of stuff).<br />
<br />
Lets take a look at what the code we wrote looks like:</div>
<div>
<br />
<script src="https://gist.github.com/rolaveric/9407725.js"></script>
You can easily recognise the "pet" package from lines 10-36 in that extract. I wouldn't get too worried about what it's doing there. The important thing is that it's there.<br />
<br />
One thing I will draw your attention to is our main method, specifically line 41.<br />
It's creating a map and setting the value of "New" to the function "pet.New()". It's then passing that to "go$externalize" which is a helper method GopherJS uses for turning Go types into primitive Javascript types. Take maps as an example. In Javascript, map keys can only be strings. But in Go, they can be anything. So GopherJS uses it's own special "Go$Map()" type internally, and then tries to convert it to a standard Javascript object when passed to "go$externalize".<br />
<br />
Then it's assigning our externalised map to "go$global.pet". "go$global" is an internal variable for referencing the global scope object in Javascript. You can see it being declared on line 2. If used in a browser, it will be equivalent to "window". Otherwise, it's whatever the "GLOBAL" variable currently is. If you're using a Javascript runtime that doesn't include either of these, you'll need to manually declare "GLOBAL" yourself.</div>
<br />
<h3>
Porting a Javascript library to Go</h3>
<div>
<br /></div>
<div>
Now we've got an idea of what our Go code will look like when it's converted to Javascript, we can start thinking about how we're going to port a part of our Javascript code to Go without breaking the rest of our Javascript code.<br />
<br />
Lets say we've got a 'User' model object which uses the global variable 'DB' to make SQL database calls:</div>
<div>
<br />
<script src="https://gist.github.com/rolaveric/9410549.js"></script>
Couple of things we know will be different when we convert this to Go.
<br />
<br />
<ol>
<li>The method names will start with an uppercase letter, otherwise they won't be exported.<br />This isn't idiomatic for Javascript, but that's OK because we're not writing Javacript. We're writing Go that runs as Javascript.</li>
<li>DB will need to be an interface, with a new function for registering a DB implementation.<br />That way we can switch implementations for Go and Javascript.</li>
<li>In Go, "User" will be a type of struct, not a type of function.<br />And while we can create methods for type instances, we can't create static methods like "User.new()". They'll need to go into the package namespace.</li>
<li>While it's possible to wraps all "User" objects with "<a href="http://godoc.org/github.com/gopherjs/gopherjs/js#MakeWrapper">js.MakeWrapper()</a>" so we can access "user.Save()", that means we also have to create getters and setter for the regular properties. Rather than add the extra boilerplate, "Save()" will be moved to the package namespace and take the "user" as a parameter.</li>
</ol>
<br />
With that in mind, here's what the refactored API looks like:</div>
<div>
<br />
<script src="https://gist.github.com/rolaveric/9463376.js"></script>
The main difference is the addition of the "registerDB()" method for registering a DB interface implementation, rather than finding it on the global scope.<br />
<br />
Now to the Go code:<br />
<br /></div>
<div>
<script src="https://gist.github.com/rolaveric/9463958.js"></script>
The "Save()" method required a "SaveJS()" wrapper to bridge the JS <-> Go barrier for the "user" object, and "RegisterDBJS()" does the same for the database adapter. You can find the full working code examples at: <a href="https://github.com/rolaveric/gopherjs-demo">https://github.com/rolaveric/gopherjs-demo</a><br />
<br />
There you have it: A Javascript library written in Go with only a little tweaking to the original API.<br />
And without compromising on the quality of our Go code either.<br />
<br /></div>
<h2>
Conclusion</h2>
<div>
GopherJS bridges that gap between Go and Javascript quite nicely without compromising on quality.<br />
There is a cost in the size of the generating code, but lets remember just how little is provided by Javascript's standard library compared to <a href="http://golang.org/pkg/">Go's core library</a>. And once you get past that initial bootstrap, there's definitely no issue with <a href="http://ajhager.github.io/enj/">performance</a>.<br />
<br />
So if you're looking for a way to port away from Javascript to Go without dual-maintaining libraries, or if you're so enamoured with Go that you can't bare to write Javascript even for the browser, then GopherJS is for you.<br />
<br /></div>
<div>
<strong>UPDATE:</strong> GopherJS has matured since I originally wrote this article. So with <a href="https://plus.google.com/+RichardMusiol">Richard Musiol</a>'s help, I've updated the examples to be more conscious of the Go <-> JS barriers. I've also created a <a href="https://github.com/rolaveric/gopherjs-demo">github repo with the examples</a> so they can be tested from end to end.</div>
Rolaverichttp://www.blogger.com/profile/07055170854302013537noreply@blogger.com0tag:blogger.com,1999:blog-6917086596782875672.post-67935515508889286732014-03-02T19:15:00.000+11:002014-03-13T16:47:10.514+11:00Wading into GoI first took notice of Go last year when I read <a href="http://blog.iron.io/2013/03/how-we-went-from-30-servers-to-2-go.html">this article</a> about how Iron.io went from 30 servers down to 2 by converting from Ruby to Go. Since then I keep peeking back at it, reading a bit more doco here, trying out the tour, and eventually attending the <a href="http://www.meetup.com/golang-syd/">local Go meetups</a>. There I finally got my burst of inspiration to build a proof of concept for replacing an old enterprise backend I work with, built on Classic ASP, with Go.<br />
<br />
The experience was quite fascinating for me because my primary language is Javascript, and my experience with modern server-side web frameworks is pretty shallow. For example, the way I keep thinking of pointers vs values in Go is the same way I think of objects vs strings in Javascript. The former is mutable, meaning it's possible to get side effects when it gets passed around, and the later is immutable. It probably oversimplifies the difference, but it works for me.<br />
<h2>
The Plan</h2>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://cdn.memegenerator.net/instances/500x/46296704.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://cdn.memegenerator.net/instances/500x/46296704.jpg" height="240" width="320" /></a></div>
<div>
OK. We're porting a legacy web application to a new platform. What's the plan?<br />
<br />
It'd be naive to say "X is better than Y, therefore we shall port all our Y to X immediately!" and leave it at that. There's other questions we need to answer:<br />
<br />
<ul>
<li>How long will it take?</li>
<li>What does all the X you've written do while you're still dependant on Y?</li>
<li>What if there's just some things that Y can do which X can't (yet)?</li>
</ul>
<br />
The answers should be:<br />
<br />
<ul>
<li>"A long time" cause that's the truth</li>
<li>"It gets used in production" because code has no value until it's used, and</li>
<li>"Then you keep using Y for those things" because, as they say, "you don't throw out the baby with the bath water".</li>
</ul>
</div>
<div>
The plan is to use the new technology as a reverse proxy which, initially, takes all requests and forwards them on to your legacy back end. Then, over time, you start porting features from the legacy platform to the new one. If something goes wrong, you can turn off that route handler and let the legacy platform pick it up again.</div>
<div>
<br /></div>
<div>
Doing this in Go is trivial. The core library already comes with a simple reverse proxy that suits our needs:<br />
<br /></div>
<script src="https://gist.github.com/rolaveric/9167845.js"></script>
<br />
<h2>
The Martini Web Framework</h2>
<div>
While the Go core library is very complete, especially for the building of web applications, there is still plenty of room to build libraries on top. For example, while Go comes with the "testing" library and the "go test" and "go cover" commands, there's space for third-party libraries to define their own DSLs for writing tests, such as <a href="http://goconvey.co/">GoConvey</a>. In the same vein, there's plenty room for different web frameworks to implement different opinions and architectures. My personal favourite is <a href="http://martini.codegangsta.io/">Martini</a>.<br />
<br />
Martini is a micro-framework, similar to Sinatra and Express. It doesn't give you bells and whistles to plug into your application (well, <a href="https://github.com/martini-contrib">not out of the box</a>), but it does give you a simple way to define chains of request handlers (like filters, if you're coming from Java servlets) and pass values to handlers through dependency injection.<br />
<br />
You can have common handlers, called middleware, which run against every request, and handlers for routes. So you can have a common Authentication handler that identifies the user for every request, and then specific Authorization handlers for different routes that make sure the user has the required access before running the final handler. Here's an example:<br />
<br /></div>
<script src="https://gist.github.com/rolaveric/9169716.js"></script>
<br />
<div>
Here's what a request to this code looks like, with the flow of control through the request and response:<br />
<br />
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQywrxOZcfstPBX2BLAVYxZZV6OHkKqzXb5F8nlAaKJOk2fQw5GAlSFmBq9Z7JOL3XuFDkPqqYi4aAfPxaPkeLLQ0a5ubuPJXrx89oFFPi6GAU0r9dS22QCrZYS7w5xLogM4P7C60ZT5c/s1600/martiniRequest.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQywrxOZcfstPBX2BLAVYxZZV6OHkKqzXb5F8nlAaKJOk2fQw5GAlSFmBq9Z7JOL3XuFDkPqqYi4aAfPxaPkeLLQ0a5ubuPJXrx89oFFPi6GAU0r9dS22QCrZYS7w5xLogM4P7C60ZT5c/s1600/martiniRequest.png" height="320" width="243" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
But how does the Authorization handler know what the result of the Authentication handler was? That's where Martini's dependency injection comes into play.<br />
<br />
It uses Go's <a href="http://golang.org/pkg/reflect/">reflect package</a> to determine what types a handler is expecting as parameters. By default it knows about the http.Request and *http.ResponseWriter objects, which is why Martini also works with any handlers designed for <a href="https://www.blogger.com/"><span id="goog_312342523"></span>http.HandleFunc()<span id="goog_312342524"></span></a>.<br />
<br />
You can add your own injectables or <a href="https://github.com/codegangsta/martini#services">services</a> by calling the MapTo() method on the martini.Context (Another default injectable) for the request. MapTo() takes a variable and the type that it should be injected for. You can also use this to wrap existing services, as Martini does with <a href="https://github.com/codegangsta/martini#mapping-values-to-interfaces">the *http.ResponseWriter</a>.<br />
<br /></div>
<h2>
Impressions of Go</h2>
<div>
Now that you've got an idea of what I've been working on, here's some of the impressions that Go made on me.</div>
<br />
<h3>
A well stocked box of goodies</h3>
<br />
<div>
Out of the box, Go comes with a standard library to be proud of. Take for example the fact that it comes with a simple reverse web proxy, ready to go. It also comes with a set of packages for compression, including gzip, and 11 different packages for encoding, including JSON, XML, and Base64. Normally I'd expect to go to third-party libraries or roll my own for at least a few of these. Not in Go.<br />
<br />
And let's not forget the 'go' command line tool itself, which can:</div>
<div>
<ul>
<li>Build</li>
<li>Test</li>
<li><a href="http://golang.org/pkg/testing/#hdr-Benchmarks">Benchmark</a></li>
<li>Calculate code coverage from tests</li>
<li>Format code</li>
<li>Fix code written for older versions of Go</li>
<li>Host a web server for serving code documentation</li>
<li>and retrieve dependant packages from Git and Mercurial repositories</li>
</ul>
<div>
The convention of using the repository domain as the package namespace is a great idea which keeps dependency management nice and simple. The only drawback I've heard is that it doesn't support the ability to set specific revisions as a dependency, which will make it awkward if a third-party package introduces non-backwards compatible changes. But there are <a href="http://www.goinggo.net/2013/10/manage-dependencies-with-godep.html">examples</a> of the community stepping up to fill the gap.</div>
<div>
<br /></div>
<div>
Another favourite feature of mine is "<span style="font-family: inherit;">go fmt"</span>, and the way the formatting conventions are enforced by the compiler. I am tired of arguments over code formatting, and I'm glad that the creators of Go have cut those arguments off at the knees, saying "This is how it is - deal with it. Now, back to the show!".</div>
<br />
<h3>
Third-party support isn't perfect, yet</h3>
<br />
<div>
I had one third-party technology requirement for my Go program; It had to support MS SQL, because that's what the legacy platform was using for persistence.<br />
<br />
go-wiki's list of <a href="https://code.google.com/p/go-wiki/wiki/SQLDrivers">supported SQL drivers</a> included an <a href="https://code.google.com/p/odbc/">ODBC driver</a> which is cross-platform, using Free TDS for Mac and Linux, so I thought this wouldn't be a problem. Sure enough, when I first tested it on Windows, everything seemed fine. Then I did some benchmarks and realised every stored procedure call was taking a lot longer than it should. When I tried the same calls with an <a href="https://github.com/mattn/go-adodb">ADODB driver</a> (which I didn't want to use because it only works on Windows), I was getting much better speeds.<br />
<br />
I haven't exhausted all my options yet to fix the issue yet. For example I've only tested it on Windows, and I haven't explored whether connection pooling will help (I'm currently opening and closing a connection on each query). But it's an unhealthy reminder that there's likely to be issues like this when moving from legacy platforms to something new like Go. If I were using <a href="https://github.com/lib/pq">Postgres</a> or a NoSQL database, there'd be no problem. But I'm not, and so there is.</div>
<br />
<h3>
Types: The good, the bad, and the "what the?"</h3>
<br /></div>
<div>
Go uses strict typing, which can be a bit of a shock coming from a dynamic typing language like Javascript. Most of the time it makes perfect sense and you wouldn't have it any other way. Here's a few common examples:<br />
<br />
The simplest example possible - a function that expects a number rather than, say, a string.<br />
<br />
<script src="https://gist.github.com/rolaveric/9302936.js"></script>
Unlike Java but similar to Scala, Go treats functions as first class. This means you can pass functions as parameters to other functions, and return them as results. But you don't want just any old function, you want one which matches your callback schema: message string as a parameter, and an error (if any) as the result.<br />
<br />
<script src="https://gist.github.com/rolaveric/9302960.js"></script>
One thing that's unique to Go is the way it handles interfaces. They're implemented implicitly. So an interface becomes a way of saying "I need 'something' which can do X" rather than "I need a Y, which is 'something' that can do X". Anything can say "I can do X" will be accepted, and can be declared without even know what a "Y" is.<br />
<br />
<script src="https://gist.github.com/rolaveric/9303031.js"></script>
Interfaces also give us a way to cheat the typing system entirely. An empty interface can be implemented by anything. So if we have a function which expects an empty interface, we can pass anything to it. Or we can have a slice (Equivalent of a Javascript Array) of empty interfaces, which can store anything. But that just means we need to use type assertions when we try to do something with that value, otherwise we could end up trying to get the substring of a number.<br />
<br />
<script src="https://gist.github.com/rolaveric/9303148.js"></script>
Here's an example which did my head in a bit at first.<br />
The <a href="http://golang.org/pkg/database/sql/#Rows.Scan">Rows.Scan()</a> method in the database/sql package expects a slice of empty interfaces, which are the destination for the values found in the current row. Empty interfaces can be anything, right? So a slice of empty interfaces can contain anything. That makes sense because you could have numbers, strings, dates, etc. all returned in the same row.<br />
<br />
The SQL driver I'm currently using returns everything as strings. So I thought "OK, I can just pass in a slice of strings. Strings can be empty interfaces, so therefore a slice of strings can be a slice of empty interfaces, right?<br />
<br />
Wrong.<br />
<br />
It's not the containers that can be anything, it's the contents. A container for strings and a container for anything are two different things; If I ask for one, I don't expect the other.<br />
In this example of Rows.Scan(), you can get around it by loading a slice of empty interfaces with the pointers from a slice of strings.<br />
<br />
<script src="https://gist.github.com/rolaveric/9303240.js"></script>
Thankfully this example is the exception, not the rule. And it demonstrates that if the typing system does start to restrict you, there are ways to bend it to your will. But it's always better to discover a problem at compile time than run time.</div>
<br />
<h3>
New language insecurity</h3>
<br />
<div>
This isn't really related to Go, it just happened to be the unknown language that I was trying.<br />
<br />
I found that doing things in Go took 3-4 times longer than it would have done in Javascript. When working on something in Javascript I would simply plan it out, and then implement it. In Go I would plan it out, implement half of it, then go back to the plan, then start implementing from scratch, then back to the plan, then redo the original implementation.<br />
<br />
This isn't because there's anything wrong with Go or right with Javascript. It's because I'm experienced with Javascript and inexperienced with Go. Experience doesn't just bring competence, it also brings confidence. When I was restarting my work in Go, it's not that it wasn't working, it's that I would start second guessing the design. "Should that have been a type? Or maybe an interface? Maybe I should just split these into separate packages... or, maybe less packages?".<br />
<br />
Sometimes you need to put your head down and say "If it compiles and my tests pass, that's good enough for me!". You can always comes back to it later when you've: a) Got a more experienced Go developer to critique your work, or b) enough hours reading other people's Go code to form your own opinions.<br />
<br /></div>
<h2>
Conclusion</h2>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
Coming from Javascript world, Go is an intriguing place that I'd like to get to know better. The core library is very complete and powerful, though somewhat dry at times. But this allows the community to build on top of it with their own opinions, like how Martini builds on top of net/http, or <a href="http://goconvey.co/">GoConvey</a> on top of testing.<br />
<br />
If you're interested in Go but haven't found the excuse to give it a try, my advice is: Find that excuse. Rewrite something, anything, just to get a taste for it. If people at your company are dismissive of the idea, then practices a little "<a href="http://www.youtube.com/watch?v=r1A1VR0ibIQ&feature=youtu.be&t=6m40s">Constructive Disobedience</a>" and do it anyway. "You decide your own level of involvement".</div>
Rolaverichttp://www.blogger.com/profile/07055170854302013537noreply@blogger.com0tag:blogger.com,1999:blog-6917086596782875672.post-38038719330212682862014-02-05T10:37:00.000+11:002014-03-11T16:31:18.257+11:00Unit Testing AngularJSIt's not always obvious how to write automated tests for the different components in AngularJS, so I'd like to share some of my techniques for testing AngularJS applications.<br />
<br />
<h2>
Automated Testing Stack</h2>
<div>
If you've got absolutely no automated testing setup at all, then I recommend looking at using one of the following to give you some scaffolding: <a href="https://github.com/angular/angular-seed">angular-seed</a>, <a href="http://yeoman.io/">Yeoman</a>, or <a href="https://github.com/joshdmiller/ng-boilerplate">ng-boilerplate</a>.</div>
<div>
<br /></div>
<div>
Here's a quick overview of each piece of the unit testing stack.<br />
<br /></div>
<h3>
Karma: The Test Runner</h3>
<div>
<a href="http://karma-runner.github.io/">Karma</a> does the work of starting our browser(s), running the tests, and reporting the results in whatever format we desire. It can also handle pre-processing code for doing things like compiling CoffeeScript or injecting Code Coverage markers.<br />
<br /></div>
<h3>
Jasmine: The Test Framework</h3>
<div>
We need a format to write our tests in. The default one used by the AngularJS community, and what I'll be writing the rest of this article with, is <a href="http://pivotal.github.io/jasmine/">Jasmine</a>. It uses a BDD (Behaviour Driven Development) style, which essentially means it tries to make your tests read like business specifications that an analyst could understand.</div>
<div>
Here's a quick example of a Jasmine test:</div>
<br />
<script src="https://gist.github.com/rolaveric/8639955.js"></script>
<br />
<div>
The "describe()" method is used to group tests. The "it()" method is the specification: a descriptive string for the spec, and a function for testing that spec. The "expect(value).toSomething()" is an assertion. You pass a value to "expect()" and then you run what's called a 'matcher' method against it. You can also run setup and teardown code using "beforeEach()" and "afterEach()" methods.</div>
<div>
Karma has an <a href="https://github.com/karma-runner/karma-jasmine">adapter</a> for interpreting the results from Jasmine, which it can then feed into various reporters. So if Jasmine isn't your poison, chances are there's an adapter out there for <a href="https://github.com/karma-runner/karma-mocha">whatever</a> <a href="https://github.com/karma-runner/karma-qunit">testing</a> <a href="https://github.com/karma-runner/karma-nodeunit">framework</a> <a href="https://github.com/karma-runner/karma-tyrtle">you</a> prefer.<br />
<br /></div>
<h3>
ng-mocks: The Helper Library</h3>
<div>
If you've ever downloaded <a href="http://code.angularjs.org/1.0.7/">AngularJS as an archive</a>, you may have spotted the angular-mocks.js file. This contains the <a href="http://docs.angularjs.org/api/ngMock">ngMock module</a>, which provides a set of helper functions to make your testing life easier. Particular the inject() method which you can pass a function with injectable parameters (eg. Services), and it will handle all the dependency injection for you.<br />
<br /></div>
<h2>
Services</h2>
<div>
Alright. Down to the actual testing.<br />
I'm going to start with the simplest example. This will work for anything produced with "module.value()", "module.constant()", "module.factory()", or "module.service()".</div>
<br />
<script src="https://gist.github.com/rolaveric/8639981.js"></script>
<br />
<div>
The relevant parts for AngularJS developers is "module()" and "inject()".</div>
<div>
<br /></div>
<div>
The best way to think of the "module()" function is that it's doing the same job as the "ng-app" directive - it bootstraps that module so you can inject it's components. The great thing is that the scope for that module only lasts for a single test. So changes you make in one test won't have an effect on the next test.</div>
<div>
<br /></div>
<div>
The "inject()" method hooks into Angular's dependency injector. So you can pass it a function with your dependencies, and it will handle their injection for you. Although it won't work if the module those components belong to has not been loaded yet by "module()".</div>
<div>
<br /></div>
<div>
Here's a more verbose example; a pattern which I often use myself:</div>
<br />
<script src="https://gist.github.com/rolaveric/8640009.js"></script>
<br />
<h3>
Handling Dependencies</h3>
<div>
I try not to make any function calls in my service constructor. This makes things simpler if, for example, I depend upon another service which I want to mock during testing (It is called "unit" testing for a reason). Lets say "myService.myMethod()" called "anotherService.anotherMethod()". Rather than test what "anotherMethod()" does within the test for "myMethod()", I just want to confirm that it gets called. I can do this by getting an instance of "anotherService", using "inject()", and replace "anotherMethod()" with a spy which tracks if and how it gets called:</div>
<br />
<script src="https://gist.github.com/rolaveric/8640024.js"></script>
<br />
<div>
If "myService" was using a method from "anotherService" in it's constructor, that would make things trickier, but not impossible, to test. Services are constructed only when they're first injected (no point constructing something that's not even being used). So the trick is to inject "anotherService" first, set up your spy, then inject "myService".</div>
<br />
<script src="https://gist.github.com/rolaveric/8640143.js"></script>
<br />
<div>
You couldn't do this if your constructor was calling one of it's own methods (eg. "myService.init()"). So when you're writing a complex constructor for a service, or controller, you really need to sit back and think "How am I going to test this?".</div>
<h2>
Filters</h2>
<div>
Filters are just functions. The key to testing them is to get yourself a reference to those functions. This is simple with "inject()". You should set a parameter with the name of your filter with the suffix "Filter". Here's an example:</div>
<br />
<script src="https://gist.github.com/rolaveric/8640158.js"></script>
<br />
<div>
Alternatively you can use the "$filter()" function, like so:</div>
<br />
<script src="https://gist.github.com/rolaveric/8640171.js"></script>
<br />
<h2>
Controllers</h2>
<div>
Now we're getting somewhere interesting. Controllers are different to services in that their dependencies aren't just services - they can be "resolve" values, such as "$scope". On top of that, not all controllers just attach properties to "$scope". Some will attach properties to themselves through "this". 2 examples are using controllers for <a href="http://www.egghead.io/video/rzMrBIVuxgM">directive to directive communication</a>, and the new 'ng-controller="MyCtrl as scope"' optional syntax for controllers being introduced in AngularJS v1.2<br />
<br />
So we need a way to inject specific dependencies into our controller, and then we (may) need a reference to the instance of that controller function. The way to achieve this is to use the <a href="http://docs.angularjs.org/api/ng.$controller">$controller service</a>:</div>
<br />
<script src="https://gist.github.com/rolaveric/8640192.js"></script>
<br />
<div>
That works if you're not doing much with the $scope except for attaching properties. But what if I'm using some of the built in functionality for scopes like "$watch", "$on()", "$broadcast()", or "$emit()"? You <i>could</i> create spies to mock all these things. I personally like to use a real $scope object. So how do I get one? Inject "$rootScope" and call "$new()" on it:</div>
<br />
<script src="https://gist.github.com/rolaveric/8640200.js"></script>
<br />
<div>
Here's my template for controller tests:</div>
<br />
<script src="https://gist.github.com/rolaveric/8640211.js"></script>
<br />
<h2>
Directives</h2>
<div>
The key to testing directives is to use the <a href="http://docs.angularjs.org/api/ng.$compile">$compile</a> service to compile a DOM element which includes your directive. $compile will trigger your directive's code, and you can then start querying the DOM element and scope to test it's behaviour.<br />
Here's a simplified version of the ng-hide directive (Similar to the original, but without $animate support):</div>
<br />
<script src="https://gist.github.com/rolaveric/8813637.js"></script>
<br />
<div>
To test it, we need to compile the directive, and then test how the element reacts when we change the scope or trigger use actions.<br />
Here's a test taken straight from the <a href="https://github.com/angular/angular.js/blob/master/test/ng/directive/ngShowHideSpec.js">AngularJS source code</a> (The best source for writing and testing directives):</div>
<br />
<script src="https://gist.github.com/rolaveric/8813721.js"></script>
<br />
<div>
Walking through it, first it uses jqLite/jQuery to create a DOM element with the directive.<br />
Then it passes the element to the $compile service, along with a scope object (in this case $rootScope), which runs the code for any directives it finds.<br />
Then it tests that the element is still visible, since "exp" is undefined and therefore falsy.<br />
Then it sets "exp" to "true", triggers the digest loop so that the $watch gets run, and then tests that the element is now hidden.<br />
<br />
Most of your directive tests are going to follow this pattern some how:<br />
<ol>
<li>Create a DOM element with your directive.</li>
<li>Pass it to $compile(), along with a scope object.</li>
<li>Change the scope.</li>
<li>Query the DOM for changes.</li>
</ol>
</div>
<h2>
Providers</h2>
<div>
A provider is really no different from a service, except that it requires a special "$get()" method for "providing" the dependency, and it can exist during the "config" phase of AngularJS' lifecycle.<br />
The trick is getting a reference to the provider in pristine condition (ie. Before "$get()" is called). The way you do this is using the "module()" helper function, provided by ng-mocks:</div>
<br />
<script src="https://gist.github.com/rolaveric/8814223.js"></script>
<div>
In this scenario we have a provider called "myServiceProvider", which belongs to module "myModule".<br />We use the "module()" function to instantiate "myModule", and then get a reference to "myServiceProvider".<br />However, calling "module()" alone is not enough. It doesn't actually do anything until "inject()" is called. So we just call "inject()" with no dependencies, meaning "myServiceProvider.$get()" has still not been called.<br />
<h2>
Conclusion</h2>
</div>
<div>
AngularJS has been built from the ground up with testing in mind, but it's not always immediately obvious to new comers as to how they might test a particular component.<br />But once you know the trick, the pattern to adopt and the services to call, there's nothing to stop you writing a suite of tests you can rely on.<br />Then library upgrades become a trivial matter of: drop in the new version, run the tests, and fix any failures. I couldn't use the weekly AngularJS builds without it.</div>
Rolaverichttp://www.blogger.com/profile/07055170854302013537noreply@blogger.com0tag:blogger.com,1999:blog-6917086596782875672.post-6776596468640616232014-01-22T09:32:00.000+11:002015-10-10T10:18:43.183+11:005 Reasons to use AngularJS<strong>Post republished to <a href="https://legacy-to-the-edge.com/5-reasons-to-use-angularjs/">https://legacy-to-the-edge.com/5-reasons-to-use-angularjs/</a></strong><br/>
<br/>
I've been using AngularJS for about a year now, and I think it's safe to say that it's one of the best things to happen to me as a web developer. It's made UI development faster, safer (ie. testable), and more enjoyable for me then ever before. And by studying it's source code and taking up it's techniques and philosophies, it's made me a better programmer outside of AngularJS too.<br />
<br />
If you haven't heard of AngularJS, go to <a href="http://www.angularjs.org/">their home page</a> right now, read through the blurbs, have a quick toy with the demos, then come back. If you're not sold on it already, read on and I'll tip the scales for you with 5 reasons to start using AngularJS for all your web development work - especially if you're working with a legacy system.<br />
<br />
<h3>
1. Less work for the same result</h3>
<div>
The story behind how AngularJS went from a hobby project developed solely by <a class="g-profile" href="https://plus.google.com/112540226618013533507" target="_blank">+Miško Hevery</a> to being a Google sponsored open source project is that Misko went to his manager, <a class="g-profile" href="https://plus.google.com/112439678898563138768" target="_blank">+Brad Green</a>, and said "You know, I bet I could rewrite our current project in Angular in 2 weeks.". It took 3 weeks and the lines of code went <a href="http://youtu.be/HCR7i5F5L8c?t=4m8s">from 17,000 to 1,500</a>.</div>
<div>
<br /></div>
<div>
The key behind such a massive reduction in code is AngularJS's declarative approach to data-binding on the UI. Lets start with a simple example. I want a text input to update the message in another part of the DOM. Here's how I might do it:<br />
<br /></div>
<br />
<script src="https://gist.github.com/rolaveric/8640249.js"></script>
Now compare to the same thing done in AngularJS:<br />
<br />
<script src="https://gist.github.com/rolaveric/8640258.js"></script>
Done.<br />
I have simply declared "Here's my application, here's an input that binds to 'message', and here's somewhere to output 'message'."<br />
The "How" is left entirely to the directives to determine.<br />
<br />
It's a contrived example, but it demonstrates the advantage of a declarative approach: Stating the "What?" and then letting the framework handle the "How?".<br />
<br />
The same can be said for dependency injection. When I'm writing a controller, I don't tell it where and how to get the '$log' service. I just declare "I need the service called '$log'".<br />
<br />
<h3>
2. It thins out your server-side code</h3>
<div>
Angular takes care of templating and routing your views, which is generally a non-trivial chunk of your server-side processing and code maintenance. You can entirely decouple your client application, leaving the server to serve and consume JSON data.<br />
<br />
This provides a great opportunity if you've been thinking of switching or experimenting with different backends. Lets say your backend is written in Ruby on Rails, but you're interested to see how it would perform with Groovy on Grails instead. You can write your front-end in Angular with a RESTful server API, then swap out your backend with something that serves that same API. It's no small thing to rewrite a whole back-end, but it's a hell of a lot easier when you don't need to worry about the UI.<br />
<br /></div>
<h3>
3. Testing is trivial</h3>
<div>
AngularJS was written from the ground up to be testable. Dependency injections lets you slip in mock versions to work with. Directives can be triggered by using $compile on HTML strings. HTTP responses can be imitated with a mock $httpBackend service. And all of this without actually attaching anything to the DOM, meaning your tests run lightning fast.</div>
<div>
<br /></div>
<div>
The barriers to testing AngularJS applications are only as high as you choose to make them. You're writing less code, so you have the time to write tests from the start. Sometimes you may feel that writing your mocks takes so much effort that it's impractical. That's a sign that either you need to take a closer look at the <a href="http://pivotal.github.io/jasmine/#section-Spies">documentation for Jasmine 'spies'</a>, or you need to rethink your design ("Why does this single unit of code need so much 'stuff'?")<br />
<br />
<h3>
4. Your user experience is more responsive</h3>
</div>
<div>
You don't always notice just how much time is taken changing from one page to another, on the web. Sometimes that's to be expected, such as when moving from a completely different 'site' to another. But when you're moving from one page to another, within the same site, with almost the exact same headers and footers, CSS includes and Javascript libraries, it should only take as long as is required to load the HTML which has changed.</div>
<div>
<br /></div>
<div>
With a SPA (Single Page Application), like Gmail, you have some initial load time on your first visit, but then content changes within that application are near instantaneous. You can manage this easily with AngularJS's built in URL routing and ng-view directive. And if that's not sophisticated enough for your needs, you can use <a href="https://github.com/angular-ui/ui-router">ui-router</a> to define your application in terms of a state machine with nested views.<br />
<br /></div>
<h3>
5. Great community</h3>
<div>
Last, but far from least, is the AngularJS community. There's no shortage of resources for learning Angular (eg. <a href="http://www.egghead.io/">egghead.io</a>, <a href="http://www.yearofmoo.com/">yearofmoo</a>), places to ask questions or just 'stay in the loop' (eg. <a href="https://groups.google.com/forum/#!forum/angular">Google Groups</a>, <a href="https://plus.google.com/communities/115368820700870330756">G+ Commmunity</a>, <a href="http://webchat.freenode.net/?channels=angularjs&uio=d4">IRC Channel</a>, <a href="http://www.meetup.com/find/?keywords=AngularJS">Meetups</a>), and open source projects for improving Angular development (eg. <a href="http://angular-ui.github.io/">Angular UI</a>, <a href="https://github.com/yeoman/generator-angular">Yeoman generator</a>, <a href="http://joshdmiller.github.io/ng-boilerplate/#/home">ng-boilerplate</a>). Everyone I've interacted with in the community has been helpful and constructive with their criticisms. Angular would not be seeing the success it has without such positive community contributions.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
If that hasn't convinced you - power to you, you must have a damn nice set up already.<br />
If your curiosity is piqued, but you still have concerns, visit the <a href="https://plus.google.com/communities/115368820700870330756">G+ Community</a> or <a href="http://webchat.freenode.net/?channels=angularjs&uio=d4">IRC channel</a>.</div>
<div>
<br /></div>
<div>
Cheers,</div>
<div>
Jason Stone</div>Rolaverichttp://www.blogger.com/profile/07055170854302013537noreply@blogger.com0