Wednesday, September 5, 2012

Gamification of day to day development work

I've been thinking a lot today about how to help developers write solid code, and write good tests, and perhaps even have some fun in the process. So what about achievements for your day to day work?

I know Visual Studio has done something like this in the past, but it's been for C++ (or C#), and as far as I understand, it's been developer centric, not project centric.

The problem with the developer centric approach is that it inherently leaves out people, and in my opinion doesn't promote the health of the project as a whole. I think a combination of the two seems to be in order, so there should be developer-specific achievements, but also project-specific achievements.

I'm really keen to develop something like this. I was recently bitten by the fact that I stopped writing unit tests (Because of time pressure, the usual BS excuse) and now of course my mind has been racing on how to stop this trend. Now I'm not that naive that I'll think something like this will solve all the worlds shitty software problems, but, if it helps even a little bit and people have fun in the process then why not?

Here's some achievements I've come up with, please feel free to add some or comment on them:

Project Achievements

  • Have to start somewhere: 5% test coverage
  • It’s improving: 10% test coverage
  • Getting better still: 30% test coverage
  • Works on my machine: 50% test coverage
  • Getting pretty solid: 75% test coverage
  • Should work: 80% test coverage
  • Will work: 90% test coverage
  • Specs may be wrong, but it works: 95% test coverage
  • The first cut is (not always) the deepest: First unit test gets added.
  • Single celled organism: Project has been active for one month
  • Fetus: Project has been active for two months
  • Baby: Project has been active for three months
  • Toddler: Project has been active for 5 months
  • Child: Project has been active for 1 year
  • Teenager: Project has been active for 1.5 years
  • Adult: Project has been active for 2 years
  • Middle Aged: Project has been active for 3 years
  • Twilight Years: Project has been active for 4 years
  • It’s not all about the code: Project gets its first “resource” file (ie. src/main/resources for Java)
  • Blink and you’ll miss it: Project takes less than 5 seconds to build
  • Watching paint dry: project takes longer than 1 minute to build
  • Don’t tell Han Solo: More than 1 developer has worked on the project
  • Three’s a crowd: More than 3 developers has worked on the project
  • It’s more fun this way: More than 5 developers has worked on the project
  • Polygamy : More than 10 developers has worked on the project
  • This is serious: Project gets its first tag
  • We can like to be doing configuration management: More than 5 tags
  • We know what’s out there: More than 20 tags
  • We’ve got a release coming up: More than 5 tags in a week
  • We’re trying to fix it (or it’s growing quickly) [this could depend on age of project]: More than 10 commits in a single day
  • It’s not working: Same as above, but for 5 commits

Developer Achievements

  • Adding functionality by removing code: LOC get less, but test coverage increases.
  • Removing a dependency: A dependency is removed from the project.
  • Getting it Back on track: Added a first test after a long period of no tests being added
  • Likes it pretty: Made a commit with only whitespace changes
  • Leave is in the bank: 15 continous days of commits
  • The Creator: First commit for a new project
  • Dabbling: Developer worked on more than 1 project
  • Branching out: Developer worked on more than 3 projects
  • Part of the furniture: Developer worked on more than 10 projects
  • Letting go of the shackles: Developer worked in more than 1 language
  • Versatile: Developer worked in more than 3 languages
  • It’s all the same: Developer worked in more than 5 languages
  • Burning the midnight oil: Developer pushed a commit between 12:00 and 05:00 am
  • Who needs to eat? Developer pushed a commit between 12:00 am and 13:00 pm
  • No Youtube: Developer pushed more than 10 commits in one day
  • Hard worker: Developer pushed more than 20 commits in one day
  • Must be a bot! Developer pushed more than 50 commits in one day
  • Diligent: 2 commits in a row where a test is added
  • Knows what he’s doing: 3 commits in a row where a test is added
  • Consistent: 2 commits in a row with a good commit message
  • Taking it to heart: 5 commits in a row with a good commit message
  • Shakespeare: 10 commits in a row with a good commit message
  • Give him the documentation work! 20 commits in a row with a good commit message
  • I’m focused: More than one month commiting to the same project

Wednesday, July 25, 2012

Steam on Linux

Steam is coming to Linux!!!. If you don't believe me check out this link: http://blogs.valvesoftware.com/linux. Valve will start off by releasing Left 4 Dead 2, with more of their games to follow.

Thursday, July 12, 2012

Regarding the Whaleventures-pact of 10/11/12 July 2012

Wow, this is quite strange, it feels like a lifetime ago when I last read the comments on Jaco's original post regarding time travel and the "whaleventures-pact" as he put it.

Firstly, I have seen the future. Heck, I just came from it. (I just realised that talking about it is more difficult than I thought it would be, because for me everything is past tense, but for you guys everything will be future tense. So forgive me if I get the tenses wrong.)

Secondly, for fear of causing a butterfly effect I have decided not to tell you guys about all the stuff that has happened (is going to happen) through the years, except that time travel is (has become) a reality as you may have deducted by now. So, let it be known that the Whaleventures-pact is a strong bond that ties us together.

Anyways, gotta run, the time travel police is closing in. Yeah, I know right!? Such a cliché.

Tuesday, July 10, 2012

Monday, July 9, 2012

Thrift TThreadedPoolServer thread pool

Don't know how many of you are still using Thrift - it's still going strong here because it works so much better than RMI.

Just a small tip, I recently came across a TThreadedPoolServer. The idea is that a thread pool gets used to serve requests from the clients - so each client has its own thread. In my opinion, this is not ideal, but this is how it's working at the moment.

There is a danger though: make sure you set the maximum number of threads in the pool! Otherwise it just keeps on adding threads to the pool - returning them I don't know when. The app was sitting at 400+ threads just now.

It's easy to do:

You can of course set a minimum etc. as well. I'm not sure when the threads are "freed" and returned to the pool - I'll investigate this later today.

Thursday, July 5, 2012

On progress of thought and not just jumping in

We all know it's hard to think. One of my previous employers always famously said "Thinking is hard work. If it wasn't, everyone would be doing it.". So I just want to share something that happened to me this morning, to illustrate this point. And also how you shouldn't just always write down the first thing that comes to mind.

