Logo

Who is talking?

Archive

Space Invaders in JavaScript

almost 4 years ago | Dave Kerr: dwmkerr.com

If you take a look at the Experiments Page you'll see that there's a new entry - Space Invaders. spaceinvaders Space Invaders is a great little game to code if you're learning a new language or technology (and JavaScript is still very much in that category for me). I'll be writing up how I made the game on the CodeProject soon enough (if you're interested you can see how I made the starfield background in JavaScript). You can check back periodically - the game is nearly done and more than ready to play with. The code is available as well, either just get it from the browser or check Space Invaders on GitHub. I'll post when it's done and the next experiment starts!

Use of Operations Research to plan optimal capacity for a Kanban team

almost 4 years ago | Lalatendu Das: Interpretations of technorealism

Imagine you are responsible for setting up a new Kanban team to develop a piece of software. You have the following contextual background while forming the teamRequirements are progressively elaborated and you expect on an average 3 new feature requests per day adding to the "To Do" listNew requirements are likely to follow a Poisson distribution. ~ Pois(3) Since new feature arrival follows a Poisson distribution, naturally the inter-arrival time will follow an exponential distributionThe feature development distribution would mimic the inter arrival time and follow an exponential distribution as well (i.e in Kanban model, you move the card from "To Do" to "in progress" as soon as you are free to take up the card)You have flexibility to change the team staffing to increase or decrease the average service timeProblem Statement:What is the optimal feature development "capacity" you should plan for to minimize the time between a feature arriving in "To Do" list and moving on to "In Progress" list (i.e. The "Wait time" for a feature). Solution - 1:The following points are evident through application of common sense / gut feelThe minimum capacity should be an avg 3 features per day ( same as "feature arrival rate"), otherwise the "To Do" list (or backlog) will grow on to inifinityThere is cost associated with increasing capacity. We need to make a trade off between minimizing the wait time in "To Do" bucket and limiting the cost development to an acceptable levelMay be we can pick a capacity anywhere between 5 or 6 features per daySolution -2: Application of Operations Research \ Queuing ModelsThe above scenario reflects an M/M/1 queue model. i.eArrival rate follows Poisson distributionservice rate (= Feature development rate in our case) follows exponential distributionSingle server (one Kanban team in this case)average wait time in an M/M/1 queue (refer to this paper)                                                                 = (Arrival rate)/ service rate * (service rate - arrival rate)in our case, arrival rate is = 3 features per day. We have option to vary the service rate (= # how many features can be developed in a day) by changing the team staffing. Given below is a plot of the Wait time as a function of service rate (= feature development rate)The following points can be inferred from the above plotWe must plan for capacity to develop >3 features per day, otherwise the wait time in "To Do" list can grow for everHaving a capacity to develop higher than 7 features per day gives diminishing returns. Having a capacity to develop 7 features may just be good enoughTo Summarize, most of the functional managers, team leaders use their gut feel (Solution #1 above) to do capacity planning. In most of the situation, the gut feel gives us good enough results. However there are certain critical situations where the business impact is so high that we require a more scientific approach to base our decisions. As we demonstrated above in solution #2, the appropriate Queuing model can be applied to make more informed decisions. 

Introducing Experiments

almost 4 years ago | Dave Kerr: dwmkerr.com

I'm staring a series of articles on learning Javascript (the first is available at http://www.codeproject.com/Articles/642499/Learn-JavaScript-Part-1-Create-a-Starfield). To help with this, I've created the Experiments page. This page will host each of the things I've been playing with in the process of learning JavaScript and coming up with good topics for tutorials. You can see the Experiments page here, there's also a link at the top of the site. If you like it, please feel free to comment on this post or get in touch.

From jQuery sphagetti to Backbone MV*

almost 4 years ago | Rocky Jaiswal: Still Learning

My current project is exciting, it is for enterprises but it has a potential to be a big hit. Sadly, I inherited PoC level code and had to make it production ready. The Rails code is well written and tested but the client side code was a complete mess (parts of it still are). For example - ...

IE is like that bad ex- you get drunk and hook up with again…

almost 4 years ago | Christian Lilley: UI Guy

… it’s not that you forgot how bad they were. It’s that you forgot the myriad and sundry ways in which they were bad. Worse, you forgot all your coping mechanisms for dealing with them. I’ve had the misfortune to be doing an Angular project for a client who relies entirely on IE8 still. Installing […]

IE is like that bad ex- you get drunk and hook up with again…

almost 4 years ago | Christian Lilley: UI Guy

… it’s not that you forgot how bad they were. It’s that you forgot the myriad and sundry ways in which they were bad. Worse, you forgot all your coping mechanisms for dealing with them. I’ve had the misfortune to be doing an Angular project for a client who relies entirely on IE8 still. Installing […]

Some Ember Goodies, NProgress, Lush Type and Spark

about 4 years ago | Eduard Moldovan: eduardmoldovan.com - tech

We had a long weekend here in Hungary, but the web didn't. Here are few interesting things I came uppon in the last few days.

Phat UI & Angular Testing

about 4 years ago | Christian Lilley: UI Guy

The world has changed. UI Engineering is 4 realz. Servers have gotten skinny, UI has gotten fat phat. To fulfill its potential, UI Developers need to learn/use some important lessons that used to be the exclusive domain of Server-side Dev. Automated testing is one of the biggest. Automated testing, in a nutshell, allows you to prevent […]

Phat UI & Angular Testing

about 4 years ago | Christian Lilley: UI Guy

The world has changed. UI Engineering is 4 realz. Servers have gotten skinny, UI has gotten fat phat. To fulfill its potential, UI Developers need to learn/use some important lessons that used to be the exclusive domain of Server-side Dev. Automated testing is one of the biggest. Automated testing, in a nutshell, allows you to prevent […]

First Class Functions - Ruby, JavaScript & Scala

about 4 years ago | Rocky Jaiswal: Still Learning

This has been a good week, thanks to the public holiday calendar in India I got a six day break by taking a couple of days off in between a weekend and two national holidays. So I utilized the time and rebuilt http://biblefind.in with Scala and Angular.js. ...

Bang Bang !!

about 4 years ago | Shadab Ahmed: Shadab's Blog

The more you learn about the linux shell, the more you love it. Reason I am saying this because I recently saw this: sudo !! This made me immediately google it and I found an excellent reference here. This is a quick summary of the source: $ !! # Repeat last command $ !x # Repeat last command that started with x $ !?x # Repeat last command that has the substring x $ !10 # Repeat 10th command in the history file $ !-10 # Repeat 10th from last command in the history file $ !!* # Fetch parameters from last command $ !!^ # Fetch first parameter from last command $ !!$ # Fetch last parameter from last command $ !!3 # Fetch third parameter from last command $ !!:s/foo/bar/ # Repeat last command substituting foo for bar If you append :p to any of the above commands then it will only print the command than running it Infinite Bang Bang Now what if the last command also contains a !!. Would it become recursive ? Let's see: # : is noop operator. This command sets up our base. # Note that the !! inside single quote doesn't expand to the previous command $ : '!!' # Let's start our recursive operation in here. This is the first sequence in the chain # Only the !! inside double quotes expands to the previous command - : '!!' $ : "!!" '!!' : ": '!!'" '!!' # Pressing up arrow, we have a second sequence # Once again, only !! inside double quotes expands and !! appears 3 times after expansion $ : ": '!!'" '!!' : ": ': ": '!!'" '!!''" '!!' # Now, third sequence - !! appears 5 times $ : ": ': ": '!!'" '!!''" '!!' : ": ': ": '!!'" ': ": ': ": '!!'" '!!''" '!!'''" '!!' # Fourth Sequence - !! appears 17 times $ : ": ': ": '!!'" ': ": ': ": '!!'" '!!''" '!!'''" '!!' : ": ': ": '!!'" ': ": ': ": ': ": ': ": '!!'" ': ": ': ": '!!'" '!!''" '!!'''" '!!''" ': ": ': ": '!!'" ': ": ': ": '!!'" '!!''" '!!'''" '!!'''" ': ": ': ": '!!'" ': ": ': ": '!!'" '!!''" '!!'''" '!!''''" '!!' # Fifth $ : ": ': ": '!!'" ': ": ': ": ': ": ': ": '!!'" ': ": ': ": '!!'" '!!''" '!!'''" '!!''" ': ": ': ": '!!'" ': ": ': ": '!!'" '!!''" '!!'''" '!!'''" ': ": ': ": '!!'" ': ": ': ": '!!'" '!!''" '!!'''" '!!''''" '!!' : ": ': ": '!!'" ': ": ': ": ': ": ': ": '!!'" ': ": ': ": ': ": ': ": '!!'" ': ": ': ": ': ": ' ... # !! appears 161 times In the sixth sequence !! appears 15681 times and in the seventh, more than 150 million times. Do not even try to run it for the 7th iteration unless you want to end up with a 2GB history file and your shell stuck for hours at 100% CPU. The 8th sequence has more than 16 Quadrillion bang bangs Now, I haven't been able to figure out the exact equation yet for the number of !! in nth sequence, but this is what happens: Any !! not surrounded by any quotes is expanded to the previous command !! surrounded only by single quotes '!!' do not expand !! surrounded by double quotes at the outermost level are expanded, even if that bang bang is nested inside single quotes. For e.g. " '!!' " The approximate equation is like this: f(n) ~ f(n-1)*f(n-1)/2 + f(n-1)/2 Let me know if you can figure out the exact equation. The above commands have been tested on sh and bash. Update: Thanks to Volker, we have code to calculate the exact number of bang bangs in nth sequence, here, which works till the 7th sequence. Volker has even submitted the Bang Bang Numbers at OEIS and the sequence has been accepted. View it over here Update2: Robin Houston wrote an analysis of these numbers on his blog. He also wrote this code for generating the numbers in the Bang Bang Numbers series: # /usr/bin/env python p, q = 2, 4 for i in range(4, 16): print "%d: %d" % (i, 4*p + 2*q + 1) p,q = 3*p*p + 2*p + p*q, 2*q + 2*p*p + 2*p*q

Running E2E for Yeoman generated angular app

about 4 years ago | Suman Paul: My Blog

Yeoman is a great tool. It gives build tool, dependancy management and unit test runner out of the box. But there is no straight way to run the angular E2E test. It needs little bit of configuration. Below are the steps that I do to run E2E test. Yeoman automatically generate karma-e2e.conf.js file. We need […]

Hello World

about 4 years ago | Suman Paul: My Blog

Motivation: Part 2 - Mastery - Take the flow test

about 4 years ago | Jimmy Skowronski: jimmy skowronski

The flow Gallup run employee engagement study in the America which shows that employee disengagement caused by “managers from hell” costs the U.S. companies over $450 billion annually. They found that only about 30% of workforce is engaged at work meaning that remaining 70% are not reaching their full potential. Organisations with high percentage of engaged employees experienced almost 150% higher earnings per share that their competitors with less engaged workforce. As it shows, engagement at work is very important factor for the company but also for us, employees. Engagement is a route to mastery. It’s a powerful force in our lives. That leads to Csikszentmihalyi, Hungarian researcher who in late 1950s started exploring “the positive, innovative, creative approach to life instead of the remedial, pathological view that Sigmund Freud had or the mechanistic work”. Under that complex title he believed that that in our lives we have too much compliance and way too little engagement. This exploration lead him to study of play. He found that when playing, many people experience something he called “autotelic experience” - from the Greek auto (self), telos (goal or purpose). In that state the goal is self-fulfilling and the activity itself is the reward. Some people call it a “trance”. I’m quite sure everyone had such moments in their life, when we were so deep in what we were doing that the world could easily cease its existence and we wouldn’t even notice. Later then we often couldn’t recall details of what was happening but we had this amazing feeling of achieving something great. He personally calls it a “flow”. Csikszentmihalyi struggled to find what causes the flow and people’s state of mind when it happens. So he designed a flow test. He asked his students to set up a timer to go off randomly several times a day. Each time the timer sounded they recorded what they were doing and how they were feeling. On the basis of this test run, he developed a methodology called the Experience Sampling Method. Take the flow test So, let’s do the flow test. Here is how. Pick up someone at work or a friend. Ask them to text, tweet or otherwise poke you no more than ten times a day in totally random moments. When that happens you take a notepad and write down answers using the attached form (see links). Do it for a t lease a week but no more than two and then collect results. Look at them and seek patterns. Have you experienced the flow? See if you can find specific situations when it happened. So, is anyone up to the challenge? Links Gallup's study on the workforce engagement On the Measurement and Conceptualization of Flow [PDF] Csikszentmihalyi's TED talk flow test form.docx

Split Tunneling on VPN via Routing Table

about 4 years ago | Shadab Ahmed: Shadab's Blog

Split Tunneling Whenever I connect to VPN on my mac, my default route is modified to this: $ netstat -nr Routing tables Internet: Destination Gateway Flags Refs Use Netif Expire default utun1 UCS 34 0 utun1 default 192.168.2.1 UGScI 0 0 en0 What this does is, route all my traffic, even the one which is outside of VPN network routed through the VPN interface utun1. The second default route via 192.168.1.1 is not even used. This is unnecessary and sometimes counterproductive as the VPN network takes extra load on bandwidth/resources for the IPs outside of its network and even bans sites which do not require banning. You can easily change your routing table to circumvent this using the script below. This way you access public IPs directly and private IPs over VPN. This concept is called Split Tunneling Modifying Routing Table Now to modify routing table for split tunneling, all you need to do is to find out the subnet of the IPs in your VPN you need access to. Let't take for example, if the subnets of my VPN private space are 10.109.0.0 and 10.110.0.0 (Any IPs starting with 10.109 and 10.110): #! /usr/bin/env bash if (( EUID != 0 )); then echo "Please, run this command with sudo" 1>&2 exit 1 fi WIRELESS_INTERFACE=en0 TUNNEL_INTERFACE=utun0 GATEWAY=$(netstat -nrf inet | grep default | grep $WIRELESS_INTERFACE | awk '{print $2}') echo "Resetting routes with gateway => $GATEWAY" echo route -n delete default -ifscope $WIRELESS_INTERFACE route -n delete -net default -interface $TUNNEL_INTERFACE route -n add -net default $GATEWAY for subnet in 10.109 10.110 do route -n add -net $subnet -interface $TUNNEL_INTERFACE done Just save the script as /usr/bin/vpn and whenever you connect to vpn, just run sudo vpn. This is what the script does: Finds wireless router IP (en0) Remove the default routes set by VPN Set the IP found for en0 as the default gateway Add the specific routes for your VPN subnet If you are connecting over wired network, just change the en0 in script to en1. Don't change your VPN DNS to make sure you can resolve private domains on the VPN. Looking at the routing table again after running the script: $ netstat -nr Routing tables Internet: Destination Gateway Flags Refs Use Netif Expire default 192.168.2.1 UGSc 1 0 en0 ... 10.109 utun1 USc 0 0 utun1 10.110 utun1 USc 0 0 utun1 As you can see now, our default gate is back to wifi router IP - 192.168.1.1 on en0 and there are some routes for the subnets inside the VPN. You can test the route as well with a route command. Route for any IP outside of your VPN: $ route get google.com route to: lga15s29-in-f5.1e100.net destination: default mask: default gateway: 192.168.1.1 interface: en0 flags: <UP,GATEWAY,DONE,STATIC,PRCLONING> recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire 0 0 0 0 0 0 1500 0 Route for IP inside your VPN: $ route get 10.109.10.135 route to: 10.109.10.135 destination: 156.107.0.0 mask: 255.255.0.0 interface: utun0 flags: <UP,GATEWAY,DONE,STATIC,PRCLONING> recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire 0 0 0 0 0 0 1280 0 To reset the routing table back, just disconnect from the VPN. Same script can be used on Linux with some modifications.

Bypassing VPN via Routing Table

about 4 years ago | Shadab Ahmed: Shadab's Blog

Whenever I connect to Cisco IPSec VPN on my mac, my default route is modified to this: netstat -nr Routing tables Internet: Destination Gateway Flags Refs Use Netif Expire *default utun1 UCS 34 0 utun1 default 192.168.2.1 UGScI 0 0 en0

Motivation

about 4 years ago | Jimmy Skowronski: jimmy skowronski

Recently, I had a pleasure of speaking about the team motivation in one of our offices. Judging on the discussion that sparked during the talk and some comments afterwards I dare assume that people liked it so I thought I will blog more about it. This post is the beginning of a series that I will write over the next few weeks. I want to cover all topics I talked about in slightly more details. In this series I will bring concepts and ideas that are mostly based on the excellent book by Daniel H. Pink “Drive” but also my own experience and other sources. I don’t remember when and how I heard about this book, but it opened my eyes and greatly changed how I think about those things. I hope you will find something useful for you, no matter if you have a team or not. Source of motivation Long time ago it was presumed that that humans were biological creatures struggling for survival. This theory was then replaced by the new one that assumed that we also respond well to rewards and punishments. That theory worked perfectly through the industrial age when tasks were mainly consisting of manual labour. For a long time everyone presumed that greater reward leads to better performance. That if-then model became the base and was used everywhere around the world with great results. All seemed to be in place, but when economies grew and people had to employ new, more complex and sophisticated skills that well established if-then model started breaking down. Researches and business leaders started slowly realising that the current model is not really working as expected. Researches around the world started scratching their heads and finally confirmed that, when the task is cognitive and requires creativity and thinking, the if-then model is failing. Moreover, they also found that when the reward was increased even further it lead to worse performance. It became clear that a new model is needed to replace the broken one. A model that will employ other type of motivation than simple reward. For that we need to look at what drives us and individuals. I and X type The old, if-then model, assumed extrinsic, the X-type behaviour when people are being driven more by external reward. As it turns out there is another drive behind our motivation, the one that is coming from our intrinsic desires. That I-type behaviour concerns itself less with external rewards and more with the inherent satisfaction of the activity itself. Of course it’s not possible to categorise all humanity to two types and nobody is just one if those two types. We are all both I-type and X-type to some degree but what is important, is how much of each of those two types type is in us. Think about yourself for a moment. What energizes you? What gets you up in the morning and fuels through the day? Is it coming from outside or inside? What makes you to do the career choices you did or will do? I’m not saying that X-type people will always neglect inherent enjoyment over what they do. Or that the I-type person will resist goodies, bonuses and better salary. I’m saying that there is main driver that is either intrinsic or extrinsic. For X-type the main driver is the reward, any job satisfaction is welcome but secondary. For the I-type the main motivator is the freedom, challenge and purpose and any extra gains are welcome but not critical. Of course we all want money and live the good life, even I-types for whom the reward is secondary but only when they have enough money to make so they don’t have to worry. The key to enable I-type behaviour is to take money off the table. People must be paid enough so they can not to worry about living and focus on that intrinsic motivation instead. If your salary will not be good enough you will automatically switch to the X-type. However is the reward raises to a certain level, money starts playing different role for I and X types. I will write more about that aspect later in the series. The three elements So the if-then model doesn’t work in our context. It’s the fact. In general I-type people perform better in cognitive tasks, they are more creative and more effective. We need then a new model, one that will nurse and boost I-type behaviour. Most of current start-ups or so called L3C companies (low-profit limited liability) realised that and that is often huge part of their success. That new model requires the three basic elements. Autonomy By default people are autonomous and self-directed. Unfortunately our life, including outdated “management”, changes that and turns us from I-type to X-type. To encourage the I-type behaviour and the high performance it enables, the first requirement is autonomy. People need autonomy over task (what they do), time (when they do), team (who they do it with), and technique (how they do it). Companies that offer such autonomy, sometimes in quite radical way, outperform their competitors. Mastery Only engagement can produce mastery – becoming better at something that matters. We are in pursuit of the mastery that is essential for the I-type. Mastery is a mindset. It requires the capacity to see your abilities not as finite, but as infinitely improvable. Mastery is also the pain. It demands effort, sacrifice and a lot of practice. And finally it’s and asymptote. It can never be achieved. Purpose Humans, by their nature, seek purpose, a cause greater and more enduring. We achieve that in our private life in many ways, by volunteering, having kids or helping others. We also need it at work. We all want to know that our work has the purpose. In the new business model the purpose maximisation is taking place alongside the profit maximisation as an aspiration and a guiding principle. That purpose motive is usually expressing itself in three ways: in goals that use profit to reach the purpose, in words that emphasize more than self-interest, and in policies that allow people to pursue purpose on their own terms. Intrigued? If you are intrigued by this post you can watch cool visualisation to one of Pink’s talks http://youtu.be/u6XAPnuFjJc or his TED talk http://youtu.be/rrkrvAUbU9Y. You can also get the book and start reading it already http://www.amazon.co.uk/Drive-Surprising-Truth-Motivates-ebook/dp/B0033TI4BW. I strongly recommend it to everyone.

Chrome’s Incognito Mode is Good for More Than Just Porn & Larceny!

about 4 years ago | Christian Lilley: UI Guy

I don’t know if it’s the latest version of Chrome or just a normal variation in experience, but over the last day or so I suddenly find that many .html & .js files I’ve changed aren’t rendering in browser. The old versions are getting stuck in Chrome’s cache and not updating. I started with ‘Force […]

Chrome’s Incognito Mode is Good for More Than Just Porn & Larceny!

about 4 years ago | Christian Lilley: UI Guy

I don’t know if it’s the latest version of Chrome or just a normal variation in experience, but over the last day or so I suddenly find that many .html & .js files I’ve changed aren’t rendering in browser. The old versions are getting stuck in Chrome’s cache and not updating. I started with ‘Force […]

How To Unit Test An Angular App.

about 4 years ago | Alex Rothenberg: Alex Rothenberg

AngularJS has a great testing story - it’s all based on Dependency Injection, the Karma test runner was written by one of its core developers Vojta Jina and it ships with a variety of mocks like the $httpBackend for unit testing requests to remote services. What I haven’t been able to find much of are examples showing how to take advantage of these features when testing an application that does more than just expose objects connected via a rest api. Today we’re going to build a simple Tic-Tac-Toe game writing unit tests along the way. http://alexrothenberg.github.com/examples/tic-tac-toe/v3/index.html Creating our new app This is the boring but necessary part where we need to get all our scaffolding set-up before we can actually start to make our app play Tic Tac Toe. We’re going to use yeoman to create our project. $ yo angular tic-tac-toe After waiting a while for npm to install our modules we’ve got our basic app created and we can go in and run all 0 unit tests. $ grunt test Running "karma:unit" (karma) task INFO [karma]: Karma server started at http://localhost:8080/ INFO [launcher]: Starting browser Chrome WARN [watcher]: Pattern "/Users/alex/blog/test/mock/**/*.js" does not match any file. INFO [Chrome 28.0 (Mac)]: Connected on socket id WfjkRe1_5u5QeZ8upOC2 Chrome 28.0 (Mac): Executed 1 of 1 SUCCESS (0.123 secs / 0.023 secs) Done, without errors. We’re going to add a few testing libraries to our bower.js file in the devDependencies section "devDependencies": { "sinon": "~1.7.3", "chai": "~1.7.2", "sinon-chai": "~2.4.0" } sinon.js so we can build our own mocks and stubs chai lets us use a really nice BDD style syntax for our assertions. sinon-chai adds the chai syntax to our spies, mocks and stubs After we tell bower to install these libraries. $ bower install And we tell karma to use them in our tests by adding these lines to our karma.conf.js karma.conf.js // list of files / patterns to load in the browser files = [ JASMINE, // & other existing files 'app/bower_components/sinon/lib/sinon.js', 'app/bower_components/sinon/lib/sinon/call.js', 'app/bower_components/sinon/lib/sinon/spy.js', 'app/bower_components/sinon/lib/sinon/stub.js', 'app/bower_components/sinon/lib/sinon/match.js', 'app/bower_components/chai/chai.js', 'app/bower_components/sinon-chai/lib/sinon-chai.js', 'test/chai-should.js' ]; One file we need to create ourselves is test/chai-should.js and it contains just 1 line test/chai-should.js chai.should(); We are finally ready to start building our app! Single player Tic-Tac-Toe To get started we’ll build the worlds most boring tic-tac-toe game. A one player game where you can put X’s on the board until it fills up. http://alexrothenberg.github.com/examples/tic-tac-toe/v1/index.html To build this we need 1) the UI, 2) business logic and 3) a controller to glue them together. For the UI we have a 3x3 html table with two angular bindings. { {markAt(0)} } will display the X or O in each space numbered 1-9. ng-click="play(0)" lets us play an X in a space when we click it. views/main.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21<div class="hero-unit"> <h1>One Player Tic Tac Toe</h1> <table id="board"> <tr> <td class="top left" ng-click="play(1)">{ {markAt(1)} }</td> <td class="top middle" ng-click="play(2)">{ {markAt(2)} }</td> <td class="top right" ng-click="play(3)">{ {markAt(3)} }</td> </tr> <tr> <td class="center left" ng-click="play(4)">{ {markAt(4)} }</td> <td class="center middle" ng-click="play(5)">{ {markAt(5)} }</td> <td class="center right" ng-click="play(6)">{ {markAt(6)} }</td> </tr> <tr> <td class="bottom left" ng-click="play(7)">{ {markAt(7)} }</td> <td class="bottom middle" ng-click="play(8)">{ {markAt(8)} }</td> <td class="bottom right" ng-click="play(9)">{ {markAt(9)} }</td> </tr> </table> </div> The next step is to build our controller that exposes play and markAt on the scope. This controller delegates to a TicTacToeGame service and the only real logic it contains is that we are playing ‘X’. This is actually how I try to write my controllers in AngularJS, as skinny as I can so they serve mostly as a mapping between the UI and services which make up the business logic. controllers/tic_tac_toe.js 1 2 3 4 5 6 7 8 9 10 11 12angular.module('ticTacToeApp') .controller('TicTacToeCtrl', function ($scope, TicTacToeGame) { $scope.play = function(position) { TicTacToeGame.playAt('X', position) } $scope.markAt = function(position) { return TicTacToeGame.markAt(position); } }); That leads us to the TicTacToeGame service which knows about the board and how to read and write to it. The most interesting thing it does is map board positions 1-9 to array indices 0-8 since our array is 0-based. services/tic_tac_toe_game.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18angular.module('ticTacToeApp').factory('TicTacToeGame', function () { var board = [ '', '', '', '', '', '', '', '', '' ]; return { markAt: function(position) { return board[position-1]; }, playAt: function(player, position) { board[position-1] = player; } }; }); Even though our controller and service are pretty simple its enough to see some interesting things as we write our first unit test. Now we’re just going to unit test the controller and have it interact with the service so we implicitly test that as well. test/spec/controllers/tic_tac_toe.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18describe('Controller: TicTacToeCtrl', function () { var scope; // load the controller's module beforeEach(module('ticTacToeApp')); // Initialize the controller and a mock scope beforeEach(inject(function($controller, $rootScope) { scope = $rootScope.$new(); $controller('TicTacToeCtrl', { $scope: scope }); })); it('plays my move', function() { scope.play(4); scope.markAt(4).should.eql('X'); }); }); There’s some angular magic with Dependency Injection going on here so let’s dig through that. Line 5 - We tell angular about our app. This initializes Angular’s dependency injector so it is later able to inject and use our services. Line 8 - Tell Angular’s injector to give us its $controller service and $rootScope Line 9-10 - We create a scope and save it in a local variable for later. Then use the $controller service to create our TicTacToeCtrl controller. Line 13-16 - Finally our test! We call play(4) and ensure position 4 is now marked with an X. At this point there’s a lot of boilerplate to help us write one simple test but in a little bit we’ll be able to take advantage of that Dependency Injection infrastructure to test write some good tests that isolate the services and controllers from each other. Adding the opposing player Its a pretty boring game when you have no one to play against so the next step we’ll take is to add an opposing player. http://alexrothenberg.github.com/examples/tic-tac-toe/v2/index.html In the controller we change it so that every time we play an X in some position we want to other player to play an O where they choose. There’s some more Dependency Injection at work here as we’re using the OtherPlayer service. On line 2 we tell angular we depend on it then on line 6 we let it decide where to move. controllers/tic_tac_toe.js 1 2 3 4 5 6 7 8 9 10angular.module('ticTacToeApp') .controller('TicTacToeCtrl', function($scope, TicTacToeGame, OtherPlayer) { $scope.play = function(position) { TicTacToeGame.playAt('X', position) TicTacToeGame.playAt('O', OtherPlayer.selectMove()) } // $scope.markAt is unchanged from before }); Now its time to write the OtherPlayer service and we have to decide how smart to make it. I’m going to go with not very smart so I can defeat it and enjoy the sweet taste of tic-tac-toe victory! It will find the first open space and go there - even a 4 year old could come up with a better strategy. services/other_player.js 1 2 3 4 5 6 7 8 9 10 11angular.module('ticTacToeApp').factory('OtherPlayer', function (TicTacToeGame) { return { selectMove: function() { for(var i=0; i<9; i++) { if (TicTacToeGame.markAt(i) == '') { return i; } } } } }); When we think about how to test our controller we have a decision to make. We could write a test like 1 2 3 4 5 6 7 8 9 10 11 it('plays my move in 4 then opponent in 1 since it is the first open square', function() { scope.play(4); scope.markAt(4).should.eql('X'); scope.markAt(1).should.eql('O'); }); it('plays my move in 1 then opponent in 2 since it is the first open square', function() { scope.play(1); scope.markAt(1).should.eql('X'); scope.markAt(2).should.eql('O'); }); The problem with this approach is that this controller test now relies on a lot of internal knowledge of the OtherPlayer server and its game strategy. If we decide to change OtherPlayer to make it play a smarter game we’ll have to change this test even though we wouldn’t have changed this controller. To me that violates the “unit” part of a unit test. A test should test a single unit, in this case our controller or our service but not both so a change to one requires a change to only its unit test. Let’s take another approach where we stub out the OtherPlayer service so we can specify how it will behave for the purpose of our test. test/spec/controllers/tic_tac_toe.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32describe('Controller: TicTacToeCtrl', function () { var scope; var fakeOtherPlayer; // load the controller's module beforeEach(module('ticTacToeApp')); beforeEach(function() { var myMocks = angular.module('MyAppMocks',[]) myMocks.factory('OtherPlayer', function() { return { selectMove: sinon.stub() } }); module("MyAppMocks") }); // Initialize the controller and a mock scope beforeEach(inject(function ($controller, $rootScope, OtherPlayer) { fakeOtherPlayer = OtherPlayer; scope = $rootScope.$new(); $controller('TicTacToeCtrl', { $scope: scope }); })); it('plays my move', function() { fakeotherPlayer.selectMove.returns(5); scope.play(4); scope.markAt(4).should.eql('X'); scope.markAt(5).should.eql('O'); }); }); It looks like it got much longer and more complicated but there are really only 3 new elements. Its easiest to understand if we jump around out of order. First the test (lines 25-30). This is our test where we control how the other play service behaves. otherPlayer is not the real service but just plain Javascript object that contains a sinon stub. For this test we are saying that if it decides to move in position 5 then there will be an ‘O’ in position 5. Now moving up we’ll see how we setup this fake OtherPlayer service. Sinon.JS is a very cool library and I’ve found its explanation of spies, stubs & mocks among the clearest anywhere. Second, creating the fakeOtherPlayer service (lines 8-16). There are three steps here. To start we register a new module MyAppMocks with angular (line 9). Then we We define an OtherPlayer service whose selectMove method is just a sinon stub (lines 10-14). Finally we register MyAppMocks with angular so the dependency injector will find our fake service when we ask for OtherPlayer. Lastly, let Angular’s Dependency Injector use our fake OtherPlayer (lines 19-23). Explicitly we ask for OtherPlayer on line 19 and save it in a local variable on line 20. We also rely on an implicit step that happens on line 22 $controller('TicTacToeCtrl', { $scope: scope });. When angular creates our controller it will also inject the fake OtherPlayer. We cannot see that but this is the key step that ties it all together. Angular’s dependency injector works so that the most recent module takes precedence over older ones which is why the OtherPlayer in MyAppMocks will be found instead of the OtherPlayer in ticTacToeApp. For us this means the one added on line 15 came after the one added on line 6. Since we have tested our controller in isolation from the real OtherPlayer service we have to separately write some tests for it. Here we will rely on the real TicTacToeGame service (since it is so simple) and our tests insure the “first open position” logic. test/spec/services/other_player.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25describe('Service: OtherPlayer', function () { // load the controller's module beforeEach(module('ticTacToeApp')); var otherPlayer; var ticTacToeGame; beforeEach(inject(function(OtherPlayer, TicTacToeGame) { otherPlayer = OtherPlayer; ticTacToeGame = TicTacToeGame; })); it('select the first space since it is empty', function() { ticTacToeGame.markAt(1).should.eql(''); otherPlayer.selectMove().should.eql(1); }); it('select the third space when first two are not empty', function() { ticTacToeGame.playAt('X', 1) ticTacToeGame.playAt('0', 2) ticTacToeGame.playAt('X', 4) otherPlayer.selectMove().should.eql(3); }); }); We almost have a game now all that’s missing is the thrill of victory when we crush our computerized opponent. Winning and losing http://alexrothenberg.github.com/examples/tic-tac-toe/v3/index.html How do we build this? We’ll just continue what we’ve built so far. First we’ll add our UI for declaring the winner and starting a new game to the html view. views/main.html <h1>Tic Tac Toe</h1> <div> <button ng-click="newGame()">New Game</button> <span ng-show="winner">{ {winner} } has won!!</span> </div> Then we update our controller to support the idea of winning. We’ve added the $scope.newGame function and also added a bunch of logic around playing. Before moving make sure no one has already won and after each move check if someone just won. In order to do that we extracted some helper functions we put inside the controller but do not expose on the scope. As my controllers and services get more complex this is a pattern I often repeat. controllers/tic_tac_toe.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31angular.module('ticTacToeApp') .controller('TicTacToeCtrl', function($scope, TicTacToeGame, OtherPlayer) { var checkForWinner = function(player) { if (TicTacToeGame.gameOver()) { $scope.winner = player; } } var playAt = function(player, position) { if (!$scope.winner) { TicTacToeGame.playAt(player, position) checkForWinner(player); } } $scope.play = function(position) { if (TicTacToeGame.markAt(position) == '') { playAt('X', position) playAt('O', OtherPlayer.selectMove()) } } $scope.newGame = function() { TicTacToeGame.newGame(); $scope.winner = null } $scope.markAt = // still unchanged from the very beginning }); We relied on TicTacToeGame.newGame() and TicTacToeGame.gameOver() so now have to write them. Again we refactored markAt into a helper function and created a few new ones like newBoard and winningLine. services/tic_tac_toe_game.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46angular.module('ticTacToeApp').factory('TicTacToeGame', function () { var newBoard = function() { return [ '', '', '', '', '', '', '', '', '' ]; }; var board = newBoard(); var markAt = function(position) { return board[position-1]; }; var winningLine = function(positions) { return markAt(positions[0]) == markAt(positions[1]) && markAt(positions[1]) == markAt(positions[2]) && markAt(positions[0]) != '' }; return { markAt: markAt, playAt: function(player, position) { board[position-1] = player; }, newGame: function() { board = newBoard(); }, gameOver: function() { var possibleThreeInARow = [ [1, 2, 3], [4, 5, 6], [7, 8, 9], // rows [1, 4, 7], [2, 5, 8], [3, 6, 9], // columns [1, 5, 9], [3, 5, 7] // diagonals ] for (var i=0; i<possibleThreeInARow.length; i++) { if (winningLine(possibleThreeInARow[i])) { return true; } } return false; } }; }); Now we can write some new tests in the controller that verify the new behavior we’ve added a newGame clears the board cannot play in occupied position (thanks to my kids for noticing this bug :) knows when I have won does not let us make any moves when the game is over test/spec/controllers/tic_tac_toe.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35describe('Controller: TicTacToeCtrl', function () { // All the old beforeEach setup remains unchanged it('plays my move and clears board for new game', function() { fakeOtherPlayer.selectMove.returns(3); scope.play(4); scope.markAt(4).should.eql('X') scope.markAt(3).should.eql('O') scope.newGame(); scope.markAt(4).should.eql('') scope.markAt(3).should.eql('') }); it('cannot play over another player', function() { fakeOtherPlayer.selectMove.returns(3); scope.play(4); scope.play(3); scope.markAt(4).should.eql('X') scope.markAt(3).should.eql('O') }); it('knows when I have won', function() { fakeOtherPlayer.selectMove.returns(4); scope.play(1); scope.play(2); scope.play(3); scope.winner.should.eql('X') }); it('does not let us make any moves when the game is over', function() { scope.winner = 'X' scope.play(5); scope.markAt(5).should.eql('') }); }); We have also added some logic to our TicTacToeGame service so we should test that too. What we’ll test is the logic around winning since we had to write non-trivial logic to get that working. test/spec/services/tic_tac_toe_game.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36describe('Service: TicTacToeGame', function () { beforeEach(module('ticTacToeApp')); var ticTacToeGame; beforeEach(inject(function(TicTacToeGame) { ticTacToeGame = TicTacToeGame; })); describe('.gameOver', function(){ it('knows top row is a winner', function() { ticTacToeGame.playAt('X', 1); ticTacToeGame.playAt('X', 2); ticTacToeGame.playAt('X', 3); ticTacToeGame.gameOver().should.be.true; }); it('knows middle row is a winner', function() { ticTacToeGame.playAt('X', 4); ticTacToeGame.playAt('X', 5); ticTacToeGame.playAt('X', 6); ticTacToeGame.gameOver().should.be.true; }); it('knows diagonal is a winner', function() { ticTacToeGame.playAt('X', 1); ticTacToeGame.playAt('X', 5); ticTacToeGame.playAt('X', 9); ticTacToeGame.gameOver().should.be.true; }); it('knows a row with both players is not a winner', function() { ticTacToeGame.playAt('X', 1); ticTacToeGame.playAt('O', 2); ticTacToeGame.playAt('X', 3); ticTacToeGame.gameOver().should.be.false; }); }) }); If you want to look at the example we’ve built its all on github alexrothenberg/angular-tic-tac-toe. I hope you’ve found this journey useful and will make sure to test the next Angular app you write!

Know Your Contact – the BlackBerry App you can’t live without!

about 4 years ago | Karan Nangru: Karan Nangru

Having developed quite a few native Enterprise BlackBerry apps, thought of creating this useful BlackBerry App :- Know Your Contact What does the app do? When you save a contact to the BlackBerry phone book, add that most important information you would like to be reminded of  before picking a call from this contact the next […]

Testing Angular.js

about 4 years ago | Rocky Jaiswal: Still Learning

As an Angular.js developer, I want to test my code, so that I can feel reasonably good about it. This sounds like a "User Story" in Scrum but it's more of a developer quest. So in this blog we will look at ways to test our Angular.js code. Let's see what we need - We need t ...