tag:blogger.com,1999:blog-50162513686108226672024-03-19T03:20:35.050+00:00SIGSTPOn programming in Perl and other random bytesjetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.comBlogger36125tag:blogger.com,1999:blog-5016251368610822667.post-24317921525161159942015-08-23T20:19:00.000+01:002015-08-23T20:27:18.529+01:00Amazon AWS EC2 and Cluster SSH<div dir="ltr" style="text-align: left;" trbidi="on">
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_VtlgemZvUiHfNDL2ulFnBLOQuLDbd-VxqVFViNE2ukk6pJnsHD7mOQASU86-_mjmJJ5WaDdDwvAh9BAaj83z01Kc3dfCRg-sK3Tzrsbxm07MIeUdpAuWFq1vGTamRA8dnlHJ3ffh3tk/s1600/plow.h6.jpg" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_VtlgemZvUiHfNDL2ulFnBLOQuLDbd-VxqVFViNE2ukk6pJnsHD7mOQASU86-_mjmJJ5WaDdDwvAh9BAaj83z01Kc3dfCRg-sK3Tzrsbxm07MIeUdpAuWFq1vGTamRA8dnlHJ3ffh3tk/s320/plow.h6.jpg" width="294" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">A devops engineer at work</td></tr>
</tbody></table>
<a href="https://github.com/duncs/clusterssh/wiki">Cluster SSH</a>, or its OSX incarnation <a href="https://github.com/brockgr/csshx">CsshX</a> are great tool to quickly connect to a collection of machines and issue interactive commands in parallel. You just configure them with a collection of machines called 'clusters', set your .ssh/config correctly for all those boxes and voila, you are now in the matrix.<br />
<br />
The problem arise when you run your stuff on Amazon's AWS on EC2 dynamic instances. It's impossible to know at a given time which instances are effectively running, and it makes your cssh (or CsshX) configuration useless.<br />
<br />
The good news is, Amazon provides <a href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/Welcome.html">an API to access and manage EC2 instances</a>. The even better new is there's <a href="https://metacpan.org/pod/Net::Amazon::EC2">a Perl package to access that programmatically</a>. So..<br />
<br />
Lets put EC2 API Access and Cluster SSH together: <a href="https://metacpan.org/pod/ec2-cssh">ec2-cssh</a><br />
<br />
<a href="https://metacpan.org/pod/ec2-cssh">ec2-cssh</a> is a small command line utility that queries the EC2 API for instances using configured sets of criteria (by tag, <a href="http://docs.aws.amazon.com/AWSEC2/latest/CommandLineReference/ApiReference-cmd-DescribeInstances.html">by whatever AWS accepts for filtering instances</a>) and generates a cssh (Cluster SSH) or a csshX (CsshX) shell command that connects you to all those maching boxes.<br />
<br />
What's even better is that ec2-cssh builds its configuration from several config file, at system level, user level, and current directory level.<br />
<br />
I'm not going to enter into details, but the idea is that you can do this:<br />
<br />
- Define the sets of instances (by tag, etc...) at project level, shared with all the devs in the project checkout in a file .ec2cssh.conf<br />
<br />
- Define your AWS credentials, your favourite cluster ssh command or your own preferred instances sets in the safety of your $HOME/.ec2cssh.conf.<br />
<br />
- Stuff can also be configured system wide in /etc/ec2cssh.conf<br />
<br />
Of course all of this is optional, and you can perfectly have one config file with everything in it.<br />
<br />
O, and by the way, <a href="https://metacpan.org/pod/ec2-cssh">ec2-cssh</a> is written in Perl.<br />
<br />
Hope you'll enjoy it!<br />
<br />
Jerome.<br />
<br />
<br /></div>
jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com4tag:blogger.com,1999:blog-5016251368610822667.post-89382762946504574702014-05-03T17:14:00.000+01:002014-05-04T23:42:45.330+01:00Image::Magick with Perlbrew.<div dir="ltr" style="text-align: left;" trbidi="on">
Image::Magick <a href="https://www.flickr.com/photos/krazydad/sets/72157628820473737/">is great</a>, but it's a pain to install if you are using perlbrew, or if your system's Image Magick library is out of date. After some googling I found that <a href="http://perltricks.com/article/57/2014/1/1/Shazam-Use-Image-Magick-with-Perlbrew-in-minutes">this was the best techniqu</a>e, but cpanm support is missing, making using Image::Magick very difficult to include in your application's dependencies.<br />
<br />
So I wrote a <a href="https://metacpan.org/release/Alien-ImageMagick">perlbrew + cpanm compatible Image::Magick perl package</a>.<br />
<br />
Note that it still depends on your perl to be build to generate the shared library libperl.so. So give it a go and if your perl is not compatible, it should tell you what to do:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">cpanm -v Alien::ImageMagick</span><br />
<br />
Then use Image::Magick as usual. Your application will have to depend on Alien::ImageMagick, not Image::Magick.<br />
<br />
Happy coding!<br />
<br /></div>
jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com2tag:blogger.com,1999:blog-5016251368610822667.post-56364765153538269992013-12-02T17:04:00.000+00:002013-12-02T17:09:34.687+00:00Blobs in Postgresql with Perl<div dir="ltr" style="text-align: left;" trbidi="on">
<a href="http://i.telegraph.co.uk/multimedia/archive/01565/blobfish_1565953c.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="200" src="http://i.telegraph.co.uk/multimedia/archive/01565/blobfish_1565953c.jpg" width="320" /></a>Are you using, or do you want to use Postgresql Blobs with Perl?<br />
<br />
Providing you are in the Moose ecosystem, here is <a href="https://metacpan.org/pod/Pg::Blobs">Pg::Blobs.</a> Pg::Blobs is a <u>role</u> that adds blobs handling methods to any Moose based package.<br />
<br />
Here is how to use it: <br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">package My::App;</span><br />
<span style="font-family: "Courier New",Courier,monospace;">use Moose;</span><br />
<span style="font-family: "Courier New",Courier,monospace;">with qw/Pg::Blobs/;</span><br />
<span style="font-family: "Courier New",Courier,monospace;"># Just provide:</span><br />
<span style="font-family: "Courier New",Courier,monospace;">sub pgblobs_dbh{ .. return the DBH .. }</span><br />
<span style="font-family: "Courier New",Courier,monospace;">1;</span><br />
<br />
Now your package My::App is capable of managing Postgresql blobs:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">my $o = .. and instance of My::App ..</span><br />
<span style="font-family: "Courier New",Courier,monospace;">my $blob_id = $o->pgblobs_store_blob($binary_content);</span><br />
<span style="font-family: "Courier New",Courier,monospace;">print $o->pgblobs_fetch_blob($blob_id);</span><br />
<br />
A couple of guidelines:<br />
<br />
Blobs in Postgresql are just numeric Object IDs. You WILL have to store them in a OID column for later retrieval. If you don't, there is no guarantee they will persist, as any <a href="http://www.postgresql.org/docs/9.1/static/vacuumlo.html">unreferenced blob can get vacuumed away</a>.<br />
<br />
You MUST wrap any blob operation in a transaction.<br />
<br />
Happy blobing!<br />
<br />
<br /></div>
jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com2tag:blogger.com,1999:blog-5016251368610822667.post-67407630468228882612013-09-17T13:57:00.001+01:002013-09-17T13:57:28.458+01:00Email::Postman - Yet another email sending package<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMb-HUsKim4N-G8nr9r-kECRbaYD8EhUuK4wykbGXD-hEBwbCF12Axjjf9GpIb25lvoZ6EW-kWk3Dr80-B3epOxI1vbcvMsyH9lEXQKcGFVS79szexCm2cBMONbFFaah4BeVMb2S3Dnxg/s1600/postman-pat.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMb-HUsKim4N-G8nr9r-kECRbaYD8EhUuK4wykbGXD-hEBwbCF12Axjjf9GpIb25lvoZ6EW-kWk3Dr80-B3epOxI1vbcvMsyH9lEXQKcGFVS79szexCm2cBMONbFFaah4BeVMb2S3Dnxg/s320/postman-pat.jpg" width="234" /></a></div>
I know I know, there is Email::Sender, and Mail::Sendmail, the 'send' method of MIME::Lite, Mail::Mailer and probably other ones I don't know about on the CPAN and also the good old pipe to /bin/sendmail trick.<br />
<br />
Each of them have their advantages, but none of them actually does what I wanted.<br />
<br />
<a href="https://metacpan.org/module/Email::Postman">Email::Postman</a> does all the following:<br />
<br />
- It can send anything that's compatible with <a href="https://metacpan.org/release/Email-Abstract">Email::Abstract</a> (<a href="https://metacpan.org/module/MIME::Entity">MIME::Entity</a>, <a href="https://metacpan.org/module/Email::Simple">Email::Simple</a>, rfc822 String, etc..)<br />
<br />
- It will manage multiple To, multiple Cc and multiple Bcc nicely.<br />
<br />
- It will report on each of the recipients individually.<br />
<br />
- It will speak to MX servers directly, according to the recipient's domain, so you don't need to manage a separate MTA to send emails.<br />
<br />
- It has got a straight forward interface:<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /><br />my $postman = Email::Postman->new({ hello => 'my-domain.com',<br /> from => 'postmaster@domain.com' }</span><span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">);</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /><br />my $email = ## any Email::Abstract compatible email.<br /> Email::Simple->create(<br /> header => [<br /> From => 'casey@geeknest.com',<br /> To => 'drain@example.com',<br /> Subject => 'Message in a bottle',<br /> ],<br /> body => '...',<br /> );<br /><br />my @reports = $postman->deliver($email);<br /></span><br />
The only thing you need to be careful about is that depending on the responsiveness of the distant MX servers, calling deliver can be slow. So ideally you want to use it through some asynchronous mechanism. <a href="http://sigstp.blogspot.co.uk/2013/08/get-bdeparse-piggy-back-through-gearmany.html">Gearman is a very popular one</a>.<br />
<br />
Give it a go!<br />
<br />
Jerome.</div>
jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com6tag:blogger.com,1999:blog-5016251368610822667.post-16439649090201002502013-08-15T20:00:00.000+01:002013-08-15T20:38:15.458+01:00The fuss about Gmail and emails.<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: inherit;">According to <a href="http://www.theguardian.com/technology/2013/aug/14/google-gmail-users-privacy-email-lawsuit">some recent news</a>, <span style="background-color: white; line-height: 21px;">"</span><i style="background-color: white; line-height: 21px;">Google has finally admitted they don't respect privacy</i><span style="background-color: white; line-height: 21px;">,". Understand </span>Google has "admitted" they scan Gmail emails for profit.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">I've been using Gmail for quite a long time now and well, this is no news at all. It's always been quite clear that by using Gmail, you agree that Google will scan your email content to target advertisement. This is how the (great) service remains free. No mystery there. Nothing to admit really, and as Google puts it, it's always been part of their standard Gmail ordinary business practises. <a href="http://en.wikipedia.org/wiki/Gmail">Since 2007</a>.</span><br />
<span style="font-family: inherit;">It's 2013 and <a href="http://www.consumerwatchdog.org/story/gmail-users-have-%E2%80%9Cno-reasonable-expectation%E2%80%9D-privacy">Consumer Watchdog</a> called the "revelation" a "stunning admission". Are those people so dumb it took them 6 years to realise what gmail is?</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">The answer is probably yes, given the fact that <span style="background-color: white; line-height: 21px;">John Simpson, Consumer Watchdog’s privacy project director has declared: "</span><span style="background-color: white; color: #333333; line-height: 18px;">sending an email is like giving a letter to the Post Office. I expect the Post Office to deliver the letter based on the address written on the envelope. I don't expect the mail carrier to open my letter and read it.".</span></span><br />
<span style="font-family: inherit;"><span style="background-color: white; color: #333333; line-height: 18px;"><br /></span></span>
<span style="color: #333333;"><span style="line-height: 18px;">What is striking in this statement is that the man clearly doesn't know what he is talking about. Sending an email the standard way (meaning without using any additional encryption techniques) has never been like sending a letter (understand a message hidden in an envelope). From the <a href="http://en.wikipedia.org/wiki/Email">late 60's/early 70's</a>, sending an standard email is more like sending a post-card without envelope wrapping. It will arrive at destination, but you can't expect the postmen not to have a quick look at it. By the way, this is how spam/malware/virus detection works.</span></span><br />
<span style="color: #333333;"><span style="line-height: 18px;"><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJzMfhxWYLkUy3cRB6YalWvn-bGfgXoy0uMBOlwB_SWMyc1rHq4tyNwT_M0ykLmxdGn0Gms6yfw4Nr0Onnuir_ysbW3Ev-_vVXcpZL5tfrhl4s2j0BDak8s1NSsfSQqxTodvJpH_BqKQE/s1600/Postcard_dubai_DL2.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="226" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJzMfhxWYLkUy3cRB6YalWvn-bGfgXoy0uMBOlwB_SWMyc1rHq4tyNwT_M0ykLmxdGn0Gms6yfw4Nr0Onnuir_ysbW3Ev-_vVXcpZL5tfrhl4s2j0BDak8s1NSsfSQqxTodvJpH_BqKQE/s320/Postcard_dubai_DL2.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">A good email analogy</td></tr>
</tbody></table>
</span></span><br />
<span style="color: #333333;"><span style="line-height: 18px;"><br /></span></span>
<span style="color: #333333;"><span style="line-height: 18px;">The fact that this John Simpson is not already aware of that clearly demonstrate his lack of technical culture, which is quite ridiculous and worrying for a guy who is a "privacy project director". If I was a "privacy project director", I would probably encourage people who actually care about their privacy to use encryption techniques. <a href="http://en.wikipedia.org/wiki/Email_encryption">Many solutions are available</a>, and again this is no news at all and used routinely by businesses.</span></span><br />
<span style="color: #333333;"><span style="line-height: 18px;"><br /></span></span>
<span style="color: #333333;"><span style="line-height: 18px;">All of that makes me think that 20 or so years after the incredible expansion of the web, and 40 something years after the invention of emails, the general public (by that I mean people who are not in IT) is still lacking essential basic IT knowledge. Like how do emails work (not in details of course), or how a website (a simple one) works. Probably the solution resides on <a href="http://coding2learn.org/blog/2013/07/29/kids-cant-use-computers/">better basic computer</a> education.</span></span></div>
jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com0tag:blogger.com,1999:blog-5016251368610822667.post-21947437370471984292013-08-13T16:23:00.001+01:002013-08-28T12:27:44.697+01:00Get a B::Deparse piggy back through Gearmany<div dir="ltr" style="text-align: left;" trbidi="on">
<a href="http://gearman.org/">Gearman</a> is a great tool to run asynchronous and/or distributed jobs over a cluster of machines. It's not a full general message queue ala <a href="http://www.rabbitmq.com/">RabbitMQ</a>, but a rather minimalist piece of software that is very simple to use, does only one thing and does it very well.<br />
To use gearman from your favourite language, the cpan provides two modules. The original <a href="https://metacpan.org/release/Gearman">Gearman</a> and the more recent <a href="https://metacpan.org/module/Gearman::XS">Gearman::XS</a>. For this post we're going to use the original Gearman, but you should be able to implement the example using Gearman::XS without much trouble.<br />
In a nutshell, writing for gearman is a two sides process, writing some client code and some worker code to actually do the job, with gearman just sitting in the middle and distributing the jobs:<br />
<br />
<div style="text-align: center;">
<span style="font-family: Courier New, Courier, monospace;">Client(s) <--> Gearman Deamon <--> Worker(s)</span></div>
<div style="text-align: center;">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div style="text-align: center;">
<span style="text-align: left;"><br /></span></div>
<div style="text-align: left;">
<span style="text-align: left;"><b>Vanilla gearman</b></span></div>
<br />
Let's have a quick pseudo code look at an asynchronous example inspired by the Perl package Gearman:<br />
<br />
<b>Worker:</b><br />
<br />
<span style="font-family: Courier New, Courier, monospace;"> <span style="font-size: x-small;">my $worker = Gearman::Worker->new(...);</span></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> $worker->register_function('sum' => sub {my $job = shift; calculate sum of decoded($job->arg) and store it somewhere });</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> $worker->work();</span><br />
<br />
<div style="text-align: left;">
<b>Client:</b></div>
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my $client = Gearman::Client->new(...);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my $handler = $client->dispatch_background('sum', encoded([1, 2, 3]), { uniq => some string unique enough });</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> ## wait for the job to be done</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> while( my $status = $client->get_status() && $status->running() ){</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> sleep(1);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> .. Retrieve sum from the storage and print it ..</span><br />
<br />
By the way '<span style="font-family: Courier New, Courier, monospace;">encoded</span>' and '<span style="font-family: Courier New, Courier, monospace;">decoded</span>' are entirely up to you, as long as they encode to bytes and decode from bytes. I personally use <a href="https://metacpan.org/module/JSON">JSON</a>, but it's a matter of taste (and performance but that's another story).<br />
Also, I deliberately skip the task sets and synchronous mechanisms as this is not supposed to be a gearman tutorial :)<br />
So here we go. You make sure that your gearman daemon is running, you fire up your worker script and while it's running, each time you run your client, it will print 6.<br />
You feel great. You've written your first minimalist gearman application and you're ready to gearmanize the rest of your long running and/or easily distributable code.<br />
<br />
<br />
<div style="text-align: left;">
<b>Why this approach is a pain</b></div>
<br />
So following the example, the temptation is great to just extend the worker like that:<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> $worker->register_function('my_long_specific_thing', \&gm_do_long_specific_thing);</span><br />
<br />
I guess that if you're reading this post, you probably already have something in your model code that is long and already packed into a function:<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> package MyApp::Object;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> sub do_long_specific_thing{</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my ($self, $arg1 , ... ) = @_;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> ...</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<br />
<br />
So in reality your gearman specialised '<span style="font-family: Courier New, Courier, monospace;">gm_long_specific_thing</span>' will probably look like that:<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">sub gm_long_specific_thing{</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my($job) = @_;</span><br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my $args = decoded($job->arg());</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my $application = .. Build or get application ..;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> $application->get_object( build object getting from args )->do_long_specific_thing( build arg1 , arg2 from the args);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">}</span><br />
<br />
Then you know the rest of the story. Every time you need something else to be gearmanized or every time you need to make a change to the arguments of one of your gearmanized method, you have to propagate your changes to the specific gearman registered functions. Your code has become a bit less maintainable, just because you want the benefits of gearman.<br />
<br />
<div style="text-align: left;">
<b>Fixing it</b></div>
<div>
<br /></div>
<div>
But what if.. you could write something like that:</div>
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">$client->application_launch(sub{ my $app = shift;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my ($oid) = @_;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> $app->get_object($oid)->do_long_specific_thing(1, 'whatever');</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> },</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> [ $oid ] );</span><br />
<br />
<br />
No more worker specific code to write. Everything is done from the application's point of view, leaving the back-end details out of the way.<br />
Want to change the API of do_long_specific_thing? No problem, just apply parameter changes where they appear in the code. No more headaches propagating the API change through the gearman specific methods.<br />
Want to make your gearmanized process longer without changing do_long_specific_thing? No problem:<br />
<span style="font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">$client->application_launch(sub{ my $app = shift;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my ($oid) = @_;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> $app->get_object($oid)->do_long_specific_thing(1, 'whatever');</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> .. and something else ..</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> },</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> [ $oid ] );</span><br />
<br />
What if you have another long thing to gearmanize? Well, you get the picture:<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">$client->application_launch(sub{ my $app = shift;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my ($oid, $arg1) = @_;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> $app->get_object($oid)->do_another_thing($arg1);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> .. and something else ..</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> },</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> [ $oid, $arg1 ] );</span><br />
<br />
<div style="text-align: left;">
<b>Implementing it</b></div>
<div style="text-align: left;">
<b><br />The client 'application_launch' method</b></div>
<div style="text-align: left;">
<b><br /></b></div>
<div style="text-align: left;">
Thanks to <a href="https://metacpan.org/module/B::Deparse">B::Deparse</a>, we can turn any sub into a plain string. The rest is trivial, so</div>
here we go:<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">## In some object that wraps the $gearman_client</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">## you can also inherit if you prefer. But I like wrapping more, cause you can store utilities.</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">sub application_launch{</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my ($self, $code, $args ) = @_;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> $code //= sub{};</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> $args //= [];</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my $gearman_client = $self->gearman_client() OR just $self;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my $deparser = B::Deparse->new('-sC'); ## C style</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my $json = JSON::XS->new()->ascii()->pretty(); ## I like pretty. I know it's larger but well..</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my $code_string = $deparser->coderef2text($code);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my $gearman_arg = $json->encode({ code => $code_string,</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> args => $args });</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my $uniq = Digest::SHA::sha256_hex($gearman_arg);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my $task = Gearman::Task->new('gm_application_do', \$gearman_arg, { uniq => $uniq });</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my $gearman_handler = $gearman_client->dispatch_background($task);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> unless($gearman_handler){</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> confess("Your task cannot be launched. Is gearman exposing the gm_application_do function?");</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> return $gearman_handler;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">}</span><br />
<br />
And that's pretty much it.<br />
<br />
<div style="text-align: left;">
<b>The worker 'gm_application_do' code</b></div>
<br />
The worker code is very similar.<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">$worker->register_function('gw_aplication_do', sub{ _gm_application_do($application, shift) });</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">sub _gm_application_do{</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my ($app , $job) = @_;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my $gm_args = $json->decode($task->arg()); ## Note you need a $json object.</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my $code_string = $gm_args->{code};</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my $code_args = $gm_args->{args};</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> </span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> my $code = eval 'sub '.$code_string;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> $code || confess("EVAL ERROR for $code_string: ".$@); ## That shouldnt happen but well..</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> ## This is not supposed to return anything, as we call that asynchronously.</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> &{$code}($app, @$code_args);</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> return 1;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">}</span><br />
<br />
<div style="text-align: left;">
<b>Adapting to synchronous calls</b></div>
<div style="text-align: left;">
<b><br /></b></div>
Adapting that to synchronous calls is quite straight forward.<br />
Remember gearman exposed functions should always return a single scalar.<br />
<br />
<div style="text-align: left;">
<b>Conclusion</b></div>
<div style="text-align: left;">
<b><br /></b></div>
<b>gotchas:</b><br />
<br />
<br />
<ul style="text-align: left;">
<li>This doesn't work with closures, so really your sub's should be pure functions and all parameters should be given as such.</li>
<li>As far as the magic goes, the parameters can ONLY be pure Perl structures; something that's serializable in vanilla JSON.</li>
<li>If you try to pass bless objects, bad things will happen.</li>
</ul>
<br />
<br />
<b>Disadvantages:</b><br />
<br />
<br />
<ul style="text-align: left;">
<li>Insecure. What if anyone injects sub{ destroy_the_world(); } in your gearman server. That's kind of easily fixed. Just implement some secure signing of the code in transit.</li>
<li>No strict control of what can be done through gearman. Developers enlightenment is the key here.</li>
<li>No strict control about what 'flavour' of gearman worker is running your code. Some people like to have specialised gearman workers exposing only a subset of functions. This can easily be fixed by adding a 'target' option to the application_launch method and exposing the same general purpose gm_application_do under different names on different machines. But again, choosing the right target falls under the developers responsibility.</li>
</ul>
<br />
<br />
<b>To sum up the advantages:</b><br />
<br />
<br />
<ul style="text-align: left;">
<li> Stable gearman worker code that's decoupled from the application code itself.</li>
<li> Flexible gearmanization of any application code you like.</li>
<li> Clarity of what's going on. No more parameter encoding/decoding to write, and no API change propagation through what should be infrastructure only code.</li>
</ul>
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRuIQs4CM2wCFxon0uKDGIdQbn7Orm9tVumd8cFzbcKP4kmH2FrnJA_CTgyEM8sSA9bGqDHXd2jbGkTtHLG6XXhI3MVfY_tuAjvcAD2XAmcR12E2o0yqJIvsozCR59D4UGxUuleCCFLy8/s1600/William-Adolphe_Bouguereau_1825-1905_-_Not_Too_Much_To_Carry_1895.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRuIQs4CM2wCFxon0uKDGIdQbn7Orm9tVumd8cFzbcKP4kmH2FrnJA_CTgyEM8sSA9bGqDHXd2jbGkTtHLG6XXhI3MVfY_tuAjvcAD2XAmcR12E2o0yqJIvsozCR59D4UGxUuleCCFLy8/s320/William-Adolphe_Bouguereau_1825-1905_-_Not_Too_Much_To_Carry_1895.jpg" width="215" /></a>Perl offers us the flexibility that empowers us to clearly separate code that deals with different concerns.<br />
As developers, we should take advantage of it and build reactive, flexible and generic enough business components.<br />
As an infrastructure developer, I don't really know what people are going to do with gearman, nor should I care too much. This approach let me concentrate on what is important: the stability, scalability and the security of my gearman workers.<br />
As an application developer, I don't care that I have to encode my functions parameters in a certain way. And I don't want to bother changing code in some obscure gearman module when I make changes to my business code. What I want is to use gearman as a facility that helps me design the best possible application without getting on my way too much.<br />
<br />
Hope you enjoyed this post.<br />
<br />
Until next one, happy coding!<br />
<br />
Jerome.</div>
jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com1tag:blogger.com,1999:blog-5016251368610822667.post-3871701952634504972013-03-25T21:12:00.002+00:002013-04-10T14:55:05.999+01:00Run Postgresql pg_dump from your scripts<div dir="ltr" style="text-align: left;" trbidi="on">
If you use Postgresql, you probably noticed that the command line tools who come with it don't accept passwords on the command line.<br />
<br />
That's a good thing, as it prevents other users of the system from spying your command line via ps and see your password.<br />
<br />
Ok, but what if you want to run let's say pg_dump from your script? Easy,<a href="http://www.postgresql.org/docs/9.1/static/libpq-pgpass.html"> just export an environment variable PGPASSFILE</a> that points to a file that contains your credentials. Note that this file MUST be in mode 0600, to prevent other users to look into it.<br />
<br />
If you use Perl, and <a href="https://metacpan.org/module/File::Temp">File::Temp</a>, that's exactly what it does, so here's a Perl snippet that uses pg_dump:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">my ( $cf, $cf_name ) = File::Temp::tempfile();</span><br />
<span style="font-family: "Courier New",Courier,monospace;">print $cf '*:*:*:*:'.$password."\n";</span><br />
<span style="font-family: "Courier New",Courier,monospace;">close($cf);</span><br />
<span style="font-family: "Courier New",Courier,monospace;">system('export PGPASSFILE='.$cf_name.'; pg_dump etc...'); </span><br />
<span style="font-family: "Courier New",Courier,monospace;">## Don't forget to unlink cf_name to avoid disk pollution.</span><br />
<span style="font-family: "Courier New",Courier,monospace;">unlink $cf_name;</span><br />
<br />
Also, don't forget to run in taint mode and sanitise everything you use to build your command. Managing correctly the returned value of the system call is left as an exercise to the reader :)<br />
<br />
Happy coding!<br />
<br />
J.</div>
jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com0tag:blogger.com,1999:blog-5016251368610822667.post-71208148968691371192013-03-21T15:16:00.000+00:002013-03-25T21:13:15.924+00:00Good old days Javascript<div dir="ltr" style="text-align: left;" trbidi="on">
Good old days Javascript:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">if( confirm('Are you sure?') ){ ... do stuff ... }</span><br />
<br />
Modern days fancy Ecma script (abridged):<br />
<br />
<ol style="text-align: left;">
<li><span style="font-family: inherit;">Think a lot</span></li>
<li><span style="font-family: inherit;">Write 100KB of untestable code</span></li>
<li><span style="font-family: inherit;">Instanciate a factory.</span></li>
<li><span style="font-family: inherit;">Build an anonymous function.</span></li>
<li><span style="font-family: inherit;">Don't forget to hoist your variables.</span></li>
<li><span style="font-family: inherit;">Fire a dozen async events in two different frameworks</span></li>
<li><span style="font-family: inherit;">Don't forget to use .promise()</span></li>
<li><span style="font-family: inherit;">Catch your events in a completely remote and random other place.</span></li>
<li><span style="font-family: inherit;">Build a jQuery UI modal dialog with appropriate call backs</span></li>
<li><span style="font-family: inherit;">Oh no, it's too slow in IE :(</span></li>
<li><span style="font-family: inherit;">Go back to step 1.</span></li>
</ol>
<div>
J.</div>
</div>
jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com0tag:blogger.com,1999:blog-5016251368610822667.post-39375086778241814012013-03-13T17:22:00.003+00:002013-03-13T17:25:58.862+00:00Mason - A Template system for us programmers<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: left;">
Templating Modules are a bit like editors. Every web application developer has a favourite one. And every template system is someone's favorite.</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
Mine is <a href="http://www.masonhq.com/">Mason</a>. But not because the Perl MVC tutorials are full of examples using Mason. Not because it's the fastest (use <a href="http://xslate.org/">xSlate</a> if you want to trade speed for flexibility). Not because it's the most popular. It's my favourite for a very plain reason: It makes me more productive and allows me to develop web GUIs using all the powerful features a programmer should biterly miss if they are taken away. That includes writing Perl code :P</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
I never heard of a business that went down because they didn't have fast enough CPUs, so I'm not fussy about trading a few CPU cycles for elegance, ease and speed of development.</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
Enough talking. Here's my contribution to the template holy war and Mason lobbying presentation:</div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="true" frameborder="0" height="389" mozallowfullscreen="true" src="https://docs.google.com/presentation/d/1cFqMisxivnoBaRz7bq4HbZlgA2OH6bA8vghF3c_X3xE/embed?start=false&loop=false&delayms=30000" webkitallowfullscreen="true" width="480"></iframe>
</div>
</div>
jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com0tag:blogger.com,1999:blog-5016251368610822667.post-2239969231784429362013-03-05T14:33:00.002+00:002013-03-05T14:35:22.261+00:00One more (good?) reason to consider NoSQL solutions<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/qpK0WAuyOl4?feature=player_embedded' frameborder='0'></iframe></div>
<br />
Btw, if you're convinced by this video - I know this is very unlikely - , <a href="http://www.amazon.co.uk/gp/product/1934356921/ref=as_li_ss_tl?ie=UTF8&camp=1634&creative=19450&creativeASIN=1934356921&linkCode=as2&tag=jerosplac-21">Seven Databases in Seven Weeks</a> is the book you'll like to read. It's very well written and gives you just the right amount of information so you can build yourself a broad and clear vision of what major NoSQL technologies can and cannot do for you.<br />
<br /></div>
jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com0tag:blogger.com,1999:blog-5016251368610822667.post-35343161677787540402013-03-02T19:46:00.001+00:002013-03-03T13:17:28.738+00:00The only bad thing about Mason<div dir="ltr" style="text-align: left;" trbidi="on">
At the moment, I'm writing a presentation about <a href="https://metacpan.org/module/Mason">Mason2</a>. The goal is to somehow convince my colleagues to consider using Mason. Instead of Template Toolkit.<br />
As part of it, I thought I'd do a bit of performance benchmarking against Template Toolkit. So I put together a reasonably complex mini set of templates using both systems. Well, as complex as TT can take in reality. <a href="http://sigstp.blogspot.co.uk/2011/01/perl-avoiding-htmlmasontemplatetoolkit.html">Which is not very much</a>.<br />
<br />
But anyway, let's jump straight to the bad news.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"> Rate Mason TT<br />Mason 901/s -- -51%<br />TT 1852/s 106% --</span><br />
<br />
As you can see, with similar settings (code caching enabled) and over 10000 runs of two pages, Mason2 is twice as slow as Template Toolkit. Mason2 is still below the millisecond per page in my benchmark, but still that's quite a big difference.<br />
<br />
As the common wisdom goes, CPU time is cheaper than programmer time, so it shouldn't be a big deal, given the huge gains of productivity you should get by using Mason2's very cool and powerful features.<br />
<br />
Stay tuned for the full presentation to come!<br />
<br />
PS: To follow up on the comments, feel free to have a look at the benchmark source <a href="https://bitbucket.org/jeteve/mason-pres/">https://bitbucket.org/jeteve/mason-pres/</a><br />
<br />
J. </div>
jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com9tag:blogger.com,1999:blog-5016251368610822667.post-79337739729064355292013-02-21T14:05:00.001+00:002013-02-21T16:49:25.392+00:00Give your application a shell (and never write any ad-hoc scripts again)<div dir="ltr" style="text-align: left;" trbidi="on">
<div>
As developers, we sometimes have to help operations going smoothly by fiddling with the data "by hand" because there's no GUI to allow people doing some rare and obscure things. One common way of doing it is by connecting to the DB and writing some SQL. But often, accessing your database is not enough, because you need your application code to be run.<br />
<br />
And for that, you need a shell.</div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_2JNAvwdCMXhLOUvnzkfgUMHtD7o_O2SDVh8DMU3gaEpf4NqwialqpIjXXUCx4zq83YzKO_Z-VNqN_1zOqzq5DxX_jWPiSwhCaVUVefw4vJ2dReesG2WsghkHAEY48noWma-W_N4gzws/s1600/Black_Walnut_Juglans_nigra_Nut_2400px.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="166" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_2JNAvwdCMXhLOUvnzkfgUMHtD7o_O2SDVh8DMU3gaEpf4NqwialqpIjXXUCx4zq83YzKO_Z-VNqN_1zOqzq5DxX_jWPiSwhCaVUVefw4vJ2dReesG2WsghkHAEY48noWma-W_N4gzws/s200/Black_Walnut_Juglans_nigra_Nut_2400px.jpg" width="200" /></a></div>
<br />
I mean a Perl application shell<br />
<br />
Perl offers a great module to implement this: <a href="https://metacpan.org/release/Devel-REPL">Devel::REPL</a> . By the way, if your using a debian based distribution and if you're wondering about the quickest way to install a CPAN module, <a href="http://deb.perl.it/debian/cpan-deb/#q=Devel%3A%3AREPL">CPAN ↔ Debian is the site you want</a> !</div>
<div>
<br /></div>
<div>
Let's say your application is called 'My::Bob'. In this example, it's fully implemented in the shell script itself, because well, it doesn't do much.</div>
<div>
<br />
So here it is, the magic bob.pl shell for your My::Bob application:<br />
<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">use strict;</span><br />
<span style="font-family: Courier New, Courier, monospace;">use warnings;</span><br />
<span style="font-family: Courier New, Courier, monospace;">package My::Bob;</span><br />
<span style="font-family: Courier New, Courier, monospace;">use Moose;</span><br />
<span style="font-family: Courier New, Courier, monospace;">## Application bob just holds a name and a couple of methods.</span><br />
<span style="font-family: Courier New, Courier, monospace;">has 'name' => ( is => 'rw', isa => 'Str' , default => 'Bob' );</span><br />
<span style="font-family: Courier New, Courier, monospace;">sub hello{</span><br />
<span style="font-family: Courier New, Courier, monospace;"> my ($self) = @_;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> return 'Hello, my name is '.$self->name();</span><br />
<span style="font-family: Courier New, Courier, monospace;">}</span><br />
<span style="font-family: Courier New, Courier, monospace;">sub count_to{</span><br />
<span style="font-family: Courier New, Courier, monospace;"> my ($self, $limit) = @_;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if( ( $limit // 0 ) < 1 ){ confess "limit should be >= 1"; }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> return map{ $_ } 1..$limit;</span><br />
<span style="font-family: Courier New, Courier, monospace;">}</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">package main;</span><br />
<span style="font-family: Courier New, Courier, monospace;">## The shell code starts here</span><br />
<span style="font-family: Courier New, Courier, monospace;">use Devel::REPL;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">## You probably want to skip output buffering</span><br />
<span style="font-family: Courier New, Courier, monospace;">$| = 1;</span><br />
<span style="font-family: Courier New, Courier, monospace;"># Build an instance of your application.</span><br />
<span style="font-family: Courier New, Courier, monospace;">our $BOB = My::Bob->new();</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">print "Hello, this is bob\n";</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">my $repl = Devel::REPL->new;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">## Inject the instance of bob in the shell lexical environment.</span><br />
<span style="font-family: Courier New, Courier, monospace;">$repl->load_plugin('LexEnv');</span><br />
<span style="font-family: Courier New, Courier, monospace;">$repl->lexical_environment->do(q|my $bob = $main::BOB ;|);</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">## Tell something useful in the prompt</span><br />
<span style="font-family: Courier New, Courier, monospace;">$repl->load_plugin('FancyPrompt');</span><br />
<span style="font-family: Courier New, Courier, monospace;">$repl->fancy_prompt(sub {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> my $self = shift;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> sprintf ('Bob (%s) > ',</span><br />
<span style="font-family: Courier New, Courier, monospace;"> $BOB->name()</span><br />
<span style="font-family: Courier New, Courier, monospace;"> );</span><br />
<span style="font-family: Courier New, Courier, monospace;">});</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">## Various autocompletion.</span><br />
<span style="font-family: Courier New, Courier, monospace;">$repl->load_plugin('CompletionDriver::LexEnv');</span><br />
<span style="font-family: Courier New, Courier, monospace;">$repl->load_plugin('CompletionDriver::Methods');</span><br />
<span style="font-family: Courier New, Courier, monospace;">$repl->load_plugin('CompletionDriver::INC');</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">## Allow multiline statements.</span><br />
<span style="font-family: Courier New, Courier, monospace;">$repl->load_plugin('MultiLine::PPI');</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"># And run!</span><br />
<span style="font-family: Courier New, Courier, monospace;">$repl->run();</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">print "\nThanks for using Bob. Bye\n";</span><br />
<br />
<br /></div>
<div>
Now, let's look at a session:<br />
<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">$ perl bob.pl </span><br />
<span style="font-family: Courier New, Courier, monospace;">Hello, this is bob</span><br />
<span style="font-family: Courier New, Courier, monospace;"> </span><br />
<span style="font-family: Courier New, Courier, monospace;">Bob (Bob) > $bob->hello(); ## Call any method.</span><br />
<span style="font-family: Courier New, Courier, monospace;">Hello, my name is Bob Bob (Bob) > $bob->name('Bobbage'); ## Change of name is reflected in the prompt</span><br />
<span style="font-family: Courier New, Courier, monospace;">Bobbage Bob (Bobbage) > $bob->count_to(3) ## Arrays are printed</span><br />
<span style="font-family: Courier New, Courier, monospace;">1 2 3</span><br />
<br />
<span style="font-family: Courier New, Courier, monospace;">Bob (Bobbage) > my $count_hello = sub{ my ($n) = @_; ## Define multiline subs re.pl(main):005:1* map{ $bob->hello() } $bob->count_to($n); re.pl(main):006:1* }</span><br />
<br />
<span style="font-family: Courier New, Courier, monospace;">CODE(0x2fcbea0)</span><br />
<span style="font-family: Courier New, Courier, monospace;">Bob (Bobbage) > &$count_hello(3) ## And call them</span><br />
<span style="font-family: Courier New, Courier, monospace;">Hello, my name is Bobbage Hello, my name is Bobbage Hello, my name is Bobbage</span><br />
<br />
<span style="font-family: Courier New, Courier, monospace;">Bob (Bobbage) > ## CTRL-D ends the session</span><br />
<span style="font-family: Courier New, Courier, monospace;">Thanks for using Bob. </span><br />
<br />
Hope this short example was useful to you. If you can build your application as an object, writing your own shell should be straight forward. Also you might want to add some credential checking before you let anyone playing with the guts of your application.<br />
<br />
Until next time, happy coding!<br />
<br />
Jerome.<br />
<br />
<br />
<br /></div>
</div>
jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com4tag:blogger.com,1999:blog-5016251368610822667.post-46594889794599519592013-01-17T12:22:00.002+00:002013-01-25T11:17:30.859+00:00What Javascript programmers should learn from Perl mistakes<div dir="ltr" style="text-align: left;" trbidi="on">
Although I spend most time developing stuff in Perl, sometime I have to fix Javascript code that's been written by JavaScript specialists. Sorry, ECMA script as it should be called. And the more I look at 2013 JavaScript programming, the more I can see some similarity with the state of Perl programming 12 years ago.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEishZhkfVZlB7yINRp8EZon9_DteAAjTY0h9YisZHc-MIrOGCBQj3jYvqSixi8LDrLjJOx4sOE_DzSXf9nodQ1aRSaiPLCJz2LNBO6rAG3lxqTnvW7O9nP15kjG0Uyu4uHP1OQ8sqBQt8I/s1600/569357841.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEishZhkfVZlB7yINRp8EZon9_DteAAjTY0h9YisZHc-MIrOGCBQj3jYvqSixi8LDrLjJOx4sOE_DzSXf9nodQ1aRSaiPLCJz2LNBO6rAG3lxqTnvW7O9nP15kjG0Uyu4uHP1OQ8sqBQt8I/s1600/569357841.jpg" /></a></div>
Remember the <a href="http://www.perlmonks.org/?node=Obfuscated%20Code">Perl obfuscated</a> code contest? Basically it was all the "serious" Perl programmer boasting about being able to write the most <strike>f...d up</strike> original version of <a href="http://en.wikipedia.org/wiki/Just_another_Perl_hacker">Yet Another Perl Hacker</a>. While this was quite fun and made quite a good showcase of Perl's flexibility and expressiveness, some Perl programmers of the time were not quite serious enough and started to (unwillingly ?) use obfuscation techniques in production code, gaining Perl a reputation of being unreadable and unmaintainable, thus not fit for serious industrial development. You know the rest of the story: <a href="http://stackoverflow.com/questions/2534756/differences-between-perl-and-php">PHP, the offspring of 1994 Perl</a> took over.<br />
As programmers, we know that you can write unreadable and unmaintainable code in any language, and you can certainly write elegant things in any language too. Although I'm not sure about <a href="http://en.wikipedia.org/wiki/Brainfuck">brainf.ck</a>. The problem lies in the fact that non-programmers easily confuse the Programming language itself and the nasty habits of programmers. Have enough people write bad *any language* code, even for fun, and *any language* will gain a bad reputation. It comes from the extraordinary appetite our lazy human brains have for generalisation. Show enough retarded programs on TV and very soon people will think that the TV media itself is retarded.<br />
So please, Javascript programmers, stop writing stuff like that:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">var layout_options = {}, optgroups = {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> globals: 'Public',</span><br />
<span style="font-family: Courier New, Courier, monospace;"> userones: 'Private'</span><br />
<span style="font-family: Courier New, Courier, monospace;"> };</span><br />
Or like that:<br />
<span style="font-family: Courier New, Courier, monospace;">var block = conf[i], options, sel_conf, k, j;</span><br />
Or like that:<br />
<span style="font-family: Courier New, Courier, monospace;">opt.lytId == cfg.actLyt_id && opt.lytType === cfg.actLytType && (option_conf.selected = true);</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj295rhXDp22Ci8OF09qYZeqr65BMUH8Cgg6xgAb_m-V8MAvFnz9S37FOnQLIvHVgBsygMHBYU46QGsy9YpYGOo68oZiIyRI-c-PA9hUqK1fhPYDN29WOZhL-U_6Ru420-1ZJw1OfAIYYo/s1600/devise04.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj295rhXDp22Ci8OF09qYZeqr65BMUH8Cgg6xgAb_m-V8MAvFnz9S37FOnQLIvHVgBsygMHBYU46QGsy9YpYGOo68oZiIyRI-c-PA9hUqK1fhPYDN29WOZhL-U_6Ru420-1ZJw1OfAIYYo/s320/devise04.jpg" width="223" /></a></div>
Maybe some prehistoric browsers will actually run that faster than if you were using the 'var' keyword sensibly or if you were using good old 'if' statements. Otherwise, I think it's safe to assume these are completely useless optimizations, paid at the high price of unreadability. Plus, you know, text editors have auto-completion, so it's useless too to save keystrokes on variable names, specially if your code goes though some optimizer/packager in production.<br />
Maybe I shouldn't rant about Javascript programming, maybe stuff like <a href="http://coffeescript.org/">CoffeeScript</a> or <a href="http://www.dartlang.org/">Dart</a> will take over and it JavaScript <a href="http://www.hanselman.com/blog/JavaScriptIsAssemblyLanguageForTheWebPart2MadnessOrJustInsanity.aspx">will only live as an assembly language</a>. Personally I have the feeling it would be a good thing. A higher level - cleaner language compiled to JavaScript taking all browsers specificities into account. Why not? I don't see anything wrong with that.<br />
But JS programmers, if you love JavaScript and want to make sure it's still used in its current form over the next few years, stop writing code that's only barely readable by your fellow gurus.<br />
<br />
Edit: Actually, someone has pointed out to me that<a href="http://www.simplyhired.com/a/jobtrends/trend/q-perl%2C+python%2C+PHP%2C+ruby"> Perl is still more popular than PHP in terms of Job offers</a>.<br />
<!-- BEGIN TREND GRAPH --><br />
<div class="chart" style="width: 540px;">
<img alt="Perl, Python, Php, Ruby trends" src="http://www.simplyhired.com/a/jobtrends/graph/q-Perl,+Python,+Php,+Ruby/t-line/embed" /><br />
<table style="font-size: 80%; width: 100%px;"><tbody>
<tr><td width="2%"></td><td align="left"><a href="http://www.simplyhired.com/a/jobtrends/trend/q-Perl,+Python,+Php,+Ruby">Perl, Python, Php, Ruby trends</a></td><td align="right"><a href="http://www.simplyhired.com/a/jobs/list/q-Perl">Perl jobs</a> | <a href="http://www.simplyhired.com/a/jobs/list/q-Python">Python jobs</a> | <a href="http://www.simplyhired.com/a/jobs/list/q-Php">Php jobs</a> | <a href="http://www.simplyhired.com/a/jobs/list/q-Ruby">Ruby jobs</a></td><td width="2%"></td></tr>
</tbody></table>
</div>
<!-- END TREND GRAPH -->
<br />
<br />
Although <a href="http://www.googlefight.com/index.php?lang=en_GB&word1=Perl&word2=PHP">PHP easily wins on Google fight</a>.</div>
jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com0tag:blogger.com,1999:blog-5016251368610822667.post-22046934205279575602012-11-23T14:07:00.002+00:002012-11-26T11:48:37.384+00:00Friday Time Waster: Watch the world go by in ASCII with Reuters' API<div dir="ltr" style="text-align: left;" trbidi="on">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAgJxUYbaogT8iolUnKgGeVbTDieqaozfljJFg4Ur0j5JhO-WTXTlUghJ6kmTxDE2iOCRnlUot4PimQK1FEofq4qReKNwC_1BdINEASixvFX13VBZQsty3ikXxypcx08wXP3Iz6cYBrGQ/s1600/Screenshot+from+2012-11-23+13:02:46.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="317" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAgJxUYbaogT8iolUnKgGeVbTDieqaozfljJFg4Ur0j5JhO-WTXTlUghJ6kmTxDE2iOCRnlUot4PimQK1FEofq4qReKNwC_1BdINEASixvFX13VBZQsty3ikXxypcx08wXP3Iz6cYBrGQ/s320/Screenshot+from+2012-11-23+13:02:46.png" width="320" /></a>I've recently released <a href="http://search.cpan.org/perldoc?WebService%3A%3AReutersConnect">WebService::ReutersConnect</a>. It's a Perl modules that interfaces with the<a href="http://reutersconnect.com/"> ReutersConnect's API</a> in OO style. To demonstrate it and hopefully entertain you on this Friday, here's how to use it to watch the world go by in glorious ASCII and from the comfort of your command line. To put it shorter: The perfect Friday Time Waster.<br />
<h3 style="text-align: left;">
The ingredients</h3>
<div>
To cook this recipe, you will need:</div>
<div>
<br /></div>
<div>
- <a href="http://search.cpan.org/perldoc?WebService%3A%3AReutersConnect">WebService::ReutersConnect</a></div>
<div>
<br /></div>
<div>
- <a href="http://search.cpan.org/perldoc?Text%3A%3AAAlib">Text::AAlib</a></div>
<div>
<br /></div>
<div>
While you can install all of this with the CPAN command, I suggest you install most of their dependencies through your OS packaging system first.</div>
<div>
If you're debian based, here are the debs to install: libmoose-perl libdatetime-perl libdatetime-format-iso8601-perl libtest-fatal-perl libxml-libxml-perl libwww-perl liblog-log4perl-perl liburi-perl liblibaa1-dev</div>
<div>
<br /></div>
<div>
Then just install WebService::ReutersConnect and Text::AAlib via your favourite channel.</div>
<h3 style="text-align: left;">
The Recipe</h3>
<div>
The Recipe is pretty straight forward, it goes like this:</div>
<div>
<br /></div>
<div>
<b>Preamble</b>. We just load the required packages and also make sure that Log4perl is not going to complain about lack of initialisation:</div>
<div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">#! /usr/bin/perl -w </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">use strict;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">use warnings;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">use WebService::ReutersConnect qw/:demo/;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">use Log::Log4perl qw/:easy/;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">use Text::AAlib;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">use Imager;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">Log::Log4perl->easy_init($WARN);</span></div>
</div>
<div>
<br /></div>
<div>
<b>Building the $reuters object and querying the freshest image.</b> Here we use the demo credentials and search for the latest picture:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;">my $reuters = WebService::ReutersConnect</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> ->new({ username => REUTERS_DEMOUSER,</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> password => REUTERS_DEMOPASSWORD</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> });</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">my ( $item ) = $reuters</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> ->fetch_search({ limit => 1,</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> media_types => [ 'P' ],</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> sort => 'date' });</span></div>
</div>
<div>
<br /></div>
<div>
<b>Building the ASCII of the picture.</b> We just download the preview URL and render it in ASCII using Text::AAlib:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;">## Load preview image </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">my $res = $reuters->user_agent->get($item->preview_url());</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">unless( $res->is_success() ){</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> die $res->status_line();</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">}</span></div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">## Build and scale image </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">my $bin_image = $res->content();</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">my $img = Imager->new( data => $bin_image , type => 'jpeg' ) || die Imager->errstr();</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">$img = $img->convert( preset => 'grey' );</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">$img = $img->scaleX(scalefactor => 2); ## Tweak to your taste</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">$img = $img->scale(scalefactor => 0.5); ## Tweak to your taste</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">## Build ASCII Version </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">my ($width, $height) = ($img->getwidth, $img->getheight);</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">my $aa = Text::AAlib->new( width => $width, height => $height );</span></div>
</div>
<div>
<br /></div>
<div>
<b>Rendering the whole thing on the console</b>. The rendering parameters are OK for me, but you might have to play with them depending on your taste/colour scheme:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;">## Print ASCII Image </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">print $aa->render( dither => 0 ,</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> gamma => 1.83,</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> bright => 50,</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> contrast => 60,</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> color => 0</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> );</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">## And some info </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">print "\n ".$item->date_created().' : '.$item->headline()." \n";</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">print "\n ".$item->preview_url()."\n";</span></div>
</div>
<div>
<br /></div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRGlJB2c_zuqvQhwvV9TZ8cynr_mbFFIdjZdNNg8xmYv5HcjGO03sHCuG4abufN7FAKY9SPbbhngGp1WW9oTpE71_IbIJqjx6zx-pRVXM57xaJcMs6sD2VsPjVnK8cKCOOHtrwoHKsGPc/s1600/Screenshot+from+2012-11-23+13:18:35.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="178" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRGlJB2c_zuqvQhwvV9TZ8cynr_mbFFIdjZdNNg8xmYv5HcjGO03sHCuG4abufN7FAKY9SPbbhngGp1WW9oTpE71_IbIJqjx6zx-pRVXM57xaJcMs6sD2VsPjVnK8cKCOOHtrwoHKsGPc/s200/Screenshot+from+2012-11-23+13:18:35.png" width="200" /></a>And that's it! Now you can put all of that together, or if you're lazy, you can just copy/paste the whole thing from<a href="http://pastebin.com/jCK2T7uZ"> this pastebin</a>. </div>
<div>
<br /></div>
<div>
Feel free to experiment with the options and the code and tell us about your improvement in the comments!</div>
<div>
<br /></div>
<div>
Happy coding!</div>
<div>
<br /></div>
<div>
Jerome.</div>
<div>
<br /></div>
</div>
jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com2tag:blogger.com,1999:blog-5016251368610822667.post-25239786153054393862012-11-08T10:52:00.001+00:002012-11-08T10:52:26.443+00:00PDFs coming out upside down<div dir="ltr" style="text-align: left;" trbidi="on">
Recently at work we received a defect report ticket addressed the tech team saying:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"><Support 1>:</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<br />
<div class="searchable">
<span style="font-family: Courier New, Courier, monospace;">When documents are added to the <Client> system, pdf attachments are coming out upside down.</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">
Referred the matter to <Account Manager>, who confirmed this is a technical issue.
</span><br />
<span style="font-family: Courier New, Courier, monospace;">
To replicate
</span><br />
<ul>
<li><span style="font-family: Courier New, Courier, monospace;">Log into <Client> system</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">Go into document 1234567</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">Click on pdf
</span></li>
</ul>
<span style="font-family: Courier New, Courier, monospace;">
Screen shots attached </span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHvXPujGYKxLM53VMXxiu-gomHkxLeelIBRicvNtSVFGDQ76VR3VrtI_32dzA0aWrUQavLnbP2PMGU5C-EZQTC9hEbeYhQLB7_Qk85PeszscG7xCctQWS1ACY7gF0i1ZgY9e2_n4TjtY8/s1600/upside-down-bicycle.gif" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="174" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHvXPujGYKxLM53VMXxiu-gomHkxLeelIBRicvNtSVFGDQ76VR3VrtI_32dzA0aWrUQavLnbP2PMGU5C-EZQTC9hEbeYhQLB7_Qk85PeszscG7xCctQWS1ACY7gF0i1ZgY9e2_n4TjtY8/s200/upside-down-bicycle.gif" width="200" /></a></div>
For obvious reasons, I cannot show you the screen shot, but it effectively shows an upside down document.<br />
<br />
One of the most enlightened members of the tech team followed up:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">We would need to see the original document that the client uploaded to
confirm, however, as this uploaded PDF is the result of manual scanning
in of a paper document, it looks very much to us as though the
paper document has been placed in the scanner the wrong way
round, and hence has been scanned upside down. </span><br />
<br />
Then Support comes back.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"><Support 2></span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<br />
<div class="comment searchable">
<span style="font-family: Courier New, Courier, monospace;">Client has advised:
</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">
Hello, scanning the document the other way around has solved the problem -
thanks for resolving this. </span></div>
<br />
<br />
D'oh. Lesson learned: Don't trust <Account Manager>'s technical issue opinions.<br />
<br /></div>
</div>
jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com0tag:blogger.com,1999:blog-5016251368610822667.post-10197172654038891882012-09-25T14:37:00.004+01:002013-02-22T18:26:19.748+00:00Understanding Unicode and UTF8 in Perl<div dir="ltr" style="text-align: left;" trbidi="on">
I know there's a lot of things out there on the subject, but when it comes to Unicode, a quick review of core concepts and bug avoidance guidelines is never a waste of time.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiimTa92N7RjSfshjZpSQinrDTbPgyyo8xxUfblS6Sk272mVh-JZ9LzQYfMYaHsKAsLg57NHvtPf30fF73Atdaun9Hifr2zMt-SyUqYlwtPKBfQRYXw_Bg7x_SfZ_OU_DKlRHI1Ya4gbms/s1600/Screenshot+from+2013-02-22+18:25:05.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="136" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiimTa92N7RjSfshjZpSQinrDTbPgyyo8xxUfblS6Sk272mVh-JZ9LzQYfMYaHsKAsLg57NHvtPf30fF73Atdaun9Hifr2zMt-SyUqYlwtPKBfQRYXw_Bg7x_SfZ_OU_DKlRHI1Ya4gbms/s200/Screenshot+from+2013-02-22+18:25:05.png" width="200" /></a><br />
I'm not a Unicode Guru, but working with third parties, I often find that a lot of people consistently fail to get the basics right about Unicode and encoding. There must be something esoteric about it. So here's yet another set of slides about Unicode/UTF8 in Perl.<br />
<br />
It's not meant to be a comprehensive presentation of all Unicode things in Perl. It's meant to insist on a couple of guidelines and give some pointers to get a good start writing a unicode compliant application and avoiding common issues.<br />
<br />
<div>
<div style="text-align: center;">
<br /></div>
</div>
<div>
<div style="text-align: center;">
<iframe allowfullscreen="true" frameborder="0" height="389" mozallowfullscreen="true" src="https://docs.google.com/presentation/embed?id=1Xepzoeqj7j5E_Od4Z6tZ4Z8z7pioWQJTh6YWoB1veRY&start=false&loop=false&delayms=15000" webkitallowfullscreen="true" width="480"></iframe>
</div>
</div>
<div style="text-align: center;">
<br /></div>
<br />
Comments are open for questions. Happy coding!</div>
jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com8tag:blogger.com,1999:blog-5016251368610822667.post-68451173337317000142012-09-21T01:25:00.004+01:002012-09-25T14:06:52.133+01:00Yes, One, I don't know - three tales about understanding people<div dir="ltr" style="text-align: left;" trbidi="on">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVD8cyl8B5BKdZUShS4PXaMj_GZfRWTsnMRSO8bVqHAukQNs9skNQm0A3PC1kDnK1Kd_HecRY769yMHVZE6IDGalI_HNpbQLnZcEeXlb3pNnTjSOzUWym2geve62Em6bNUcyLXoAqvFME/s1600/tour_de_babel.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVD8cyl8B5BKdZUShS4PXaMj_GZfRWTsnMRSO8bVqHAukQNs9skNQm0A3PC1kDnK1Kd_HecRY769yMHVZE6IDGalI_HNpbQLnZcEeXlb3pNnTjSOzUWym2geve62Em6bNUcyLXoAqvFME/s200/tour_de_babel.jpg" width="194" /></a>As application developers, it's crucial that we understand what other people are saying, and we're often in a position where misunderstanding is an easy trap to fall into, specially when we speak with people with no computer science background. Yes that happens. Scary hu? The key point when this happens is to forget about everything you know about basic understanding, even in your native language. So here are three tales about how even the most simple language elements can lead to misunderstanding, and what to do about it.<br />
<br />
<br />
<br />
<br />
<b>Yes</b><br />
<br />
I started working for (very little) money as a bio-informatics consultant. My main duty was to write and use software to produce - in a few hours of number crunching - enough hypothetical results that would take molecular biologists decades and millions of investors hard earned Euros to validate in the wet lab. At this time, my brain was fresh from university and I was formatted to think about the world in terms of 1's and 0's. And there were only 10 categories under which my mind was ultimately classifying things. True and false. So the word "Yes" for me had only one meaning. It meant something was true in the past, now and in the future, independently of circumstances. So as you can guess, there were not many questions you could answer with a plain "Yes" to me. For instance to the question "Do you like hummus", if you answered me "Yes", then I would have served you hummus for the rest of your life. Well only until you've finally decided by yourself to tell me that "actually yes I like hummus most of the time, but not always". Which is actually closer to the reality. If it just about culinary tastes, it's OK, but when it's about work then the misunderstanding is annoying at best. And I've made this mistake quite a few times: Taking a biologist "yes" for a computer science "yes" and mis-design something as a consequence. Now I try to remember, I don't take "yes" as an answer. When I hear "yes", I try to question it further, think twice and make sure I deal with the case where this "yes" is not true. Because in the real world, it will happen.<br />
<br />
<b>One</b><br />
<br />
I bet that like me you've noticed the following fact about software development:<br />
<br />
"Given enough time and business analysis, any unique relationship will eventually have to turn multiple."<br />
<br />
It works for almost everything. Your users can set their preferences? One day you'll want to manage multiple set of preferences. You display the hottest deal of the day on your homepage? Quite soon you'll want multiple. A document has got a language property? What about mixed language documents? multiple. A user has got a postal address? No, they've got multiple addresses - work/home/mum/dad. OK so now they have multiple addresses, but they choose a favourite one. Humm, what if they want a different favourite depending on the context. Think "Deliver to work, but send the bill to home". Multiple again. Programming language has got single inheritance? The next one will have multiple. And you can go on and on about it. There's no end to multiplying. I wonder sometimes why unique relationships are included in UML. I think it's to trick developers into believing people saying "One". But don't be fooled. There's no such thing as "One". If you don't believe me, read this multiple times.<br />
<br />
<b>I don't know</b><br />
<br />
This one is not strictly speaking about computer science, but about science in general. I think that people with a scientific background of any kind are used to deal instantly with equivalence and equations. For instance, given the speed and the mass of a moving object, we instantly know its kinetic energy because we know that E = 1/2mv^2. It also works transitively. I don't want to go into too complex examples, but let's say you have <i>a,b,c, d=f(b,c) , e=f(d,a)</i>, and let's say I give you<i> a,b,c</i> and ask you if you know '<i>e</i>'. Someone with science background will tell you "yep, because you know <i>a</i> and <i>d</i>, and you know <i>d</i> because you know <i>b</i> and <i>c</i>". I did the test with my wife - who's got a biology background - yesterday, so my statistics are pretty solid. To me this is a perfectly natural way of thinking. Until I took a class in finance.<br />
<br />
In an attempt to avoid spending my elderly years begging in the streets of London, I took this class in finance on <a href="http://www.coursera.com/">coursera</a> to understand how the wheels turn. And the lecturer looks to me like a brilliant man, full of common sense with very good pedagogy. I highly recommend this class. Anyway. One thing that stroke me is that sometimes I was kind of lost into the teacher's thinking. He was presenting a example, where <i>a,b and c </i>were known and was asking the question: "Do you know <i>e</i>". And the right answer was not "Yes of course, because <i>e=f(f(b,c),a)</i>". The correct answer to him was "I don't know". And I understood why I sometimes didn't understand him. Because for him , "I don't know" doesn't mean the same as my "I don't know". To me "I don't know" means "It cannot be reached within a reasonable computing time". To a mathematician or a physicist, or a biologist, it will probably mean more or less the same. But to him it means something different. It means "I don't know it yet because I haven't calculated it yet". Once I understood that, the rest of the class was suddenly crystal clear, because I had understood that the meaning of this simple sentence "I don't know" meant something different between him and me.<br />
<br />
<br />
The fact that we cannot assume that everybody shares the meaning of such simple concepts like "Yes", "One" , "I don't know" and probably lot of other ones is quite fascinating and tells us that effective communication between human beings of different backgrounds is probably one of the most difficult things to achieve at work and in life in general.<br />
<br />
I don't know if there's a solution to this, but until people more clever than me find one, I'll try to stick to this rule: <strike>Don't speak to non IT people</strike> Try to understand what meaning others attach to basic phrases.<br />
<br /></div>
jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com0tag:blogger.com,1999:blog-5016251368610822667.post-1219913781833433582012-09-15T19:34:00.001+01:002012-09-15T19:34:13.198+01:00JS/HTML/CSS: A braindump from a backend guy<div dir="ltr" style="text-align: left;" trbidi="on">
It's a wonderful sunny Saturday outside yet I'm here bloging about web development. I should see a doctor, but in the meantime please suffer my brain dump about things browser related.<div>
<br /></div>
<div>
I'm not really a front end developer, in the sense that I have very poor graphic design skills, that my knowledge of Javascript and CSS is limited. However over the time I had <a href="http://www.careerjet.co.uk/">my fair bit of front end development</a>, more recently <a href="https://jpmorgan.tal.net/vx/lang-en-GB/mobile-0/system-48/appcentre-americas_jobs/brand-6/candidate/jobboard/vacancy/1/adv/">here</a>, not counting <a href="http://libsquare.net/">the things I do for fun</a>, so yeah, I don't have expert level knowledge about all of this, but I feel I have enough experience to broadly think about some general guidelines about what should be fed to the browsers. So the goal of this post is not to dictate what I think is right, but rather to put some ideas on the table and calling for critics and alternative and/or improvement suggestion. So if you're a JS Ninja, or a CSS old-master, please be indulgent, and share your art in the comment.</div>
<div>
<br /></div>
<div>
Ok let's get started with the general page structure. I like a page source to be clean and organised (not like my bedroom), but also the goal here is to allow the browser to render the page as soon as possible. In other words, to reduce the time to first pixel:</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><html></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <head></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <title>My Wonderful Page</title></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <meta name="description" content="Some meaningful and reasonably long description"></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <span class="webkit-html-tag" style="white-space: pre-wrap;"><script <span class="webkit-html-attribute-name">type</span>="<span class="webkit-html-attribute-value">text/javascript</span>" <span class="webkit-html-attribute-name">src</span>="/js/head.js"></span><span class="webkit-html-tag" style="white-space: pre-wrap;"></script></span></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <link type="text/css" rel="stylesheet" href="/one/css/file.css" /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> </head></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <body></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <div></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> All sorts of HTML stuff.</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> </div></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <script type="text/javascript"></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> head.js('https://ajax.googleapis.com/.../jquery.min.js',</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> 'https://ajax.googleapis.com/../jquery-ui.min.js',</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> 'http://mysite.com/js/site.js'</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> );</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> head.ready(function(){</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> installFancyJS($(document));</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> });</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> </script></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> </body></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"></html></span></div>
<div>
<br /></div>
<div>
Let's go though this step by step.</div>
<div>
<br /></div>
<div>
<b>Use a JS Loader</b>. So the idea here is to do as little as possible in the header, and deport the heavy lifting to the end of the body. In your header, you should have only one and only one minimal script, and this script should allow you to load things later at your page bottom. Here I use <a href="http://headjs.com/">head.js</a>. It's got other fancy base features but <a href="https://github.com/chriso/load.js">load.js</a> is also a good alternative if you like to make it even smaller. Let your page be pear shaped.</div>
<div>
<br /></div>
<div>
<b>One CSS File</b>. Not two, not three. One, and preferably on the same domain as your main site (so relative URLs are welcome here). Why is that? Here we reduce the number of extra requests the browser has to do to a minimum of erm ... one, and by having the CSS hosted on the same hostname, you avoid doing extra DNS queries, saving you precious milliseconds. Some people even argue that you should have your CSS in the page itself. I'm not sure about this one. It's true that it saves you the extra query entirely, but at the same time, your page is now heavier and therefore longer to download. There's probably a reasonable limit under which this actually saves time, but I'm not sure about its value. Of course in the development environment, you probably want to have your css neatly organized, so you don't have a giant ball of spaghetti monster to deal with. I've tried different techniques to achieve that, but didn't come with something I really like yet. Suggestions?</div>
<div>
<br /></div>
<div>
<b>All sorts of HTML Stuff</b>. <span style="color: #b45f06;">Warning. Controversial bit</span>. What? HTML stuff, controversial? Well yes, as it seems to me that with the advent of the uber-ubiquitous Ajax coolness, a large amount of people chose to ignore a fundamental fact of life (at least of life as a developer): Browsers were born to render HTML and dynamic web servers can generate HTML. For instance, I know a site where every time they need to display a table of something (let's say historical stock prices), they first display an empty table, and then, when all the page JavaScript is loaded, they make a second query to get the data to populate the table. It drives me mad. Not only I don't see the point* , but more importantly, you can imagine how it kills the 'time to useful pixel' of their pages. It's not that I'm against Ajax. not at all. I love it, I was doing it wayyyy before jQuery became popular. In fact you'll find here some posts I wrote about <a href="http://sigstp.blogspot.co.uk/2011/02/slice-your-html-to-ajax-anything.html">how to easily 'ajax' anything</a>. But I kind of believe that if you want to do JS object models and get JSON from the server instead of HTML, you'll be much better off developing your backend as an API and generate your GUI using something like <a href="http://www.adobe.com/uk/products/flex.html">flex</a>, or <a href="https://developers.google.com/web-toolkit/">GWTK</a> (please add yours to the list :)). I certainly reckon the incredible value and power of OO JS/Json for complex and specific information manipulation and display (down with flash and applets!!), but for general pages development, I prefer to stick with good old HTML, specially if the application is 'browsing' oriented.</div>
<div>
<br /></div>
<div>
<b>One JS Function that does it all</b>. I call it (observe my creative naming skills) 'installFancyJS', and it takes one argument: the jQuery** context it's going to used in. So what does this function do? Well, it installs callbacks and all sort of responsive code in the page just after it's loaded. More precisely in the given context. To give you a very minimal example:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">function installFancyJS(context){</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> installTopClick(context);</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> ....</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">}</span></div>
</div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">function installTopClick(context){</span></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> $('div#topbar' , context).on('click', function(ev){</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> $('html,body').animate({scrollTop: 0 },</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> { duration: 'slow', easing: 'swing'}</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> );</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> });</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">}</span></div>
</div>
<div>
<br /></div>
<div>
The reason why I propagate the context everywhere is that when I get a new bit of HTML using Ajax, I want to be able to install the full set of Javascript features on the newly created slice of document. In here's an minimal example of Ajax callback that uses the function:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">function(data){</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> var newbit = $(data);</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> container.replaceWith(newbit);</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> // install fancy js on the container's new content. </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> installFancyJS(container);</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span></div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
That's is for now. I hope you enjoyed reading this and found some interesting/ridiculous/horrible things to talk about.</div>
<div>
<br /></div>
<div>
Jerome.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
* But I see the reason: they got tied to the horrible datatables.net.</div>
<div>
**yes I use jQuery, please rant and suggest in the comments if you know a better one.</div>
</div>
jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com2tag:blogger.com,1999:blog-5016251368610822667.post-60237937542479397972012-08-21T21:29:00.001+01:002013-11-07T14:17:15.299+00:00The goodness of testing<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: right;">
</div>
<div style="text-align: justify;">
<div style="text-align: right;">
</div>
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgI5odS11adfHi8HwkghpBrq-cNm0E8BnpT2Qtsi-Yg8XTSRU_bFcHmkzf2EHLdGQK3qeskvHHCtmVmbHIC0bEGv0bWVUm162lcr2kyypgGaCygkoupow-7nD8WB6rhalQkAy-AqgxVR1A/s1600/coyote.jpg" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="241" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgI5odS11adfHi8HwkghpBrq-cNm0E8BnpT2Qtsi-Yg8XTSRU_bFcHmkzf2EHLdGQK3qeskvHHCtmVmbHIC0bEGv0bWVUm162lcr2kyypgGaCygkoupow-7nD8WB6rhalQkAy-AqgxVR1A/s320/coyote.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Wall e-coyote testing a new rocket design</td></tr>
</tbody></table>
<b id="internal-source-marker_0.5532943727448583" style="font-weight: normal;"><span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;">There’s a common view amongst programmers that testing (that is writing tests) is a painful thing you have to do to please your manager, or something you can avoid doing if your manager hasn’t got a clue. Let’s try to debunk that and show that testing is actually fun for the following reasons:</span></b></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b id="internal-source-marker_0.5532943727448583"><span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;">It guarantees code correctness.<span style="font-weight: normal;"> That’s quite obvious. Less obviously it forces you to think about what your code correctness actually is. By writing test, you will more easily think about those pesky edge cases that other users of your code will inevitably notice.</span></span></b></div>
<div style="text-align: justify;">
<b style="font-weight: normal;"><span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"><br /></span></b></div>
<div style="text-align: justify;">
<b id="internal-source-marker_0.5532943727448583"><span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;">It gives you a safety net when you refactor.<span style="font-weight: normal;"> Imagine you’ve finally decided to repay some technical debt and re-write your poorly written methods (don’t tell me you haven’t got any). If you’ve got good test coverage, no worries. You can refactor and rewrite your module, increase performance, cleanup poorly written code without worrying about breaking anything. Understand anything that’s tested.</span></span></b></div>
<div style="text-align: justify;">
<b style="font-weight: normal;"><span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"><br /></span></b></div>
<div style="text-align: justify;">
<b id="internal-source-marker_0.5532943727448583"><span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;">It forces you to write better APIs.<span style="font-weight: normal;"> By putting you in the role of a user of your code/module/API, it forces you to think about the nicest way to use your module. This is creative, fun and interesting: How, as a client of your library, would you like to be able to use it. How would you like to interact with your piece of software? What do you expect from it? What should it expects from you? You decide, and because you're hopefully lazy and imaginative, you'll come to think about something nice and neat. If anybody else uses your code in the future, you will attract a lot of developer love. Because people will go: "hum, that’s neat, and it works first time." And that's a lot of doughnuts for you.</span></span></b></div>
<div style="text-align: justify;">
<b style="font-weight: normal;"><span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"><br /></span></b></div>
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="http://www.barnabas-france.org/wp-content/uploads/2010/11/moise-ouvre-la-mer-rouge.jpg" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="http://www.barnabas-france.org/wp-content/uploads/2010/11/moise-ouvre-la-mer-rouge.jpg" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Moses Testing the power of the LORD</td></tr>
</tbody></table>
<div style="text-align: justify;">
<span id="internal-source-marker_0.5532943727448583"><span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"><span style="font-weight: normal;">You can see your test as a kind of </span>contract<span style="font-weight: normal;"> about what is supposed to work now and forever more (biblical voice needed). It’s a </span><b>contract between You, your future You, anyone who touches your code in the future, and also with the outside world.</b><span style="font-weight: normal;"> Why the outside world? I sometime think that everything that’s not tested doesn’t exists. It’s probably a philosophical view, but as a programmer, I like to think in binary terms. Something is there or something is not there. At least until quantum computers are on our desktops. So what about a feature that is not tested? It can break without anyone noticing, or it can break and only the users notice (very bad). So is it there or not? Well, if it can go away silently, I think it’s safer to assume it’s not there. Ask your sales team if they feel comfortable about selling stuff that can vanish at any time. Anything outside testing shouldn’t be assumed to be existing. That leads to what I deeply think about testing.</span></span></span></div>
<div style="text-align: justify;">
<b style="font-weight: normal;"><span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"><br /></span></b></div>
<div style="text-align: justify;">
<b><span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"><span style="font-weight: normal;">Testing does not help to make your product more reliable. </span>Testing <u>is</u> your product.</span></b></div>
<div style="text-align: justify;">
<b style="font-weight: normal;"><span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"><br /></span></b></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b style="font-weight: normal;"><span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;">Comments welcome!</span></b></div>
<br /></div>
jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com0tag:blogger.com,1999:blog-5016251368610822667.post-49723259407340054372012-04-03T14:19:00.000+01:002012-04-03T14:19:28.255+01:00Do you speak Franglais?<div dir="ltr" style="text-align: left;" trbidi="on">If you want to sound more clever than you really are in a French company, it's a good idea to forget about speaking French correctly and start speaking 'Franglais' instead. Franglais, spoken with the appropriate French accent, is a very effective way to impress your colleagues and your manager (in Franglais: "ennepluswone"), giving them the feeling that you hold and MBA from Harvard although the last time you were involved with the anglo-saxon's business culture, it was at 'Wall Street institute, 26 Rue de Lyon Paris'.<br />
<br />
So here's a quick list to get you started in Franglais:<br />
<br />
Cible -> Target<br />
Concours -> Contest<br />
Premieres étapes -> Early Stage<br />
Mis en favoris -> Bookmarké (Bookmarked in English, but the french would prononce 'Bookmark-aide')<br />
Délocalisé -> Offshore<br />
Processus -> Process (you save two letters!)<br />
Commuté -> Switché (Switched in English)<br />
Appel groupé -> Confcall<br />
Tarifs -> Pricing<br />
Défi -> Challenge<br />
Concentré -> Focusé<br />
Plein Ecran -> Full Screen<br />
Atelier -> Workshop<br />
Externalisé -> Outsourcé<br />
Mondial -> Worldwide<br />
Sauvegardé -> Backupé<br />
Feuille de route -> Roadmap<br />
Fonctionnalité / Attribut -> Feature<br />
<span style="background-color: #fafafa; text-align: center;">Retransmis -> Forwardé</span><br />
<span style="background-color: #fafafa; text-align: center;">Date butoir -> Deadline</span><br />
<span style="background-color: #fafafa; text-align: center;">Incit</span>é<span style="background-color: #fafafa; text-align: center;"> -> Incentivé</span><br />
<span style="text-align: center;">Recommandations</span><span style="background-color: #fafafa; text-align: center;"> -> Guidelines</span><br />
<span style="background-color: #fafafa; text-align: center;">Discussion -> Chat</span><br />
<span style="text-align: center;">Collègue</span><span style="background-color: #fafafa; text-align: center;"> -> Co-worker</span><br />
<span style="background-color: #fafafa; text-align: center;">Personalis</span><span style="background-color: #fafafa; text-align: center;">é -> Custom</span>é (Customis - aide)<br />
Invité -> Guest<br />
Avertissement -> Warning<br />
Contenu -> Content<br />
Ordonnanceur -> Scheduler<br />
<br />
Ps: Thanks to Michel Poulain for his '<a href="http://poula.in/pages/bingo.html">Bingo du Franglais</a>'</div>jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com0tag:blogger.com,1999:blog-5016251368610822667.post-72855444758662669162011-08-24T22:18:00.002+01:002011-08-25T09:39:21.992+01:00LaTeX: Included graphics resolution<div dir="ltr" style="text-align: left;" trbidi="on">While most graphic files on the internet have a resolution of 72pixel/inch, you need to keep in mind that this resolution is often not suitable for printing. To illustrate that, let's take two images that have the same number of pixels (348 x 350):<br />
<div>One is set at 72pixels/inch:<br />
<div><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCS5zQbsgvvStIhTFI8WlFjPbsRfWH9odz67NGPZlL8o-4kifRjekAafSLfsG_So09v9iHSQl7ZoyZ5D1-JzAhNLqXMOjrSF9BT13Kbv_fp-NzIarkuU1mO_qP2QLzLJJugH0y9CzBbd4/s1600/lowres.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCS5zQbsgvvStIhTFI8WlFjPbsRfWH9odz67NGPZlL8o-4kifRjekAafSLfsG_So09v9iHSQl7ZoyZ5D1-JzAhNLqXMOjrSF9BT13Kbv_fp-NzIarkuU1mO_qP2QLzLJJugH0y9CzBbd4/s1600/lowres.png" /></a></div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">And the other one is set at 144pixels/inch:</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwiRaHqr7HqDUO22UcmGwIfIFvXu3h2reUpIRwkYgSkosGOhxWnZThVlUhjMlwT2JIs9BL79xvhWgHf4b3hatikBiM8L338hBef79E_pnyA7_l8sASDiGYfo4T8z5uRPLcRY-BxGW9ecE/s1600/highres.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwiRaHqr7HqDUO22UcmGwIfIFvXu3h2reUpIRwkYgSkosGOhxWnZThVlUhjMlwT2JIs9BL79xvhWgHf4b3hatikBiM8L338hBef79E_pnyA7_l8sASDiGYfo4T8z5uRPLcRY-BxGW9ecE/s1600/highres.png" /></a></div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div>As you can see here, there's no way to tell the difference between them on the screen because your browser displays these images according to their sizes in pixels, regardless of their resolution.</div></div><div><br />
</div><div>Now if you write a LaTeX document that includes them both:</div><div><br />
</div><div><div>\documentclass{article}</div><div>\usepackage{graphicx}</div><div>\begin{document}</div><div>\includegraphics{lowres.png}</div><div>\includegraphics{highres.png}</div><div>\end{document}</div></div><div><br />
</div><div>Here's what you get as the resulting pdf:</div><div><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMq0CW7eDUyAjOsTYToJ5_Pn8xF5Aa6Meq_Vuua1He5Ew9UXdNO3UQR6UtSt8VXK_RqWbCHaE4HfIrjNYw61L3eRLkyA0HABe3qCRoWEpuCyU80h2VlLbzCBU31fvRWuRVCLkCEf5TE5s/s1600/Screenshot-doc.pdf.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="388" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMq0CW7eDUyAjOsTYToJ5_Pn8xF5Aa6Meq_Vuua1He5Ew9UXdNO3UQR6UtSt8VXK_RqWbCHaE4HfIrjNYw61L3eRLkyA0HABe3qCRoWEpuCyU80h2VlLbzCBU31fvRWuRVCLkCEf5TE5s/s400/Screenshot-doc.pdf.png" width="400" /></a></div><div><br />
</div><div>As you can see, the original 72px/in image will appear 'too big', pixelized and blurry on your piece of paper, whereas the 144px/in one will be twice as small and keep its sharpness.</div><div><br />
</div><div>So don't hesitate to experiment with resolution when making LaTeX based documents.</div><div><br />
</div><div>That's all for today!</div></div>jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com0tag:blogger.com,1999:blog-5016251368610822667.post-59661270854450400702011-04-02T14:09:00.000+01:002011-04-02T14:09:34.199+01:00Implement Ajax actions using page slices [Part 2]Last time I discussed how to implement Ajax browsing using page slices] generated<br />
at server side. If you haven't read that yet, I strongly encourage you to do so, cause there's little chance the rest of this post will make sense to you.<br />
<br />
Read Part 1- <a href="http://sigstp.blogspot.com/2011/02/slice-your-html-to-ajax-anything.html">Implement Ajax browsing using page slices</a>.<br />
<br />
This time we're going to apply the same technique, but we'll implement some actions. By actions I mean simple interactions for instance 'vote a comment up', or 'follow a member', 'delete an item' etc.. Any kind of interaction that does not require more than a click from the user in an Ajax interface.<br />
<br />
For instance, on <a href="http://libsquare.net/">libsquare.net</a>, if you are logged in, you can vote up or down any review that appear on the <a href="http://libsquare.net/libs/14">jQuery page</a>:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheoVDzVJ-Xi7eFYnivJsyGM0FeV3QJXsu5vWNxUVo5qXFIzE-vWgjy_q46fdlr8zYxvOHcEqNNVbHNdnGS8sdLG2GF6V40KUyh5HiRyjv4okE9C02ojCY5r5vO4Hfa0g3lBi8qI2HGYl4/s1600/review_box.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheoVDzVJ-Xi7eFYnivJsyGM0FeV3QJXsu5vWNxUVo5qXFIzE-vWgjy_q46fdlr8zYxvOHcEqNNVbHNdnGS8sdLG2GF6V40KUyh5HiRyjv4okE9C02ojCY5r5vO4Hfa0g3lBi8qI2HGYl4/s1600/review_box.png" /></a></div>So how do we implement that?<br />
<br />
<span style="font-size: large;">The pure HTML flow</span><br />
<br />
First let's remember that <a href="http://sigstp.blogspot.com/2011/02/slice-your-html-to-ajax-anything.html">page slicing</a> is designed to allow us to implement things without JavaScript, so let's just do that. Here's the work flow of the vote up feature without any JavaScript: <br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGxWqIg9Mg3o5Rkri3A-aAiK-Gt3LEGYeb9CtZSlJneZAKaQmWUq01j4Zc7p-xxrOH3afZf1QkvfJU9VdJEQ6Fqe4_uVkQnLXeU589J8phxlHU8PKgHK1J74RiT1CAoZ-fvejSH5N4dkE/s1600/vote_flow.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGxWqIg9Mg3o5Rkri3A-aAiK-Gt3LEGYeb9CtZSlJneZAKaQmWUq01j4Zc7p-xxrOH3afZf1QkvfJU9VdJEQ6Fqe4_uVkQnLXeU589J8phxlHU8PKgHK1J74RiT1CAoZ-fvejSH5N4dkE/s1600/vote_flow.png" /></a></div><br />
The user clicks on vote up, he arrives on a page where the vote up is pre-selected, clicks submit and is redirected to the page review with the vote count updated.<br />
<br />
<span style="font-size: large;">Let's Ajax this!</span><br />
<br />
First let's give a class 'do_vote_up' to our vote up link:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><a href=".../review/111/vote_up" class="do_vote_up">Vote up</a></span><br style="font-family: "Courier New",Courier,monospace;" /><br />
Then we need to give an ID and slice the container that contains the voting unit:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><div class="slice_container" id="review_vote_111"></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"><& /slice.mas , id => 'review_vote_111' &></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> ... Your vote display html code ...</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"><a href=".../review/111/vote_up" class="do_vote_up">Vote up</a></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> ...</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"></&></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"></div></span><br />
<br />
Let's assume /review/111 is a page that always display the review with it's voting part.<br />
<br />
Now we're only a small bit of Javascript away from the full Ajaxed feature:<br />
<div style="font-family: "Courier New",Courier,monospace;"><br />
</div><span style="font-family: "Courier New",Courier,monospace;">$('a.do_vote_up').live('click', function(event){</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> event.preventDefault();</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> var a = $(event.target);</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> var container = a.closest('.slice_container');</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> var target_url = a.attr('href');</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> var result_url = target_url; result_url.replace('\/vote_up','');</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> // Post a vote up query to the voting URL.</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> $.ajax({</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> type: 'POST',</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> url: target_url,</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> data: { vote: 1 , vote_submit : 1 },</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> success: function(){</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> // On success, reload the voting slice that now contains the updated vote.</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> container.load(result_url,{ page_slice: container.attr('id') });</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> }</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> });</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">});</span><br />
<br />
Et voila, the vote up action is now Ajaxed. Implementing the same thing for the vote down is left as an exercise for the reader :P<br />
<br />
Next time I'll be speaking about submitting forms and dealing with redirections in Ajax. Stay tuned and thanks for reading!jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com0tag:blogger.com,1999:blog-5016251368610822667.post-69605416620157126602011-02-21T20:20:00.002+00:002011-04-02T13:14:46.962+01:00Slice your HTML to Ajax anything. [Part 1]There's roughly two ways of addressing Ajax on your website:<br />
<ul><li><b>Designing your pages with Ajax in mind. </b>This usually means you'll have a growing number of features that require JavaScript to work. The <a href="http://www.w3.org/TR/WAI-WEBCONTENT/#gl-new-technologies">W3C recommendation</a> specifies that you should provide JavaScript-less versions of your features. So it means you will have to develop your features twice to maintain accessibility. Sounds a painful thing to do.</li>
<li><b>Designing your pages without Ajax in mind</b>. This means you design only good old pure html/params & forms techniques to animate your features. This is good for accessibility, this is good for testability, this is good for search engines because all your features are accessible via plain links. The only problem is... well there's no Ajax coolness.</li>
</ul>But we're going to fix that, and it's not going to be painful at all providing you:<br />
<ul><li>have got zero business logic in your rendering layer. Meaning each part of it is idempotent. This is hopefully the case when you use a MVC model for your application.</li>
<li>use a rendering layer that's capable of manipulating its buffer, and renders the whole page in this buffer before sending it.</li>
</ul>For this post, I'll be using <a href="http://www.catalystframework.org/">Catalyst</a> as the MVC and <a href="http://www.masonhq.com/">HTML::Mason</a> as the View layer. We'll focus on implementing Ajax results paging. (Other ajax aspects will be dealt with in later posts).<br />
<span class="Apple-style-span" style="font-size: large;"><br />
</span><br />
<span class="Apple-style-span" style="font-size: large;">Principle of ajax page slices.</span><br />
<br />
The idea of page slices came to me when I was looking at<a href="http://api.jquery.com/load/"> jQuery's load function</a>. It's got a very convenient trick called 'load page fragments' that allows you to do stuff like:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;">$('#container').load('page_url?offset=2 #result_id');</span><br />
<br />
It will look for an element having the id<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> 'result_id'</span> in the returned document and replace the content of #container with it. Here's a full example of html/javascript that implements this:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"><div class="container"></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> <div class="result" id="result_id"></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> <p>This is page 1</p></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> <p>item 1</p></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> <p>item 2</p></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> <a class="page" href="page_url?page=2">Go to page 2</a></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> </div></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"></div></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"><script></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> $(document).ready(function(){</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> $('a.page').live('click',function(e){</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> var a = $(e.target);</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> var result = a.closest('.result');</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> var container = result.closest('.container');</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> container.load(a.attr('href') + ' #' + result.attr('id'));</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> });</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> });</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"></script></span><br />
<br />
This does the trick on the client size but it doesn't save much time on the server side.<br />
Plus it requires DOM parsing of the whole document to find the result_id element. Altogether, chances are that your ajax paging will be slower that a simple whole page reload. To fix that, we're going make the server output only the required slice for us.<br />
<br />
<span class="Apple-style-span" style="font-size: large;">Let the server do the work.</span><br />
<br />
First let's have a look first at the intended client side code:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"><div class="container" id="result_id"></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"><!-- This is the slice 'result_id' --></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> <p>This is page 1</p></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> <p>item 1</p></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> <p>item 2</p></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> <a class="page" href="page_url?page=2">Go to page 2</a></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"><!-- End of slice --></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"></div></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"><script></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> $(document).ready(function(){</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> $('a.page').live('click',function(e){</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> var a = $(e.target);</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> var container = result.closest('.container');</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> container.load(a.attr('href'), { page_slice: container.attr('id') });</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> });</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> });</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"></script></span><br />
<br />
On the server side, we need a technique to output only the required slice, discarding any previously generated HTML, and aborting the rendering so no more subsequent HMTL is rendered. In Mason, this is easily done by implementing a content wrapping component.<br />
Here's how it looks in under Catalyst (the <span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;">$c </span>bit):<br />
<br />
Component <span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;">page_slice.mas</span>:<br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"><%args></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> $slice_id </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"></%args></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"><%init></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> my $requested_slice = $c->req->param('page_slice');</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> if( ( $requested_slice // '' ) eq $slice_id ){</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> # Discard any previously generated content,</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> # output the content and finish rendering</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> $m->clear_buffer();</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> $m->out_method->($m->content);</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> $m->abort();</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> }else{</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> # This component is transparent</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> $m->out_method->($m->content);</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"></%init></span><br />
<br />
Here's how to use this component in your <span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;">page.mas</span>:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;">% deal with param('page') to compute results and next page.</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"><div class="container" id="result_id"></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> <&| /page_slice.mas , slice_id => 'result_id' &></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> <!-- This is the slice 'result_id' --></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;">% # Output the right results</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;">% ...</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> <a class="page" href="page_url?page=<% $next_page %>">Go to page <% $next_page %></a></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> <!-- End of slice --></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> </&></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"></div></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"><script></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> $(document).ready(function(){</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> $('a.page').live('click',function(e){</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> var a = $(e.target);</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> var container = result.closest('.container');</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> // Use the container ID as the slice ID.</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> container.load(a.attr('href'), { page_slice: container.attr('id') });</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> });</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"> });</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"></script></span><br />
<br />
<br />
When clicking a '.page' link, a request will be sent with the param 'page_slice'. Thanks to this, the component page_slice.mas will output only the requested page slice, and this will populate the container.<br />
<br />
Your paging will obviously works without JavaScript. There's no Ajax specific code at server side. This is:<br />
<ul><li>Good for <b>accessibility</b>. Try using your paging with lynx. It just works.</li>
<li>Good for <b>SEO</b>. Our beloved search engines will crawl these links, even if they don't do Ajax.</li>
<li>Good for <b>testing</b>. Because Ajax is not needed to use your application, you can easily unit test your features from your web test suite.</li>
<li>Good for <b>reliability</b>. If for some reason your JavaScript is broken, the feature will still be available.</li>
</ul>Of course this technique can be applied to any kind of browsing features: sorting, faceting etc..<br />
Next time we'll discuss performing an action in Ajax, and managing Ajax redirections.<br />
<br />
I hope you enjoyed this post, thanks for reading!jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com0tag:blogger.com,1999:blog-5016251368610822667.post-83032902186480901192011-02-21T14:15:00.002+00:002011-03-10T10:58:41.571+00:00Avoiding encoding headache<div style="font-family: inherit;"><span class="Apple-style-span" style="font-size: small; line-height: 18px;">David Wheeler recently posted about <a href="http://www.justatheory.com/computers/programming/perl/encoding-is-a-headache.html">encoding headaches</a>. I'm not going to copy/paste my reply here, but the crux of it is:</span></div><div style="font-family: inherit;"><span class="Apple-style-span" style="font-size: small; line-height: 18px;"><br />
</span></div><div style="font-family: inherit;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="line-height: 18px;">Encoding is for i/o; </span></span><span class="Apple-style-span" style="font-size: small; line-height: 18px;">in the Perl space, text must be Perl character strings.</span></div><div style="font-family: inherit;"><span class="Apple-style-span" style="font-size: small; line-height: 18px;"><br />
</span></div><div style="font-family: inherit;"><span class="Apple-style-span" style="font-size: small; line-height: 18px;">I repeat:</span></div><div style="font-family: inherit;"><span class="Apple-style-span" style="font-size: small; line-height: 18px;"><br />
</span></div><div style="font-family: inherit;"><span class="Apple-style-span" style="font-size: small; line-height: 18px;"></span></div><div style="font-family: inherit; line-height: normal; margin: 0px;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="line-height: 18px;">Encoding is for i/o; </span></span><span class="Apple-style-span" style="font-size: small; line-height: 18px;">in the Perl space, text must be Perl character strings.</span></div><div style="font-family: inherit;"><span style="font-size: small;"><br />
</span></div><div style="font-family: inherit;"><span style="font-size: small;">Write that 100 times, display it next to your monitor(s), record it and play it whilst sleeping on your ipod for one week, have it tattooed on your fingers, and in no time you'll be known as the encoding guru in your company.</span></div><div><span class="Apple-style-span" style="font-family: Verdana,Helvetica,Arial,sans-serif; font-size: 14px; line-height: 18px;"><br />
</span></div>jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com0tag:blogger.com,1999:blog-5016251368610822667.post-71933090266155725862011-02-07T17:51:00.002+00:002011-03-10T10:58:51.453+00:00Some say MySQL does not have any sequencesNot true, it's got only one, and it's per session:<br />
<div><br />
</div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">select last_insert_id(last_insert_id() + 1);</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span><br />
To be reset like that:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">select last_insert_id(0);</span></div>jetevehttp://www.blogger.com/profile/10262102551420196339noreply@blogger.com0