So, I had a list: [a,b,c,d,e]. I wanted to get the "pairs" in this list. So basically, I wanted a function f(l), that given [a,b,c,d,e] would give me [[a,b],[b,c],[c,d],[d,e],[e,a]]. I wanted to use this to draw lines, connecting a bunch of points. (Note: it is important that the last element in the list connects to the first, otherwise I'll have a gap in my line drawing)

So, the classical way to do this, would be to go ahead and code up something like:

This works. But it's not particularly elegant, and it has a special case for the last entry, which I don't like, and would like to avoid. Also, it's very specific - I can't easily change it to pair n and n+2, or n,n+1,n+2 for example (Not that I need it at the moment, but still, its a very *specific* implementation.

So then I thought, what about taking the list, and zipping f(x) = x, with f(x) = x + 1, over the length of the array. That would give me the indexes of the pairs. So, I would end up with a list like: [[0,1],[1,2],[2,3],...] etc. and then I could just use that list, and map over it to get the appropriate elements in the original list. I could even then zip additional lists as well, for eg. f(x) = x + 2, f(x) = x + 3 which will give me 4-element pairs. Nice.

Problem solved right? On further inspection - not really. There is still a MASSIVE edge case there at the end. In fact, with this solution, the edge case is probably even more difficult to manage then in the purely imperative form. So I decided, I'm not even gonna code up the solution like this, cos I haven't yet had enough caffeine to deal with this edge case mess.

So then I realised, that basically what I want to do, is "rotate" the original list, and zip the original one, with the rotated one. Yes, good old ROT-n. So I take my input list, rot-1 it, and then map the input list with this rotated list. This gives me _exactly_ what I want, and also solves the edge case problem for me very elegantly! I now also have the ability to pair an arbitrary number of elements from the list, by just rot-1'ing, then rot-2'ing, then rot-3'ing, and then zipping all these lists together. Very nice.

But now, I need a rot-n function. Javascript (or underscore) doesn't have one, so I'm gonna have to implement my own. Dammit, right? Remember those varsity excercises where we did rot-13 in like first year? Not really lus to implement this right now! And then, what will I gain, really? Then I could just my original implementation!

Then, I had a quick chat with Gary, and we came to the conclusion, that a rot-n list, is simply the concatenation of the tail of the list, from (n,length), with the head of the list from (0,n). This makes my job much, much easier. Turns out, rot-n in Javascript looks as follows:

So, armed with that, my original solution simply becomes:

Much nicer hey? And also, more general. And I sommer got a rot-n function out of the deal as well!

This was just my latest example of how it helped me to think things throught a bit before I start to write the solution. I'm very much a Just Do It guy, but it's good to sit back and think, you tend to get much more out of it then what you just intended to write.

Monday, July 2, 2012

You selfish pig!

Ok, so the story goes as follows:

You are on a plane on the aisle seat. At the window is guy in a business suit. Quiet and seemingly very annoyed. You don't like him. In the middle, a proverbial little old lady is sitting. In contrast to the guy in the window, she seems rather chirpy. In the middle of the flight she starts talking to the both of you: "Fellows... you know what? My husband was in the steel business and he died last year, leaving me with a fortune. I'm bored and I want some fun. I'll tell you what. I'll give $100,000.00 and if you can decide how to split it, you can have it. If not, you both get nothing."

For the first time in the flight the guy at the window seems interested. "My name is Dick. What's the catch?" he says. "Ok Dick", the lady continues. "You can decide how the money should be split and if the handsome fellow next to me agrees, you can have the money, okay?". "Sure!", Dick says. "I'll take $99,000.00 and the guy in the aisle can have the other $1,000.00"

So what do you do? Can you feel Richard Dawkins' selfish gene stirring in your loins? Logically, you should always accept, because you have nothing to lose. Right?Strangely, the majority of people starts declining at around 60% (i.e. 60% for the proposer and 40% for the decider).

I was wondering what a computer will do with this... I set up the experiment as follows: A hundred thousand agents playing the game in a tournament fashion. Pick two random agents, let them play, repeat (they play one game, one the decider, the other the proposer). Each agent evolves two values. One value (the "proposition") is the value it will propose and the "decision-threshold", which is the minimum it will accept. Therefore, for a [0.9, 0.6] pair, the agent will propose 90% of the money for itself and will only accept a minimum cut of 40%, when it has to decide. I allowed this to evolve (population size of 100,000). After several generations, quadrillions of games, the most successful agent was as follows:

 P:0.73 D:0.85

This means, proposing a 73%-27% split and declining any selfish agent that wants more then 85% was optimal. Hell, this was not at all expected! I repeated the experiment several times, each time with similar results. The decision-threshold was always slightly higher, but the proposition threshold seemed to be fairly stable at around 0.7-0.9. How come? Can computers really be selfish too?

EDIT: After further experimentation, I found that the TOTAL money distributed amongst individuals tend to increase (i.e. the group improves as a whole) - and rather quickly as well.

If I initialise all agents to the most narsistic value of (P,D)=(1,0), which means I want all the money and if you don't propose I get everything, I say no.  The total money made by each generation changes as follows (generation; total money):



After which it stabilises.  This is completely emergent as I never test the total money made by the population.

Thursday, June 28, 2012

Djikstra's algorithm in node / javascript

So tonight I had to implement Djikstra's algorithm to do some very simple pathfinding in an experimental thing I'm working on, so seeing as nothing has happened in June I decided I'll post the code.

Perhaps someone finds it useful some day, perhaps someone wants to discuss it or improve it. The code is very rough as I needed it *now*. Probably some bugs in there as well. I'm gonna start to use it now so I'll update the code as I find them :) I started of all functional but very quickly reverted back to old habits as the impending deadline loomed :)

Anyway, so it was fun writing some proper algorithm code again after how many years of businessy stuff :)

Djikstra in JS:

Thursday, May 17, 2012

cannedhttp - Testing HTTP based webservices in Java

So, recently I've again been writing webservices using HTTP as the transport in Java, and after getting used to node.js land where it is so, so easy to test these kinds of webservices, I was longing for the same kind of compact, self-contained testing. So, I came up with cannedhttp, a small self-contained 'canned' webservice testing tool to help with testing webservices.

The idea is very simple, most requests, especially in unit-testing scenarios, always need to return the same content. So, why can't this just be done with static webservers? Well, the problem with using static webservers for this is that you need to be able to set the HTTP response code, the HTTP headers (such as Content-type) and so forth, and also the different HTTP verbs such as POST, PUT, DELETE. Normally, static webservers only support GET.

So canned-http takes a very simple approach to this problem - your file structure is your web service endpoints. All files have an HTTP verb as the suffix - such as .GET, .POST, .PUT etc. All files also have a very simple file structure allowing you to specify http response code, headers, and content.

In addition to this, it also gives you a very basic router API to add handlers to intercept requests, allowing you to check whether your code is actually sending the correct requests through. It also allows you to customise the response - giving you the ability to start doing some real testing around your webservice calls, while not being reliant on an external webserver at all. It also gives you predictability - seeing as at it's basic form, cannedhttp always returns the same content for the same request.

Here is a sample canned file, showing how you could do a SOAP response for example:

Placing this file in a subdirectory as /one/two/soap.GET, will allow you to test a SOAP webservice at /one/two/SOAP

Here is some code showing the basic router API:

So, there it is. Hopefully this can be of use to some of you. I know it's been helping me the past week or so. It really has sped up the development of webservice code for me - some of the stuff I haven't even tested against a "real" webservice - I've just followed the spec documents and used the examples in those and made sure I could parse them, right there in my unit tests.

