Speed up your Grails tests (Spring Security)

We run a Grails application with Spring Security. Our integration tests are slow: 5m34s for 414 tests including about 45secs app boot time. That's about 1,4 test per second. Not that great. These tests are mainly functional tests, using GEB. I suspected the overhead of the browser automation would be the culprit, but when it comes to performance, measure, don't guess.

I started writing well scoped tests: one that does nothing, one that hit a dummy controller that returns ok, one that creates a Company and cleans it afterwards, one that creates a Company and an Employee - a pattern we use extensively in our tests.

It turned out the Employee creation was severely impacting the performance. I suspected some GORM inheritance issues (Employee extends User), or some missing index. Again, I knew better than guessing. None of them were actually at fault. Indexes have no impact when you create then delete a single user. And there was nothing foul with the inevitable outer join.

I narrowed to some code generated by Spring Security:

def beforeInsert() {
    encodePassword()
}

By commenting out the encodePassword(), I noticed a tenfold speed improvement. That was it. The password is encoded using bcrypt and it is inherently slow to hash (I would almost say: it is slow by design). So how do you bypass the password encoding during tests? A first messy attempt to add a transient flag to User did not pan out, and instead, a colleague pointed out the S2 password parameters.

By default, S2 uses 10 rekeying rounds and 1000 hashes. It does not allow to go below a certain threshold, so we settled for this:

application.groovy

if (Environment.current == Environment.TEST) {
    grails.plugin.springsecurity.password.bcrypt.logrounds = 4
    grails.plugin.springsecurity.password.hash.iterations = 1
}

There, we now have reasonably fast tests without fiddling with the User definition.

When our Employee was under the spot, my colleague fired XRebel and ran an API operation involving employee creation. He noticed that the password encoding operations took about of the third of the time:

On top of that, we added 2 containers to our Circle CI build, moved to the latest version and tweaked the build scenarios, cutting build and deployment time almost by three.

Nice teamwork with Eric Darchis and David Nguyen at Adessa Software. Improvement is a continuous effort.

 Hacked in translation

Original news

Check Point researchers revealed a new attack vector which threatens millions of users worldwide – attack by subtitles. By crafting malicious subtitle files, which are then downloaded by a victim’s media player, attackers can take complete control over any type of device via vulnerabilities found in many popular streaming platforms, including VLC, Kodi (XBMC), Popcorn-Time and strem.io. We estimate there are approximately 200 million video players and streamers that currently run the vulnerable software, making this one of the most widespread, easily accessed and zero-resistance vulnerability reported in recent years.

That's heavy. An upgraded version is already available for VLC, but what bothers me is the lack of information and the faulty update mechanism. When I launch VLC on my MacBook Pro:

You’re up-to-date!

VLC 2.2.4 is currently the newest version available.

No, I'm not up to date, and no, this is not the newest version available on the VLC website:

Version 2.2.5.1 • Mac OS X • 33 MB

I wish I had a decent package manager like on most GNU/Linux distros.

Debian package vlc

  • jessie (stable) 2.2.5-1~deb8u1
  • stretch (testing) 2.2.5.1-1~deb9u1
  • sid 2.2.5.1-1~deb9u2

As a side note, this does not make VLC risk free on that particular distro as other vulnerabilities remain.

Digging on the VLC webiste, I find no info on the vulnerability exploit and the supposed fix.

Log:

Changes between 2.2.5 and 2.2.5.1:
Security hardening for DLL hijacking environments
Translations updates
Misc: (...)

So I download the source code (you need to follow two links in order to have access to the repository):

$ git clone http://git.videolan.org/git/vlc.git
Cloning into 'vlc'...

Maybe on some branch?

vlc (master)$ git branch -lr
  origin/HEAD -> origin/master
  origin/master

Nope, a single branch, but some tags:

vlc (master)$ git tag -l | grep 2.2
2.2.0-git

Good luck finding when and where and how it was fixed. Reddit gave me pointers to 2 commits but the commenter is not sure at all that they are relevant. Well, I'm note sure what I expected, but I suppose the nasty bug is fixed.

 Macbook Pro Blue Screen Of Death

Rare footage of a user taking a picture of a BSoD on a MacBookPro late 2016

This is getting worse. This week, I had to hard reboot several times while connected to an external LG 27" screen.

 Macbook Pro late 2016 - Good and Ugly

When the new MacBook Pro model was announced late October 2016, I was disappointed]. I searched for alternatives, and found none. So I ordered a high-end MBP. It felt wrong. So I cancelled it. I kept looking for alternatives. I found none. So I re-activated my order.

After four months, here are my impressions.

UPDATE Stability issues - BSoD

The Good

  • Screen is fantastic, even better than before.

  • Trackapd is gorgeous. All other trackpads are a joke next to this one.

  • Perfomance is astounding. No CPU throttling AFAKT, super fast m2 SSD. I haven't tried anything fancy with the Radeon 460 GPU though.

  • I love the clacky keyboard. Not clicky, but clacky. That's probably because I own a Das Keyboard 4C Ultimate with clicky Cherry Blue keys. I could go clacking all day long with this MacBook Pro. But I guess many people are not going to like this keyboard however.

  • Still practically zero maintenance. TimeMachine got your back. No driver issues. I just can concentrate on my work.

  • It's thin and light, but this obsession to gain a few millimeters and grams is ridiculous considering the tradeoffs (less battery, user maintenance possibilities close to zero, limited connectors - see below).

The Less Good

  • TouchID could be nice. It's a bit slow, but it works, except when the laptop lid remains closed because it's connected to an external monitor. Then, the TouchID is useless at best, when it does not prevent me from logging in with a password. That happens every once in a while (I have to open the lid and "type in" my finger).

  • The battery is not what it used to be. It's not weak, but it's not as good as previous generation. If only they had made the laptop slightly thicker in favor of a bigger battery...

  • Stability is not what it used to be. Not a disaster, but I have to force reboot more often than I used to.

  • No more MagSafe. The magnetic part saved my previous laptop a few times when I accidentally tripped on the cable. Here, the USB-C is both slippery to grab and hard to pull. #fail

The Ugly

  • Atrocious Touch bar. Useless at best. Often buggy. And for a developer, function keys matter. They're still there, but they become inconvenient to access.

  • Very inconvenient USB-C ports. Yes, I use a single cable (sound + image + power) to connect it to my LG 27" 4k screen. It's neat, and it's great. And my Nexus 5X also has the right connectivity. Sure, it's future proof. But the future is not quiet there yet, and the projector connections in the meeting rooms have at best HDMI (hello VGA). Beyond that, I need an adapter for practically everything: USB type A external HDD, meeting room projector, ethernet, SD card reader... You get used to carrying them dongles along, which defeats the purpose of having a slim laptop.

  • No on-site guarantee. This ain't Dell or Lenovo or the ridiculously overpriced HP. It's a consumer device, not a pro device. Hopefully, the hardware is well designed and not likely to fail. But I keep my 2012 model in reserve, just in case something would go wrong, as I can't afford to remain without my working tool for a single day in case of a repair. Yes, it's ridiculous.

  • User serviceability is close to nil. Practically nothing can be replaced by the user. Glued battery, soldered RAM - that was already the case on the previous generation. Now even the SSD cannot be replaced, or at least it won't be easy.

Go for it?

I'd consider Dell and Lenovo long and hard before buying. If you can live with sub-par screen, PWM, dumb pre-installed software, plus manufacturer and MS Windows non sense features that is.

If MS Windows is not your thing, and if you don't want to go down the GNU/Linux road on a PC, and if you're looking for a high end machine, then I'm afraid the MacBook Pro remains a strong choice.

 Un vieux PC peut encore servir - ThinkPad T400

Nettoyage de printemps au bureau. Je récupère deux vieux PC portables destinés à terminer leur vie au parc à conteneurs. Le plaisir des choses simples, comme remettre une vieille machine en état de marche.

En ces temps d'obscolescence programmée, certaines machines sont plus durables que d'autres, comme par exemple les Lenovo ThinkPad séries T et P, dont les T400 et P60 (datant de 2009 et 2007 je pense) posés sur ma table sont issus. Si leur utilisation dans un environnement professionnel n'est plus à l'ordre du jour, il leur reste encore de beaux jours dans un rôle domestique. Leur recondtionnement n'est pas une activité strictement geekesque où seul le plaisir de chipoter compte, mais aussi une façon de lutter contre le gaspillage.

On trouve encore facilement des pièces de rechange, neuves ou d'occasions, et il est relativement simple de procéder soit même à une réparation (même si certaines parties nécessitent parfois un effort important de démontage), ce qui fait de ces modèles de bons candidats à la remise en état.

Mes deux PC sont vieux et sales; l'un des deux est couvert d'une substance jaunâtre et par endroit un peu épaisse qui est probablement de la nicotine, et il est certain qu'il n'a jamais vu de lingettte nettoyante. Celle-ci attendra : pour ne pas perdre de temps, d'abord s'assurer qu'il pourra fonctionner avant d'entamer les opérations sanitaires. J'ai envie de porter des gands en silicone entretemps.

Après un inventaire des composants, je canibalise des pièces du P60 en faveur du T400, qui est techniquement supérieur. J'installe GNU/Linux Xubuntu 16.04.2 LTS. Essai concluant. La machine répond étonnament bien, mieux que certains modèles récents ou neufs plombés par MS Windows alourdi par son écosystème toxique d'inévitables logiciels gourmands installés contre la volonté de l'utilisateur et dans le but de lui faire payer une licence.

J'y vais ensuite franchement avec le nettoyage - ça passe ou ça casse, mais pas question de le laisser dans cet état répugnant. Je remarque que la nicotine est plus présente à gauche qu'à droite; sans doute les cigarettes étaient posées dans un cendrier à gauche du PC.

À force de patience et de minutie, la machine semble comme neuve! Les chiffres et les lettres sur les touches sont encore parfaitement présents et ne présentent pas de trace d'usure, témoins de la qualité de fabrication. J'adore le look retro, je l'avoue, à l'opposé du design du MacBook Pro, et si la solidité et la conception ne sont plus celles du temps d'IBM, il en reste encore quelque chose malgré tout.

Le résultat est très gratifiant : la machine répond bien, sans lenteurs malgré une démarrage assez long, et je peux visioner des videos en 1080p, sur youtube; quoique cela ne soit pas des plus utiles sur l'écran à faible résolution. Je me connecte au Wifi et je transfère une photo par bluetooth. Le lecteur de DVD s'ouvre sporadiquement sans raison. On verra ça plus tard.

Pour lui redonner un coup de boost, je remplace le disque dur par un SSD. Et le gain de vitesse est énorme.

S'ils ne font plus le poids en entreprise, car techniquement dépassés, ces deux vieilles récup' pourront encore faire l'affaire pour un usage domestique. En effet, à part passer du temps sur Facebook, lire des emails, écrire parfois une lettre, et regarder des videos sur youtube, soit des opérations qui se font largement depuis un navigateur, que demande le peuple?

Spécifications

Lenovo ThinkPad T400

  • Écran 14" 12800x800 VGA
  • CPU Core 2 Duo P8400 @2.26GHz
  • RAM 4Gb
  • HDD 80Gb @5400rpm
  • Wifi, bluetooth, lecteur DVD

Mise à jour:

  • SSD Kingston UV400 240Gb (100€)

Durabilité et maintenabilité

