Pixelastic

You can clip our wings but we will always remember what it was like to fly.

Posts from June 2011

ParisJS #8

(The whole conferences were in french, but as I'm writing every post on my blog in english, I'll write this one too.)

Tonight I was attenting the 8th parisjs meetup. We had the chance to have it hosted at Valtech, in a very wealthy part of Paris, in somptuous quarters and a large room with giant screen (and great pizzas too).

Anyway, this time the meetup was split in two : first part was made of complete talks, while second part only had small lightning talks. With pizza and beer in between.

Wakanda

The first talk was about Wakanda. Wakanda is a complete suite of client/server Javascript which goal is to help create business oriented apps. It is created by the same company as 4D, but this time is completly open source.

The product seemed well done, but kinda monolithic : server side js, client side javascript framework, application studio, debugguer.

I can surely see it used for creating Intranet applications, for some very specific business cases. I have an ambiguous feeling about Wakanda. I think they did a very good job, the whole package seems really neat, the IDE is clear, client/server communication is smooth, etc. On the other hand I'm always suspicious of apps that can do everything.

(Note that I didn't try the product, I only heard about it tonight for the first time and watched a 20min presentation so that's a little light for me to give a precise opinion)

Joshfire Framework

A few months ago, @sylvinus from Joshfire told us that they planned to realease their framework, modeslty named Joshfire.

This is by far the most interesting presentation of the meetup. Joshfire is a javascript framework aimed at working seamlessly between any devices : desktop, mobile, iPad, TV, anything.

It's basic idea is to abstract to its bare bone any interaction. From what I remember, for any "page" you want to define you have to write two JSON structures.

One defines the data tree (what your data is), the other defines the UI tree (how your data can be interacted with). It also ships with some adapters (an adapter is the link between the UI Tree and a specific device).

All you have to do to port your Joshfire app to a new device is to write (or grab if it already exists) an adapter. The main logic and data code is the same for every device, the maintenance is now only focused on any specific device.

Even if the main idea of Joshfire is awesome, their documentation and licensing is even more awesome : the project is already completly documented, with examples and is also completly free and available on github.

CSON, no sorry, JISON

@jie was supposed to talk about CSON, a compressed JSON. But as he already gave a very similar talk (about BSON) at the last #parisnode event, he changed the subject.

I'm not really sure what the real subject of the talk was. I think he mentionned compiling Javascript into Javascript (much like CoffeeScript), but it eventually turned into a Jison demo.

Jison seems to be a tool for automating lexing and parsing languages, to output new code. In effect, this could allow for transforming a custom language into an existing language. CoffeeScript, Haml or Sass works that way : they take a new language as input, and return Js, Html or Css as output.

The advantages are that the custom language is usually much more concise, easy to write and easy to read.

Anyway, this presentation was full of nice quotes :

The language I'm about to show you is totally useless.

Pipe ? What is that ? Oh, you mean the strokes.

The bad thing about Jison is that its documentation is crap

Why does it work ? It was supposed to fail !

Overview of a dev life

This talk wasn't about any new shiny technology. It was about those old browsers and bad habits we had 10 years ago, and how we still managed to make great websites.

This remind me of the "good ol' days" when I discovered the web with FrontPage and ClaraSoft. When IE6 was considered a modern browser.

@molokoloco show us that he managed to simulate ajax using nested iframe, had a website still online and running even after 10 years, was able to code full websites in 3 days, and had read more than 50.000 blog posts. And all that while still using Windows and Dreamweaver.