Cisco VPN client with certificates only

I had a whale of a time trying to connect to a Cisco VPN gateway this past day and a half. The company I am connecting to is using IPSec with certificates, and not IPSec with a group name and password, as is easily supported by vpnc (which I have done before). Unfortunately I only realised that after trying openconnect and vpnc. I wrote this little HOWTO as a gist on github: HOWTO connect to a company's VPN using the Cisco VPN client on linux

I hope it will also help someone else in the future. It is definitely going to help me when I have to do it again.

Wednesday, May 9, 2012

Disqus - revisit

Right, so it's been a while since we last discussed, Disqus (see what I did there).

Original post: Disqus is pissing me off

And let me save you from any sort of suspense you may have regarding whether my feelings have changed: they have not. That is why my vote is to: drop it. As soon as possible.

As highlighted in that post, there are issues surrounding administering Whaleventures / Disqus while logged into your own, personal Disqus/Google accounts. There are issues where the thing marks innocent comments as spam. It forces the revealing of firstnames and lastnames, and our resident incognito users don't like that. Then you've got the issue where you can't embed links. Oh, don't forget the issue with code formatting. It seems you need to be a Disqus formatting guru to get it to preserve whitespace.

I have exported our comments as of this moment (2012-05-09 19:50), and they provide you with a nice XML file. The content of the XML file looks straightforward enough. If we get consensus, I will figure out a way to re-import our old comments back into whatever new system we choose, even if I have to generate each of you your own customized python script or whatever with your comments in it.

So, who's with me? Are we gonna drop Disqus?

Tuesday, May 8, 2012

Code weirdness

I recently came across very strange behaviour in the tertiary operator:

<boolean-expression> ? <statement> : <statement>;

See if you can spot it. The idea is as follows. If the number is a round number (i.e. 4.0 or 8.0) then the number should be displayed without the trailing .0. However, if it is not, the fractional part should display. Here's the test class containing three tests... Which test(s) fails and why?

Friday, May 4, 2012

Find the bug - part 3 (Windows edition)

I have come across a strangeness with Java on Windows with regards to file handling, i.e. the following code:

The code works fine on Linux, but on Windows it complains that the "from" file cannot be deleted, when the file is supposed to be moved using the Google Guava Files.move(File from, File to) method. There is a very subtle thing one has to do to get it to work on Windows. What is it?

Post your answers in the comments and then I will let you know after a while :)

Monday, April 23, 2012

A "Guicier" Apache XML-RPC

Call me old-school if you like... I guess I am. When everyone was raving about Guice, I was simply taking note of it. "Oh sure... another thing to pass other things around." However, something stuck, because the good programmer in me was referring me back to Guice when the bad programmer was whispering "static state singleton" in my ear. It did not take me long to start appreciating what Guice can do. Unfortunately, I found the Internet to be "not-so-good" for Guice examples, mainly for three reasons:
  1. The examples were too trivial to extend to real applications.
  2. The more complicated examples were doing really horrid things. (Like a singleton class that keeps the injector available for lazy and even not-so-lazy instantiations. Sorry, but why is this better? That's like taking an orange-overall crook, dressing him in a suit and calling him an honest politician. Uhh... wait... that's not what I mean...) 
  3. Guice does not lend itself well to already badly written code, hence the difficulty to find examples that deals with those situations. 
What made things a bit tricky was the Guice-rules I made for myself, either because it felt right or made understanding better (I am good with algorithm design, but find keeping a large complex system in my head a daunting task.)
  1. You have one injector and one injector only. Inject once and throw it away. The only exception I make to this is a cool trick in anonymous inner classes (more on this, later). 
  2. Keep the modules few, and put them in the same package as the program entry point. It is after-all the place where the module is used. 
  3. Do not go too far. You can easily over-guice and this DOES make matters worse. 
  4. Do not force Guice down the throat the people that will make use of your code (i.e. if you are writing a library). There is enough of that in the computer world. 
The really first challenging problem that had be baffled was Apache's immensely beautiful enigeering marvel that is XML-RPC. One of the big problems with this library is the way in which the handlers get created. Apache uses its own internal reflection approach to create the class, which cuts Guice out of the picture. Fortunately (?), in their infinite wisdom, they created a RequestProcessorFactoryFactory interface which allows you do do the creation yourself. (It sounds almost like the proverbial "I know that you know, that I know that you know I know, did you know that?)

Regardless, in order to get this working another injector needs to be passed to the servlet, violating my first rule. However... I found a workaround. I'll let the code speak for itself. Here goes:

First the main class where everything gets wired up. Simple and self-explanatory:


Secondly, the servlet. This merely redirects traffic to the handler and sets the factory. Note the injection. Also note the absense of an injector:


Thirdly the handler with some test injection (demonstrating that we can inject anything we want). It merely echoes the request:


...and lastly, the module. The magic happens in the getRequestProcessorFactoryFactory provider. Have you ever had the need to write an anonymous local inner class within yet another anonymous local inner class? Well, now you do. I call it the Russion-doll pattern (anti-pattern?) Guice has access to the injector so you can merely inject it here as well:


So, the order of creation. The main class gets an instance of the SimpleServer, which needs an instance of a ServletContextHandler, which needs a RequestProcessorFactoryFactory which needs an injector to inject an instance of a new handler. Basically boils down to lazy instantiation which is set up in the module.

Wednesday, April 18, 2012

Doto

I've always had an issue with code like this: (event though I do it all the time)


Nothing wrong with it, but wouldn't it be nice to be able to chain those calls and avoid declaring that local variable?

I am currently reading "The Joy of Clojure" and came across the doto macro in clojure, which enables you to do the above like so: 
   (doto (new java.util.HashMap) ; or just (java.util.HashMap.)  
         (.put 1 "One")  
         (.put 2 "Two"))  
Nice!  But alas, I am forced to use Java by day so I tried to figure out the best approach to do this.  The first one comes to mind is this:
 new HashMap<Integer, String>(){{  
     put(1, "one");  
     put(2, "Two");  
   }};  

Which works perfectly except that it assumes you are the one constructing the object.  So I tried a more functional approach:


I believe I've gone and made it worse :(

I also tried a js implementation, which is pretty redundant for maps/objects as object literals are built in:


I would love to see some alternate solutions/improvements or maybe event implementations in other languages!  


Friday, April 13, 2012

These Steps

We all can probably agree that there are too many to-do lists and step applications, websites, browser plugins, IDE plugins, etc.

I have had a look at a few, but I always end up with a notepad list or "//Todo" entries in my code.

Here is another one with a collaborative, documentary and multiple integration future:

Some features include:
  • A hierarchy of steps, with current edge steps ordered, unordered, tabs and options with leaf steps youtube, image, code.
  • Sharing of steps via a link or to another registered user.
  • Exporting to PDF.
  • Reference steps from other areas in the hierarchy.
  • Editing: copy, cut and paste steps (nodes).
  • Keyboard shortcuts for navigation and editing.
