Over the weekend I wanted to get a bit deeper into the CoffeeScript and get around how it feels working with it. I gave myself task to do something simple but inspiring. Therefore I implemented simple version of Conway’s Game of Life to be played in browser. Go here to see how it looks like.
CoffeeScript
CoffeeScript is a little language that compiles into JavaScript. Underneath all of those embarrassing braces and semicolons, JavaScript has always had a gorgeous object model at its heart. CoffeeScript is an attempt to expose the good parts of JavaScript in a simple way.
In other words, CoffeeScript is an attempt to replace JavaScript syntax with a better one based on experiences from Ruby and Python worlds. Beside that it introduces couple of new abstractions which natively do not exist in the vanilla JavaScript like classes, list comprehensions, return of multiple values from function etc.
CoffeeScript brings a lot of relaxation on the original JavaScript syntax and makes writing it at first weird experience but only until you get used to it. Afterwards it gets obvious that it takes much less to write the same thing in CoffeeScript than in plain JavaScript.
My observations on developing with CoffeeScript
First and obvious observation is that with CoffeeScript you need additional tool in your toolset which will continuously compile your work to JavaScript. I used Jasmine for writing tests and I based my setup on this gist which proposes using guard Ruby gem for tracking changes and compiling CoffeeScript files into JavaScript ones.
It looked a bit weird at start, but after couple of hours playing it started getting better. One thing I had always to do is to look in the actual compiled JavaScript to see how to do some things i.e. how to pass index to function that maps an array. But it was intuitive enough that I almost didn’t need official documentation. Here I have to tell that it might not be as intuitive to people without experience with writing Ruby and Python code or lack of understanding for rather mathematical
(a, b) -> a + b
function notation.
At the end I really liked it. Problem that I was solving didn’t need using some advanced CoffeeScript constructs like classes but one that I used like multiple return values from the function really show how much you can get out of language if you have some basic tools implemented within.
Last several months I was developing mostly in the Rails framework and since Rails 3.1 is going to have CoffeeScript enabled by default I suppose I’ll give CoffeeScript a chance again in next months and write more about experiences developing more complex things again in future.
Code is on GitHub
You can find the source code for the implementation of the game on GitHub
If we look at the developments in the software testing area, step beyond in evolution after TDD is, so called, BDD (Behavior Deriven Development). It is hard to describe BDD in couple of sentences. Excerpt taken from Wikipedia says:
BDD focuses on obtaining a clear understanding of desired software behaviour through discussion with stakeholders. It extends TDD by writing test cases in a natural language that non-programmers can read. Behavior-driven developers use their native language to describe the purpose and benefit of their code. This allows the developers to focus on why the code should be created, rather than the technical details, and minimizes translation between the technical language in which the code is written and the domain language spoken by the business, users, stakeholders, project management, etc.
If this looks a bit complicated, in one sentence it would mean: BDD helps programmers and non-technical stakeholders understand each other better and develop software which will be the most representative model of the problem solved by writing the software itself.
Jasmine: BDD for your JavaScript
Jasmine is a library for BDD testing of your JavaScript. It offers range of possibilities to describe software functionalities by simple and descriptive tests, which is one of the basic principles of BDD based development. This way tests usually serve as the most accurate software documentation. More about Jasmine library on the GitHub repository.
After you download standalone Jasmine distribution from here you’ll find in the archive all you need to write your first tests together with the example of your code organization. The most important fie is SpecRunner.html which, when run in browser, will execute tests and give you report about the state of the tests. SpecRunner.html is very simple and self explanatory. lib folder contains Jasmine library, src folder contains code to be tested and spec folder contains actual software specifications as tests.
Further, I will implement simple object that can register multiple callback functions and call them with given data. Something like simple observer. I will always first write tests and then implement functionality to make tests pass.
Example of simple JavaScript observer with Jasmine tests
We start from the downloaded archive for standalone Jasmine library. We need to delete example code provided with the library to implement our own example.
cd jasmine-standalone # folder in which we extracted downloaded archive
rm src/*
rm spec/*
Also, from SpecRunner.html file we delete references to just removed scripts. Therefore, part which includes them stays empty like this:
...
<!-- include source files here... -->
<!-- include spec files here... -->
...
First test
In TDD and BDD philosophy one rule is essential for success.
First you write the test which will at the beginning fail, then you implement code which should satisfy specification described by test. Then, you execute test and continue with implementation until test passes. When that happens you know that implementation is OK.
According to this we create file to place our tests in spec/ObserverSpec.js and we define first test to simply check existence of the observer object.
describe("rs.ji.observer", function () {
it("should be present in the global namespace", function () {
expect(rs.ji.observer).toBeDefined();
});
});
And we add this specification to SpecRunner.html to execute it:
<!-- include spec files here... -->
<script type="text/javascript" src="spec/ObserverSpec.js"></script>
If we now open SpecRunner.html in some browser (i.e. Google Chrome) we will see one failing test.
It is important to take a look in how our test looks like. If you read the test you’ll see how descriptive it is and how with simple words expresses how our code should behave, although example is very simple. Here it takes some creativity of the developer to make tests really valuable but more than that is important that developer have deep understanding of the dictionary and terminology of the domain for which software is developed because understanding of the domain should be heavily embedded in the test definitions.
Next step is to implement the code which will satisfy test. We will create file src/observer.js
// defining so called namespace objects so I can namespace observer into
// rs.ji.observer
var rs = {};
rs.ji = {};
// observer implementation
rs.ji.observer = {};
And we will add it to SpecRunner.html:
<!-- include source files here... -->
<script type="text/javascript" src="src/observer.js"></script>
If we run SpecRunner.html again, we can see that our test passes, it is green
Rest of implementation
Now, when we know for the principle “First failing test, then implementation” we can add new functionalities to our simple example. We add next test:
it("should be able to register callback function", function () {
// define function to be placed into the observer register
function callback() { return null; }
rs.ji.observer.register(callback);
var callbacks = rs.ji.observer.getCallbacks();
expect(callbacks.length).toBe(1);
expect(callbacks[0]).toBe(callback);
});
And implementation that makes this test pass:
rs.ji.observer = {
callbacks: [],
register: function (callback) {
this.callbacks.push(callback);
},
getCallbacks: function () {
return this.callbacks;
}
};
We want to check if we can register multiple callbacks. This functionality should be supported already, but we write test to confirm this:
// before every test we reset array of callbacks
beforeEach(function () {
rs.ji.observer.callbacks = [];
});
it("should be able to register multiple callbacks", function () {
function callback1() { return null; }
function callback2() { return null; }
rs.ji.observer.register(callback1);
rs.ji.observer.register(callback2);
var callbacks = rs.ji.observer.getCallbacks();
expect(callbacks.length).toBe(2);
expect(callbacks[0]).toBe(callback1);
expect(callbacks[1]).toBe(callback2);
});
Programmers often use print, echo and friends to test code for certain functionalities. That takes time as for writing a test, but from other side tests are possible to be executed all the time after this initial check is done even when we move to implement something else.
If we run SpecRunner.html in browser, all tests should pass.
Last thing our observer should do to satisfy its basic purpose is to update callback functions with some new information. That means it should be able to call them with some data. To define this functionality we write new test:
it("should provide update method to execute all callbacks with provided data", function () {
window.callback1 = function () { return null; }
window.callback2 = function () { return null; }
spyOn(window, 'callback1');
spyOn(window, 'callback2');
rs.ji.observer.register(window.callback1);
rs.ji.observer.register(window.callback2);
rs.ji.observer.update("data string");
expect(window.callback1).toHaveBeenCalledWith("data string");
expect(window.callback2).toHaveBeenCalledWith("data string");
});
Here we use some advanced techniques of spying on methods (SpyOn) in order to see if some method is called while other is executed.
As a helper, we will add jQuery library to src/jquery.js location and add it to SpecRunner.html file:
// observer implementation
rs.ji.observer = {
callbacks: [],
register: function (callback) {
this.callbacks.push(callback);
},
getCallbacks: function () {
return this.callbacks;
},
// added update method to inform registered callbacks
// uses jQuery to iterate over the array
update: function(data) {
$.each(this.callbacks, function (i, callback) {
callback.call(null, data); // call every callback with provided data
});
}
};
Complete picutre
That is it, now we have full implementation of simple observer with tests that can pretty clearly describe functionalities of the software we developed and they can as well prove in every time that needed functionalities are working OK by executing them in the browser (or different browsers to see if they will work in all of them).
Complete files:
describe("rs.ji.observer", function () {
beforeEach(function () {
rs.ji.observer.callbacks = [];
});
it("should be present in the global namespace", function () {
expect(rs.ji.observer).toBeDefined();
});
it("should be able to register callback function", function () {
// define anonymous function to be placed into the observer register
function callback() { return null; }
rs.ji.observer.register(callback);
var callbacks = rs.ji.observer.getCallbacks();
expect(callbacks.length).toBe(1);
expect(callbacks[0]).toBe(callback); // so we need to have first funtion in registered callbacks
});
it("should be able to register multiple callbacks", function () {
function callback1() { return null; }
function callback2() { return null; }
rs.ji.observer.register(callback1);
rs.ji.observer.register(callback2);
var callbacks = rs.ji.observer.getCallbacks();
expect(callbacks.length).toBe(2);
expect(callbacks[0]).toBe(callback1);
expect(callbacks[1]).toBe(callback2);
});
it("should provide update method to execute all callbacks with provided data", function () {
window.callback1 = function () { return null; }
window.callback2 = function () { return null; }
spyOn(window, 'callback1');
spyOn(window, 'callback2');
rs.ji.observer.register(window.callback1);
rs.ji.observer.register(window.callback2);
rs.ji.observer.update("data string");
expect(window.callback1).toHaveBeenCalledWith("data string");
expect(window.callback2).toHaveBeenCalledWith("data string");
});
});
// defining so called namespace objects so I can namespace observer into
// rs.ji.observer
var rs = {};
rs.ji = {};
// observer implementation
rs.ji.observer = {
callbacks: [],
register: function (callback) {
this.callbacks.push(callback);
},
getCallbacks: function () {
return this.callbacks;
},
update: function(data) {
$.each(this.callbacks, function (i, callback) {
callback.call(null, data);
});
}
};
If you havent heard of Khan Academy yet you should immediately get out that rock you are hiding under. No joke, Khan Academy is a big thing. Watch this TED talk to see how amazing is what Salman Khan is doing. I was really happy when I saw that John Resig of jQuery fame has joined their crew to help bringing this extraordinary mission to the next level. It is really extraordinary, especially for the times of today when everything is in profits and money. But it doesn’t matter only because of that.
I come from Serbia, country which is in kind of development. Last 20 years where not that good for us. Degradation of every part of society to the critical level happened during that time. People mostly without jobs, hope and will to go forward despite the fact that time passes by them fast. Yes, time passes by and developed world is changing even faster every day. And if you stand still for 20 years, you can imagine how far world goes in front of you. It goes so far that you, from your own point of view don’t understand any more all that modern development and trends.
So the big question for countries like Serbia is how do they catch up with the modern world. How do you learn things you have to know when you don’t have access to good and innovative education, have no great people to lead the country because they are all spread around the world. Well, there are options. And improving education of people is in the core of all of them. In this context Khan Academy really matters. Not as final solution but more as announcement of future where education is going to be much less institutionalized and much easier spread across the globe, especially in the countries which need this the most.
Internet has evolved to a point where it is becoming a platform for spreading something more than Facebook and Farmville. Recently I watched TED talk of Chris Anderson on how web video powers global innovation and I could not agree more. And Khan Academy proves this in practice on a high scale and is able to motivate thousands to join the train of global education improvement and to bring it to the higher level. This might lead to looking at the education in whole lot different ways than before and using peoples potential most efficiently to solve problems of underdeveloped communities. It brings some hope at least.
Currently I live in Switzerland, country blessed by the best standard in the world and really great performance in every aspect, from administration to education. One thing I see here is that people are not aware enough how others in the world live and when aware it is on the level of general empathy and not on the level of doing something with it. Paradoxically, countries like this can give the most to the world, not only by sharing money but experiences and knowledge about their success as well. Internet in this case might be a great leverage for small and great ones to influence world wide.
Considering all of this, I though I could be one among this army of good people to help on this idea. I’ll try to contribute on this topic as much as I can in my spare time and motivate others to do the same. Translating as much videos to Serbian would be one of primary goals and promoting the idea as well.
It was long time ago since I realized that every discussions about this or that technology falls into water without putting it in the context of the real-world problem. And, unfortunately, real world today doesn’t lack problems. What it lacks are people of good will to solve them, or at least good people lack organization and coordination in order to efficiently solve these problems. Random Hacks of Kindness project was started with idea to address this problem.
RHoK works by bringing together experts in development and volunteers with a broad set of skills in software development and design to solve problems defined by NGOs and other institutions which work in the area of disaster management.
Last weekend RHoK happend for the first time in Switzerland. Frank, driven by his experience from RHoK #2 in Berlin, organized great event in Basel and gathered around 20 of us to attack some of the RHoK problem definitions we found interesting. On the following video you can see presentations of all the teams, their problem definitions and explanations of solutions.
I worked with Max, Phillip, Felix, Thomas and Chad from SecondMuse on the problem defined by Caritas Switzerland. Overall idea was to gather different sources of scientific GIS data for different global community risk related information like percentage of child hunger per country or intensity of cyclones in coastal areas and to present this information in usable way on one map with some tools to examine data more deep. Technically, the most difficult part of the problem is the fact that, as far I could understand, GIS area lacks standardization of data exchange file formats, and getting head around this domain in 2 days is really hard. We did not finish much on the practical side, but we examined the problem from technical side and came to deeper understanding of the problem domain and some ideas how it can be solved properly in future. One visible thing we made is half-working prototype of Google Map with two custom tile layers, more like proof of concept for our idea.
Beside great time, meeting great people and working on challenging problem I found that participating to this event additionally boosted my motivation to get deeper into non-technical side of problems of communities around the world. Also I became more aware how important is to motivate people to put some effort into solving this kind of problems and how easy is to help if proper environment is set and some basic organization is provided.
On the line of organization, I liked that we could give the input about how we could improve the event organization for future. I found couple of possible optimizations of the process which might help me achieve better results next time:
As software developer I’m sensitive to quality of requirements. Problem definitions, as given today, are definitely not the best to work with. If we could involve engineers in the problem definition process before problem definition comes for implementation it might help to get more done during the short and intense 2 days of hacking. And even more important maybe is to have the problem owner present in place for all time during the event. This not only helps team but even more helps them to understand the problem better for future.
The way teams are formed is not the most efficient. Although, getting together with group of completely unfamiliar people is personally great and can lead to lot of innovation, it makes continuity a bit harder. Working with people you know and trust is from other side more efficient but can lead to not that innovative approaches. If these could be combined in a way I’m sure we could achieve better results and insure better continuity which is essential for finishing the project to some usable state. Therefore I’ll try to make effort to form a team for next RHoK and try to stick to a problem until it is finished at least in the basic version.
Event should be promoted to the broader audience and involve more different professions like designers, usability experts, product owners, scrum masters and other involved in agile software development which is I believe the most appropriate for this way of attacking problems.
In future whole RHoK idea should be expanded to involve problem areas other than disaster management. I would personally be the most interested in problems related to online education of countries in development, and others certainly have their own preferences as well. This way we might gather much bigger community around it.
JavaScript development has got really much momentum and its popularity is peaking. In the moment of design it was probably never foreseen as such success. Maybe that is why we have to satisfy to using only its “Good Parts”. There are lot of compromises with it, in order to make programming it a success overall. One thing that I always found weird is usage of that = this concept. JavaScript guru Douglas Crockfordexplains on his website this concept of preserving connection of method with parent object regardless of the context of invocation. In practical usage I saw this pattern used for essentially the same reason but on other places. Consider this example (code purpose and quality in general do not matter that much)
// Returns array of positions of current players on the field
tofu.Table.prototype.getPlayerPositions = function() {
var positions = [];
var that = this
$.each(this.rods,
function(i, rod) {
var left = that.getRodDistance(i)
// produce positions for all players
for (var j = 0; j & lt; rod.men_number; j++) {
var position = {
left: left,
top: j * rod.men_distance + rod.position
}
positions.push(position);
}
});
return positions;
}
The main point here is that we try to preserve reference to parent object with var that = this because $.each(this.rods, … ) will overwrite reference to local variable this. In that case we access closure reference that to refer to our original object.
And there is a problem, I keep seeing this pattern all around. As I understand programming, proper naming of “things” is very important. And one that calls everything around in the terms of this and that might not be considered much smart Can’t we have a name for that reference. Considering same example with small change in code I think it looks more natural than before and more readable and self explainable
// Returns array of positions of current players on the field
tofu.Table.prototype.getPlayerPositions = function() {
var positions = [];
var table = this
$.each(this.rods,
function(i, rod) {
var left = table.getRodDistance(i)
// produce positions for all players
for (var j = 0; j & lt; rod.men_number; j++) {
var position = {
left: left,
top: j * rod.men_distance + rod.position
}
positions.push(position);
}
});
return positions;
}