(Small side note : I praise both @molokoloco and @jie for what they managed to do. I know how easy it is to procrastinate and configure UI, test new tools and IDE instead of getting things done. That didn't seem to be an issue for them.)

mongoDB

This talk was the first in the serie of lightning talks (less than 20mn). It was about mongoDB and how to integrate it in a nodejs app.

As I had never tried nor nodejs nor mongoDB I didn't quite grasp what it was really about. All I get is that in order to get a result from a mongoDB query, one have to go through 3 steps of connection to the DB. In the asynchronous world of nodejs, this doesn't work well, so each step has to fire a callback once executed.

From there, I was lost. There was something about manually calling a callback once initialized, but honestly I didn't get it.

Anyway, I learned from a small talk during pizza time that mongoDB was better than couchDB (performance-wise), and that one have to sacrifice binding to the altar of redundancy to get really fast response time.

Audio demo in less than 1kB. No, 800B. No, wait, 200B

This time the talk was a very fun demo. Using some simple minification techniques, Js was able to play a random music.

This involved encoding the wav file in base64 (taking special care of some chars), and then playing it in an audio tag. Adding a bit of random to play a different note on each loop.

Fun, but interesting.

Some words about the Observer Pattern

This talk was more about theory than practice. Maybe it was the late hour, but it didn't catch my attention as the other did. Maybe someone would re-explain it to me ?

Well, I got the general idea : coding a js snippet that hard code the name of the elements that should react is bad practice because of the maintanability nightmare it cause when elements are removed.

Instead, the speaker advocate the use of a MessageBroker. Some kind of general listener that then dispatch event to element registered to that event (am I right ?).

Then someone in the audience noted that the opposite pattern should work better : that every element registered itself to an event and react when such event is fired (am I still right ?)

Honestly, I really am not sure about this talk, so if anyone could fill the blanks and correct me, I'd be glad.

Sencha and Sencha Touch

I won't go into too much detail on that talk. This was a generic presentation of Sencha (formerly known as ExtJs). I already had the basic understanding of ExtJs (but not the expertise of some of the ExtJs experts in the room), so I was really only half listening.

Sencha is a great product. It is very similar to what Wakanda was showing in the first talk. It is destined to data-heavy applications with lots of numbers, columns, charts, pies, etc.

Sencha Touch is a mobile version of Sencha. It is iOS oriented and emulate the standard UI elements in HTML.

Mozilla Labs

A quick list of the Mozilla Labs projects. I honestly don't remember them all, except Tilt that is a 3D viewer of any web page. It simply calculate the DOM depth and create a pyramid-like structure that you can browser in 3D.

I'm sure that beyond the cool and shiny aspect, it can be useful as a debug/optimisation tool.

Conclusion

Once again, thanks to #parisjs for those talks, always inspiring and a way to meet new people.

For all the new readers, I have an unfixed bug in my comment section : your post can be invalidated if your are using Chrome with an email auto-filler. My custom anti-spam will flag you as spam because Chrome fills an hidden honeypot field.

Working on Wednesday #4 : Rails for Zombies

 

(I finally managed to update Ubuntu to the 10.10 version, configure Unity to make it more usable, and I'm not ready to start the RoR tutorial I wanted to start last week.)

I used vim this week (instead of nano) for very simple file editing. I will force myself to use only vim on wednesday to really learn it. I plan to completly drop Komodo Edit once I'll be familar enough with vim to gain more time than I lose.

Rails for Zombies

Anyway. I finally get to start the Rails for Zombies tutorial. And here is what I learned.

There are two distinct things I'm going to learn here : Ruby and Rails. I discovered that I was already familiar with a lot of basic concepts of Rails, thanks to cakePHP. Model and table convention, model relationships (belongs to, has many, etc) were exactly the same.

Ruby on the other hand was new. But also very interesting. No need to add () after a method to call it when no args are passed, possibility to chain method of the same object (much like jQuery) and the use of dynamic (yet strongly typed) vars.

The first part of the tutorial (basic CRUD) was easy. I didn't find how to make a complex SQL query like this (cake) one :

$Zombie->find('all', array(
'order' => array('Zombie.graveyard' => 'ASC', 'Zombie.name' => 'DESC'
));

I guess it's just a matter of time before I learn how to to do in Rails anyway. I saw that there was more "advanced" method (much like the cake find method) that would surely allow such finding.

Part 2 : Validation and Relationships

The second part of the tutorial was more about models. Validation rules were pretty much the same as those of cakePHP. But the Ruby syntax makes it more concise.

I couldn't find how to retrieve the validation errors when saving an object using the create method (no problem when manually calling save, though).

I enjoyed being able to create binded instances by simply adding the binded element to the model. Not very clear isn't it ? Here some code to explain it better. The last two lines have exactly the same effect :

class Zombie < ActiveRecord::Base
end
class Weapon < ActiveRecord::Base
belongs_to :zombie
end
Weapon.create(:name => "Rocket Launcher", :zombie_id => 2)
Weapon.create(:name => "Rocket Launcher", :zombie => Zombie.find(2))

Later on, I had to select all weapons binded to a specific Zombie. I was able to find the a specific zombie using any of the two following commands :

z = Zombie.where(:name => "Ash").first
z = Zombie.find(:first, :conditions => { :name => "Ash" })

Then, I wanted to find the weapons binded to this zombie. First I tried the following command :

Weapon.where(:zombie_id => z.id)

Obviously, this worked. But I wanted to test some more of the Rails magic. So I tried something along the lines of what I did in the previous chapter and tried to use my z var directly instead of z.id.

Weapon.where(:zombie => z)

This didn't worked. Well, I guess I'll also learn why later one. But one even more weird thing is that the following command did work even I'm not really sur why ?

Weapon.where(:zombie_id => z)

That's all I did today (well I also did some more Mercurial an Dingux testing, but I that wasn't really work)


Alternate content with SWFObject

SWFObject allow a web developer to add an alternate content in place of the swf file is the user doesn't have flash installed.

In the case of a web app this is great to provide your user with a link to the Adobe website. You then tell your users Flash is needed and provide a link for them to install it.

Unfortunatly, if for one reason or another the swf file you try to load is unreachable (maybe your host is down ?), SWFObject will display the same alternate content. Meaning that a user with a perfectly correct Flash version will see an error message telling him that he does not have Flash when in fact the error is on your side.

That's not very user friendly and makes you look bad.

So, to fix this, I added two error messages as alternate content :

<div id="alternateContent" class="alternateContent">
<div class="noFlash message">It seems that you do not have the Flash player installed. Please install it, by <a href="http://www.adobe.com/go/getflashplayer" target="_parent">following this link</a>.</div>
<div class="error404 message">Sorry, we were unable to load the game. Please try again in a few moments.</div>
</div>

Then, in CSS I decided to hide them both :

.alternateContent .message { display:none; }
.alternateContent.noFlash .noFlash { display:block; }
.alternateContent.error404 .error404 { display:block; }

And finally, in Javascript I checked for the current Flash version. If it's equal to zero, it means that Flash is not installed, so I display the noFlash error message, otherwise, I guess it's a 404 error and display the other message.

var flashVersion = swfobject.getFlashPlayerVersion(),
alternateContent = $('#alternateContent')
;
// Displaying one message or the other
if (flashVersion.minor=='0') {
alternateContent.addClass('noFlash');
} else {
alternateContent.addClass('error404');
}

This is not bulletproof : I only test for two cases. And a better solution would also have been to put the error message dynamically using Javascript instead of polluting the HTML markup with contradictory text.

SWFObject must be included in the <head>

We just discovered a strange behavior on one of our test VM (one without Flash installed). I don't know how we've missed it before.

When embedding the main flash file of our application, the alternate content wasn't displayed to players. In fact it seemed to be displayed very briefly then disappear.

I had correctly embeded it with the static publishing method and added a call to swfobject.registerObject to soften the edges. I remembered it working correctly in my tests, so I quickly made a small test case.

It occurs that the alternate content was corretcly displayed if I removed the swfobject.registerObject call and only used the static publishing.

I also found that everything worked fine if I called the swfobject.js file in the head, but started to bug when I moved it at the end of the page.

As I didn't want to add a call to a .js file in my head, I google a bit and I finally found that one have to call swfobject.switchOffAutoHideShow(); right before the swfobject.registerObject call. This seems to fix things by not hiding the alternate text

Edit

I spent some more hours trying to debug the last corner cases. We had a user using Firefox 3.5.3 with Flash 10.0.42.34. Using SWFObject, we required at least version 10.1. Unfortunatly, the app was still loading, but was buggy because of features not present in the user flash version.

After some tests, I discovered that the swfobject.js code MUST be included in the <head> of the document (well, before any .swf in the page, so better put it in the <head>).

Doing so, you won't even need the previous fix (swfobject.switchOffAutoHideShow()).

I would have loved putting it at the end of the page, with the others JS files, but I guess I won't have a choice here.

Working on Wednesday #3 : The long path to get it done

This morning I started reading a lot of online blog post, framework description and other webdev material online I had in my bookmarks. After reading them, I saved them on my pinboard account to find them easily later.

Lot of good JS and CSS framework/libraries in there, I hope to be able to test them soon.

I also check my mailbox and respond to mails from my normal job. I shouldn't. I'm on a day off, I have to force myself to completly cut out those external calls.

Now, let's the work begin

Anyway, I finally finished the vimtutor. I still have a some difficulties to remember the mapping of the basic hjkl movement keys (I always want use k to move down instead of j). However, I feel confident enough in it to try writing my new code in it.

So, I headed to the Rails for Zombies tutorial. I thought it was free but the "win $5 worth of online teaching" / "next course costs $5" make me doubt it a little. Well, we'll see.

After registering to it, I wanted to save my login and password to KeePass as I always do.

Unfortunatly, KeePass on my Ubuntu machine works by using mono, and the keyboard interaction weren't that good (caret is slightly misplaced, inputs lags before getting displayed, text selection is weird). So I thought "Hey, let's see if there is a new version". Big mistake.

It appears that there was indeed a new version, a real one, with apt-get and stuff while mine was some hackish install I manually made a few month ago.

But wait, this means manually adding a ppa directory. No big deal, I trust the author. What ? Still doesn't work ? Hmm, I see. I need mono 2.6, and I only have 2.4.

What ? 2.4 is the latest available version on Ubuntu 10.10 ? You mean I must upgrade to 11.04 ? Hmm. Why not. I'll have to do it eventually, so let's go.

So I ran all my updates, to have the most up to date system. Unfortunatly, language-pack-gnome-fr doesn't want to upgrade so the OS upgrade isn't displayed.

Wait, what am I doing ?

And that's when I remember that my initial wish was to learn Ruby on Rails and that I was now on the road to upgrading my whole operating system. That is not exactly speaking procrastination, but it makes me do so much other things that my initial goal that I really looks like it.

I finally managed to purge my packets, upgrade to 10.10 and then to 11.04. But this took me 4 hours, and now it's 11PM and I guess I won't start this rails tutorial today, after all.

cakePHP : Fatal error: Class 'Controller' not found

Last Friday, just before turning off my computer and going home, the cake project I'm working on was displaying a scary Fatal error: Class 'Controller' not found in /var/www/project/app/app_controller.php on line 5

Today, I'm getting back to work and here's what happened. After a morning of trial and error, I finally reverted back to a previous svn commit, then re-updated to the latest one and it seemed to solve the issue.

But later on the day, after another update, it started bugging again and the error message wasn't very helpful.

After much googling, this bug report gave me a hint : I had new models but didn't create the corresponding tables. Strangely, creating the missing logs table for my Log class solved the issue.

Hope this blog post will be usefull for anyone else struggling with this error message.


Working on Wednesday #2 : Why I want to quit PHP

Here it is : my first Wednesday off. Well, not completely off because I had a technical meeting this whole morning, and my cousin dropped by in the evening so... I finally didn't have as much time reading and learning as I wanted to.

Anyway, those past weeks I started thinking about what I intended to learn, and why. The main reason is that I want to be able to build website and apps faster, with less hassle and better overall quality. And the more I thought about that, the more it became obvious that PHP was the main bottleneck.

My journey accross PHP land

I've been writing PHP for the last 12 years. I started as a script kiddy, putting things together, hacking strings, saving stuff in databases, building my own toolbox and finally making websites out of it.

Then, as I started my first job in a web development company, I started to organize stuff to be able to use and reuse code accross projects.

Later, when I started as a freelancer, I learned cakePHP, and it let me much more time to focus on each project while still reusing the common code of previous projects easily.

PHP is just so easy

I can be considered a PHP coder. I have some years of experience to consolidate that. Nevertheless, I don't consider myself "good" at PHP. I just write PHP, and that's all.

I think there isn't any flavour in writing PHP : it is so easy anyone can do it. I don't feel like I know those special stuff that can make one an "expert". PHP just feels so easy, you just write code and it works.

The only area where I can think that my years of experience can be used is in tracking PHP bug or weird error messages (If you haven't read this website, go now).

It just does not feel right to be able to say "Yeah, you should work with me. Why ? Because my strength is that I'm very good at understanding PHP bugs".

There is no "PHP Philosophy", no good practices that were kept in mind by PHP lead developers when they wrote the language and they wanted us to follow. Instead, we just have a bunch of functions, and play with it as in a sandbox.

Adding some pattern in this mess

Over the years you learn (the hard way) how to organise your code. PHP5 gives a little hope by adding more OO features. No need to get back on the namespace delimiter choice, this is one more example of the PHP weirdness we'll have to work with.

The best thing that happened to me in PHP world over those years is cakePHP. It took me quite some time to get it, having to learn the whole MVC pattern (and deal with some of cake internal inconsistencies/limitations) but the result was worth it.

A clear separation of model structure, controller logic and view rendering gave me my sanity back. I does abstract a lot of things, and makes things cleaner on the outside, you can just concentrate on writing your app code.

But even with cakePHP, you still have to write PHP.

Summing up

So, to sum up, here are my feelings about PHP

  • No peculiar love for the PHP syntax and (non-)patterns
  • Growing list of bugs/inconsistencies you have to work with
  • Don't feel like I'm any better than any new PHP coder, no skill required
  • Best thing in PHP is cakePHP, an external framework

That's why PHP is the first language I'll drop in my new learning, and I'll replace it with Ruby.

Ruby seems to fit more in my vision of a language that tells its developers what are the good and bad way of writing code. And as cakePHP is largely based upon Rails, I think catching up won't be too difficult.

Also, Rails just realease it's version 3, so now the best time to learn it from scratch.

Next week

This first day off was much shorter than I expected it to be. I wanted to start coding some Rails code, following the Rails for Zombies tutorial. I also had plans for using vim a little more.

Next week I might write about vim, or maybe how to organize javascript code, depending on the time I had.

Ghost posting on FB.ui streams

We had a bit of an issue when launching our app a few weeks ago. Everything was working fine on our test apps, but when live, all the stream messages we posted (we call them "Sharings") had a random text appended.

Most of the time it was a generic Facebook text, but sometimes it was a creepier SQL request just displayed plain on the user feed.

The Facebook text was (for the sake of search engine goodness):

Facebook is a social utility that connects people with friends and others who work, study and live around them. People use Facebook to keep up with friends, upload an unlimited number of photos, post links and videos, and learn more about the people they meet.

As the issue only occurs in production mode and never on any of our test environments, this was pretty difficult to debug.

Here was the code used to post the Sharing :

FB.ui({
[...],
'title' : 'Title of the Sharing',
'caption' : 'Text of the Sharing'
});

As I later found out, the caption key is not supposed to hold the Sharing text. The description key should be used for that. I'm not exactly sure was caption was for, but it seems that if you let the description key empty, then Facebook fills it automatically with a placeholder text.

The solution simply was to put the text in the description text, and leaving the caption key empty :

FB.ui({
'title' : 'Title of the Sharing',
'caption' : '',
'description' : 'Text of the Sharing'
});

As this behaviour is counter-intuitive, undocumented and random, I think posting it here could help other lost souls like me.

SWF caching issues accross browsers

Here are some quick notes on various browser caching behavior. I was fiddling with Wireshark to optimise my caching strategy and found some quirks one should be aware of.

First, let's define some reload vocabulary.

  • initial load is the first time the page is loaded, when the cache is empty.
  • hard reload is the classical reload. Clicking the Reload icon, or pressing Ctrl+R / F5.
  • link reload is when the page is loaded again after you click on a link to it
  • soft reload will be loading the page again by pressing enter in the address bar
  • navigational reload is the reloading of a page that occurs while using the previous/next buttons.

For the rest of this blog post, we will assume an HTML page loading the same .jpg file multiple times and the same swf file multiple times too (we will use both IE specific and general swf markup).

The html itself is not cached.

Also, all those static assets will have a Cache-Control:max-age=29030400 header.

All the network tests have been made using Wireshark.

Chrome

Initial load : Download of jpg and swf once each. Perfect.

Link reload & navigational reload: Nor jpg nor swf is loaded again. Perfect.

Soft reload & hard reload : The jpg is downloaded again but not the swf. Chrome sends a Cache-Control:max-age=0 header to the jpg request, to force loading it again.

Reloading images is a standard behavior on images, but I wouldn't have expected it on soft reloads.

Safari 5 Win

Safari behaves much like Chrome, with one important difference. It does not cache swf files at all.

Initial load : The jpg gets downloaded perfectly, but the swf gets downloaded multiple times, one per instance.

Link reload & navigational reload : The jpg is correctly fetched from cache, but the swf are all downloaded again. No swf is ever cached.

Soft reload & hard reload : Much as Chrome, Safari forces the reload of the jpg here. As you might guess, it also reload all the swf too, multiple times.

It means that Safari 5 does not cache any swf file at all. That's pretty impressive.

This same caching bug is talked about on this other blog. I've also tried including flash files from within another flash file (much like the Satay method). The results are the same : no swf flash is ever cached, even in the same html request.

It is supposed to have been fixed in Safari Mac (anyone can confirm this? I don't own a Mac) but the issue is still here on Safari Windows.

IE6, IE7 and IE8

IE6, IE7 and IE8 behaves the same here. They have a less severe version of the bug than Safari 5. At the time of writing I didn't have IE9 to test on it.

Initial load : Same bug as Safari here. The swf are downloaded multiple times, once for each instance. The jpg is only download once.

Link reload, navigational reload and soft reload : This time, everything is fetched from the cache. Actually, even the html is seems fetched from cache (I didn't investigate that much)

Hard reload : Html and jpg are fetched from the server, swf file stays in the cache.

It appears that (surprisingly) IE behaves quite well. Its caching behavior is more aggressive than the others (soft reload is really soft). However, it still have a nasty side effect of loading swf files multiple times on the same page. Shouldn't happen a lot in the real world, but still nice to know.

Firefox 4.0

Initial load : No issue arising. It does fetch each resource once.

Link reload, navigational reload and soft reload : Fetches everything from cache, nice.

Hard reload : Re-request jpg and swf files by adding a Cache-Control: max-age=0 request header. This feels like the expected behavior.

 


Take care of that favicon

Even if you are not referencing it in your HTML markup, browsers will try to get a file named /favicon.ico on your server root. Let's see some good practice regarding this file.

Make it small

The smaller the file, the faster it will get downloaded. As it is a less than important file, we don't want to delay the loading of our page for such a tiny graphic. The default file format for such a file is image/x-icon, meaning the .ico extension.

I think it's a Microsoft legacy format, but well understood by every browser. Be careful when putting your favicon, don't just find a cool .ico file and drop it here. Icon files are containers, they hold various image format ranging from 16x16 to 512x512.

You clearly don't need the bigger one and the 16x16 will be highly enough. So, be careful.

The best way of creating the favicon I've found is to first create it as a .gif, then running ImageMagick upon it. On Linux, this means running

convert favicon.gif -resize 16x16! favicon.ico

Make it cacheable

This file will be requested by the browser on every request, so you'd better make it cacheable to limit the number of requests.

Also, note that you can't change the name of the file, favicon.ico will always be fetched.

I choose to cache mine for a year, like any other static asset. I could have gone for a month, to allow updating them more often but I've never ever changed a favicon, so a year seems better.

A note on Safari Win

From the tests I've done, almost all browsers behave the same regarding favicon fetching and caching : the fetch it last, and do not issue a Cache-Control:max-age=0 on a refresh to force redownloading it.

Except Safari Win. It fetch it along other downloads and re-dewnload it on a page refresh.