Some features that are in the works:
  • Exporting to Json.
  • Websockets for real time collaboration.
Some suggested features being considered for future implementation:
  • Cucumber support, such that steps are confined to the structure of a cucumber file, this would be awesome for collaboration between the developers and clients.
  • Gist support, such that a leaf step can reference a gist.
It is still under development but it looks promising, give it a try!

Tuesday, March 20, 2012

Gister - gists at your fingertips

So long time no post... been busy with a lot of real life stuff.

Introducing: Gister

Luckily I got some time to play again on Sunday night - and the result is a script called gister

gister can save, cat arbitrary files from gists, or execute them if they have #! at the top.

Why? I hear you asking silently to yourself. Well, the inspiration behind this was as follows: I was busy writing a script to execute a command for each commit in the history of a git repository. This resulted in the following script/gist: git-foreach.sh

Simple enough. This gist clones the repository, goes through EVERY commit in the repo (for all branches), and then executes a script that was passed in as an argument for each of the commits. So this resulted in yet another script, stored as a gist on github.

Cool, that's handy. Now combining the two scripts we get a nice newline seperated list of the number of files for each commit. Now let's say we want to plot this. Lets use gnuplot. But everytime I use gnuplot, I need to go re-study the syntax of the plot files for gnuplot. And everytime I do that, I end up with basically the same script that I've written 70 times in the past. So I decided, screw it. I need a better plan.

So that's where gister comes in. The idea behind this is to store all these handy scripts that you write, as gists on your github account, and then run them from the internet, right in your shell. So no need to download anything, or to put something in your PATH everytime you want to run a small script. You just install gister once, and you can cat/run/store any public gist on github. This also works for OTHER peole's gists as well, of course. So we can all sharea nd publish our neat little scripts online for people to use.

So go to and install gister. Download the single .sh file, give it +x permissions and (optionally) put it on your path, and start playing with it. I suggest creating a $HOME/bin directory, placing gister there, and then putting it on your path in your .bashrc . This will probably be where gister installs binaries one day should it get that functionality.

Here are some things you can do with it:

Get a response from the magic 8ball:

Get a gnuplot of the number of lines over time in any git repository (you need to chdir to the root of the git repo):

Play a simple maze game in your terminal:

It also supports passing arguments to the online gist, but appending a "-" followed by the arb arguments:

So there you have it. Play with a bit. It would be awesome if you guys could find any other interesting things you can run with gister on github. Remember the limitations though. The Gist MUST have a filename, and multi-file gists will not work at the moment. Of course, if you want to help out, here is what's needed in order of importance:

  • 'Anonymous' gists - ie. gists with no filename, just an id.
  • Multi-file gists

Those are all immediate featues, adding value which will be valuable later regardless. Now, what about the future? I'm thinking along this following lines:

  • Ability to install the gists locally, in $HOME/.gister_bin on something. Which can then be on your path.
  • Ability to track versions, sort of like a package manager for shell scripts. So gister -u runs through all installed gists and updates them
  • Ability to track not only shell scripts, but arbitrary documents. This needs to work both ways. I want to use gists to store notes, for example. So I would have a gist for all my notes, and install/track it with gister. Whenever I update a file, I use gister to upload all the changes I made.

So play with it a bit, let me know what you think. This was only tested on zsh. Bash should work. Other shells may not work.

Thursday, March 15, 2012

Knockout.js

I am no HTML, CSS or JavaScript expert, but I have seen some nice JavaScript libraries the past few weeks. Nico introduced us to node.js and I am sure everybody is familiar with jquery. Kaveen also mentioned HighCharts. Yesterday Marlo introduced me to Knockout.js which helps to "simplify dynamic JavaScript UIs by applying the Model-View-ViewModel pattern". I am not going to try and show you some code examples, because I think the Knockout.js developers have done a very good job themselves. Just head on over to http://learn.knockoutjs.com and play around with their "interactive coding exercises". Let us know what you think about the Model-View-ViewModel pattern..?

Friday, March 2, 2012

Find the bug - part two.

Nico, a wonderful idea! Here's my contribution:

The most complicated thing in the world to understand is concurrency. Not even Einstein's General Theory of Relativity comes close. Here is an interesting gem that I got from a newsletter quite some time ago. I found the puzzle incredibly interesting and it convinced me to NEVER EVER EVER EVER:
  1. Assume I understand concurrency.
  2. Use the old core Threading stuff rather than the new modern concurrency frameworks (i.e. Threading pools, etc.).
  3. Assume I understand concurrency.
  4. Skip testing threaded applications - because I'm clever, it makes sense... and besides I understand concurrency.
  5. Assume I understand concurrency.
Oh, I almost forgot, the most important rule is to never assume I understand concurrency (not even at a job interview at google)!

Look at the following Rorotika-inspired class and tell me what happens. Keep careful track of all the delays.

OSGi and your strong opinions

Most of you should know by know that I have started a new job yesterday. So far the Development Manager has pointed me towards the following educational slide shows of IBM:

OSGi Feature Overview:
http://publib.boulder.ibm.com/infocenter/ieduasst/v1r1m0/index.jsp?topic=/com.ibm.iea.wasfposgi/wasfposgi/1.0.0.0/Overview/wasosgijpafep_OSGi_overview/player.html

Modular and dynamic OSGi Applications Part 1: Motivations and specifications:
http://publib.boulder.ibm.com/infocenter/ieduasst/v1r1m0/index.jsp?topic=/com.ibm.iea.was_v8/was/8.0/ProgramingModel/WASV8_OSGi_part1/player.html

Modular and dynamic OSGi Applications Part 2: OSGi applications support in WebSphere Application Server:
http://publib.boulder.ibm.com/infocenter/ieduasst/v1r1m0/index.jsp?topic=/com.ibm.iea.was_v8/was/8.0/ProgramingModel/WASV8_OSGi_part2/player.html

OSGi is the "Open Services Gateway initiative framework" which is a "module system and service platform for the Java programming language that implements a complete and dynamic component model". Thank you Wikipedia.

I am still working through these. So far I like the fact that OSGi is a way of enforcing modular architecture and deployment as well as the fact that it is a solution to the multiple versions of the same class on the CLASSPATH problem. What are your strong opinions on OSGi and/or alternatives?

Meta-post

I enjoy looking at the statistics of our blog. Particularly those of the "traffic sources" and the "audience". These respectively show which sites refer to our blog and where people are located that visit our blog. We suddenly had a spike in the number of visitors from Russia. Unfortunately we cannot see which post(s) caused the traffic from these sources. Here are some screen shots for the statistics of the past week:

Audience

Traffic Sources

Thursday, March 1, 2012

Can you find the bug? Part One