Apple est parmi les pires, non pas parce que leurs composants seraient de piètre qualité et auraient une courte durée de vie - c'est plutôt l'inverse, avec une fiabilité supérieure à la moyenne - mais parce qu'en cas de panne ou tout simplement d'usure, le remplacement de pièces s'avère onéreux, difficile, voire impossible, précipitant le matériel vers une fin de vie prématurée. Sur le MacBook Pro fin 2016, quasi rien n'est remplaçable facilement : la batterie est collée, la mémoire est soudée à la carte mère (c'était déjà le cas sur les modèles précédents), et aujourd'hui même le SSD n'est pas remplaçable par l'utilisateur, ou alors très difficilement.

Au moins les composants Apple sont-ils de bonne facture, contrairement aux produits grand public vendus à vil prix chez Mediamarkt ou à la Fnac, qui ne valent souvent rien en terme de durabilité et qui n'auront souvent aucune perspective de mise à niveau au-delà de la période de garantie.

Idéalement, une machine devrait combiner une bonne conception et un bon assemblage, avec des composants de qualité qu'on pourra changer soi-même.

Acheter un bon PC d'occasion comme ceux-ci n'a peut-être pas beaucoup de sens, car en plus du prix d'achat et des aléas d'une telle acquisition, il faut sans doute prévoir un budget supplémentaire. Par contre, si vous parvenez à récupérer une telle machine, le jeu en vaut la chandelle pour peu que jouer les "repair café" soit dans vos cordes.

GNU/Linux

En remplacement de Microsoft Windows, GNU/Linux fait figure de logiciel durable. Il est disponible dans de nombreuses déclinaisons et variantes appelées "distributions", dont des versions adaptées pour des machines âgées et moins performantes, en plus d'être (largement) libre. Une des plus connues est Ubuntu. Elle est très simple à installer et à utiliser et est livrée avec l'environnement graphique ("bureau") Unity, un peu lourd pour une vieille machine. Sa déclinaison Xubuntu est basée sur XFCE, nettement moins gourmand en mémoire et en processeur, tout en restant pratique.

L'installation et la prise en main nécessite sans doute l'assistante d'un "geek", mais par après, je trouve cette solution plus pratique que MS Windows (mais moins que macOS), même s'il faut parfois composer avec le fait que ce n'est pas MS Windows.

 tradr - Cryptocurrency trading simulator

I made an half-baked attempt to build an automated cryptocurrency trading program, and it did not turn out to perform well. So I did the most obvious thing to do in that case: release the code under a free license, and hope it will be useful to someone.

GitHub

It was intended to work with Ether ETH, but it can equally work with Bitcoin BTC, or actually with an stock.

The missing piece is a component that would perform the actual trading, using a third-party trading API. But since the algorithm is not doing anything great, I left that part out.

The project has a detailed README so there is no point to reproduce it here.

 Trapped

Today I released the source code of Trapped, a labyrinth HTML5 game experiment made with Phaser.

The game: you are trapped in a labyrinth. The trick: the walls only appear as you get close to them. Well, that was fun to code! Kind of lame result though but hey, it's free software (as in libre).

You can play it from here. Mouse click or tap to move around.

 Android 7.1.1 Bluetooth issue

If you buy a smartphone other than an iPhone, you can buy one of the many brands that ship with a modified, bloated, and deprecated version of Android. Manufacturers are desperate to stand out in a busy market so they decide to "improve" the software, but them not being Google, they mess it up most of the time. Huawei P9 is a good example. The urge is too big for them to resist. Primum non nocere does not apply here. Expect 18 months of updates as per programmed obsolescence, after that your smartphone will be stuck in the past.

Or you can try one of the few smartphones that comes with a recent, unaltered version of Android. Like the excellent Nexus 5X. It shipped with Android 6.0 when I bought it, with an upgrade to Android 7.0 readilly available. But issues were reported so I preferred to delay the upgrade. Enter version 7.1.1. Should be stable and polished enough I thought. Indeed: the phone reacts better and the user interface has again been improved. But wait. I can't seem to connect it to the car via bluetooth any longer. And I'm not alone. Probably thousands of people are stuck, trying to figure out what to do, following useless phone reset procedures and wasting time with tech assistance. What a mess! I managed to connect it after several attempts - the usual voodoo applies here, where you try every little and seemingly unrelated configuration variations until it works.

Now I feel like I've been somewhat beta-testing the phone all that time... although I bought it at tag price. I understand why some people pay top price for an iPhone and never want to hear about Android.

 Macbook Pro late 2016 no thanks

Quick follow-up after I cancelled my order for a new MackBook Pro: yes, it's slick and the screen is fantastic, but it's still questionable and fraught with limitations.

The Good

Fantastic screen and insanely fast PCIe SSD (both read and write).

The Bad

TouchBar: see here and there or there. The layout changes in each app, so you can't use your muscle memory. Reviewer found no feature that can't be done with a shortcut. Limited use at best, and draining some battery power. Why not a touch screen like on the Dell XPS? I'm still convinced it's even worse for developers that heavily use function key as shortcuts.

Trackpad: so large it can swallow a squirrel but your right palm will rest on it, triggering unwanted clicks. See here or there

CPU: hardly better than the old gen.

GPU: slightly better, but less than what you would expect from a new generation. Would prefer nVidia, although they're not friendly to GNU/Linux

Battery life rant. In theory, it is as good as the last gen. In theory.

Upgradeability: Everything is soldered. RAM, battery, SSD. Not that I remember changing components a lot on my Mac, but it happened to me in the past. Should any part need to be replaced, you'd be forced to return the laptop to the store and find a replacement for days, maybe weeks.

Stability: Lots of bugs (that emoji bar showing on the screen!). Maybe he got unlucky.

Don't be fooled by the reviews telling you the USB-C connectivity only is okay, and that it will become standard next year. You'll still have to put your GoPro SD card in a dongle. Same with your Nikon/Canon camera SD card. And you won't throw away your USB 3 hard drive either if it's still functioning, so you'll need an adapter. The projector in the meeting room won't magically accept USB-C - be grateful if it has an HDMI port. So no, that's not a future-proof choice, unless you plan to start using you MBP in 5 years, or to replace every other connected device.

Still overlooked by most reviews: the lack of on-site next-business-day warranty.

Finally, the price is ridiculous.

Conclusion

Conclusion of a long time Apple user (we're talking 30 years): "I'll be holding to my last generation one". For Snazzy Labs, it's a decent computer but with terrible value for the money and he suggests you skip it for now.

 Unsecured wireless access point

Just finished configuring a TP-LINK TL-WR841N wireless access point. It also allows wired connections. About 20€ on Amazon. No fuss. Easy installation. I can even contemplate installing OpenWrt. Later. And it is amazing to find out that it ships with 2 vulnerabilities out of the box.

WPS is enabled by default. Its goal is:

to allow home users who know little of wireless security and may be intimidated by the available security options to set up Wi-Fi Protected Access, as well as making it easy to add new devices to an existing network without entering long passphrases.

But a major security flow has been found in this protocol in... December 2011. Yep. And it's right there staring at you, in November 2016. Not even just the mandatory push-button to enable it - that may be acceptble - but the permanent, brute-force ready PIN code. Good job.

Also out the box, WPA is enabled. Not just the more secure WPA2, but the ill-conceived WPA that was only a quick fix for WEP, the previously broken protocol. Many years ago. Outstanding work.

So I've disabled WPS, and WPA is set to version 2 only, although it still appears as WPA/WPA2 on my network list. I might need to move to OpenWrt sooner than expected. This is 2005 over again, when wardriving was all the rage and wifi access points were unprotected by default, or WEP-crackable at best. Nobody cared back then, and nobody cares today. Or maybe some people do, but they have no idea the appliance they buy is flawed, nor should they. I assume this model is far from being an exception. Not cool.

 I've cancelled my order for a Macbook Pro late 2016

tl;dr - After lots of hesitation, I ordered a new (high-end) Macbook Pro (late 2016), then cancelled a few days afterwards. The USB-C only connectivity, the limited user serviceability, the slow upgrade cycles and the lack of on-site warranty made me question my purchase. The premium price tag for medium-range specs and the lack of serious innovation did not help.

USB-C connectivity only

At first, I though that replacing all those heterogeneous connectors by their versatile and modern incarnation was a great idea. Then I realized I don't have a USB-C external harddrive, and I would need an adapter. A SD card reader will have to be carried around and plugged in when needed. Same goes for external display, ethernet (that's not new), meeting room projector (that's not new neither and screw VGA anyway). Even an additional battery loader requires additional cables.

Apple realized that would deter customers and, in an unprecedented move, reduced the price of its adapters. Not sure it's entirely good news.

More alarmingly, there may be compatibility issues. I also spent time watching videos from that guy who repairs Apple products for a living but won't buy one for himself. And he showed that MBP USB-C can have serious issues. Was it a defective item? Could be. Is it a design issue? Maybe. Anyway it made me wary.

Limited owner serviceability

You know it when you buy it. The RAM is soldered to the motherboard, so don't be cheap and aim high when you place your order, because you won't be able to increase the quantity afterwards. If the RAM is defective, tough luck, it will be a trip to the store and to tech service in order to replace it.

If the battery must be replaced, it's going to cost you 209€ (VAT incl, Belgium price) and your laptop will be unavailable for several days. And it will happen, specially if you bought your MBP when the new model came out four years ago and that you waited for the next major upgrade to replace it.

The screen and the rest of the hardware are also hard to fix.

That's a bunch of issues I gleefully discarded when I bought my MBP, mid 2012. Now the incredible battery is reaching its end-of-life and the once vague concern has become a real issue.

The previous model (the so-called first unibody) gave the owner some leeway to replace parts, and I easily swapped a HDD for a SSD, only to find out that the flat cable was so poor it couldn't handle the SSD bandwidth (freeze and crash would inevitably occur within the minute).

Today I would not even bother to attempt to upgrade a component. Actually, the SSD is now soldered too. Game over.

No on-site warranty

The overpriced Apple Care (314€) covers hardware failures, but there is no option for next-business-day on-site repair. It means that in case of hardware issue, you will have to send your laptop to Apple and find a replacement solution for the days or weeks to come. And since you are unlikely to be able to perform basic maintenance on your own (like replacing a battery or RAM), the odds of running into trouble are even bigger.

Now I don't put too much faith in any on-site warranty. The brand and the product have to be reliable in the first place. But relying on Apple built quality solely is a dubious proposition at best for a professional user. That's what I've done for years, and luckily nothing ever broke. I always had a spare MacBook Pro that could do the job, should the main one fail. But now that I'm older and full of wisdom, I'm not sure I want to go down that road anymore.

The lack of on-site warranty disqualifies the Macbook Pro as a "pro" machine in my opinion.

Lack of useful innovation

Touch Bar, yeah. It's cool. Even if you don't find it useful, it's not going to make your life worst, right? Wrong. And not only for mainframe operators or people stuck in 1971. As a developer, I use the keyboard extensively, and many functionalities are bound to function keys, even in the most modern and hype editors. Unlike many fellow coders, I try to avoid using the mouse as much as possible, and I try not to look at the keyboard (this guy showed me the mighty way of the keyboard shortuts).

A missing function key row is therefore an inconvenience to me.

A flat representation of the function row on the Touch Bar won't give me any tactile information on the key position, forcing me to look at the keyboard, increasing eye fatigue (I'm getting old, yes, and I need a 3k screen badly). So to me it's a negative-value feature, although I reckon it makes perfect sense for the general public.

Aside from the TouchBar, where is the killer novelty? A revolutionary screen (like the first retina)? A form-factor you won't find from the competition? A new material or design (like the first aluminium unibody)? No, only the Touch Bar, that's it.

Slow upgrade cycles

If I buy a brand new Macbook Pro, why should I care?

  • I buy a new Mac now, wait for 4 1/2 years for a major upgrade to come, and remain without warranty on an obsolete machine for more than a year. Been there, done that with my current mid 2012 MBP.
  • I buy a new Mac now, wait for 3 1/2 or 4 years, abandon all hopes for a major upgrade, then buy a new MBP, faster but still designed around the same architecture while the competition already offers more modern options.
  • I buy a new Mac now, replace it in 2 1/2 years, get a marginally improved computer, not too far off from the competition, then I only have to wait for 2 years to get a shiny replacement. Does not seem like a financially sound or rational option. Could work though.

As opposed to, with a PC: I can change practically when I want and get an up-to-date laptop with little to no need to stretch or delay my purchase.

Price

As a freelance developer, this is not really an issue. Not that we freelancers pile up money. Actually, it's the only substantial investment I do every 2, 3 or 4 years, and I use it as my primary tool. We have it easy in our profession: no store, no rent, no factory, no stock to pay upfront. Just a laptop and few licenses. Even a 50% overprice is not a real issue if you get a flawless experience in return.

Yet, for the price, I feel like I'm not making a good deal. That's a budget of around 3600€, including the Apple Care, plus extra for the dongles, and despite a whooping 220€ discount (didn't even have to ask for it, it was offered when I ordered as a professional). For no-so-fantastic specifications, even if the build quality is great, this steep price makes me uneasy.

Arguably, it is not crazy expensive compared to HP (HP EliteBook 1040 G3 V1A79EA for €3,586.00 and HP ZBook G3 Y6J62EA for €4,137.00). That's what I would call ludicrous.

But for €2,608.32, I can get a gorgeous Dell XPS15 (4k touchscreen, SDD 512Gb PCIe). Or for €2,884.39, a well spec'ed Lenovo ThinkPad P50 (4k screen, SSD 1Tb PCIe NVMe). And the Alienware 15 with it insanely powerful components comes at €3,181.00, if only I had the might and the will to carry it with its power brick.

All of them ship with a 3yrs onsite warranty.

What's next?

I'm still pondering my next purchase. If it wasn't for Microsoft Windows, I would have bought the Dell XPS 15 already. But it has been plagued with issues after its launch (BIOS updates required), and even if it got better, it can still turn out to be problematic. But it could manage. Installing GNU/Linux on the other hand is very tricky, even with recent kernel that fix most problems (but regressions have been reported).

We're talking CPU throttling, abysmal SSD write speed, BSoD, SSD not found on Windows. Add sleep/resume issues, external screen freeze, audio jack crackling or failure to detect on GNU/Linux. And the switch between the nVidia GPU and integrated video chip (Optimus) is bogus on that OS (applies to all manufacturers).

The Lenovo Thinkpad P50 has a larger footprint, and the screen is non touch and not as good but it's more robust, service friendly by nature, with no major issues reported on Windows and much less issues on GNU/Linux.

Still, it won't be the nice, smooth, pleasant ride I've enjoyed with my MacBook Pros and OSX.

Who knows, I might buy a Mac after all if things turn out okay in the coming weeks. I'm neither a fanboy nor a hater, just a professional looking for the best gear to get my job done with pleasure.

 Pas terrible le support Apple

Support #Apple:

  1. Commande "pro" uniquement par téléphone. Oui. Pas par internet.
  2. Pas de possibilité de les contacter par email. Téléphone uniquement (heureusement un 0800 gratuit);
  3. Personne ne peut m'envoyer d'email confirmant l'annulation de ma commande. 30 minutes d'attente de discussion mais une réelle bonne volonté de mon interlocuteur;
  4. Pas moyen de joindre le store de Bruxelles - par téléphone bien sûr (je raccroche après une demi-heure) - pour un remplacement de batterie;
  5. Pas de réponse au point 3 sur twitter.

Non pas que je m'attendais à mieux, ni que j'imagine que d'autres marques fassent mieux non plus, mais c'est pas terrible.

 Le Livre Dont Vous Êtes Le Héros (github)

Fin 2013, j'ai mis en ligne une version jouable d'un livre dont vous êtes le héros, avec quelques explications.

De temps en temps, je reçois un email de remerciement, ce qui fait toujours plaisir. Cette fois, on me propose de contribuer au code. Je me suis dit que le moteur de jeu gagnerait à être mis en ligne, ce qui est chose faite.

 Usine à gaz ordinaire

Quelqu'un me résume sa journée au bureau :

  • Elle a été bloquée pour gérer la TVA parce que, quelque part dans la DB ou dans un fichier, il y a une virgule. Elle suspecte que le fichier XML généré devrait plutôt contenir un point comme séparateur de décimal, mais elle n'a aucune envie de chercher à l'aveugle; #encoding #format

  • Le système sur lequel se déroule l'opération mélange SAP, un truc IBM, un logiciel d'agréagation à exécuter en local et une session sur un autre serveur et chaque mois, un nouveau bug apparait; #UsineAGaz

  • Précédemment, c'était des caractères non ASCII dans le fichier XML qui posaient problème. À l'aide de notepad, elle appuie sur flèche droite sur les noms de société qui posent problème et, remarquant que le curseur reste parfois sur place, elle fait delete pour effacer un caractère invisible. Cela résoud le problème; #l33t #notepad

  • La société en charge de ce logiciel lui a finalement envoyé un "nightly build" pour contourner le problème. Elle exécute le fichier .exe ainsi reçu; #c0wb0y #NoFear

  • Ce logiciel a été choisi parce qu'il ne coûte pas cher. Sans doute vrai si on ne tient pas compte des coûts cachés;

  • Le processus inclut la connexion à un serveur en... Windows 3 - et c'est même pas le maillon faible dans l'histoire; #Archeology

  • Le gars de l'IT se demande si le dernier problème n'est pas dû au passage SQL Server 2005 à SQL Server 2008 et s'il ne serait pas opportun de passer à SQL Server 2014. Elle s'en fiche, du moment que ça marche, et suspecte que d'autres bugs apparaitront et qu'elle sera coincée avec la version remise à jour et pas forcément compatible, parce que ça lui est déjà arrivé; #HistoryRepeatsItself

Ah oui, j'oublie de préciser : son métier, c'est comptable, pas informaticien. Par contre, elle se demande si ces informaticiens connaissent le leur, de métier. Je lui confirme que cette façon de fonctionner est parfaitement conforme aux pratiques usuelles en entreprise.

 Fedora 23

Installed Fedora23. I was looking for a sturdy workstation environment, and I was disappointed after one hour:

  • Terminal freezed;
  • File manager crashed;
  • No obvious way to access my NAS (NFS);
  • Blank screen freeze on shutdown (twice);
  • Fonts not very readable in Firefox;
  • No 720p video on youtube;
  • Failed to play .flac or .mp3 from my NAS;
  • Messed up dual boot with Windows 10

After a while (or was it because I had started a NFS service? I'm not sure), my NAS finally appeared in the network part of the file manager, so that was ok.

Arguably, the video limited to 360 is the default behavior in Firefox on GNU/Linux. You have to fiddle with some settings to activate higher resolutions. I would have appreciated an option to easily enable it though.

The dual boot issue was not that bad as Windows entered repair mode on its own and healed itself. I might have done something wrong during installation. Or not.

However I must stress out that the installer is the best I've ever seen. Smart and efficient.

But the crashes and freezes of the file manager, the terminal and the shutdown process, and the failure to play music did not impress me at all.

I'm typing this from Ubuntu 16.04 LTS and, despite the fact that it is heavyweight, it has been a pleasant experience I must say.

Well, I still have a partition with Manjaro+XFCE. A nice choice, maybe before moving to Arch. We'll see.

EDIT:

Rythmbox failed to play music from my NAS on Ubuntu too, so this is not a Fedora issue.

 Les clichés des générations X, Y et Z

Ce genre de cliché a quelque chose de dérangeant. On peut parfaitement se reconnaitre dans une des colonnes, et la prévalence de certains traits de caractères est peut-être avérée, mais certains d'entre nous se retrouvent un peu dans chacune.

Personnellement, je présente un mélange des bons et des moins côtés de chaque supposée génération, avec une tendance marquée vers Y et Z alors que je ne suis qu'un vieux crouton de X. Se voir catalogué en fonction de votre âge est alors stigmatisant et erroné, comme face à n'importe quel préjugé en fonction d'appartenance à un groupe (âge, sexe, situation géographique, origine sociale, etc).

Pour ne rien arranger, certains "+" et "-" sont hautement contestables, comme ceux relatifs à la hiérarchie et celui d'esprit de compétition. Ces classifications trahissent avant tout les conceptions de leurs auteurs plus qu'elles ne nous apprennent sur leurs supposés sujets et in fine contribuent à l'enracinement de préjugés.

 Un simple formulaire de contact

Un formulaire de contact peut donner lieu à un nombre impressionant d'erreurs de conception, et à aboutir à un résultat hasardeux. Même pour de grandes entreprises. Surtout pour de grandes entreprises. Exemple pratique avec Bosch.

Le lien "Contact" est visible sur une petite barre de menu en haut du site, ce qui est d'emblée supérieur à ce qu'on peut trouver sur certains sites de sociétés qui ne souhaitent manifestement pas être dérangées par les questions de leurs clients. C'est positif, mais de là, les choses dégénèrent.

Lien "Envoyer un email". J'aboutis sur un formulaire de contact. Je ne suis donc pas en train d'envoyer un email. L'expérience m'apprend que derrière ce type de formulaire en ligne se cache souvent l'envoi d'un email à un collaborateur, ou à une boite mail fonctionnelle partagée par le service chargé de répondre, en dépis de toute considération d'efficacité et de qualité dans le suivi, ce qui explique la terminologie employée. Le client ne partage pas forcément cette connaissance du terrain, et il se peut que la terminologie "envoyer un email" soit devenue courante pour désigner un formulaire en ligne, sans doute aidée par des générations de pratiques de suivi défaillantes.

Ce n'est pas Vincent Alsteen qui me contredira; il en a eu tellement ras-le-bol des formulaires en ligne qu'il s'est exilé :-)

Le formulaire à proprement parler cumule les erreurs :

  • Cadre "Votre adresse" qui reprend l'adresse, les coordonnées, l'objet de la demande et d'autres informations parasites. "Votre demande" aurait été plus approprié.
  • Le numéro de téléphone et l'adresse sont obligatoires, mais pas l'adresse email. Voilà qui est étrange. Vont-ils me répondre par SMS? En m'appelant? Par courrier postal? Là, je commence à être inquiet.
  • Demander l'adresse est en décalage par rapport à l'objectif poursuivi. Au téléphone, me demanderait-on mon adresse pour poser une simple question sur les garanties? (Note : oui chez Scarlet, mais ce n'est pas un exemple à suivre...)
  • Présence de 2 champs spam "newsletter" et "information sur les produits". On se réjouira de l'opt-out, mais cela n'a rien à voir avec la finalité recherchée par le client, à savoir poser une question ou introduire une demande.
  • Pourquoi ces deux cases à cocher ne sont-elles d'ailleurs pas regroupées?
  • Qu'est-ce que la question "recommandation" vient faire là? À nouveau, on ignore le client pour tenter de l'utiliser à des fins de marketing et d'évaluation. Combien de personnes vont-elles répondre n'importe quoi? Si je n'ai pas encore acheté de produit de la marque, que vais-je répondre? Pourquoi la recommandation porte-t-elle sur un ami ou un collègue, et pas un membre de ma famille? Pourquoi m'embêter avec cela?
  • Recommandation sur une échelle de 0 à 10. Une telle finesse est une aberration. On ne dit pas "je te recommande cette marque avec 8 sur une échelle de 10". On dira plutôt : "je te recommande vivement", "très fortement", "je te déconseille", etc.
  • Le bouton "Envoyer un e-mail" est conforme à ce qui a été annoncé sur l'écran précédent. L'action est précise et spécifique. Dommage que la partie "email" soit sans aucune pertinence en ce qui me concerne. "Envoyer votre demande" serait plus conforme à ce que je suis en train de faire.

Je ne serais pas étonné d'avoir omis l'une ou l'autre bizarrerie tant la liste est longue. Enfin, une fois le formulaire envoyé (enfin, je veux dire l'email), je suis redirigé vers cet écran :

L'échec est total. Aucun feedback. Pas de confirmation, pas de message d'erreur. Et, sans surprise, aucun email de confirmation ne m'est envoyé. Il est vain d'attendre une réponse.

Un simple exemple d'expérience utilisateur comme on en recontre quotidiennement, sans plus y prêter attention. Essayez avec des sociétés comme Proximus, vous comprendrez l'ampleur que peut prendre le phénomène.

Cependant, ces erreurs et approximations de design passent (presque) comme une lettre à la poste. Dans "Don't make me think", Steve Krug nous dit que l'utilisateur "se dépatouille" :

"We don't figure out how things work. We muddle through"

Je suis souvent impressioné par la capacité des utilisateurs à tolérer des applications, des écrans et des sites totalement abscons. L'utilisateur voit un formulaire, le remplit, clicke sur le bouton, et passe à autre chose, faisant fi de l'horreur qu'il vient de traverser, sans que cela ne semble l'émouvoir.

En déduire que faire n'importe quoi n'a aucune incidence sur l'expérience de l'utilisateur serait par contre une grave erreur. Bosch écorne sans doute un peu sa réputation de solidité et de sérieux avec un site mal conçu, et a contratio rate une occasion de la renforcer.

Steve Krug expose cela de manière plus édulcorée :

"If people manage to muddle through so much, does it really matter whether they "get it"? This answer is that it matters a great deal because while muddling through may work sometimes, it tends to be inefficient and error-prone."

Bonus : les causes

À titre d'exercice, le lecteur tentera d'établir les causes qui ont mené à cette situation. Suggestions :

  • La mise en forme a été confiée à un stagiaire ou à un junior sans aucune supervision, "parce que c'est facile";
  • Le département marketing a demandé d'ajouter une case à cocher "newsletter", et "on" s'est executé sans poser de question;
  • Plus tard, le même département, mais pas forcément la même personne, s'est dit que ce serait bien de proposer du spam et d'ajouter une autre case à cocher. On s'est à nouveau exécuté, sans même se soucier de la cohérence avec la case précédente, parce qu' "on ne va pas commencer à passer du temps à réfléchir sur la façon d'ajouter une case à cocher, tu l'ajoutes au formulaire et c'est bon";
  • Aucun test d'usabilité n'a été effectué (sur ce point, je suis prêt à parier);
  • Aucun test tout court n'a été réalisé ou, si cela a été le cas, les tests n'ont rien révélés car le formulaire était conforme aux spécifications (sans doute inexistantes);
  • La réalisation est prise en charge par des personnes incompétentes, paresseuses, démotivées ou en burn-out;
  • Des protestations sur cette aberration informatique ont été émises mais balayées du revers de la main parce que "ça marche comme ça, c'est bon";
  • Une fois le formulaire mis en ligne, des modifications "en vitesse" ont été effectuées mais sans retester l'ensemble;
  • Il n'existe aucun test automatisé pour couvrir ce formulaire;
  • Aucun des intervenants n'a jamais ouvert une page d'un bouquin de Steve Krug.

À vous d'ajouter des causes probables, sur base de vos expériences plus ou moins concluantes dans le monde IT.

Épilogue inattendu

À ma grande surprise, Bosch me répond quelques jours plus tard. Voilà qui était inespéré et qui me permet de conclure sur une note positive. Vincent, tu peux revenir à présent.

 Adorable GNU

At the end of his pre-FOSDEM talk on free software, rms auctioned an adorable gnu.

"If you have a penguin at home, you need a gnu for your penguin."

Download link

The audience was allowed to film and publish the presentation provided that:

  • The file format is free (as in "libre" or "vrij"). No mp4 or friends;
  • Accessible on a website that does not use proprietary javascript in the browser. Exit youtube and possibly every known online video hosting service;
  • No geo-tagging.

My usual video upload workflow goes like this:

  • Connect the GoPro camera to the MacBook
  • Import the video using Movie
  • Crop the video clip using the mouse
  • Add a title
  • Choose "export to youtube"
  • Done

The restrictions imposed by rms turned out to be challenging. My GoPro camera most certainly doesn't know anything about a free format. (i)Movie on OSX neither. So I booted my not-entierly-free GNU/Linux distribution (Manjaro) on my old desktop. And the struggle to find a suitable video editing software began :-)

Cinerella

After contemplating the confusing, old-fashioned interface for minutes, I concluded it would take me ages to figure out how this software works.

Probably inappropriate for my simple editing needs.

Link

Pitivi

Looks good, needs serious polishing compared to OSX Movie but that's ok. I couldn't get anything decent with the presets, even after tweaking. The best I could be was a low-quality 7Mb output. You can watch it, it's probably more than enough, but it's not what I wanted.

It crashes during encoding if you leave a blank on your video strip. Crashes if you enter something "wrong" in the video codec parameters (even a valid value, as proved by ffmpeg later). Annoying bit rate setting in bits per second, so you have to enter 2000000 rather than 2M. But that doesn't matter, since it crashed during rendering anyway.

I went to their IRC channel, asking for tips. A committer told me he has no idea what settings to use.

Link

Openshot

Much more usable than Pitivi, but even "high quality" HD 720p yields a poor result. With a supposed 15Mb bit rate, although 2Mb will prove much better with ffmpeg. Weird.

Link

Handbrake

Very convenient, simple and intuitive. Sensible presets you can further tweak - and I had to make trials and errors here too. But the webm format was missing :(

Link

ffmpeg

At the stage, I turned to the command line. After several trials and errors with ffmpeg, a suitable output was achieved with the following parameters:

$ ffmpeg -ss 0:12 -i GOPR0684.MP4 -c:v libvpx -qmin 0 -qmax 20 -crf 5 -b:v 2M -c:a libvorbis -threads 8 adorable-gnu.webm

The original file was 598Mb for slightly more than 2 minutes at 1080p (yes, the GoPro doesn't do much compression for obvious processing power reasons), and the converted video was 98Mb.

  • -ss 0:12 skips the first 12 seconds, where I'm settling the camera.
  • -c:v libvpx to use the vpx codec.
  • -crf 5 is the "quality" level. Lower means better. This parameter alone is not ideal, as it doesn't give the encoder any leeway to adjust the quality depending on the frame (more or less complex to encode).
  • -qmin 0 -qmax 20 adding a "min/max" quantization resulted in an overall superior output. This implies a bit of tweaking.
  • -b:v 2M for variable bit rate, with a target average of 2Mb/s. Again, this is the result of experimenting; 1M gave insufficient quality.
  • -c:a libvorbis to use the vorbis audio codec.
  • -threads 8 to use the 2 CPU cores. I've read that 0 should use all cores, but it wasn't the case.

Here, I have a decent output, although I don't have my title anymore :)

Link

Upload to you... no wait

There are numerous video hosting sites other than youtube.

But 1. although they appear to be free (gratis), you are the product; 2. the javascript they run in your browser is proprietary; 3. you are subjected to the host policy, and your video can be suppressed if it doesn't fit the host policy and 4. the file format is not free.

I asked for a free (libre) alternative on Twitter, StackOverflow, Reddit, G+, FB. The result did not surprise me: I got no answer.

So I SFTP 'ed it to my website. I don't expect the video to be a hit, otherwise my bandwith quota would quickly be exceeded B-)

Conclusion

I'm certainly not bashing at those free softwares. They're free, the source is available and I'm free to fix them if I'm not happy with the way they work. They fell short, given my expectations, but they may be suitable in other conditions.

In comparison to the Apple walled-garden, this simple operation required a substantial effort. All of this reminded me of the huge, gratis convenience many tools and platforms deliver, but what do I give up in exchange?

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

 Richard Stallman @FOSDEM2016

C'est un Richard Stallman un peu en retard et légèrement malade qui se présente en marge du FOSDEM 2016. Connu sous ses initiales rms, il est le fondateur du mouvement du logiciel libre.

Tout en entamant sa présentation, il enlève ses chaussures et chaussettes avant d'imprégner ses pieds de crème. Oui, c'est comme ça :-)

Le pitch (tl;dr) : les logiciels propriétaires vous privent de vos libertés et assujettissent leurs utilisateurs.

D'entrée de jeu, quelques règles pour ceux qui souhaitent filmer ou photographier. Vous pouvez prendre des photos, mais merci de ne pas activer la géo-localisation, et de ne pas les publier sur Facebook ou toute autre plateforme qui considère ses utilisateurs comme des "utilisés" ("used's rather than users"), ou qui demande d'exécuter du code javascript propriétaire. Vous pouvez filmer et mettre en ligne, mais pas dans un format propriétaire. Le ton est donné.

Stallman nous rappelle les quatre libertés du logiciel libre, numérotées de 0 à 3 :

  1. la liberté d'exécuter le programme comme vous voulez, pour n'importe quel usage;
  2. la liberté d'étudier le fonctionnement du programme, et de le modifier pour qu'il effectue vos tâches informatiques comme vous le souhaitez; l'accès au code source est une condition nécessaire;
  3. la liberté de redistribuer des copies, donc d'aider votre voisin;
  4. la liberté de distribuer aux autres des copies de vos versions modifiées; en faisant cela, vous donnez à toute la communauté une possibilité de profiter de vos changements; l'accès au code source est une condition nécessaire.

En ligne de mire du discours : Microsoft, Apple, Amazon, Apple, Facebook avec, en filigrane, la complaisance vis-à-vis les gouvernements (et la NSA). Quelques exemples :

  • Apple a refusé à plusieurs reprises une application sur son AppStore pour des raisons falacieuses, avant d'admettre que c'était pour des raisons de sensibilité politique;
  • Microsoft a nié la présence de "backdoor" dans Windows XP, ce qui est pourtant avéré, et ne nie même plus leur présence dans Windows 10;
  • Amazon efface à distance des livres de sa liseuse Kindle, et enregistre vos moindre gestes (changement de page, marque-page, surlignage);
  • La liste est longue.

La liberté du logiciel participe selon lui aux libertés fondamentales, dont elle n'est qu'une des facettes, compte tenu du fait que les logiciels prennent une place de plus en plus importante dans notre société.

Le discours devient néanmoins moins précis dans les cas limites, notament lorsqu'il s'agit de distinguer le milieux scolaire, où tout devrait être libre, du reste. Mais qu'en est-il de cette conférence, tenue dans une université? Aussi, un logiciel qui permet de créer la musique tombe-t-il sous le coup de la définition? Quid si je décide de graver un programme sur un circuit intégré? Les appareils ménagers peuvent-ils contenir des logiciels privatifs ou qui assujettissent les utilisateurs? Confronté à de telles questions, rms botte en touche en affirmant qu'il est vain de discuter ce qui n'est que son opinion.

Je reste sur ma faim. Il n'en reste pas moins que Stallman a foncièrement raison, et de plus en plus raison à mesure que le temps passe. Nous sacrifions de la liberté et nous nous laissons assujettir en échange de commodité.

La présentation se mue ensuite en une vente aux enchères, lors de laquelle une peluche GNU part à 120€ :-)

Le charismatique orateur enfile finalement son habit de prêtre et son auréole pour un prêche humoristique et geekesque à souhait. Un régal pour les nerds.

Video de la vente aux enchères à suivre...

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

 Journée Agile 2015

Comme à l'habitude, rien que du bon (ou presque) lors de la Journée Agile 2015 qui s'est tenue cette semaine à UMons. Rapide compte-rendu.

Keynote : Le bonheur au travail par l’agilité - Laurence Vanhée

La diva du bonheur au travail a certainement fait l'hunamité. Si elle (ou plus vraissemblablement "ils") a réussi à transformer un ministère aussi passéiste pour en faire un endroit de travail efficace et agréable, il est sans doute possible de faire la même chose n'importe où.

Un participant se demande si la rotation forcée des bureaux n'a pas un côté fort impersonnel, et si cela ne perturbe pas les petites habitudes qu'on aime avoir. Perosnnelement, j'échangerais n'importe quel bureau fixe standard (chaise d'entrée de gamme, aucun réglage de la table en hauteur, reflets, promiscuité inadaptée, éclairage aléatoire) contre n'mporte lequel des bureaux vu sur les photos.

Humains, Échouez! - Alan Hortz

Petit rappel : nous sommes des êtres humains. Dès le plus jeune âge, nous échouons, quand nous apprenons à marcher. Vous imaginez un parent punir son enfant qui tombe alors qu'il fait ses premiers pas? Cela n'aurait pas de sens. Par après, l'échec n'est pourtant plus aussi acceptable. Pourtant, c'est ce qui nous permet de faire des essais et de progresser.

Note : sans doute à ne pas confondre à la maxime "plus on échoue, plus on a de chances de réussir" de la méthode La Rache.

Toute histoire a son héros - Thierry Croix

Storytelling, bullet points mortels, peintures rupestres, Starwars, Einstein et bien d'autres. À l'instar de la Force, grande est la puissance d'une histoire que vous allez raconter. Une présentation en phase avec son sujet, en ce qu'elle privilégie la forme sur le fond. S'il est plaisant d'assiter à un one-man show - l'auteur est aussi comédien - cette approche trouve ses limites face à un public averti.

Une conclusion un peu cynique : oui, le storytelling est une forme de manipulation, et alors? Ce serait comme ça que la société fonctionne. Et alors? Je ne souhaite pas faire partir des cyniques et des manipulateurs, voilà tout. Je n'ai rien contre le storytelling si l'histoire est vraie, même si elle est un peu enjolivée par du dolus bonus.

Introduction à SAFe - Stéphane Rondal

SAFe = Scaled Agile Framework, ou le Scrum à une échelle plus grande qu'une seule équipe. Loin de la surenchère d'effets spéciaux et des présentations "one-man show", c'est une introduction bien technique auquel on a droit. SAFe est utilisé par ING et KBC, pour prendre des entreprises près de chez nous. Lampiris lui emprunte quelques éléments.

SAFe est-il Agile ? J'avais des doutes sur SAFe avant la présentation, et il ne font que ce renforcer. Perte de cohésion par l'appartition de rôles supplémentaires, retour par la bande des jours-hommes, cadre lourd qui semble à l'opposé de l'agilité... J'avais été séduit par l'approche de Spotify telle que documentée par Henrik Knieberg. Avec SAFe, on ne retrouve même pas de cadre pour les croisements entre équipes tels qu'on les trouve chez Spotify (Chapter, Guild, Tribe...)! Un comble pour un framework qui semble aussi détaillé.

Ce framework me donne l'impression qu'il sert aux décideurs à se rassurer, car il est vrai que les méthodes agiles pêchent par une certaine légèreté à grande échelle.

Gameworking et si jouer c’était la meilleure façon de travailler - Sacha Lopez

"La plus grande bataille de pouces multijoueurs de Belgique". Et un échec collectif, la compétition prenant le pas sur la collaboration. Le jeu est traditionnelement exlcu du monde du travail, perçu comme futile, alors qu'il permet de véhiculer une approche positive et libérée de toutes sortes de carcants.

Au final...

À part quelques récriminations au sujet de Leffe périmées en fin de drink, je crois que ce fut une excellente journée, terminée par un tour dans Mons en plein effervescence avant le Doudou.

 Un sandwich contre vos données personnelles

J'ai failli enregistrer ma carte de fidélité "class' croute" pour recevoir des points, puis je me suis dit : ai-je vraiment envie qu'une entreprise de plus connaisse mes habitudes alimentaires associées à mon nom, mon adresse, mon numéro de téléphone et mon email ?

Et puis d'abord, je ne sais même pas combien de points je gagnerai par salade ou par sandwich avant de profiter de 5€ de réduction. On ne m'achète pas aussi facilement.

Oh oui, je réalise à quel point c'est vain avec Google, votre supermarché, votre pharmacie, l'État... qui savent déjà tout de vous.

Posez-vous la question dans l'autre sens : pour 5€, acceptez-vous de céder vos données personnelles à une entreprise commerciale?

 Upgrade to Java 8

We are spoiled. One year after Java 8 came out, we can already use it at work. In my field (business applications) and in my country (Belgium), we are now certainly ahead of most large corporate organizations. Maybe we got lucky. I heard the IT department made bitter experiences for waiting too long before upgrading end-of-life products and softwares. Probably why they were readily amenable to a move to Java 8. The expected benefits from Java 8 were high, so I pushed for it without a second of hesitation.

Our path to Java 8

We took the following path from Java 6 to Java 8 :

  • Groundwork and preparation : migrate the Java 6 Maven project to Java 8
  • Scramble a talk on the relevant new features in Java 7 and 8 for your teammates, with the emphasis on lambda expressions
  • Prepare a lambda hacking lab with exercises for 2 hours
  • A few weeks later, follow-up with a wrap-up presentation, share code and discuss the Java 8 experience

Groundwork

My now former colleague Pierre Verhaeghe branched the code base and started to move to Java 8. They were minor issues and inconveniences, but no showstoppers.

Tools and libs to upgrade :

  • Moving from Tomcat 6 to Tomcat 8
  • cxf codegen 2.7.0 -> 3.0.3
  • javassist upgrade to 3.17.1-GA
  • DB2 (yes...) JDBC driver had to be upgraded to db2jcc4
  • p6Spy updgrade
  • slf4j scope set to 'provided' and deploy it in Tomcat 8
  • Upgrading to Eclipse Luna, although this step was not mandatory

Code changes

  • Make sure you have a comparator for TreeMap and TreeSet!
  • Some Guava code needed to be fixed
  • Added @PowerMockIgnore("org.slf4j.*") to 3 failing TestNG unit tests
  • Using Strict Math for some operations (`pow), because the non-strict version allows deviation between platforms, hence our phonetic algorithm failed.
  • Latest servlet version forbids duplicate attributes in JSP. They were several of them. Expect runtime failures if you have no E2E test coverage. IntelliJ issues a red error at least.

Prepare the team

We started with a talk on the relevant new features in Java 7 and 8, with the emphasis on lambda expressions. Take your time, don't rush things at this stage. It can be daunting for some of your colleagues, specially if they've had no prior exposure to functional languages.

Lab

A theorical presentation can only take you so far. I had the chance to join a vJug one year before, where Brian Goetz gave a talk on lambda. This was followed by a world-wide lab. I found this was good idea to redo it in the office. I added some exercises of my own to cover additional practical cases.

It's all on GitHub. Pierre added code illustrations of many Java 7 features.

Follow-up

6 weeks after the lab, it was time for us to share code snippets and discuss what Java 8 brought us. I took the chance to talk about traits (more on that in another post, maybe).

Misc

Learning curve and productivity

If you're considering moving to Java 8, one of the things should not worry about is the team productivity and learning curve.

We were a bit concerned at first, knowing that some of our colleagues had no prior exposure to functional languages. If you have experience in Python, Scala, Prolog, Groovy, ... it will be a walk in the park. If not, it will still be very pleasant. We were actually impressed by our colleagues adaptability. They picked up the new idioms in a snap, challenging us with though questions, and catching small mistakes in the presentation :-)

Eclipse

Code completion is far behind what you get with IntelliJ. Eclipse Luna seems to struggle at the slightest hindrance. This being said, I'm under the impression that Eclipse struggles on many occasions. The cross you bear is often the cross the management chooses for you.

Performance

There were questions on lambda expression performance. It is difficult to put figures on the table. After some research, I came to the following conclusion : "I wouldn't worry about it".

A bit unsettling I admit.

We had performance issues in the application before Java 8, and we still have them afterwards, no more, no less. We typically filter out records in the DAO layer, and we work on small memory collections. Typically 5 to 100 items. For a modern CPU, this is negligible.

Capturing expressions are slower, but even then, on tiny collections, I don't think it's going to make a difference. If you use lambda expression idiomatically, for small, pure functions, you won't need to capture anything and it should perform well.

My conclusion stands provided that you don't need micro-optimized code, and that you remain considered. YMMV.

In any case, measure, don't guess is the cornerstone of profiling and performance testing. Often I've been puzzled by the gap between the suspect and the actual offender. Again, I'd be very surprised if lambda expressions, as we use them, would cause any issue.

Guava

Most of Google Guava functional expressions are not needed anymore in our code. We simply kept them as is, removing them when the opportunity arises.

Dates

One of the great promises of Java 8 is java.time.*. Indeed, it's nice. We use java.util.Date to represent days - in our business, we need days a lot - plus utility classes. As expected, we're not magically going to replace of java.util.Date by java.time.LocalDate. Replacing dates on legacy code is no small undertaking. So we're mostly stuck with dumb old dates.

Pros and Cons

To sum it up :

(+)

  • Code readability
  • Functional expressions elegantly capture functional analysis
  • Less code -> less bugs

(-)

  • Debugging lambda expressions suck, big time. One more reason to stick to simple functional expressions.
  • Converting a list of X to a list of Y was more easily achieved with Goolge Guava, but in practice, that should not happen a lot if you use generics correctly.

Overall, it's a huge win, it pays off in no time, and everybody in the team was glad we did the move.

 Agile & Scrum - Questions pratiques

Alexandre Auquier et moi-même remettons le couvert avec une deuxième présentation Agile et Scrum.

Produit minimum viable, shuari, du développement en cascade à l'agilité, water-scrum-fall et avalanche, éligibilité d'un projet, écueils, et pas mal de questions pratiques.

Illustré avec des photos d'avions.

 Is it ok to resell your data?

Amongst the options of my gandi.net account, there's a disturbing option labelled "Reselling of your data".

Fortunately, it has been preselected to "no". The accompanying text is eloquent:

"Our contract with ICANN requires that we sell our WHOIS database to any party that requests it. However, you have the right to refuse the sending of your personal data in such an event. Only click on YES and proceed to the next form if you accept that your personal data may be sold."

I suspect they are contractually bound to ask for my consent, just in case I'd like to have my personal data sold to a third party against my own interest and without any financial compensation. If it's the case, I love how gandi.net handles the situation, with a clear and factual explanation.

The outcome remains however appalling.

 OSX Yosemite 10.10.1 wifi problems

Not fond of the recent OSX 10.10.1 update, supposed to improve wifi reliability. Not that I had any problems with my two MacBook Pro's. Not at all. I simply upgraded, and started having trouble with my old mid 2011 (rev 8,1) edition. Looks like I'm not alone.

Symptoms: wifi disconnects randomly after a few minutes. I deleted the network, rebooted like if I was running MS Windows, then joined the network again: it didn't help. Even rebooted the access point, just in case.

Now I'm resorting to the infamous "Reset SMC" procedure. I assumed all pre-retina era MBP without soldered batteries fell in the "battery you can remove" category. So I grabbed a screwdriver to open the lid only to find out this is actually a "battery you should not remove on your own": a warning sticker and deterrent triangle screws made it clear I'm not supposed to even touch that thing.

The applicable reset procedure requires you to press the left side Shift+Control+Option keys at the same time, then release them at the same time, then to press the power button to turn on the computer. Except that the MBP boots up as soon as I release the keys and power button. I have faith in the instructions (this not your average HP / Lenovo lousy Engrish webpage), so I assume I must have done something wrong. I realize "Option" is "alt", not "cmd". Let's try again. Fingers crossed. We'll see if the wifi problems are still there.

Nasty update; I didn't even have the wifi problems it was supposed to fix. I don't care much about eye candy updates. But I really do care about very high reliability. YMMV but OSX used to offer me a vastly superior experience as far as reliability and stability was concerned. Not that much since Steve Jobs left the building. Yet, unlike MS Windows, they only have to support a very limited range of devices they manufacture themselves so the least you can expect is something (close to) flawless.

 The worst-case scenarios

As developers, it is our responsibility to properly take worst-case scenarios into account.

"Taking worst-case scenarios into account is something that web design does poorly, and usually not at all."

Eric Meyer follows up on his "Inadvertent Algorithmic Cruelty" blog post. The picture of his daughter, who died last year, appeared on a party-like background of his Facebook auto-generated "Year in Review".

I believe his statement can be extended beyond web design considerations. In my experience, all "worst-case scenarios" are poorly taken into account in our industry.

Think about security and the well-known fallacies:

  • "This is not likely to happen" (but are you willing to take the risk and pay the price?)
  • "Who would target us specifically anyway" (let's not point fingers here)
  • and the dreaded "It's going to delay the release" (but even after the release, we won't do anything about it)

Think of any "process" where users are left stranded because their situation was considered unlikely to happen and was discarded based on other fallacies:

  • "We'll handle this case manually" (and of course there is no way for the user to reach someone who will help her)
  • The now patentable "This is not likely to happen" and its variant "This will happen to what? A dozen of people?" (so let them suffer, that will teach them a lesson)
  • "It would make things more complicated for all other users" (then you're probably doing it wrong)

Think about accessibility issues (motor or visual impairment). Often I can sense the manager's conflicted feelings. See that fancy menu item that requires careful clicking and pointing? You know some people won't be able to access it. We should do something about it. We know it's the right thing to do. But it will at best require more time and money. So let's not do it. Then you can look the manager in the eyes with a smirk that says: "I hope you can look at yourself in the mirror" :-)

This is when the worst-cases were not simply overlooked, then ignored when complaints started to flow in (closing your eyes won't make this issue disappear).

Sounds a bit like Dilbert, I know.

Of course, even when you think long and hard, there is not always a perfect or even a satisfactory solution. Our job is to make sure we take the worst-case scenarios in consideration and treat them adequately, whatever that implies in our company context.

 Hello World bootloader in assembly

Web development can sometimes be boring. Let's do something else. Today we'll write a bootloader that displays "Hello, World!". In assembly language. Just for fun.

Note: for maximum fun, try MOS 6502 AL on Commodore 64. It is simple, with only a few 8 bits registers, has a well documented memory layout and with amazing capabilities for a ludicrous 64kB RAM.

Caveat emptor

  • This blog post and the code is largely inspired from OS Development Series
  • This is not my primary field of expertise so feel to correct me and don't take the facts listed here at face value

Vocabulary

  • Assembly language (AL): "low-level programming language for a computer"
  • Assembler : "a program which creates object code by translating combinations of mnemonics and syntax for operations and addressing modes into their numerical equivalents"

"Calling the language assembler might be considered potentially confusing and ambiguous, since this is also the name of the utility program that translates assembly language statements into machine code. However, this usage has been common among professionals and in the literature for decades." — Wikipedia

Toolchain

Any distro will do the trick. Bochs might not be working on recent OSX versions. Didn't check on S Windows.

Bootloader

  • Stored in the Master Boot Record (MBR), on the first sector of the disk
  • Size is exactly 1 sector, or 512 bytes
  • Ends with a signature of 0x55 and 0xaa at bytes 511 and 512
  • Loaded by the BIOS POST interrupt 0x19 at address 0x7c00
  • Runs in 16 bits mode

Keep in mind that we have no filesystem and no operating system. No DOS, no Windows, no Linux and none of the associated interrupts, libraries and routines.

16 bits real mode

Real mode is an operating mode of all x86-compatible CPUs. The x86 family is backward compatible with the old DOS systems. Because they were 16 bits, all x86 compatible computers boot into 16 bits mode.

  • Uses the native segment:offset memory model
  • Limited to 1 MB of memory
  • Limited to the 16 bits registers
  • No virtual memory
  • No memory protection
  • No multitasking
  • No code privilege

Notice that because of the segment:offset model, a given physical address can be represented by many segment:offset combinations. They overlap.

Show me the code

See this gist. It's actually pretty simple. Things get crazy when you start to handle a filesystem and want to load a program in memory, like in a dual-stage bootloader, but there's nothing that complex here.

org         0x7c00

The org directive defines where the program expects to be loaded into memory. Not where it is actually loaded - that is controlled by whoever does the loading, here the BIOS POST [SO ref]. Its sole function is to specify one offset which is added to all internal address references within the section nasm doc.

You can try to modify the address, for instance to 0x7c01. The program will/may still work but the message will then be truncated.

There is no print function or anything like that. You practically have to point to the first character in the message buffer, load it in a register, print it, then move the pointer to the next character until you reach end of buffer (represented by 0). So we can consider ourselves lucky to have the lodsb (Load String Byte) instruction:

"LODSB transfers the byte pointed to by DS:SI into AL and increments or decrements SI (depending on the state of the Direction Flag) to point to the next byte of the string."

So it does this:

AL <- DS:SI
SI++

Given our message:

msg:            db      "Hello, World!", 0

We can set SI to point to the first character:

mov     si, msg                 ; SI points to message

To print a character at the cursor position, we use service 0x0e (Write Character in Teletype TTY Mode) of BIOS interrupt 0x10 (Video and Screen Services).

mov     ah, 0x0e                ; print char service
int     0x10                    ; print char

The character is loaded in AL by lodsb, while SI is incremented for us.

To detect the end of the string, we look for a 0. The obvious way is to do cmp al, 0 but a common idiom is to use or al, al. It's faster or 1 bit shorter, I'm not sure. In a similar fashion, mov ax, 0 is often replaced by xor ax, ax. In any case, after comparing AL to 0, whether with cmp or or, we test the zero-flag to check if we've reached our 0. If it's the case, we jump to the halt label. Otherwise, the character is printed and we jump back to the loop.

.loop   lodsb                   ; AL <- [DS:SI] && SI++
        or      al, al          ; end of string?
        jz      halt
        int     0x10            ; print char
        jmp     .loop           ; next char

No, there is no if-then-else construct. Conditional jumps (like jz) and unconditional jumps (jmp) are part the game.

When we're done, we simply halt:

halt:           hlt

Remember that our bootloader must be exactly 512 bytes, and that the two last bytes must be 0x55 and 0xaa. We need to fill the space in between, using some handy directives:

  • $ reprensents the address of the current line
  • $$ is the address of the first instruction
  • So 510 - ($ - $$) gives us the number of bytes we need for padding
  • times repeats the given line or instruction

Combining all of that together, we have our padding:

times   510 - ($-$$) db 0

We still need to add our 2 bytes signature:

dw      0xaa55

Because the x86 processor family is little endian, the least significant byte (0x55) is stored in the smallest address. You might argue that two consecutive db would be more explicit and I'd agree.

Compile and check

Your linux usually ships with as but its syntax is both backward and cluttered. I opted for nasm, which is also available on OSX and Windows.

$ nasm -f bin hello-boot.asm -o hello-boot.bin

You want a "pure" binary file, hence the -f bin flag.

Make sure the generated file is exactly 512 bytes (ls -l will do). If you open it with an HEX editor, you will be able to see the hello message, the padding and the signature. Notice 0x55 and 0xAA are is the expected order.

BOCHS

You probably don't want to install our little bootloader directly on your hard drive. A portable x86 PC emulator like BOCHS is much more convient. For our exercice, quemu should do fine too. Feel free to use whichever you are comfortable with.

apt-get install bochs bochs-x

You might want to install bochs-wx too. For some reason, I couldn't display the registers with the info command without the GUI.

Create a configuration file. We will simulate a 1.44Mb floppy disk.

debian@debian:~/$ cat bochsrc.txt
megs: 32
romimage: file=/usr/share/bochs/BIOS-bochs-latest, address=0xfffe0000
vgaromimage: file=/usr/share/bochs/VGABIOS-lgpl-latest
floppya: 1_44=hello-boot.bin, status=inserted
boot: a
log: bochsout.txt
mouse: enabled=0
display_library: x, options="gui_debug"

Remarks:

  • The last line is for GUI debugging and is optional
  • The location of romimage and vgaromimage may vary depending on your distro and even on the program version
  • The nasty address for the BIOS image may change from version to version

Launch bochs. Press c then enter to continue (why does it stop in the first place?). Witness the result :-)

Running on real hardware

Emulation is great for development and testing but it's not the real thing. Let's run our toy for real. One "convenient" way to do so is to install it on a real floppy disk. It is no surprise that my MBP has no floppy drive (it doesn't even have a DVD/BR drive), but I aslo have a desktop PC running Windows for gaming. But first, I must dig up a floppy drive, a disk and some cable. I know I can call @chewie301 if need be.

Reader aged less than 25 may have never seen that device. Some assembly required. Find the FDD socket on your motherboard. Do not forget to adjust your BIOS settings to boot from floppy.

That hazardous assembly will do. Make sure you don't block the rotating part under the drive if you don't mount it in a proper rack. I have cygwin installed, and although I can't manage to mount to floppy drive, it is actually accessible. Copy the bootloader to the boot sector:

$ dd if=hello-boot.bin of=/dev/fd0 count=1 bs=512
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.0617447 s, 8.3 kB/s

You should hear a satisfying mechanical sound as the heads and the platter move while the payload is copied.

Reboot.

The drive remains spinning with the light on, certainly because of the harsh halt command at the end (TODO: improve).

 Rex Mundi hacke Tobasco et Z-Staffing

Le très actif groupe Rex Mundi frappe à nouveau en publiant des données piratées des bureaux d'interim Tobasco et Z-Staffing :

Dear friends and foes,

Here is the full data leak from Xtra-Interim.be, another Novation.be project with numerous SQL injection vulnerabilities. Our advice to Xtra-Interim: ask Novation for a full refund. And damages, if possible.

Just a quick note: a little bird told us that the Belgian police's new stance is to advise victims not to pay, in the hope that we would eventually quit hacking Belgian websites if there was no money to be made out of it.

In truth, we won't stop regardless of whether we get paid or not.

It is just too damn fun.

Rex Mundi

Le ton est donné : que les sociétés visées acceptent ou nom de payer une rançon, les attaques continueront. Parmi les données publiées cette année et aujourd'hui, on retrouve nom, prénom, email, adresse, date et lieu de naissance mais aussi numéro de registre national et numéro de compte.

Epinglés à leur tableau de chasse de 2014 :

Quelques reflexions

En vrac :

  • Il est grand de nous interroger sur la façon dont nos informations personnelles sont disséminées dans la nature sans aucun contrôle de notre part et sans date d'expiration.
  • Les applications et les sites visés étaient-il raisonnablement sécurisés ? S'agit-il d'attaques "évidentes", telles que de nombreuses injections SQL comme déclaré, ou bien a-t-on utilisé des vecteurs sophistiqués mettant en échec les protections érigées dans les règles de l'art ? Dans le premier cas, il est temps de remonter le niveau de notre industrie. Dans le second, les choses se corsent et il faut placer la barre plus haut.
  • Les sociétés concernées ont-elles pris contact directement avec leurs clients ? (Je parie que non)
  • Quel dédommagement pour les clients victimes ? (Aucun je devine)

On collecte, c'est comme ça

Petite illustration pratique d'une personne qui a postulé à plusieurs reprises pour un contrat de travail auprès de recruteurs.

  • "Pouvez-vous me donner votre carte SIS?" (en Belgique, carte liée aux prestations de sécurité sociale)

Bon réflexe :

  • "Pourquoi faire?"
  • "Pour lire votre numéro de registre national"

Ceux-ci jouaient le rôle d'intermédiaires et à aucun moment il n'était question de signer un contrat avec eux. Bien entendu, on aurait pu continuer dans la lignée du : "... et pour en faire quoi?", mais ce n'est sans doute pas le moyen le plus évident d'obtenir un emploi.

Suit une demande de numéro de compte. Aucune pertinence entre les données récoltées et le but recherché. Dorénavant, il suffira peut-être de citer Rex Mundi pour décliner ce genre de demandes parfaitement inopportunes qui illustrent à quel point les données personnelles sont souvent traitées comme une simple marchandise.

 Virtualbox guest additions common errors

Like many of you, I've installed my share of Virtualbox instances.

And there always come a dreaded moment: the one when you install the Guest Additions. It can fail for many reasons, sometimes with a misleading message.

Here are the reasons I've come to identify when installing a GNU/Linux guest.

  • Media locked
  • Execution denied
  • Missing kernel headers
  • Missing packages
  • Kernel headers mismatch
  • Out-of-date Virtualbox version

It all starts here in any case:

Device -> Insert Guest Additions CD Image

The diagnostics and suggested commands are for Debian.

Media locked

You get the error message:

Unable to insert the virtual optical disk
VERR_PDM_MEDIA_LOCKED

The CD is already mounted. Check on the desktop.

Permission denied

The Guest addition CD is mounted. You double-click VBoxLinuxAdditions.run in your file manager and nothing happens. If you open a terminal and run the script manually, you get:

root@debian:/media/cdrom # ./VBoxLinuxAdditions.run
bash: ./VBoxLinuxAdditions.run: Permission denied

Although permissions seems correct:

root@debian:/media/cdrom # ls -la VBoxLinuxAdditions.run
-r-xr-xr-x 1 root root 7146957 nov 21 15:58 VBoxLinuxAdditions.run

In /etc/fstab, change this:

/dev/sr0        /media/cdrom0   udf,iso9660 user,noauto     0       0

To this:

/dev/sr0        /media/cdrom0   udf,iso9660 user,exec     0       0

Remount and execute.

Note: you might also see briefly the same error after double clicking the program from the file manager, depending on the guest OS and desktop; you'll have to open a terminal to troubleshoot as described above.

Missing kernel headers

This one is obvious when kernel headers are actually missing:

The headers for the current running kernel were not found.
If the following module compilation fails then this could be the reason.

This is a warning message. If you see no error, try to restart the guest and see if it works. Otherwise, install the headers. But you might need extra packages too!

apt-get install build-essential linux-headers-`uname -r` dkms

Or maybe a more sustainable version would be:

apt-get install build-essential linux-headers-generic dkms

Missing packages

Your kernel headers are installed but you get the "headers for the current running kernel were not found" message. See above: you might be missing some packages.

Kernel headers mismatch

Your installation is probably not in the expected state. You have installed kernel headers, but they are more recent than the actual kernel.

root@debian:/ # uname -r
3.9-1-amd64

root@debian:/ # dpkg-query -l linux-headers
(...)
ii  linux-headers-3.16.0-4     amd64     Header files for Linux 3.16.0-4-amd64
ii  linux-headers-3.16.0-4     amd64     Common header files for Linux 3.16.0-4

Last time it happened to me, I simply upgraded the kernel:

apt-cache search linux-image
$ apt-get install linux-image-flavour

Out-of-date Virtualbox version

When none of the above seems to fix the problem, you might have an outdated version of Virtualbox. The sad thing is that you still get the misleading error message: "The headers for the current running kernel were not found", or the same error installing a VBox addition service.

Update Virtualbox to the latest version and try again.

 Hack a duck

Contributing to an open-source project like DuckDuckGo is a fun and fulfilling experience.

My first contribution to the search engine DuckDuckGo is now live. It's a simple "instant answer", like many others available. So if you want quick meaningful data regarding QoS and uptime, call the duck. It's nothing revolutionary but it's always pleasant to watch something you've worked on go live.

I was already a part-time user of DDG, a search engine that does not spy on you, when I ran into "DuckDuckHack - Now you can hack your search engine". The idea is simple : "Hack on things that you know and care about to improve search results for your community". There's a large "Start coding" button, but you can also contribute without writing code by submitting and discussing ideas.

My criteria for an open-source project

Before I started, I had considered the following criteria:

  • Friendly community
  • Project management
  • Toolchain, build process and code quality
  • Karma

Working on a great tool within a hostile or an unwelcoming community is not my cup of tea. The very nature of the activity, even if you implement a feature entirely on your own, is to work with other people. You will be in touch with another or several other human beings to discuss implementation, look and feel, usability and relevance.

I first connected to the DDG IRC channel. Somebody asked a question and he received a friendly answer. Good. Then I went to their GitHub repo and I randomly picked one or two pull requests. Healthy discussions we taking place, with mutual respect between the developper and the DDG staff and collaborators. Obviously a friendly community I thought; that part was covered.

Some projects are better managed than others. If you go to the bug tracker and see many issues remain unanswered, that's not a good sign. If pull requests are piling up, I don't feel like submitting mine. With DDG, pull requests were processed in a timely fashion and the idea site was active. A strong indication that your hard work will be taken into account.

From there, you can already jump in. I followed and commented some ideas, asked for a status update when appropriate. I noticed an idea for a goodie was open for a year. I tracked the corresponding pull request. The work was done, the PR was closed but the goodie was not live. Weird. I asked on IRC and... a committer apologised that it got lost, although I wasn't even the author! The feature was quickly revived, the original author popped in to finalize the job and it was rolled to production. How friendly is that?

Ok, so from here, you know you have a nice community and a well-managed project. But as a contributor, I like it when I can jumpstart quickly thanks to up-to-date documentation and easy-to-configure tools. It's obviously the case with the doc. They use GitHub and Codio, a web IDE where everything is already set up for you. No need to install any toolchain on your computer! That's super cool.

Of course, you don't expect all projects to be perfectly clean and tidy. I suppose LibreOffice and Mozilla Firefox require a little more than a git pull followed by a grunt serve to run. I just expect the project to be reasonably well documented and with a decent toolchain, given its size. No doubt it was the case here.

There's always an overhead for your first contribution however, no matter what. It's just nicer when this overhead is kept as low as possible. Split your overhead costs by contributing more than once ;-)

And finally, it's better to work on something that matters to you, for instance a program or a tool you use on a daily basis. One might also argue that open-source contribution is always good for karma anyway.

Hacking the duck

Required skills:

  • git, GitHub: fork, branch, pull request, comments and code review
  • Programming. It's in Perl but any developer worth is salt should be able make it work without prior exposure (albeit more slowly)

I think that covers all you need!

First, find a validated idea to work on, or submit your own and wait for feedback. I spotted the uptime calculator and it felt like a good match for a newcomer. Make it clear that you are working on it (more on that later). Then Determine your instant answer type amongst SPICE, GOODIE, FATHEAD and LONGTAIL then navigate to the corresponding section of the documentation.

Fork the repository and start your Codio box as explained. I strongly advise you take some time perusing the code of existing "goodies". It is good practice to create a branch on your forked version of the repository, although in this case, working on the master branch should cause you no harm. If you are not familiar with git and GitHub, you might want to brush up your skills in that area first in order to be comfortable when the time comes to submit your work.

For me there was a catch: it's all in Perl, of all things. Yep. Well, the language should not be a concern for a seasoned developer (unless it's VB), so I thought I could live with it :-) I was a noob at work. This was a good occasion to discover Perl. It's not that bad actually. One can even write legit code and still be able to read it afterwards. I was positively surprised. Seriously.

So after a few trial an errors I was able to launch the local instance of DDG with the command duckpan serve and display a dummy text.

Now it's time to start coding. I elected to work in a TDD fashion, as much as I could. The DDG/Codio environment is great but you have to restart your duck after each modification, which is somewhat slow. It's way faster to launch your unit tests. TDD has many advantages beyond that anyway, and I grew more confident my Perl code was actually working as I intended.

Test a lot and pay attention to the details. The world is watching, no pressure. People will review your code. Show them the best you can as a courtesy.

Then, when you're ready... It's time to create your pull request.

From here, the outcome is totally dependent on the feature and how you implemented it. Someone pointed me to a project library that I could use to for extra consistency. Then there was some discussion on the design. I changed things here and there, improving the original version. At some point, there was some confusion on a suggestion. That can happen, we're not talking face to face. Later, it got to a point were additional changes were not improving the situation. It meant we were done.

About Perl: on DDH, it's okay if your code does not feel "perlish". They don't expect everybody to have extended PERL knowledge. In fact, it's quiet the opposite. As long as your code is clean and correctly structured, you should be fine, even if you haven't used the relevant Perl tricks. I received several suggestions to apply interesting Perl idioms of course, and I applied them to my code. Contributing is also about learning.

Hopefully your PR is closed and approved. Just wait for it to become live... Then pat yourself on the back for a job well done :-D

It wasn't my first time

Truth be told, I had already implemented another goodie earlier. But I failed to report I was working on it: before committing myself, I wanted to make sure I was actually going to do it. And guess what? Someone else issued a pull request just a few hours before me on the same idea!

What happens in that case? On a not-so-nice project, committers yell at you for the wasted time and effort, discard one of the PR, and everybody is frustrated. Here, @moollaza asked us what to do. The "other guy", @jarmokivekas, suggested to take my code, but I had no shame to admit his was better. I suggested to take @jarmokivekas 's version, and rip off the extra features and additional checks that were present only in mine. No ego fight. Code was reviewed, improved, and I participated in the tests. Both of us are listed as contributors. It's live here.

Like I told you, it is a nice project and an excellent place to start if it's your first time.

 vim happiness

Je n'entrerai pas dans la guerre vim vs emacs. Pour moi, c'est une question de goût et de préférences.

Une question plus pertinente : faut-il, en 2014, alors qu'on a quelques bons éditeurs à disposition, s'attarder sur un éditeur du passé? vim vous offre une puissance assez inégalée, à condition de le maîtriser et de le configurer, ce qui est bien plus difficile que de bien connaître Eclipse ou IntelliJ (ProTip: préférez ce dernier à celui qui précède, héhé). vi était obligatoire lors de mes études, selon l'adage : "le jour où vous serez devant un terminal avec rien d'installé, vous n'aurez pas d'autre choix que vi. Autant être préparé". Même pas vim et encore moins gvim. Sans surprise, ce cas de figure ne s'est produit qu'une seule fois sur ma carrière, ce qui m'a procuré un sentiment de bien-être incomparable. L'investissement "de base" était donc pour moi réduit, puisque j'avais de toute façon déjà souffert lors des études.

La pratique est aussi, à mon avis, un mal nécessaire : plus qu'avec des outils plus simples, les raccourcis se perdent assez vite quand on ne l'utilise pas.

À vous de voir si cela en vaut la peine si vous débutez.

Dans l'affirmative, voici quelques références qui pourront vous être utiles. Mais si vous accrochez, attendez-vous à une expérience assez unique.

Learning vim

  • Vim pour les humains (Vincent Jousse) - Excellente introduction pour les débutants avec une aide à la configuration durant la prise en main. Les habitués apprendront encore l'un ou l'autre truc. Payant en prix libre; un chapitre gratuit pour évaluation. Si vous n'êtes pas débutant, vous resterez peut-être un peu sur votre faim.
  • Learn to speak vim – verbs, nouns, and modifiers (Yan Pritzker) - Explication claire des concepts de base qui font de vim un éditeur différent. Une fois ces principes en tête, la suite vous paraîtra naturelle.
  • Learn Vim Progressively (Yann Esposito) - Bien agencé : de "Survice" à "Superpowers".
  • Vim Text Objects: The Definitive Guide (Jared Carroll) - On retape sur le clou des text objects. À survoler.
  • Shortcuts cheatsheet - Fiche récapitulatives des principaux raccourcis vim.

Extensions

  • NERDTree - "Allows you to explore your filesystem and to open files and directories". On se rapproche d'un IDE...
  • exVim - "Turn Vim into a nice programming environment" - une étape de plus.
  • git wrapper - Le support de base pour git me suffit; pour le surplus, je passe par SourceTree ou IntelliJ.

Misc tricks

 Testez votre site sous Internet Explorer mais attention

Tester un site avec Internet Explorer quand vous ne travaillez pas sous Windows n'est jamais des plus pratiques. La solution passe généralement par l'installation d'une machine virtuelle, ce qui est lourd et demande de posséder une licence, même s'il faut tempérer ce point au sujet de Windows 10 disponible gratuitement en preview release. Un logiciel tel que celui-ci aide grandement à tester différentes versions, mais la version la plus récente n'est généralement pas (ou mal) supportée, outre des problème de stabilité.

L'initiative modernIE de Microsoft est donc la bienvenue. Rendez-vous ici et identifiez-vous avec votre compte Live, ou créez-en un. Sur cette même page, téléchargez le client Remote Desktop qui vous convient. Suivez les instructions pour lancer une instance de test.

Vous êtes prêt à tester avec une installation légère, rapide et sans soucis de license.

Mais. Il y a un "MAIS".

J'ai testé mon site ainsi que certaines applications de mon labo, et plus particulièrement ma démo javascript de "Matrix" pour constater des problèmes d'affichage.

RemoteApp - modern.IE, Windows Server 2012 R2, IE 11.0.9860.0

Alors que dans VirtualBox, Windows 10 preview, IE 11.0.9841.0

Remarquez que la police "matrix" fait défaut dans la version modern.IE et que des caractères latins apparaissent à la place.

Idem avec Font Awesome. Modern.IE:

Alors que tout est bien avec ma configuration VirtualBox:

J'ignore ce qui cause cette différence :

  • l'OS
  • la virtualisation
  • la différence mineure de version IE?

Si c'est dû à la virtualisation (j'en doute), alors le teste n'est pas fiable. Si c'est dû à la différence mineure de version, alors IE est vraiment la pire des plaies - mais ça, on s'en doutait déjà. Si c'est l'OS, le teste n'est non seulement pas fiable (je doute fort qu'on s'intéresse à la compatibilité Windows Server 2012) en plus de poser question quant à la cohérence.

En toute hypothèse, modern.IE est un outil à manipuler avec recul et je ne prendrais ce que je vois à l'écran pour argent comptant.

 The growing rebellion against cumbersome type systems

According to the golang FAQ, "there is a growing rebellion against cumbersome type systems like those of Java and C++, pushing people towards dynamically typed languages such as Python and JavaScript".

During a keynote that was way to short for him to decently develop his ideas, Rob Pike puts the finger on some of the things that hurt us developers.

It can be summarized with the following bullet points:

  • The languages mainly used today are verbous, noisy and complex.
  • His personal analysis shows us how we got there. C became dominant in reasearch field on Unix. The need for higher level constructs lead to C++, a poor choice but with the advantage of compatibility with C.
  • C++ became the language of choice in parts of industry and research. Java came as a clearer, simplified version of C++.
  • In the late 1990's, Java took its place as a standard language for teaching.
  • Programming has become too complicated and hard to use. Like in a bureaucracy, every step must be justified. Replication became a placeholder for safety.
  • The clumsiness of the main languages caused a reaction. Simpler languages have become popular (Python, Lua, JavaScript, Erlang). Some rigourous and elegant languages have also arisen (Scala, Haskell). Despite the "standard model", these alternative approaches are the sign of a renaissance of programming.
  • A confusion arose. The world has split into a false dichotomy: nice, interpreted, dynamic versus ugly, compiled, static.
  • Go tends to combine the safety and the performance of statically typed languages with the expressiveness and comodity of dynamically typed and interpreted languages. It also aims at being suitable for modern systems.

You may of course disagree with Rob Pike's views but I can certainly relate to them. There are so many good tools out there. Don't accept the status-quo only because it is more comfortable. Don't dwell on the same tech stack only because it works although it hurts your productivity. Join the rebellion, free yourself from the past and break the vicious circle.

 Payer pour LinkedIn In Mail

En pressant le bouton "Send InMail" sur la page d'une annonce LinkedIn, on me propose de payer 21,99€/mois pour contacter le recruteur.

Rien n'est gratuit, et si vous ne payez pas pour le produit, c'est que vous êtes le produit. Je préfèrerais que les recruteurs paient - ce qui est déjà le cas et devrait suffire, tout en étant "naturel". Mes données personnelles étant déjà monétisées, je suis déjà le produit et je ne suis pas prêt à payer en sus pour un service à la valeur ajoutée presque nulle.

 Download songs with SoundCloud API

It might not be what you think. This is not a link to a website that will download all your favorite songs. This is better. This is a Python script.

EDIT: The original 5 lines script has been turned into something slightly bigger, hosted on GitHub.

You can download a single song, or a complete playlist.

 Observations sur le développement et le déploiement chez StackOverflow

Article surprenant sur le développement et le déploiement chez stackoverlfow. Quelques points que j'ai relevé :

Garbage collection driven programming

Ceci inclut de se dispenser de TDD (on peut comprendre), d'éviter des couches d'abstraction (cette manie de la programmation en lasagnes doit cesser), et d'utiliser... des méthodes statiques, même si cela n'est pas très catholique ou orthodoxe O.O. Pour des raisons de performance.

Ce dernier point me fait froncer les sourcils. Le langage utilisé, C#, est-il un bon choix si son mode d'écriture usuel pose des soucis de performance? Passer systématiquement par des méthodes statiques ressemble à forme d'optimisation prématurée. Mais on peut s'imaginer que cela renforce au moins la cohérence de style (tout est statique plutôt qu'un mix).

Do only what needs to be done

Très peu de tests unitaires et autres parce qu'ils déploient fréquemment et préalablement sur meta.stackexchange, qui leur sert de site de tests d'acceptance et que leur communauté leur remonte rapidement les bugs, avant de déployer sur SO à proprement parler.

Étrange postulat. Bien sûr, une éventuelle erreur sera rapidement détectée par leur communauté, mais pq la laisser se propager aussi loin? Comment avoir une grande confiance dans le code écrit si la couverture en tests est lacunaire? Juste en le relisant? Quid en cas de modification majeure? Cela semble marcher pour eux. "You Aint Gone Need It really works" disent-ils, poussé à l'extrême, rejetant non seulement le "TDD" mais carrément les "T".

No bureaucracy

"There’s always some tools your team needs." Quand je pense aux entreprises qui choisissent Eclipse "parce que IJ est payant" ou dans lesquelles la moindre licence à 50€ exige de suivre une procédure d'approbation dont le coût interne réel excède celui de ladite licence, quand ce n'est tout simplement refusé parce que "ce n'est pas standard" dans l'entreprise, je me dis que je ne délire pas en me tenant à l'écart.

Go down to the bare metal

Ils descendent au niveau "IL", en quelque sorte le bytecode en .Net. Conséquence logique d'une focalisation extrême sur les performances. Pas le genre de chose qu'on rencontre sur un projet usuel en entreprise.

Lire aussi : les morceaux des powerscripts utilisés lors du build (ça vous change de maven), les machines surdimensionnées avec pour conséquence l'inadéquation d'Amazon EC2 qui serait hors de prix, le culte du SSD, ...

 You just made your first flattr

C'est un article de Korben qui m'a décidé à me créer un compte flattr - bien entendu, les sollicitations insistantes de Lionel Dricot n'y étaient pas étrangères non plus.

On ne peut pas éternellement se plaindre des publicités, à la fois intrusives et inadaptées pour soutenir un site, même si on ne les voit plus avec Adblock Plus; ni du contenu foireux produit quand il n'est pas carrément pompé par des journaleux ou des "bloggueurs influents" sans se décider à aborder les choses autrement.

Vous pouvez allègrement et sans risque de contradiction bloquer les pubs et, si c'est légal là où vous vivez (hem), pirater du contenu en même temps que vous soutenez des sites gratuits ou en prix libre. Payer pour un truc gratuit? Mais c'est débile? Selon les normes classiques, un peu. En voyant les choses différemment, pas forcément (Waow, ça va m'en faire des billets à soutenir).

Me voilà donc "flattrant" ces deux héros des internets. Le compte flattr se crée en deux coups de cuillers à pot. Pour l'instant, ma rétribution est ridicule et symbolique et il ne faut pas compter dessus pour devenir riche ni même pour en vivre :-)

Premier bémol : les trackers, que je bloque en masse avec Ghostery. Les boutons flattr en font partie. Je dois donc autoriser flattr en parmanence, avec le tracking permanent que cela entraîne (bof) ou au cas par cas, quand je décide de donner. Mais sur ploum.net par exemple, le bouton n'apparaît même pas comme étant désactivé par Ghostery comme c'est le cas d'habitude. Je perds l'indice de son existence. Par contre, sur Korben, le bouton est là. Ca sent le javascript dans le premier cas.

Et encore, une fois sur flattr.com, le bouton me redirige vers une page blanche, même si Ghostery n'annonce pas avoir bloqué quoique ce soit. En chipotant un peu, Ghostery finit par montrer qu'il bloque... le bouton flattr sur flattr.com. Il suffit de l'autoriser sur ce site.

Deuxième bémol : la connexion à d'autres comptes (Twitter, Github). Je passe outre le problème typique des droits souvent trop étendus réclamés pour accéder à votre/vos autres comptes (pas testé ici). Ce n'est pas parce que je "star" un repo Github ou que j'ajoute un Tweet à mes favorits que je souhaite donner. Donc non pour le moment.

Ca ne veut pas non plus dire que l'auteur a un compte flattr pour le coup... Tiens, pas mal comme tactique pour inciter des personnes à s'inscrire pour récolter des flattr non sollicités.

Ces deux remarques sont d'importance mineure; il vous suffit de ne pas connecter votre compte flattr à d'autres comptes et de comprendre comment Ghostery marche (il n'est pas rare qu'il bloquent certaines fonctionnalités essentielles sur certains sites).

En tout cas, la démarche a du sens et, si vous vous lancez, ne risque pas de vous ruiner.

 Belgian Groovy/Grails User Group

That's it. I'm starting a Groovy/Grails User Group in Belgium. The idea is to discuss about Groovy & co of course, but also to promote its use in the enterprise world. Which is far from what it could be.

Would you be interested in joining me for an informal first meeting, around a beer or a coffee, in Brussels? I'd be pleased to meet you!

RSVP on meetup.com

 XKCD password scheme is broken

According to Bruce Schneier, the XKCD password scheme is no longer a good practice to follow:

(...) the oft-cited XKCD scheme for generating passwords -- string together individual words like "correcthorsebatterystaple" -- is no longer good advice. The password crackers are on to this trick.

I suppose it is still better than the Tr0ub4dor&3 scheme anyway, but Schneier suggests his own:

My advice is to take a sentence and turn it into a password. Something like "This little piggy went to market" might become "tlpWENT2m". That nine-character password won't be in anyone's dictionary. Of course, don't use this one, because I've written about it. Choose your own sentence -- something personal.

But looking at the other examples he provides, this falls short when it comes to remembering it, or to mentally recall the transformation. Did I use a capital letter, a 2 substitution for to, an exclamation mark...

Don't fall for the "base string + variant" scheme anyway, where you always use the same base string, then add a (short) suffix depending on the website. For instance timbsp4ws ("this is my basic string password for websites") followed by blacne (inspired from "blog.ackx.net"). An attacker that has compromised your password on any given website could derive your password for other websites, e.g. it would be timbsp4wshoco on hotmail.com.

So I'd stick to the Password Safe approach, or any other password vault that suits you (side-note: I'd keep it local to my computer though, not sync'ed in the cloud). One very long and hard-to-guess password to rule them all, and each individual site uses a generated random long password.

Bruce uses 12 characters by default, I use 32; but beware that this causes issues on some ill-conceived sites. Often, they limit your password length to 12 or even 8, but have the courtesy to let you know. Sometimes however, the webiste will accept your 32 characters password but actually silently truncate it (I believe phpBB caused me some troubles in the past).

 Google Drive sous OSX

Image Google Drive

Récapitulons. Synology CloudStation ne tient pas la route, et hubiC non plus.

J'ai de sérieuses réticences à confier l'intégralité de mes documents et photos à Google, même s'il en possède déjà une fraction significative. Mais pour partager un dossier de travail avec d'autres personne, c'est l'occasion de tester le client Google Drive OSX.

Et c'est simple et efficace. Pas de "indexing in progress" sans fin ou d'informations contradictoires comme avec hubiC; pas de conso CPU affolante ou de freezes comme avec Synology.

Sauf qu'on est victime du nivellement par le bas des interfaces. Les interfaces anti-ergonomiques et surchargées étaient légion dans les années 2000. Heureusement, les gens semblent ne plus vouloir de ces horreurs conçues par des bozos. Revers de la médaille : la simplification de l'interface s'accompagne d'un appauvrissement de fonctionnalité. One size fits all.

Disons que je voudrais synchroniser pour partage certains dossiers parmi mes documents et mes photos, mais pas tous. Parce que ça serait trop volumineux, donc trop coûteux et moins rapide. Disons que je souhaite synchroniser deux dossiers comme ceci :

/Users/youri/Documents/Info/Linux == /Info/Linux
/Users/youri/Pictures/Butterflies == /Pictures/Butterflies

WRONG. Google Drive crée un dossier pour ses besoins ou vous choisissez un dossier sur votre machine. La synchro part de là. Avec les limitations suivantes :

  • Vous ne pouvez synchroniser qu'un dossier à la racine, pas un sous-dossier;
  • Les documents sur votre Drive qui ne sont pas déjà dans un dossier seront synchronisés de toute façon - WTH.

Pas possible donc d'indiquer arbitrairement et simplement vos deux dossiers à synchroniser. Sans doute serait-ce trop compliqué à comprendre. Et avant de comprendre pourquoi les fichiers à la racine était d'office synchronisés, j'ai dû m'en référer à la documentation.

Résultat, pour parvenir à mes fins :

  • Je ne peux pas démarrer d'un sous-dossiers en vue d'une synchro+partage côté Google Drive. Les sous-dossiers sont bien entendus synchronisés mais il faut partir d'une répertoire racine.
  • Mes fichiers paresseusement non classés doivent être déplacés dans un répertoire fourre-tout ou rangés dans des dossiers adhoc pour ne pas être synchronisés.
  • Sur mon portable, j'ai dû déplacer mes fichiers à synchroniser vers le répertoire Google Drive. À leur emplacement d'origine, j'ai ajouté un Alias (symlink) vers le répertoire Google Drive, qui m'oblige donc à ré-organiser mes fichiers à sa sauce (l'alias dans l'autre sens ne marche pas).
mv ~/Documents/Info/Linux  ~/GDrive/Documents/Info/Linux
mv ~/Pictures/Butterflies  ~/GDrive/Pictures/Butterflies
~/Documents/Info/Linux ===> ~/GDrive/Documents/Info/Linux
~/Pictures/Butterflies ===> ~/GDrive/Pictures/Butterflies

Rien de rédhibitoire mais mon cas d'utilisation est-il à ce point tordu que je doive en venir à de telles contorsions ?

Autre gros bémol: le client n'est pas exempt de soucis de stabilité. De temps en temps, "une erreur s'est produite" et je m'en sors en relancer l'application. Dans un cas, j'ai été forcé de supprimer mon dossier Google Drive local, de reconfigurer le client et de relancer la synchro.

 Tripping on Go: bloxorz

The Go language

Go is a fast, statically typed, compiled, garbage-collected language that feels like a dynamically typed, interpreted language.

It was designed and developed to make working in a modern environment (multicore processors, networked systems, massive computation clusters) more productive, lightweight and pleasant.

A basic bloxorz solver

After a short intro and a few samples on the golang website, nothing beats coding when it comes to learning a programming language. Something not too trivial but not too complex neither, and prefarably fun.

A bloxorz solver seemed appropriate. It's a simple, yet addictive game where you move a rectangular block around squares on a floating platform, following certain rules. Well, just try it!

I didn't bother taking into account all the fancy terrain variations like soft squares (where the block must be lying rather than standing up), switches, bridges and other puzzling tricks. For the exervice, plain terrain will do.

Blocks

Let's start with a Block. The Block is a simple struct.

type Block struct {
   ax, ay, bx, by int
}

Provided x and y vectors, it is able to move around, or more exactly, to create a new block based on its current position and the vectors.

// Create a new Block moved relative to this Block
// according to the given vectors.
func (block Block) move(dx, dy int) *Block

move is a method that applies to a Block, takes 2 int arguments and returns a pointer to a (new) Block.

BFS, channels and goroutines

For each candidate solution, we must retain the path followed as a list. And we'll also need a queue for our breadth-first search (BFS). But there are no lists nor queues per se in Go. To me, that's the most suprising (and maybe disappoitning) part of Go: unlike in other languages, there is little built-in support for collections. More on that later.

Leveraging the presence of channels, each time the BFS runs into a solution, we send it to a channel. A channel can be seen as a pipe, for commmunication purpose. As they say in their slogan:

Do not communicate by sharing memory; instead, share memory by communicating.

Sending data to a channel is as easy as this:

// Found a solution
solution <- newPath

The caller (here, a unit test) can simply call the Solve function with a channel and wait for one or more solutions on the channel. Since we're mainly interrested in the (or one of the) optimal solutions with the smallest number of moves, we'll read the first one and be done with it.

solutionChannel := make(chan Path)
go Solve(terrain, solutionChannel)

solution := <-solutionChannel
fmt.Printf("%s first solution in %d moves: %s\n",
    name, len(solution)-1, solution.String())

The call is made in a goroutine, with the invokation go Solve. A goroutine is a function executing concurrently with other goroutines in the same address space. The language authors did not want to call them threads, coroutine or processes because of the inaccurate connotations they convey. They are not threads - several goroutines can be multiplexed on a single thread.

The combination of channels and goroutine is one of the powerful Go constructs.

The actual iterative BFS solving function works with a Terrain, a pointer to a Queue and our solution channel. The queue is initialized with a single path containing the start block.

func solveIter(terrain Terrain, queue *lang.Queue, solution chan Path)

No rocket science for the rest, only an exercise to get acquainted with the language. Note: there are certainly things that leave to be desired, for instance, methods on Path are partly on a *Path and partly on Path. While technically correct, this is not consistent. And I'm sure I should be closing my channels somewhere, but my attempts lead to dreaded deadlock error messages at compile time.

Pros and Cons

I like:

  • The C and Pascal style in a nice and modern design
  • Programming model easily holds in your head
  • Concurrency made easy (or easier)
  • Fast to compile, fast to execute
  • Importance of idioms and unified style

I don't like:

  • Lack of collections
  • Lack of generics (not that bad actually)
  • Lack of exceptions

C, Pascal, and modern design

Chirashi sushi, Wikipedia

Being a C-family language with significant input from Pascal makes Go exquisite. It's like eating chirashi sushi. It might not be to your liking. But don't let the "C" part fool you. There is no pointer arithmetic and the syntax looks more like Pascal than C. The syntax includes changes from C aimed at keeping code concise and readable.

Go is not object-oriented in the usual sense. There is no type hierarchy:

A type automatically satisfies any interface that specifies a subset of its methods, which allows to reduce bookkeeping. Types can satisfy many interfaces at once, without the complexities of traditional multiple inheritance. Interfaces can be added after the fact if a new idea comes along - without annotating the original types. Because there are no explicit relationships between types and interfaces, there is no type hierarchy to manage.

Simple programming model

The limited amount of concepts makes it easy for Go to fit in your head. There is no steep learning curve. It's not like, say, Scala.

Concurrency

Concurrency is at the heart of Go and makes concurrent programming easy (or easier).

Fast

If Ken Block was a developer, Go is what he would probably use for his gymkhana.

Idioms and style

Idioms are important in Go. The documentation often refers to Go idioms and that's a good thing. 16 mentions of "idiom" on the "Effective Go" page. That ought to count for something. Unified style is encouraged by the use of the formatting command go fmt.

Collections

As mentionned before, the limited built-in collections came as a big surprise. One of those "this can't be" moment, followed by "I must have missed something", before you realise that's just the way it is. Sigh.

Arrays, slices and map are all you'll get. You can implement a Set with a map, a few wrapper/helper methods and maybe an empty interface. Fair enough, but why would I want to spend time on that?

There's a doubly linked list that didn't fit the bill for my Path so I ended up rolling my own Tail, Contains and friends myself. Again, not the most productive thing to do even though we're not talking about a great amount of work.

And for the queue, I borrowed from hishboy, but relying on "some lib found on the internet" for such a trivial purpose, no matter how good and carrefully designed it is, seems like a poor man's solution.

EDIT 2014-03-01: In Go, "a channel is just a simple thread-safe FIFO". If you don't need peek/poll operations, like it is the case here, a channel will do. There's more than one way to skin a cat. Thank you Martin for your comment.

Generics

Generics are missing, for better or for worse. All things considered, it's wiser not to have them rather than adding an ill-designed incarnation of them. Actually not a deal breaker. The worst implication is probably the limited support for collections and the possible heavy use of the empty interface interface {} to satisfy your needs.

Exceptions

No support for exceptions neither, but the justification does not hold the water IMO.

We believe that coupling exceptions to a control structure, as in the try-catch-finally idiom, results in convoluted code. It also tends to encourage programmers to label too many ordinary errors, such as failing to open a file, as exceptional.

So try-catch-finally would be more convoluted than, say, checking a possible error return code of each call that would fit in a try block? Nah, I don't buy it.

I would also argue that a failure to open a file, in itself, does not have to be handled on the spot. What would you do instead in Go ? Check an error code, log it and... use panic? Or return? Rather, a throws FileNotFoundException as in Java does not imply you have no clue of what you are doing.

Well, it might be the case with a poor or a beginner programmer, but a poor programmer will also fail to check return codes properly. Again, I'm not convinced.

Throwing an exception may simply indicate that there's nothing you can do about it if it happens, and that it is not your responsibility to act upon it. Probably the caller will be able to display an error message in a Swing component, or send an HTTP error code with some JSON to its client. Often, it is none of your concerns.

On the bright side, Go makes it easy to report an error without overloading an error value and to treat it:

if value, err := MySqrt(i); err != nil {
    fmt.Println("Error!"")
} else {
    fmt.Println("It's ok!")
}

Yet I don't find it more readable nor more zen than exception handling. But that's ok.

The defer construct however is interesting.

func CopyFile(dstName, srcName string) (written int64, err error) {
    src, err := os.Open(srcName)
    if err != nil {
        return
    }
    defer src.Close()

    dst, err := os.Create(dstName)
    if err != nil {
        return
    }
    defer dst.Close()

    return io.Copy(dst, src)
}

Too bad the unpretty if err != nil { return } ruins the days.

Where to start

 Raspberry Pi with Linksys WVC54GC IP camera

Raspberry Pi

This is the toy I wish I had when I was 12. Back then, any computer part used to cost a small fortune.

The current model B offers:

  • 512Mb RAM
  • ARM11 CPU (ARM v6 instruction set)
  • Broadcom VideoCore IV @250MHz GPU
  • 2 USB ports
  • 100Mbps Ethernet
  • HDMI 1.4 output
  • Audio on jack or via HDMI

For 36€ on Amazon, it's a bargain. Do not forget to add to your cart:

  • A fast SD card with enough space, for instance, SanDisk SDSDU-008G-U46 class 10 8Gb. The SD card is a bottleneck so it's no place to save a few euros on a slower model.
  • Micro USB power supply. I bought a 5V 1500mA to be able to plug a USB disk (or more) without the need for an external power supply.

Optional: a box. Buy it or DIY. Professional style, even more sturdy design or hacked from the kitchen. You can even steal some Legos from a kid. It's really up to you.

For the moment, I left it nacked, standing next to a wireless access point.

Raspbian

You have the toy. Minimal assembly required. You need an OS. For general purpose, you can go for Raspbian, a GNU/Debian derivate for the Pi.

Follow the instructions. It boils downs to these steps:

  • Format your SD card using an appropriate tool (regular format commands won't work)
  • Download NOOBS (New Out Of Box Software). Choose "offline and network install" if you plan to fiddle with the material and if you suspect you'll be re-installing from scratch soon
  • Unpack NOOBS to your SD card
  • Plug the SD card into the Pi slot
  • Plug the Pi to an HDMI monitor or TV
  • Plug a USB keyboard (a USB mouse is nice as well, as some options are difficult to access or are even unreachable during the installation procedure without a pointing device)
  • Plug the power cord (no switch)
  • Follow the steps on the screen

Do not forget to enable ssh(d) if you plan to keep your PI away from your screen and to access it from your computer (recommended).

Fixed IP

Do not unplug the monitor just yet. By default, Raspbian will use DHCP to acquire an IP address on your network. Since my Pi won't be connected to a screen nor to a keyboard, I prefer a fixed IP so that I don't have to nmap my network looking for the precious circuitry.

pi@raspberrypi ~ $ ip addr show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether b8:27:eb:10:a2:75 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.64/24 brd 192.168.1.255 scope global eth0
       valid_lft forever preferred_lft forever

pi@raspberrypi ~ $ netstat -nr
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         192.168.1.1     0.0.0.0         UG        0 0          0 eth0
192.168.1.0     0.0.0.0         255.255.255.0   U         0 0          0 eth0

Currently, the Pi dynamicly assigned address is 192.168.1.64 (actually, it's the first available DHCP address in my network, that's how it's configured here).

So I have:

  • broadcast address 192.168.1.255
  • gateway address 192.168.1.1 (my main Scarlet router)
  • netmask set to 255.255.255.0
  • network is 192.168.1.0

I want to assign 192.168.1.6 to my PI. Make sure the address is compatible with your network settings and of course avoid using an address already in use.

Backup your current network interface configuration file:

pi@raspberrypi /etc/network $ sudo cp interfaces interfaces.ori

Edit it (I use vi because I was traumatised during my studies but feel free to alleviate your pain by launching nano instead)

pi@raspberrypi /etc/network $ sudo vi interfaces

auto lo
iface lo inet loopback

# iface eth0 inet dhcp
iface eth0 inet static
address 192.168.1.6
netmask 255.255.255.0
network 192.168.1.0
broadcast 192.168.1.255
gateway 192.168.1.1

allow-hotplug wlan0
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet dhcp

Save and quit (:wq). Inspired from this page. Reboot: sudo reboot.

After a few seconds, you should be able to connect to your Pi at its new address:

youri@gyros ~> ssh pi@192.168.1.6
pi@192.168.1.6's password:
Linux raspberrypi 3.10.25+ #622 PREEMPT Fri Jan 3 18:41:00 GMT 2014 armv6l
Last login: Tue Feb  4 11:24:42 2014 from 192.168.1.65

The camera

To watch what's going on in my backyard, I'll plug an old Linksys Wireless-G Compact Internet Video Camera WVC54GC. It used to be the only cheap IP camera, below 100€ back then. With its limited power, its limited firmware and a staggering 320x200 resolution, don't expect anything fantastic here. But it was a sturdy a slick design for a sweet price. It still runs fine after many years.

It is an IP camera, meaning you don't have to (and you actually can't practically) plug it directly to the Pi. Plug it anywhere in your network next to an ethernet cable, or run it wirelessly (less reliable and less performant).

Again, setting a fixed IP is a nice thing:

Don't bother setting up the clock; it will be lost as soon as you unplug the camera and the poor thing is to dumb to resync on its own. We'll let avconv add the timestamp (more on that later).

The camera ships with an ActiveX to view the stream. If you don't use IE, you're out of luck. If you're not on Windows, you're out of luck (or are you?). You can still access it from any decent player, be it mplayer or VLC:

File -> Open Network

Stream visible at http://192.168.1.xxx/img/video.asf

Make sure you change the default username/password and to only allow access to authentified user. By default, anyone on the network (and so possibly anybody in the neighborhoud if wifi security is disabled) can access the video stream. In User, select "Only users in database" next to "Allow access by" to restrict access. You can access the stream with:

http://username:password@192.168.1.xxx/img/video.asf

AFAIK, there is no way to turn wifi off on that thing, and the best available version of security (if you have one of the latest firmware) is WPA/TKIP. Fortunatelly, it seems that wifi is turned off - or at least not responding - when a network cable is plugged to the camera. Nice side-effect.

This is what you can get from the camera (original resolution):

Told you, it's old and cheap. You can actually see the camera reflection in the window as it is tilted downwards. Not an ideal position. If you record from behind a window, it's better to keep the camera level but then I'd be recording the tree canopy and the sky.

Recording

Use avconv (formerly ffmpeg) to record from the camera. I've decided to capture 10 images per minute rather than the video stream to avoid clogging the network. Remember that our "IP" camera is accessed on the network.

For increased flexibility, I've stored the command in a tiny script.

pi@raspberrypi ~ $ cat capture.sh
#!/bin/bash

TS=`date +"%Y%m%d%H%M"`
FOLDER="/home/pi/ipcam/$TS"

mkdir $FOLDER
avconv -i http://username:password@192.168.1.xxx/img/video.asf -vsync 1 -r .1 -an -vf "drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf: text='%d/%m/%Y %H\:%M': fontcolor=white@0.8: x=7: y=460" $FOLDER/frame%d.jpg

Frames will be stored in a sub-folder in /home/pi/ipcam. Because my avconv version has no -n option to avoid overwrite, I create a new folder based on the current time each time the script is started. That way, images are never overwritten in case the Pi is rebooted.

-r .1 means "0.1 FPS", equivalent to 10 frames per minute. The drawtext will add a timestamp to each frame (remember, you can't rely on the camera to do it for us). Nevermind the y=460 outside the image boundary (320x200). The program is lenient and the timestamp will be visible at the bottom of the frame. You must specify a fontfile path as there is no default value.

chmod u+x capture.sh

Test it: ./capture.sh. You'd want it to run it automatically everytime the Pi is started.

pi@raspberrypi ~ $ sudo ln -s /home/pi/capture.sh /etc/init.d/capture
pi@raspberrypi ~ $ sudo chmod 755 /etc/init.d/capture
pi@raspberrypi ~ $ sudo update-rc.d capture defaults

Reboot: sudo reboot. Your ipcam folder should be filling up. How much? Pretty much. 140MB/day or 984Mb/week or approx 4Gb/month. I don't want to keep more than 1 day worth of image (or garbage), so let's add a cron to clean up on a daily basis:

pi@raspberrypi ~ $ cat cleanup_cam.sh
#!/bin/bash

FOLDER="/home/pi/ipcam"
find $FOLDER -type f -name "*.jpg" -mtime +1 -exec rm {} \;
find $FOLDER -type d -empty -exec rmdir {} \;

pi@raspberrypi ~ $ sudo crontab -l
0 1  *   *   *     /home/pi/cleanup_cam.sh

Deleting files on a SD card is no small task. Deleting 3 days of frames took more than 2 minutes!

pi@raspberrypi ~ $ time ./cleanup_cam.sh
real    2m18.666s

Wow, that's slow. The Pi is doing well considering the constrained CPU. If you do a top:

 PID USER      PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND
3069 pi        20   0 38472  11m 3628 R  22.7  2.6   1285:39 avconv
4386 pi        20   0 10732 7268  768 S  13.6  1.6   0:10.99 find

That's about 23% for recording and 14% for finding and deleting older images... Recording the video stream was about 45% alone (that's still ok).

Random tips

Always shutdown your Pi cleanly, aka do not unplug the power cord but instead, issue the following command:

pi@raspberrypi ~ $ sudo shutdown now

Or, to reboot:

pi@raspberrypi ~ $ sudo reboot

Not sure Raspbian offers the latest software packages from GNU/Debian. Even after apt-get update && apt-get upgrade, I'm still running a slightly older version of avconv:

pi@raspberrypi ~ $ avconv
avconv version 0.8.6-6:0.8.6-1+rpi1, Copyright (c) 2000-2013 the Libav developers
built on Mar 31 2013 13:58:10 with gcc 4.6.3
Hyper fast Audio and Video encoder

Although the Debian wheezy package is libav-tools (6:0.8.9-1) [security].

But that may be considered "acceptable" for a toy.

Next time: Raspberry Pi as a media center with HiFi capabilities.

 I won't Go to FOSDEM next year

I don't think I will be going to FOSDEM next year.

Last year, in 2013, I was lucky enough to get a seat in the Python track by grabbing a chair one talk earlier than planned. 3 talks went on with the room overcrowded in a sickening heat and I congratulated myself for coming extra-early - the previous talk was not that bad anyway.

Following another track, I was lucky to be able to sit or stand against a wall in yet another full room. So the idea was not to move too much around. Cherry picking your sessions can be hazardous as your forfeit your seat (or even your spot in a corner of the room).

Yet I was happy to contribute financially.

This year, I got lazy and I arrived only 15 minutes before a Go talk, in the middle of the morning. What was I thinking ? Sorry sir, no seat left, and this year you can't enter the room. I understand that; it was probably unsafe to let so many people in last year.

By the time you're facing a closed door, it is too late to join the Python track. Same scenario as last year, the room is packed full of people.

At this point, I didn't want to take a chance on my third choice and to queue a half hour only to realise that people are not leaving the room after the current talk is over. And I suspect this is a vicious circle : the more entries are denied, the more people stick to their seat.

FOSDEM is obviously the victim of its own success and has managed to outgrow its venue - no less than a university campus! But I'm getting too old for this.

Slightly disappointed, I went back home. I still have presentations to catch up on Parleys.

 Blogguer sous GitHub avec JBake

À la recherche d'un moteur de blog pour ce site, je m'étais fixé les caractéristiques suivantes :

  • Administration minimale
  • Style modifiable
  • Simple
  • Gratuit
  • Avec mon nom de domaine
  • Pas de publicité
  • Contenu ré-utilisable
  • URL arbitraires
  • Power-user

Rien que ça... Mais j'étais prêt à faire une concession de taille : une solution technique ne me rebute pas, du moment qu'elle reste simple.

Plateformes classiques

Blogger

Premier essai : la vieillissante plateforme Blogger, reprise par Google. Pas convaincu :

  • Les thèmes proposés sont un peu passés de mode
  • La prévisulation n'aboutit pas avec certains thèmes (ceux qui ont justement l'air moins vieux)
  • Système de commentaires G+ peu pratique
  • Contenu exporté souillé par de nombreuses balises HTML

Wordpress.com

C'est la version "cloud" de Wordpress. Une Rolls disponible en ligne, mais...

  • URL partiellement figées (avec la date dedans)
  • Thèmes gratuits limités et peu ou pas configurables
  • Nom de domaine propre en supplément
  • Publicité possible sur la version gratuite.

Les prix ne sont pas excessifs et c'est certainement une excellente solution si vous voulez une solution clé en main. Prenez la version payante, ajoutez votre nom de domaine en supplément et achetez un des nombreux thèmes du catalogue.

Trop facile :-)

Pourquoi ne pas installer WP sur mon serveur ? Parce que c'est une pièce d'infrastructure de plus à administrer. Base de données, mises à jour de sécurité du blog... Idéalement en double : sur ma machine comme environnement de développement et sur mon serveur en production. À terme, migration majeure à prévoir.

Un peu trop pour l'usage basique que j'en fais. Sans doute mon expérience avec DotClear (du temps ou il faisait jeu égal avec Wordpress) m'a refroidi.

JBake + GitHub Pages + Disqus

Mon choix s'est porté sur un combo qui pour l'instant me plaît bien :

JBake

Image JBake

JBake is a Java based open source static site/blog generator for developers.

Le descriptif est un peu trompeur : il n'est pas nécessaire d'être développeur. Il suffit d'avoir Java 6 (ou plus récent) installé et d'être prêt à adapter quelques fichiers de templates avant de générer un site statique. Certainement pas pour le grand public mais si vous avez un quelques connaissances techniques, c'est à mon sens moins compliqué que d'installer un DotClear / Wordpress sur un hébérgement mutualisé.

Le thème de base, plutôt moche, est basé sur la précédente version de Bootstrap. À vous de faire (un peu) mieux, par exemple en vous inspirant de Bootswatch et en adaptant les templates JBake ou en recommençant from scratch.

Incorporer un thème bootswatch n'est pas aussi commode qu'on le voudrait, car il faut alors mixer l'existant de JBake et le thème bootswatch. Il est sans doute plus simple de repartir d'un thème bootswatch et d'en dériver les templates que de tenter de faire correspondre des morceaux bootswatch avec ceux de JBake (surtout quand les versions ne correspondent pas).

Les templates sont en Freemarker. Rien de bien sorcier, par exemple pour lister vos posts sur la page d'accueil :

<#list posts as post>
    <#if (post.status == "published")>
        <div class="post">
            <a href="${post.uri}">
                <h1>${post.title}</h1>
            </a>
            <p class="small">
                ${post.date?string("dd MMMM yyyy")}
            </p>
            <p>${post.body}</p>
        </div>
    </#if>
</#list>

Le contenu peut être formaté en AsciiDoc, Markdown et HTML, ce qui est bien pratique. Vous éditez donc vos billets localement, avec l'éditeur de votre choix. La seule contrainte concerne les headers de chaque billet. JBake en a besoin pour générer l'output statique.

title=Blogguer sous GitHub avec JBake
date=2014-01-29
type=post
tags=blog, blogger, github.io, jbake, wordpress
status=published
~~~~~~

La page que vous être en train de lire est le résultat après génération du contenu statique.

Un billet peut être mode draft. Cela veut dire qu'il n'apparaîtra pas dans la liste des billets, mais il sera malgré tout accessible directement par une URL non publiée :

http://blog.ackx.net/blogguer-sous-github-avec-jbake-draft.html

La structure de vos billets est libre. Autrement dit, vous pouvez les classer par année, par mois, par catégorie, ou... pas du tout! Cette structure se retrouve dans l'URL du billet. Par exemple, la structure suivante :

+ content
    + blog
        + 2013
            + foo.md
            + bar.md

Sera traduite par les URL suivantes :

 http://votre.site/blog/2013/foo.html
 http://votre.site/blog/2013/bar.html

Si par contre vous ne souhaitez pas faire apparaître d'information de date ou de catégorie dans les URI, comme c'est le cas sur ce blog, placez simplement tout le contenu directement dans le répertoire content.

 + content
    + blogguer-sous-github-avec-jbake.md
    + the-matrix-animation-html5.md

Qui donne ici :

http://blog.ackx.net/blogguer-sous-github-avec-jbake.html
http://blog.ackx.net/the-matrix-animation-html5.html

J'aime ! Quand votre contenu est prêt, vous générez le site statique (en supposant que jbake est dans votre PATH) :

youri@gyros blog.ackx.net> jbake
JBake v2.2.0 (2013-10-23 22:24) [http://jbake.org]
Baking has started...
Processing [./content/about.html]... done!
Processing [./content/automatisez-avec-cuisine.md]... done!
...
Rendering [output/about.html]... done!
Rendering [output/blogguer-sous-github-avec-jbake-draft.html]... done!
...
Copying [./assets/css/asciidoctor.css]... done!
Copying [./assets/css/bootstrap.min.css]... done!
...
...finished!
Baked 16 items in 3325ms

De l'ordre de 3-4 secondes pour générer quelques pages : on peut considérer cela comme très lent. Votre contenu est prêt à être servi dans le répertoire output. Localement, n'importe quel serveur fera l'affaire mais vous pouvez utiliser directement JBake et y accéder via http://localhost:8820/ :

youri@gyros blog.ackx.net> jbake-s

Note : si vous préférez les gems aux pom.xml, Jekyll est l'approche proposée par GitHub.

font-awesome

Une petite ligne qui change pas mal de choses...

    <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">

Et vous avez accès à des pictogrammes awesome.

GitHub Pages

Image JBake

Votre site statique en HTML est généré, fort bien; et maintenant, où le déployer ? N'importe quel serveur HTML fera l'affaire. J'aurais aisément pu utiliser mon instance Amazon EC2 micro et profiter d'une de mes recettes Cuisine pour FabricSSH pour déployer tout cela facilement.

Mais un petit git push est une idée sympathique… Enter GitHub Pages ! Suivez les instructions en les adaptant à notre approche JBake qui génère ses artifacts dans output.

C'est facile

  1. Créez un repo publique username.github.io. Pour ce blog, YouriAckx.github.io.
  2. À la racine de votre projet JBake, clonez le repo : git clone https://github.com/username/username.github.io
  3. Renomez username.github.io en output. À présent, le produit de jbake est "lié" à votre blog GitHub.
  4. Lancez la cuisson de votre blog : jbake
  5. Commit des changements
  6. Push vers GitHub : git push
  7. Admirez le résultat en ligne à l'adresse http://username.github.io (il faut qq minutes de patience après le premier push)

Honnêtement, compte tenu du fait que j'ai déjà un serveur Ubuntu en place, j'aurais tout aussi bien pu me contenter d'un tar/gzip/scp et le tour était joué, mais c'était l'occasion d'essayer la version GitHub du blogging. Cela reste bien pratique si vous n'avez aucune infrastructure à votre disposition.

Votre nom de domaine

Vous pouvez associer votre nom de domaine à votre blog GitHub Pages.

  1. Pour faire pointer un sous-domaine vers votre blog, ajoutez un record CNAME vers username.github.io. Cela se passe chez votre fournisseur (GoDaddy, OVH, …)

    youri@gyros blog.ackx.net> dig blog.ackx.net +nostats +nocomments +nocmd
    ;blog.ackx.net.         IN  A
    blog.ackx.net.      21561   IN  CNAME   youriackx.github.io.
    
  2. À la racine de votre repo (dans notre setup, elle coïncide avec le répertoire output de JBake), ajoutez un fichier CNAME qui reprend votre sous-domaine

    youri@gyros blog.ackx.net> cat output/CNAME
    blog.ackx.netyouri
    
  3. Commit + Push

C'est également possible avec un apex; voyez la page d'aide à ce sujet.

Avantages et inconvénients

Petits plus : avec GitHub, vous bénéficiez de leur Content Delivery Network ainsi que de leur protection contre les attaques de déni de service.

Petit moins : tout ce que vous poussez vers GitHub reste gravé dans la pierre des internets. Si vos deviez retirer un contenu litigieux ou gênant, n'importe qui pourrait encore y accéder via l'historique du repo…

Disqus

Image JBake

Ah, les commentaires ! Disqus donne le ton en la matière et pas uniquement pour les sites statiques. Certains sites de taille respectable leur délèguent la gestion des commenentaires pour ne pas avoir à en supporter la charge.

Il est paradoxal pour moi d'utiliser Disqus alors que je le bloque avec Ghostery…. Mais je fais pareil avec Google Analytics, bloqué chez moi mais déployé sur la plupart des sites que je gère. La contradiction n'est qu'apparente : si la plupart des gens ne prennent pas la peine de les bloquer et/ou que cela ne les dérange pas, il n'y a pas de raison de se passer de ces services.

Ouvrez un compte Disqus et suivez les instructions pour l'installation.

Dans JBake, vous devrez modifier post.ftl pour les commentaires sur chaque page et index.ftl ainsi que footer.ftl si vous souhaitez renseigner un compteur de comm' pour chaque post.

Variables JBake

Pour éviter de vous répéter et d'harcoder des valeurs dans vos templates, ajoutez deux variables au fichier jbake.properties (yourshortname est le nom de votre blog sur Disqus) et n'oubliez pas d'adapter le host :

site.host=http://mon.boblog.com
disqus.no.comments=0 Comments
disqus.username=yourshortname

Commentaires sur les pages

Dans post.ftl, ajoutez une ligne à l'endroit où doivent apparaitre les commentaires :

<div id="disqus_thread"></div>

Et un peu de javascript, tel que proposé sur la page d'installation Disqus et remis à la sauce JBake :

<script type="text/javascript">
var disqus_shortname = '${config.disqus_username}'; // Required - Replace example with your forum shortname
var disqus_identifier = '${content.uri}';
var disqus_title = "${content.title}";
var disqus_url = '${config.site_host}${content.uri}';

/* * * DON'T EDIT BELOW THIS LINE * * */
(function() {
    var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
    dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
    (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
</script>

<noscript>
    Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a>
</noscript>

content.uri et content.title sont pré-définis dans JBake. config.site_host est la variable site.host définie plus haut (remarquez que le . est devenu _ et qu'elle est préfixée par config). En pratique, ça donne quelque chose comme ça :

content.uri = /blog/2014/un-bo-post.html
content.title = Un bô post
config.site_host = http://mon.boblog.com
config.disqus_username = yourshortname

Compteur sur la page d'accueil

Même principe. Plaçons le javascript dans footer.ftl :

<script type="text/javascript">
var disqus_shortname = '${config.disqus_username}'; // required: replace example with your forum shortname

/* * * DON'T EDIT BELOW THIS LINE * * */
(function () {
var s = document.createElement('script'); s.async = true;
s.type = 'text/javascript';
s.src = 'http://' + disqus_shortname + '.disqus.com/count.js';
(document.getElementsByTagName('HEAD')[0] || document.getElementsByTagName('BODY')[0]).appendChild(s);
}());
</script>

Et le compteur vient se loger dans index.ftl

<a href="${post.uri}#disqus_thread" data-disqus-identifier="${post.uri}">${config.disqus_no_comments}</a>

Remarquez que j'identifie le post via l'attribut data-disqus-identifier.

Commit+Push et le tour est joué.

Réglages

Sur votre page d'administration Disqus, vous pouvez choisir la modération des commenentaires ou pas, obliger à s'identifier avec de commenter, etc.

Your data are belong to us

Bien entendu, gardez à l'esprit que vous confiez une partie de votre contenu à un tiers, avec toutes les questions que cela entraîne en cas de fermeture ou plus vraissemblement de dégradation ou de modification tarifaire du service à terme.

Bonus

Le template complet de ce blog est disponible sous GitHub.

Source

 hubiC n'est pas à la hauteur

Après une expérience décevante avec Synology CloudStation, je poursuis mes recherches avec une évaluation de hubiC, une "plateforme de stockage en ligne" par OVH.

Le produit est typique de ce qu'on peut attendre de OVH : une infrastructure impressionnante, des prix imbattables et une mise en oeuvre médiocre.

25Gb offerts et 100Gb pour 15,59€/an : on ne peut pas passer à côté.

Et contrairement aux offres US, j'ai plus confiance en OVH pour ce qui est de la confidentialité (mais bon, sans chiffrement, cela reste une profession de foi).

Essai avec près de 25Gb de données. Au final, non merci :

  • Plantage du client lors de la première installation (sous OSX, ça fait désordre). Je passe le fait qu'une deuxième application doit s'installer, wtf.
  • Feedback défaillant lors de la connexion et forte conso de CPU
  • "Indexing in progress". Sauf que quand tout a déjà été synchronisé et que vous changez localement un fichier, on se demande ce qu'il fait pendant... plus d'une heure. Avec un SSD, difficile de juger à l'oreille de ce qui se passe.
  • Discordance du volume utilisé affiché localement et sur le site.
  • Plutôt lent, mais rien d'insurmontable. Vous ne synchronisez un gros volume qu'une seule fois vers hUBIC

Ce sont surtout ces indexations parfois sans fin qui m'inquiètent. S'il est réellement en train de passer en revue tous les fichiers, il faut craindre pour la durée de vie de votre disque dur ou SSD.

 Java8 Lambdas Hacking to Groovy

Last week, I joined a meetup with Hermes in Nivelles for a Java 8 Lambda Hacking live stream event with Brian Goetz.

It was about time Java introduced lambda expressions. I've been developing in Groovy for a while and the switch to Java is always (extremely) painful. But it's much better now.

I took the opportunity to redo the Java8 lab exercises in Groovy and I was surprised to see the Java syntax can be expressive. In some more involved cases, I would argue Java is even more expressive than Groovy. Yes, really.

So, is Java grooving now? Check out the code and see for yourself.

lambdas

 Off-topic on Stackoverflow: that's enough

Dear StackOverflow,

I stumble on questions marked as "off-topic" weekly, every time with valuable, non biased answers. Most of the time these answers are better than any other found on the internet.

Arguably, you wanted to deter trolls and to prevent sterile "I prefer" comments. But that's not what's happening. People are behaving. Valuable answers are up-voted and emerge on top. Should any troll spawn, he would be quickly down-voted to see his comment fade into oblivion. You already have a secret weapon against trolls : your community. And it works.

So we have topics of interest with quality answers, judging by the number of votes on the question and replies. Then moderators come in, mark the question as "off-topic", triggering numerous comments from frowning users, and as they're right do to so, other people actually up-vote these comments.

The overall topic quality and readability is actually degraded by the "off-topic" banner and the ensuing comments.

What should you do when enforcing a rule causes inconvenience instead of solving a problem ? Amend the rule, of course.

Otherwise, there might be an open gap for a "SO off-topic x vs y" quality site.

 The Matrix - Animation HTML5

Image The Matrix

Petite animation utilisant Javascript et l'élément canvas en HTML5.

En action ici, avec les sources sur github. Le reste du lab est par là.

 Le Livre Dont Vous Êtes Le Héros

À quel livre dont vous êtes le héros aimiez-vous jouer dans votre jeunesse ?

J’aimais bien la série «Sorcellerie», et j’avais eu la mauvaise idée de commencer par le dernier tome, «La Couronne des Rois». Autant dire mission impossible.

Image - Les Collines Maléfiques

Les années 80 étant loin derrière nous, je m’étais mis en tête d’y jouer avec une version plus moderne, en ligne ou sur tablette. C’était au début de cette année 2013. Il y avait bien quelques versions artisanales jouables par exemple dans la série Loup Solitaire, mais je n’ai rien trouvé qui me convenait pour sorcellerie.

Voilà une chouette idée de projet à réaliser durant mon temps libre, me suis-je dit.

Entre-temps, une réalisation professionnelle a été rendue disponible sur iPad. Mais je n’allais pas pour autant laisser tomber. C’est en tout cas bon signe : cela veut dire que des nostalgiques s’intéressent encore à cette série. Voici, pour votre plus grand plaisir, le premier livre de la collection entièrement jouable en ligne :

http://ldvelh.ackx.net/

Ce premier tome est certainement le moins palpitant de la série. Il a pour but de permettre au héros d’accumuler des indices et des objets qui lui seront fortement utiles dans la suite de sa quête. N’oubliez pas de mémoriser toutes les formules avant de commencer votre aventure. C’est la règle!

Développement

Il s’est avéré que la quantité de travail nécessaire était bien plus importante que ce que j’avais pensé. L’auteur avait une imagination débordante. Si les règles de base sont relativement simples, le nombre d’exceptions et de cas particuliers est énorme. Chacune de ces exceptions demande un traitement ad hoc, ce qui m’a pris un temps exorbitant.

Quelques exemples :

  • Un marchand vous propose une arme mais vous pouvez en marchander le prix en lançant un dé.
  • Si vous portez le Brassard d'Escrime de Ragnar, vous aurez le droit d'ajouter 2 points à votre Force d'Attaque, lors des combats, si l'arme dont vous vous servez est une épée.
  • La malédiction de Malanka vous fait perdre un point d’endurance supplémentaire à chaque fois que vous perdez des points d’endurance, sauf lorsque vous utilisez la magie.
  • Vous tentez de briser une serrure à l’aide de votre épée. Pour cela vous lancez à chaque fois des dés. À chaque essai, la lame s’émousse un peu et vous perdez un point d’habileté si vous utilisez cette arme lors d’un combat.

Ou encore celle-ci : “Chaque fois que la Manticore vous infligera une blessure, lancez un dé. Si vous obtenez un 5 ou un 6, elle vous aura piqué avec sa queue de scorpion et vous perdrez alors 6 points d’endurance à moins que vous ne Tentiez votre Chance avec succès. Si vous êtes Chanceux, la blessure sera normale et vous n'aurez perdu que 2 points d’endurance ; si le chiffre obtenu au dé est de 1 à 4, le coup porté par votre adversaire vous fera simplement perdre les 2 points habituels d’endurance”.

Jamais rien de bien compliqué pour un développeur mais l’accumulation de ce genre de traitement sur plus de 400 chapitres m’a fortement ralenti dans ma progression !

Technos

Je n’allais pas laisser les geeks sur leur faim :-)

  • AngularJS
  • (twitter) bootstrap
  • LESS CSS
  • HTML5 local storage
  • bower
  • Gradle
  • Pas de backend
  • Serveur “HTML statique” (nginx)

AngularJS est un framework JavaScript open-source offrant une architecture MVC aux applications web. Les manipulations du DOM sont découplées de la logique métier. Des directives interprètent des tags HTML pour obtenir les comportements voulus. Une emphase particulière est mise sur les tests unitaires et e2e, facilités par la dependency injection.

Dans LDVELH, il n’y a que très peu de two-way data-binding, mais il reste néanmoins de nombreux avantages à utiliser AngularJS. Sa mise en oeuvre est tellement simple que cela en vaut la peine, même pour une application triviale.

Le design n’étant pas ma tasse de thé, je me suis reposé sur LESS, que j’ai customisé. Pour ce faire, j’évite de modifier directement les fichiers bootstrap, ou même de les customiser sur leur site avant téléchargement. C’est chercher les ennuis lors des mises à jour. Je préfère inclure les fichiers LESS de bootstrap et faire un override dans ma propre feuille de style, en LESS aussi bien entendu.

@import "lib/bootstrap/less/variables.less";
@import "lib/bootstrap/less/mixins.less";

@highlight: #B7521E;
@linkColor: @highlight;
@linkColorHover: darken(@linkColor, 15%);

Il faut juste penser à inclure `bootstrap.less avant votre propre feuille de style.

Le tout est compilé par le navigateur à l’aide de Gradle pour le déploiement.

Sur ce point, cela veut dire que mon environnement de développement diverge de la production, mais Gradle n’est pas un foudre de guerre et attendre quelques secondes pour recompiler  après chaque modification n’est jamais agréable. Un middleware LESS sur node.js aurait l’avantage d’unifier les environnements en offrant une compilation quasi-instantanée.

Gradle compile donc les feuilles de style LESS mais nettoie aussi les fichiers (p.e. less.js ne doit plus être inclus) et il inclut/exclut les fichiers sources qui vont bien. Une tâche `scp me permet de pousser un .zip vers mon serveur AmazonEC2. Là-bas, un petit script en python déploie ce zip en test et se charge de cloner test vers production.

Pas de backend autre que le serveur statique, en l’occurence nginx. Bien plus léger que httpd, cela compte sur une instance EC2 micro. Un backend (middleware, db, identification du joueur...), c’est de la maintenance et je voulais éviter. Local storage pour se souvenir de la progression du joueur.

Bower n’est là que pour éviter de télécharger des libraires à la main mais il est clair que le workflow n’est pas le même que quand bower est utilisé avec grunt et node.js.

 KDE 4.8.4

Ça doit faire quatre ans que je n'ai plus touché à un bureau sous GNU/Linux. L'ennui et la monotonie de OSX; sont très largement compensés par une utilisation sans soucis et pratiquement exempte d'interventions pour des réglages. Tout cela profitant à la productivité.

Mais la bienveillance de GNU/Linux me manque. Comme tout geek, j'aspire à une liberté de choix et d'utilisation en restant relativement proche de la machine. Ce que j'ai complètement perdu avec OSX.

Plutôt que de passer le week-end dans mon transat, à tailler les haies, à tondre la pelouse, pourquoi ne pas se virtualiser une distribution GNU/Linux et tester différents desktops?

Avec KDE, une de vos premières tâches consistera à donner aux applications GTK un aspect présentable. Firefox (ici renommé en Iceweasel) ou Synaptic ont un aspect hideux.

Firefox sous KDE

Vous voici parti à la recherche de recettes de grand-mères, le problème étant que personne ne sait vraiment comment faire et que les réponses varient au gré des distributions et des versions de KDE, sans que celles-ci soient explicitées.

Voici donc ma recette, qui vaut pour KDE 4.8.4 sous Debian testing/jessie, sans certitudes que certaines étapes ne soient pas superflues et sans avoir cherché à comprendre tous les mécanismes à l’œuvre.

Installez les paquets suivant :

gtk2-engines gtk2-engines-oxigen kde-config-gtk-style kde-config-gtk-style-preview qtcurve

Contrairement à ce qui ce dit parfois, il n'est pas nécessaire d'installer lxappareance. Rien qu'à la lecture de la description du paquet, on voit bien que cela n'a pas vraiment de sens :

LXAppearance is a GUI application for the Lightweight X11 Desktop Environment(LXDE).

Sans doute suggéré à tort car il contient une dépendance vers gtk2-engines.

Dans System Settings (l'ex KDE Control Panel aka KControl), dans l'onglet GTK, assurez-vous que Qt Curve est sélectionné pour GTK2 et Default pour GTK3.

Voilà, ça va déjà mieux pour la présentation, mais l'expérience utilisateur en prend déjà un coup.

Si vous comptez utiliser Konqueror pour naviguer, encore que vous avez à présent un Firefox Iceweaselé fardé comme une voiture volée, vous souhaiterez certainement passer du moteur KHTML à Webkit, ne serait-ce que pour profiter d'un affichage décent des interwebs.

L'aspect général de KDE est délicieusement ringard mais surtout gentiment lourdingue.

Tout est conçu pour être ajustable dans les moindres détails. Une fenêtre a typiquement, en plus des 3 boutons minimiser/maximiser/fermer, deux autres boutons "menu" et "visible on all desktops". Parfois un bouton d'aide s'ajoute au premier groupe de trois.

Et une foultitude de réglages est généralement disponible dans le menu "réglage" (Konqueror) ou directement dans la barre d'outils (Dolphin). Une fois que vous aurez appuyé sur la clé à molette de ce dernier, vous trouverez, outre "Tools" ou "Go", un "Configure Dolphin", un "Configure Shortcuts" et un "Configure Toolbars".

Le "Kickoff Application Laucher" est bien fichu. Sa bonne lisibilité contraste avec le reste.

Où est le package manager, le truc qui permet d'ajouter des applis et des paquets? Hmmm... Installons Synaptic et Apper.

Les applications que j'installe via Synaptic n'apparaîssent qu'après un reboot, gni?

Alt-F2 fait apparaître une boîte de recherche bien pratique. Celle-ci a parfois tendance à disparaître juste après son invocation. Peut-être dû à la virtualisation?

On peut ajouter des widgets sur le desktop dont la plupart m'ont l'air peu utile. Quand vous passez la souris au-dessus d'un widget, une petite barre apparaît à son côté, vous permettant de le configurer, de le maximiser (?) ou... de le faire pivoter. Cette dernière possibilité m'a toujours laissé perplexe et est la parfaite illustration de l'esprit de configuration à outrance.

Mention spéciale au widget "show desktop" qui, en toute logique, disparaît derrière les fenêtres applicatives ouvertes. Donc pour l'atteindre, s'il est caché derrière vos fenêtres, vous devez d'abord minimiser celles-ci. Wait, what?

Après quelques heures, un message "No network connection available" apparaît dans le coin des notifications et Inceweasel et Konqueror se figent. Il est temps de redémarrer, sans que je sache si ce problème trouve sa cause dans la virtualisation ou dans une instabilité de KDE.

Impression : un desktop attachant qui me rend nostalgique des Sun SPARC utilisées durant mes études. Une pléthore d'options de configuration directement visibles nuisent à la lisibilité.

 Synology CloudStation : pas des plus stables

Stocker vos documents, photos et film sur un NAS à la maison est pratique. Rapidement apparaît le besoin de synchroniser tout ou partie du NAS avec votre laptop et d'autres appareils.

Synlogy propose sa Cloud Station pour y répondre.

Petit test avec la configuration suivante :

  • Synology DS210J
  • DSM 4.3
  • Client OSX 10.8.5
  • 10Gb de documents

Sur papier, c'est juste ce qu'il me faut. Les tutoriels et les articles sur internet vous présente généralement un produit lissé mais je suspecte souvent leurs auteurs de ne pas avoir sérieusement testé ou d'opter pour un présentation flatteuse.

Car dans la pratique, c'est loin d'être satisfaisant pour un utilisateur exigeant.

  • L'installation sur le NAS n'est pas conviviale. Il faut d'abord activer le "Home folder". Je n'ai aucune idée de quoi il s'agit. Il faut ensuite comprendre que les permissions sur un folder partagé (par exemple "Pictures") doivent être activées distinctement que le partage dans Cloud Station. Rien d'insurmontable pour un public geek (sans doute ceux qui utilisent un tel produit) mais on peut faire mieux.
  • Pour obtenir une première synchro, mieux vaut d'abord copier manuellement tous les fichiers du NAS vers votre laptop avant de lancer la syncro. À défaut, le client Cloud Station synchronise quelques fichiers puis affiche"All sync"avant de reprendre peu après, puis s'arrête à nouveau. L'opération risque d'être plus longue que prévu.
  • Finder devient lent sur les répertoires en cours de synchro. 2 secondes à chaque click, parfois 4 ou 5 sur des répertoires plus remplis voire des beachballs.
  • Les freezes s'étendent jusque sur le bureau, alors qu'il ne fait pas partie de la synchro. Peut-être parce que le client se loge dans la barre supérieure et qu'une instabilité se répercute sur le bureau avec OSX ? Je n'en sais rien, je fuis d'habitude les softs instables...
  • Instabilité du NAS : ralentissements et, après 2 jours, blocage complet, CPU au taquet et reboot laborieux. Le modeste DS210J a montré ses limites.
  • Un plantage client

Une fois le système mis en place et le gros du travail de synchronisation effectué, ça roule. Mais un rsync est tellement plus stable...

EDIT : l'appli refuse de répondre, même après redémarrage -> Move to trash

 Journée Agile 2013

Pour ceux qui me l'ont demandé et pour ceux que cela intéresse, voici les slides de ma présentation "Scrum depuis les tranchées - Petit guide des bonnes (et des moins bonnes) pratiques" donnée à la Journée Agile 2013 à Louvain-la-Neuve.

Une journée d'un grand cru, avec une organisation sans faille et des orateurs de kalitäy.

 Automatisez avec Cuisine

Image Cusine pour FabricSSH

On est tous convaincus qu'il faut automatiser l'installation de nos serveurs. Mais l'investissement dans un tel outil n'est pas forcément rentable pour une petite équipe de développeurs.

Et si on vous proposait un outil archi-simple, avec une courbe d'apprentissage assez douce, et qu'en plus, on vous filait une première recette ?

Cuisine est une alternative alléchante à Chef ou à Puppet. En guise d'introduction, un article sur stackful-dev.com et une superbe présentation de l'auteur.

C'est open source, pas trop bare-bone sans être trop abstrait et c'est en Python. Adapté à un projet plutôt qu'à l'administration d'un parc de machines.

Que demander de plus? Une petite recette pour déployer un Tomcat + MySql + nginx sur Ubuntu server, par exemple !

 Source on GitHub


Older posts are available in the archive.