With this year being a leap year and all, I've been looking at a couple of famous leap year (and general date) blunders tonight. It's quite embarassing how often we as programmers get date arithmetic wrong. I've read about a couple tonight, not the least being a bug in old apache commons-net which made files created on 29 Feb dissapear from FTP file listings!
Anyway, if I'm honest, I'm sure there is code out there that I've written that could also potentially have leap year problems. You need to be wary when working with dates. For example, doing something like:
    Date lastYear = new Date(today.getYear() - 1, today.getMonth(), today.getDay())
for working out a date a year back could be potentially problematic. So we should just be always wary of date arithmetic when writing such code.
In any case, this post has got another point: I want to start a sort of "game" or "tradition" on the blog if you will. I want to call it: "Can you find the bug?". The idea being, that whenever we come across a piece of code with a subtle, or huge, or blaringly obvious bug in our daily lives, we share it, and "challenge" the others to see if they can find it. Not with the idea of mocking the code or the author, but with the point of learning. And also testing our bug-catching eyes. Because there's no better way to learn than to analyse code that is actually running in the wild. Kind of like our own DailyWTF - but a bit more focused, and perhaps relevant.
Now we shouldn't be shy, it could be code we wrote ourselves (I know I've had a couple epic ones!).
Now today, I've got a doozy for you guys. I'm not going to give you the full story just yet... but let's just say this code comes from a VERY prominent IT company, and this was code that actually shipped in a product that this company delivered and was used by millions of people all over the world. This piece of code also made the product in question completely and utterly useless on a certain day. I want you guys to find out what the bug, and that day is. Bonus points if you can tell me the company/product in question. This bug is not limited to a certain, specific, once off day - it will happen on any day that fits a certain pattern.
The original code was C, and for the purposes of this excercise I took the relevant part and transcribed it into python. Here it is:

I've verified that the general case of the bug exists by running it myself. You can run the script with "python ". The point of the code was apparently to find out the year,month,day that a given value representing "days since 1980" falls in. I've just transcribed the relevant parts. Hope I didn't screw it up!
So, see if you can spot the bug. Additionally, what would you do to fix it?
Hope you guys enjoy! And if this works out to be a fun exercise we'll do it again!

The Good Saltmine Slave

An article about characteristics of good employees was circulated where I work and I couldn't help myself from reading it with the context of [database] saltmine slavery in mind. Here is a quick interpretation:

1. You ignore job descriptions - Willing to go into the deepest shafts to get the salt even when assigned a nice surface patch in the shade

2. You're eccentric - You rile up your co-slaves with your humour and positive working attitude even at the risk of angering the slave drivers - happy slaves == more salt and happy masters

3. But you know when to dial it back - when the slave driver cracks his whip, you work shut your piehole and work as if your life depends on it

4. You praise openly - You pat your slave friends on the back if they've gathered acceptable amounts of salt and tell them that the masters appreciate their effort

5. You complain in private - If some slave pisses you off, go beat him up somewhere deep in the mine - you don't want to start a riot and stop the others from gathering the precious minerals

6. Speak up when others are intimidated - When you haven't had food for 3 days(not less), speak up - if you die of hunger your bosses will get less salt and have to get new slaves

7. Like proving others wrong - that nice pocket of salt in the dangerous underwater cavern CAN be mined.  You do not just want the master satisfied - you want him to smile.  Possibly, other motivations can also play a role, for example stupidity.

8. Always fiddling - You always try to find ways to gather more salt, unselfishly ignoring the fact that you'll spend the rest of your (short) life in the hole you're digging to get it

Of course the article was not referring to slaves hundreds of years ago, but I had fun thinking this up.  Feel free to suggest improvements to my interpretations!

One last thing: Any parallels you might see to your own life or to people you know's lives is unintended.

Disqus is pissing me off

Bwhahahaha

For some reason, my personal account seems to be linked to the blog's disqus account. I just had a "whale" of a time (see what I did there) to try to sort out this confusion - and I've come to the conclusion that it's gonna be impossible.

I think what happened was that I was logged into the blog disqus admin interface when I logged into my google account, and now it seems my google account is forever linked to whaleventures disqus account.

Also, a comment from Dawid was logged as spam: http://whaleventures.blogspot.com/2012/02/managing-callback-spaghetti-in-nodejs.html#comment-452433000

I cannot see any reason why in the world that comment should be marked as spam.

So the point is, if any of you moderate using the whaleventures account, be sure to use an incognito window or even another browser or something. And, disqus just lost some major points in my eyes. Also, the fact that Wiehann had to find a work-around for notifications didn't make it start off on a lot of points either. Lets give it another week or so, but perhaps its prudent to start thinking of ways to migrate to another commenting system?

Wednesday, February 29, 2012

Dinosaurs and Programming

Ever since I can remember I've had a love for dinosaurs. Even now, I sometimes secretly dream of flying off into the African sunset on a Pterodactyl, gunning down antelope with a .50 caliber machine gun (see http://theoatmeal.com/comics/ptero). If it wasn't for computers (or computer games actually) I would probably have studied Archaeology.

Now, at this point in time you may be asking: "What does dinosaurs have to do with programming or Whaleventures for that matter?" Well ... a lot actually. Let me set the scene for you: I was 9 years old and in standard 1 (we still referred to it as standard 1 back in the day) when Jurassic Park was released. For a 9-year old dinosaur freak, this was the biggest thing since chocolate coated vanilla ice-cream. Every time I got a glimpse of a trailer or poster somewhere I would nag my dad about it. Finally; I think out of sheer desperation to shut me up; my dad took me to see Jurassic Park. However, there was one technical difficulty: Jurassic Park's minimum age restriction was 10, while I was obviously 9 years old. With a suspicious look from the lady at the counter, and a white lie or two, my dad got me into the theater. I was in for an awesome action-packed 2-hour roller-coaster ride that involved a T. Rex eating a man straight off the toilet, Velociraptors raining down death and destruction on the main cast and Brachiosaurus sneezing a ball of snot in a girl's face.

At the time, I din't notice it, but years later when I watched Jurassic Park again, something interesting caught my attention. One of the characters in the movie is a computer programmer by the name of Dennis Nedry (or Ned). If you didn't watch the movie, note: some spoilers are up ahead. He is basically the guy that was responsible for the downfall of the entire park. One set of scenes (right after the shit starts to hit the fan), is of particular interest where Samual L. Jackson (he goes by the name Ray Arnold in the movie) tries to get the security system of the park up and running again. Here is an outline of what sort-of happened:


In the abovementioned set of scenes we get to see a strange operating system, with some lines of code in a strange (or not-so-strange) programming language.

Thus, to kick off part 1 of our: "Identify the programming language / operating system in the movie / television program"-series the first challenge (which is not that difficult) is to identify the programming language in which the Jurassic Park system is coded. The first one to provide an answer (do not cheat!, I'm watching you) will get 500 internets for his/her efforts. Here is a hint (more or less) of what you'll be looking for when watching the movie:


The second challenge is to identify the operating system that is running Jurassic Park. Lex (the hacker girl) is also using it when she tries to lock the Velociraptors out during a chase scene much later in the movie. If you can identify this (without cheating) you'll be really hardcore and you'll win 20000 internets (seriously).

So, go to your nearest video store this weekend, and rent this excellent movie. You'll be amazed by the special effects (given that it was 1993), the action scenes, and more importantly: the DINOSAURS!!!

Managing callback "spaghetti" in node.js

Although node.js' evented I/O model works really, really great for writing tcp/http servers, which are inherently event driven domains, sometimes you just want to execute a number of steps in sequence, wait for them all to complete, and then take some action.

Let's take the example of adding some sample data into a test mongo database. This is a pattern you see a lot. Some test framework, be it mocha/vows/nodeunit whatever, it doesn't mater. But there is a before hook, and you want to populate the database with a nice set of initial data for your test.

Now normally, you would end up with what I call callback "spaghetti". A bunch of async calls, taking callbacks, being called in sequence, each taking the next step as a callback, until finally you end up with a heavily-spaghetti, difficult-to-follow piece of code. And it's always the same pattern over and over again. To give an example, here is some demo code using mongojs to populate a mongo db for testing:

Now as you can clearly see, this very quickly gets unwieldy and annoying to work with. Luckily, there is a pattern to get around this. It is mentioned in the book Secrets of the Javascript Ninjas by John Resiq (thanks Dawid for the tip). On a basic level, it has the following form:

So basically, you have an array of functions. These functions each do their work, and call the shared "callback" function. The "shared" callback function simply pops the first function in the array, and executes it. Next time, it again pops the first item, and executes it. Until the array is empty. At this point your sequence of steps is completed.

This is a very nice pattern, and something that I know I've come up with in some form of another a couple of times already. But I always love it when someone actually comes along and "solidifies" the pattern. I don't know what the pattern is called, I just know that I like it.

So, I thought, what about trying to make it even more generic? What if you can have some function, that takes a "done" functions, and a list of "step" functions (each taking a callback) which do their async work, and then calls the callback, that was passed in to them. So, I came up with this:

This node module exports a single function, waitForAll. This function takes a variable number of arguments (as is natural with any JS function). The first argument is the "done" function - this gets called upon completion of all the async steps. All the other arguments are then treated as async step functions. So inside the function, the list of actions, and the in-between callback function gets created. The in-between callback function is then partially applied as the first argument to all the action step functions inside the preparation code. This means that all functions passed in already have their first argument bounded to the internally created callback function. All that is left then, is to capture inside the internal shared callback function, the arguments that were passed to that function, and apply them to the partially applied function from the first step. This allows us to pass data from the one async step to the next. Consider the following test:

As you can see, the steps are now simply arguments passed to the waitForAll function. The first argument being the done function. Each step gets the callback, and all parameters passed in from the previous step. It is the single duty of each step to ensure that the callback() function gets called when work is done.

This means that, the first example becomes much much simpler to comprehend/manage:

A big win for readability in my opinion.

Raspberry Pi vs cstick Cotton Candy

Two similar ideas with very different prices :)

Raspberry Pi launched two models of their "mini-computer" (micro-computer?) today. Model A costs $25 while Model B costs $35.

FXI Technologies also opened the cstick Cotton Candy for pre-order and it costs $199.

Deep down, you know that IDEs suck

Let's not kid ourselves, most IDEs are pretty good in general. There is however, an area where they are particularly bad. That just happens to be the editor - the main component every developer works with!

Now, an editor is the main tool every programmer uses. Without a good editor, you are simply wasting your time. Most people will probably say that IDE editors are great because they have some form of code generation and type checking.

While that may be slightly true, the editor still is the most un-feature-rich part of all IDEs. The refactoring support may be useful, but it does not aid you in writing the text that is your logic. The IDE is nothing more than a simple text editor that has some hooks allowing you to see type errors / syntax problems / etc.

So what can we do about it? Sadly not too much :P The IDE frameworks are generally monstrous and do not allow for much customization. It seems strange to say, but Emacs got it right. An editor that allows the user to customize it completely. Similar efforts are going into Sublime Text 2 (which has Python at the core) and obviously VIM (with VIMScript). These editors are what people should be using to make themselves more productive. If the editor is missing something like a snippet expansion etc, the person using the editor can just implement it themselves and more importantly, share it with the world on GitHub :)

So what does an awesome editor, something like Emacs, not have? This is what IDEs have tried to solve, but mostly very badly. It simply needs the interaction with the compiler and/or linting system. One technology that enables this is the SWANK protocol. The SLIME mode in Emacs uses it and the Clojure guys have managed to use it to create very nice tooling for Clojure.

ENSIME is another gem, it is a server (and Emacs mode) that caters for Scala and to a lesser degree Java. This means that the SWANK protocol is all that is needed for an editor to get these features (along with the editor actually being able to use this data in some way. ENSIME has very advanced Emacs support and integration is currently underway for Sublime Text 2 and for Vim. Very good stuff.

The point is, people find reasons to blame the IDE. Agreed, its a valid complaint and you have to wait for a while for the fix to propagate into the next release. Unfortunately, software like eclipse is, simply put, very, very poor. I don't care about the notion of a "workspace" and neither should the IDE / editor. Let me write my programs effectively, thats all I as a "professional" ask for. Let the stupidity die and lets really move forward!

Tuesday, February 28, 2012

I would like to have Funtoo

I am a gentoo fanboi, but I heard about Funtoo a while ago which is a different variant of gentoo, like Sabayon and also Google's ChromeOS according to http://www.internetnews.com/skerner/2010/02/google-goes-with-gentoo-portag.html. Both are from the same creator, Daniel Robbins. To me it seems that the major difference is that the portage tree is stored in git of which I am also a fanboi. I will be getting a new laptop soon and I am considering making the switch to Funtoo. I will post my experiences here.

Monday, February 27, 2012

First message in gmail

So for some reason today, I wanted to find out when I registered my gmail account. I couldn't see any direct place on the UI or whatever, so I found out that if you go to https://mail.google.com/mail/#search//p99999999 it shows you the first message ever received.

Mine is my "Gmail is different" e-mail, which I'm assuming is like your welcome e-mail. It's dated 2004-09-01

Whats yours?

Saturday, February 25, 2012

Spatial Competitive Evolution

Okay, time to post some (semi-)tangible stuff.  The philosophical discussions have their place, sure... but that is mostly based on opinions and biases from past experiences.  Experience and empirical observation is, in my opinion, what this blog should be all about. (There I go again with philosophy... sorry, dear reader.) 

Ok, I am going to assume that you are familiar with Evolutionary Algorithms (EAs).  If not, where have you been? :-) No worries, have a look at http://en.wikipedia.org/wiki/Evolutionary_algorithm.

Some of the problems that I currently experience with the run-of-the-mill EA includes the following:

  1. The populations are simply too small.  Evolution does not work effectively with anything under a 1,000 individuals. The biological metaphor on which EAs are based, operates on hundreds of thousands or even millions of individuals.  Small populations tend to cause a dramatic drop in diversity with a high occurrence of genetic drift.  Representing a large population (say, 100k+) tends to be too expensive in terms of processor and memory requirements and problems which do allow large populations are typically simple, trivial problems.
  2. Selection tends to operate on the entire population space.  Again, this is unnatural and tends to produce algorithms with a higher selective pressure.  Do you really date someone from Japan, Jamaica and Portugal at the same time? ...and if you do, how do address the language barrier? 
  3. Most fitness functions are one-dimensional in nature.  Several characteristics are measured on a like-for-like basis (very similar to the zero-sum games of classical AI.)  What I mean by this is that a feature is identified (by the creator!) and individuals are measured in exactly the same way against that feature.  The evaluation is therefore rigid and static - and limited by some predefined bias.  This, in my opinion, is the true ball-and-chain of classical EAs. This often result in an "unfit" individual, with a small, yet break-through component in its genetic make-up (the super-genius in the wheel-chair) to become extinct.  Furthermore, a high selective pressure coupled with this, short-sighted fitness function really tends towards a hill-climbing rather than true evolution.
I am fully aware that many people with disagree with me on many of these points.  Thank you, you're more than welcome (please share why)... I am currently experimenting with a new idea (I think) that I call "SCE" or "Spatial Competitive Evolution", which tries to address these issues to some extent.  It has not been as successful (yet!) as I hoped, but I am continuing fiddling with it.  Here's the main ideas:
  1. The algorithm operates on a 2d grid (for now), where each cell represents an individual. Individuals can only reproduce and compete with its eight neighbouring cells (extending this beyond is of course also possible). This increases diversity remarkably well and take-over time takes much longer.  Unfortunately, genetic drift still occurs and larger populations are still required.  This is very similar to the "lbest" algorithm of Particle Swarm Optimisation.
  2. The fitness function is relative-based (that is, in competition with its neighbours).  The function varies in that only a specific evaluation region of the fitness function is applied during evaluation.  The fitness function itself evolves with the individual and has the ability to include all evaluation regions.  This allows different sub-sets of the population to excel at different aspects then elsewhere on the grid.  Eventually take-over will occur and the fitness function will evaluate all regions.  This is true evolution, where the environment change (the lion runs faster) and you have to adapt (as the gazelle, you better learn some camouflage... and if the trees disappear? ...well then you better learn to run faster!).
  3. Except for the fitness function and population representation, the standard EA is followed with standard mutation and cross-over functions.  Some changes come into play with the 2D grid, but these are rather intuitive.
Results... well... not that well at this point.  I've used the algorithm to evolve pieces of text that resembles a predefined line of text (text-writing Shakespearean monkeys comes to mind).  The fitness function starts off by evaluating a single letter and this then expands over time with the individual.  It takes significantly longer to find the final solution (compared to a vanilla GA), but it does eventually get there...

I often keep things like this secret... but I realise that sharing it on this blog will help in determining if this approach has any merit (especially with all these smart people on this blog!).  I will submit what I have on Github soon (and details to follow on this blog).  You're welcome to clone the repository, play with it and let us know if you find a working set of parameters.

Disqus-ting

Sigh, for the life of me ... I couldn't get disqus to send out multiple email notifications for any new comments that were posted. As a workaround, I'm forwarding all of the whaleventure gmail emails to you guys (and by you guys I'm referring to the moderators, duh!). This is the single email address that gets notified whenever a comment is posted on disqus. If you don't want to receive these emails, then just don't verify the forwarding-authorization email that you received. I don't know if there is a better way of doing this? If someone out there figured it out: you will receive an award of 57 internets if you can provide us with a solution, plus you'll be really metal and stuff.

Friday, February 24, 2012

The internet and its opinions and cliques

NOTE: Everything in this is related to the "technology"/"development" "community" roaming the twitters and the blogs and the forums and the mailing lists

The Internet is a strange beast. It seems to form opinions. Even though there are millions of people using it, and millions of people chattering and reading, popular opinions seem to rise up, and unpopular opinions seem to get lost.

It's like a sort of a crowd effect - you know, the kind of thing where a crowd of people get together, get all hysterical and then kill some "outsiders" because they walk funny or sit strange or whatever.

This has been going on throughout human history. Crowds do strange things to us. They immediately create an "us" and "them" effect. Now I'm no evolutionary biologist, but I would presume it's got something to do with survival. People are quite receptive to "anti-them" sentiment, so much so that some of the worst atrocities in human history have been commited by powerful dictators stirring up and feeding on this sentiment.

And the fact is, these "outsiders" are classified not by any sort of objective assesment - it's simply hearsay that forms these opinions. And the opinions rise up, because they are powerful.

Ok, so enough with the abstract. What am I getting at?

Well, I feel the same things happens on the discussion channels on the Internet. The Internet is a quick moving thing - so quick in fact that it's hard to keep up. So the time to produce and consume information is limited. In fact, some forums of communication even have a strict 140 character limit!

This all lends itself to the fact that these "anti-them" and "pro-us" sentiment get the most attention, because they are the most powerful. They also tend to rise up, and become stronger and stronger over time. You see this a lot in technology discussions. An opinion by someone may start out like "I think x is better than y because of a and b". Then this gets disseminated into the big wide Internets, and then people either agree or disagree.

Now the very nature of the forums (I'm looking at you twitter) is that you need to be quick to respond. You also need to be short (there is after all a hard limit to the amount of characters you can send). This results in, not discussion, but bashing, or confirmation.

It is much easier to say "Yes! I agree with John that x is better!" or "No! John is wrong, x sucks." then to actually take on the arguments and reflect on them. This process then repeats and repeats, and in my opinion, you end up with camps. Little cliques who are vehemently pro-something or anti-something-else.

Now, I guess its human nature to form camps. To try and surround ourselves with people with similair ideas and notions. This is not conductive to argumentation or improvement though. And I feel that discussions on the Internet fall into this trap a lot.

So can we please stop putting ourselves in camps?

I don't think theres any point into forming these cliques. Its not conductive to open discussion, or learning in general. Just saying "x sucks" makes you blind to x. It doesn't make you knowledgable. You don't need to protect yourself by dissing "x" because you're afraid that you only know "y". You also don't necessarily need to always pronounce the pros of "y" at all costs. It's all good. We're all humans. There's no need for camps.

So, let's start getting rid of our cliques and our camps. Let's embrace the things that we like, but don't try to evangelise them. Let's also not be so afraid of things we don't like or know, that we completely diss them out of hand.

I'll start: Hi, my name is Nico. And I am a programmer, with opinions.
  • I like dynamic typing - even though I understand and see the merits in static typing
  • I like javascript for the server - even though I don't pretend that it's the next coming of Jesus Christ. it is still javascript after all
  • I dislike the boilerplate in Java - even though I understand the power of the community around that language
  • I've always loved python since I started using it - even though I think the python lambdas don't really work
  • I like Linux - even though I still play my games in Windows.
  • I love programming with functions - even though I realise that OO is still the predominant paradigm
  • I prefer closures over objects - even though I realise that an object is a closure, and a closure is an object

Thursday, February 23, 2012

Automating Jenkins job creation

So, here at work we've got a lot (and I mean a LOT) of git repositories.
We also got an underused build server which Gary and myself put up way, way back. Now my mission in life is to get this thing into peoples lives. If it saves one guy (such as myself) from forgetting to git add a new file he added, it would be worth it for that reason alone.
So, in any case, there are so many repos that it would be impossible to add them all by hand. Luckily, jenkins comes with a nice command line tool. So I though, I'll just write a script to import all the repos!
But then I saw, even better! They've got a REST API for creating jobs. Just go to http://your_jenkins_server/api to see the docs for it.
So in any case, this endpoint expects an XML file of the same format as it stores internally. So to get this format, I first used the "get-job" command on the Jenkins CLI to get an example XML file.
Then, the process seemed simple.
  • Get a list of all repos
  • Run through each of the repos, and clone them
  • If theres not a pom.xml, go to the next repo (its not buildable, thus doesn't belong on a build server)
  • If there is a pom, grab the groupId,artifactId and populate the job xml
  • POST the resulting job XML file to the jenkins server API
Sounds simple right? Well it was, actually. Guess what took the longest? Getting the damn groupId and artifactId from the XML file! For some reason, python's libxml2 didn't want to do XPath queries on the pom.xml, because of the super-awesome over-engineered XML namespace abortion. So, I had to resort to a hack to get the data from the XML. See if you can spot the hack in the code :)
Anyway, heres the code if anyones interested (and if we maybe find out it broke everything and need to reload everything :) )

Blog logo

I have been thinking of a logo for the blog. I searched the Internet a little bit and I quite like this cartoon drawing (even the "simple framework" one will do) from How to Draw Cartoons online . Maybe it can serve as some inspiration for Clemens? The author (Jeff Scarterfield) is very passionate about drawing and also has a similar view on creating things, which is something we all value. I don't know if we are allowed to just use the drawing. I would prefer if Clemens could create something that is unique though.

CraneCard - HighCharts

High Level overview -  I created a little reporting engine that takes a JSON file with a certain structure and produces the chart above.Within the engine the chart is generated from an HTML Table.

More Details Later...

What we've been up to

I think a summary of what we've been up to in our spare time is in order. These are only the things I know of, if there's anything else please let me know:
  • Cilib - Gary/Wiehann/Theuns have been busy working on this. I know Gary is very excited about their inevitable move to Scala
  • When Again? - A very interessting side project I've been working on with Dawid and Gary. Code is here
  • gapaint - Jaco's GA image evolution app. Very cool!
  • The above was used to create an animation of the doom logo here
  • jsdoom - my life hobby project. Creating a tribute to my favorite game of all-time, Doom. Code is here
If I left off anything, or there is anything else you want to add, let me know in the comments. I'll update the post.

The origins of Whaleventures

So, you may be wondering, what the hell is Whaleventures? What is the point of this blog? What do whales have to do with coding, or even anything in general? Other questions may be flowing through your mind at this point as well: Why am I reading this? Why should I care? What is the point ?

Let's start with a story. A story about a young boy (or girl for 21st century compliance) who likes to create. And learn. And learn to create. And create to learn. Now this boy (girl) doesn't have a name, because he is every one of us. He may still be inside of you today, however advanced your age may be. But the point is, this boy is there. He exists. And he likes to create. And he likes to learn. Sometimes he hides away, because he feels threatened or locked in, or not appreciated, but he is always there.

The story goes further that this boy likes openness, and freedom. And that's why he has an arrangement - an arrangement to escape. To escape from restrictions. To escape from rigidness. To escape from everything that wants to diminish or block creativity and learning. That want to monetise it, and direct creativity for any purpose other than pure creation itself.

Now whilst this boy realises that there is nothing wrong with creating things and selling them for money, he does miss the pure form of creation. And thus, he uses his whale to escape. To escape to the outside world, to the primitive world. To get out of corporate mumbo-jumbo and return to where creativity and learning can be pure. This escape, is his whale. And he does this on the big, vast ocean. An ocean of endless freedom.

Whaleventures is the ongoing story of creation and learning.

Whaleventures is a coding/tech blog. Whaleventures is also a place for ranting about technology. It's also a place where you can show off your newest creations. Whaleventures is also a place where we can learn from each other!

Whaleventures is a state of mind. It is about curiosity, learning, striving for better things. It is about experimenting, creating and exploring. It is about being careless, but also very careful at the same time. The art of creation is integral to each and every human being, and it is something that brings us all together.

Whaleventures is a celebration of the spirit of creation, in the purest possible sense. Because only by sitting on top of the little water splash on the whales' back, surfing through the big wide ocean, do you have the freedom to explore new things and ways of thinking and building. You're most certainly not gonna get that freedom if you don't actively look for it. No one will hand it to you.

You need to get out on your whale, into the big scary ocean, and start learning again. And creating.

Above all, life is about creating. And learning. And having fun.

Building your own IDE

So, recently, I've been dabbling a bit in node.js / javascript. This has led me to the conclusion that these monolithic IDE's we use every day, are a Bad Idea (i'm looking at you eclipse). Because of the bloatedness of IDEA/eclipse/netbeans for javascript / HTML development I went back to basics. Basically building my own IDE using smaller, more specialized components. So, my basic setup is as follows:
  • Sublime Text 2 - text editor and syntax highlighting
  • jslint - Lint tool for Javascript code. It's basically a syntax checker, together with a bit of static analysis
  • npm - this is the node package manager. Think maven. It can also run your tests
  • guard - this is a ruby gem I use to watch for file changes. It can execute arbitrary commands whenever a file changes
  • libnotify/notify-send - libnotify is used to make popups on the desktop
Right, so those are the pieces. How do they fit together though? Well, easy. Guard is setup to watch my source/views and tests. Whenever any of these changes, the complete test suite is run using npm, and the output is received as JSON. I then parse the JSON to create a popup on my desktop, which instantenously gives me the results of the unit tests. This works so well that I haven't really touched the browser in the last week to test my javascript code. Here's the code for the test running/popup: Here's my guard file: The popups look really nice. They are also quite customisable (depending on your notify backend). Try
notify-send "Test" test
on your PC to see what it does. Anyway, first post! Here's an example of the popup: