J'anticipais découvrir de vraies petites perles dans ce mince volume qui traite des bonnes parties du langage de programmation PHP. Chez O'Reilly, c'est à croire que le département marketing s'est caché derrière le succès de son équivalent JavaScript : The Good Parts (par l'excellent auteur Douglas Crockford) pour lancer une série et nommer cet ouvrage qui ne mérite pas son titre : PHP: The Good Parts. Sérieusement, ce résumé des bonnes parties semble être le minimum pour faire quelque chose d'à peine fonctionnel et d'inutile! Au moins s'il avait été nommé Apprendre PHP en 7 jours, j'aurais abaissé mes attentes pour être moins déçu. Tout ça pour dire que j'ai fini par survoler le reste du bouquin sans grand intérêt.
C'est un peu ma faute aussi : la mention au dos du livre indiquant "No previous experience with PHP is necessary" aurait dû me mettre la puce à l'oreille mais je l'ai remarquée seulement au moment d'écrire ces lignes. Ça m'apprendra de me procurer un livre sans même l'avoir feuilleté!
Bien sûr, j'ai surligné quelques rares passages, surtout par souci de révision ou pour expérimenter une approche différente dans le vaste éventail des fonctions offertes.
Comme tous les livres de références PHP sortis depuis les 3 dernières années, vous y trouverez là-aussi le classique survol de certains nouveaux concepts propres à la version 5.3 (fonctions anonymes - closures, goto * beurk *, NOWDOC, namespacing, classes DateTime et DateTimeZone).
Même s'il se détaille à moins de 20$, de grâce, gardez votre argent. La presque totalité du contenu se retrouve dans la documentation officielle de PHP (en plus d'y avoir noté quelques mauvaises pratiques agaçantes). Si le développeur novice ou amateur souhaite faire le saut à PHP et veut avoir des repères rapides, il y trouvera peut-être son compte mais j'ai vite considéré que ça représentait une perte de temps pour le développeur intermédiaire ou expérimenté. À mon avis, l'auteur est passé à côté de l'objectif car il y présente qu'une simple introduction et non les meilleures parties que le titre nous promettait.
Si l'auteur a réussi à compresser les "bonnes parties" dans 176 pages, il aura aussi su résumer les mauvaises parties dans une annexe de 4 pages. Selon l'auteur, il n'y en a pas vraiment (LOL), seulement des zones plus particulières (tricky areas).
Un incontournable de la littérature PHP ? Loin de là.
Dans la catégorie Arithmétique appliquée et impertinente, calculez en kilogrammes, le poids du cerveau d'un imbécile
Nous savons qu'il est composé de :
- 520 grammes de certitude
- 200 grammes de vulgarité
- 430 grammes d'autosatisfaction
- et 250 grammes de substances organiques diverses (excipient)
Réponse : le cerveau d'un imbécile pèse 1,4 kilogramme (soit environ 3 lbs).
Sachant que le poids moyen d'un cerveau normal est de 1,4 kilogramme et que l'intelligence ne se mesure pas au poids de l'encéphale, la majorité des hommes en tireront la même conclusion que notre ami Woody Allen :
Mon cerveau ? C’est mon second organe préféré.
Les vrais programmeurs ninjas codent avec un verre dans le nez
En lisant l'article Pourquoi les développeurs travaillent-ils la nuit (une traduction du billet original de Swizec Teller intitulé Why programmers work at night), j'ai bien rigolé quand j'ai vu l'image humoristique du livre Coding Drunk, Make Programming Fun Again, inspiré des couvertures de la série O'Reilly.
Pourquoi cette approche serait-elle farfelue ? C'est pourtant tout ce dont j'ai retenu la première fois que j'ai regardé le film Drunken Master de Jackie Chan (celui de 1978) alors qu'il excelle dans ses combats à l'aide des techniques du "karaté soûl" (vous pouvez visionner le film en entier sur YouTube : Drunken Master (1978) - Full Movie). Le savoir-faire, c'est d'abord et avant tout de savoir créer les conditions optimales pour performer. Au final, c'est le résultat qui compte.
Coding Drunk est un livre fictif dont la couverture a été générée à l'aide d'un outil comme O'Reilly Maker. À mon tour, je me suis amusé à configurer ce que serait la couverture de mon livre si je me décidais à faire imprimer mon blogue (aviez-vous remarqué que si on retire le L de livre, ça fait ivre ?).
Toutes les raisons sont bonnes pour procrastiner ce matin... Vraiment.
* Pour éviter de m'attirer les foudres des critiques, je me dois m'inclure une note moralisatrice : consommez de façon responsable et conduisez prudemment. À moins que ce soit buvez de façon responsable et codez prudemment...
Ça fait plusieurs jours que je n'écris plus. C'est que je profite des vacances de Noël pour reprendre là où j'avais laissé mes signets dans quelques livres entamés et laissés-pour-compte. C'est ça le problème, trop de livres et d'intérêts, je passe d'un à l'autre pour finalement les achever quelques mois plus tard. Présentement, c'est la brique In the Plex sur l'histoire de Google qui occupe mon temps.
Dans un autre billet, j'avais mentionné que mon plus grand regret était qu'une vie est beaucoup trop courte pour lire tout ce qui m'intéresse. Malgré tout, je viens de recevoir aujourd'hui même un autre livre commandé sur Amazon (heureusement il fait à peine 125 pages) et je comptais bientôt aller regarnir ma bibliothèque pour raccourcir ma wishlist de lecture.
À quel point peut-il y avoir trop de livres ? Quand Larry Page de Google a eu l'idée qu'il serait utile de pouvoir chercher dans la totalité des livres publiés, son entourage déclara que ce serait impossible. Page considérait que ça pouvait être faisable et dispendieux, mais pas impossible. Il essaya de figurer ce que nécessiterait ce type d'opération et calcula que les coûts étaient raisonnables. Si Google achetait une copie de chaque livre publié à 10$ et qu'il existait 30 millions de bouquins, les coûts n'étaient que de 300 millions de dollars. Pour lui, ça représentait peu d'argent pour être en possession de la base de connaissance la plus précieuse au monde (en 2010, Google se ravisa et estima plutôt à 130 millions le nombre total de livres sur le globe).
Rendons nous à l'évidence :
- contrairement à Page, mon portefeuille représente une fraction de sa petite monnaie
- je suis un humain normalement constitué et je ne lis pas à la même vitesse que Johnny 5 dans Coeur Circuit
C'est pour ces raisons que je dois être très sélectif dans ce que je veux donner comme nourriture à mes yeux et mon cerveau. Et avec les Interwebs, c'est impossible de lire tout ce qui est publié (à l'avenir, je devrai songer de me contenter à regarder que les images, comme un vrai homme!).
Les dernières pages que j'ai lues aujourd'hui racontaient la naissance de Google Books (nom de code Ocean pour réfléter la vaste mer d'information à explorer). Saviez-vous que le premier livre qu'ils ont numérisé était The Google Book, un livre illustré pour enfant par Vincent Cartwright Vickers (1879-1939) ? Dans le titre, le terme Google fait référence à une créature étrange qui avait des aspects empruntés à un mammifère, un reptile et un poisson.
Ensuite, ils ont fait des tests avec un livre de photos, Ancient Forests par David Middleton, Algorithms in C par Robert Sedgewick et le livre Startup par Jerry Kaplan. Lors de leurs tests, un livre de 300 pages comme Startup prenait 42 minutes à numériser, soit plus rapide que ce qu'ils s'attendaient (ils ont accéléré le processus par la suite).
Ce qu'ils ignoraient et que Steven Levy fait remarquer, c'est l'ironie à la fin du premier livre numérisé qu'ils ont choisi, The Google Book :
The sun is setting
Can't you hear
A something in the distance
Howl!!?
I wonder if it's
Yes!! it is
That horrid Google
On the prowl!!!
Traduction :
Le soleil se couche
N'entends-tu pas
Quelque chose au loin
Hurlement!?
Je me demande si ce n'est
Oui!
Cet horrible Google
À l'affût!
Au moins s'ils avaient choisi de numériser l'annuaire téléphonique, ça se serait terminé sur une note plus positive avec Monsieur Zzopardi.
Quand j'ai acheté cette jolie petite clé USB de 32 Go sur eBay, ça semblait une véritable aubaine (un prix ridicule, à peine 15$, livraison incluse). Dans la même page, le marchand chinois offrait 3 modèles, soit une canette de Coca-Cola, de Pepsi ou de Heineken, chacun décliné en version 4, 8, 16 ou 32 Go avec un prix proportionnel.
Une fois reçue, j'ai glissé la clé dans l'ordinateur. Elle indiquait bien une capacité de stockage de 32 Go. Superbe! Pourtant, quelque chose semblait anormal. J'ai alors utilisé le petit outil H2testw pour m'assurer qu'elle était conforme et fiable à l'utilisation. Le test écrit et vérifie les données sur la totalité de la mémoire flash et présente un rapport indiquant les erreurs rencontrées. Ainsi, une série de 32 fichiers de 1 Go (.h2w) est généré à même le lecteur et est ensuite vérifié, d'où l'importance de le faire lorsqu'elle est vierge ou nouvellement formatée.
Attendez-vous aussi à ce que ça soit très, très long comme en témoigne les captures d'écrans ci-dessous.
Après plus de 1h30 d'attente, ça s'annonçait mal... Les premiers 3,6 Go sont testés fonctionnels et les suivants sont déjà corrompus.
Au final, 27,4 Go sont inutilisables sur une possibilité de 32 Go. Le verdict tombe : "The media is likely to be defective". Évitons donc d'y stocker des documents importants...
Heureusement que j'ai testé le média avant de laisser le feedback au vendeur (qui n'a jamais retourné mes emails pour obtenir réparation). Est-ce qu'il le savait au moment de la vente ? Je l'ignore. Mais c'est dommage pour lui car à voir dégringoler son pourcentage de feedback positif (de 99% au moment de l'achat à 93%), je ne suis pas le seul insatisfait.
Si vous allez faire un tour du côté du marché Jean-Talon ces temps-ci (maintenant que l'hiver est commencé), vous y trouverez une abondance de fruits et légumes sur les étalages. Sans surprise, ils n'ont pas poussé chez nous et la courte saison d'agriculture au Québec nous oblige à nous approvisionner dans de multiples pays qui ont la chance d'avoir un peu plus de chaleur. Qui dit importation rime aussi avec transport, pollution, manque de fraicheur et prix à la hausse.
J'avais vu un reportage à la télé sur les fermes Lufa, une entreprise québécoise d'agriculture urbaine qui a eu l'ingéniosité d'installer des serres sur le toit d'un entrepôt du Marché Central de Montréal, à quelques minutes de chez moi. Si vous circulez sur le boulevard de l'Acadie, c'est du côté du Canadian Tire que vous pourrez les apercevoir. Croyez-le ou non, c'est 6000 lbs de légumes qui sont récoltés chaque semaine.
Frais, local, responsable. Trois mots qui définissent bien ce que je recherchais. Un ami déjà inscrit m'a assuré que le petit panier serait suffisant pour ma copine et moi. Du moins, pour commencer. La semaine dernière, j'ai finalement décidé d'en faire l'essai durant les mois d'hiver. L'inscription est sur une base de 12 semaines, ce qui me garantit des légumes frais, cultivés à Montréal durant la grosse période de froid. Et je l'avoue, ça sera bon de manger santé après s'être empiffré durant le temps des fêtes.
Quelques jours plus tard, voilà arrivé le moment de la cueillette. Je viens à l'instant d'aller récupérer mon panier au point de chute le plus près de chez moi (situé à moins de 2 km de ma maison).
Voici ce que j'ai reçu dans mon 1er panier :
- Laitue Boston et le trio de laitues
- 4 sortes de tomates
- 2 concombres libanais
- 3 piments forts
- 2 gousses d'ail
- 4 pommes
- 1 courge butternut
- 1 pot de confiture biologiques aux bleuets
- Échalottes
- Fines herbes mini-fenouil
Et comme il y aura des légumes surprises à chaque semaine, c'est parfait pour la diversité dans l'assiette et pour être créatif en cuisine.
Entre des légumes qui ont poussé à plusieurs milliers de kilomètres, qui ont passé plusieurs jours en transport et sans doute un certain temps en entreposage versus des légumes locaux frais cueillis le matin même (rien de moins!), le choix est évident. Chapeau pour l'initiative.
Un chat noir qui traverse votre chemin signifie que l'animal va quelque part.
Bon matin chers lecteurs. J'écris ces lignes en prenant un petit déjeuner à peine nocif pour ma santé, à savoir une tranche de pain grillé tartiné avec du beurre d'arachides accompagné d'un grand verre de lait au chocolat. C'est quand même mieux que d'avaler un Reese's d'une livre et ça goûte à peu près la même chose (la portion complète est de 2280 calories et 132 grammes de gras).
Il faut l'avouer, parfois nous nous alimentons si mal que c'en est presque honteux. Non ça l'est. Quand j'ai écrit le billet sur Le plaisir insoupçonné de manger du Velveeta, c'est dire à quel point l'alimentation américaine a pu déteindre sur la culture culinaire canadienne. Heureusement, ça ne représente pas notre quotidien, on s'alimente généralement mieux mais on se laisse parfois tenter par le comfort et le junk food.
Attendez-moi un instant, je vais me faire une autre toast.
Oui, en étendant la pâte brune et crémeuse sur le pain, je comprends le dédain que pouvait ressentir le petit Grégory (le petit Basque que nous avions hébergé pendant son séjour au Québec) lorsque nous lui avions présenté ce condiment pour son premier petit déjeuner en Amérique. Intrigué, il avait ouvert le pot, regardé dedans, essaya de se familiariser avec l'odeur et le referma aussitôt, jugeant que ça ne répondait pas à ses attentes. C'est comprenable, ce produit brillait par son absence sur les tablettes des supermarchés français et donc, pratiquement méconnu.
Comment peut-on ressentir la même sensation face à un produit alimentaire ? Quel produit équivalent pourrait susciter le dégoût de ce côté de l'océan ? Contre toute attente, c'est ma copine qui m'a apporté la réponse lorsqu'elle a entendu la pièce Vegemite (The Black Death) de l'artiste américaine Amanda Palmer (album Goes Down Under).
Qu'est-ce que le Vegemite ? Selon What's Cooking America, c'est un produit australien typique et apprécié des enfants du pays de Crocodile Dundee au même titre qu'un sandwich au beurre de peanuts l'est pour un jeune américain. Fabriqué à partir des restes d'extraits de levure de bière, de différents légumes et d'épices, la pâte résultante possède une couleur rouge-brune, presque noire, et elle est reconnue pour être riche en vitamine B.
Mis à part un goût très salé, laissons Mme Palmer résumer la saveur :
Vegemite? It tastes like sadness.
It tastes like batteries. It tastes like acid.
I cannot hold a man so close who spreads this cancer on his toast.
It is the Vegemite, my darling, or it's me.
Élogieux.
Et à voir la réaction des étudiants canadiens confrontés à un test de goût par leur enseignant, c'est loin de faire l'unanimité...
Je n'ai pas encore eu la chance d'en trouver au supermarché. Mais si vous connaissez un commerçant montréalais qui en vend, j'oserai relever le défi d'y goûter et mettre ainsi ma vie en péril.
Pour les nostalgiques de l'époque où Musique Plus était déjanté et se permettait d'excellentes parodies avec Cinéma-Twit et Parodies sur Terre (vers le milieu des années 90), en voici une de Star Wars mettant en vedette Hand Solo et Chabada.
Avec La fin du monde est à 7 heures, c'est le genre de truc que j'aimerais bien retrouver sur DVD. En attendant, quelqu'un a eu l'excellente idée de le rendre disponible sur Google Videos, pour le bon plaisir de tous.
Quelques extraits mémorables :
- Michael Douglas qui saute les plombs sur le creton versus le Paris Pâté ou encore pour le poulet : viande blanche que je voulais, viande blanche! Pas d'la putain de viande brune avec de la tiraille dedans.
- je vais te dire quelque chose qui va te refroidir pour de bon : je suis un mec!
- tous les extraits avec Business (un personnage assez rural) dont le fameux "on a un spécial de 50% si vous prenez une escalope avec une salade. Non merci mais une escapade avec une salope, j'hairais pas ça".
- les extraits de l'émission d'Ed Sullivan (vers 1h18) avec les chansons Dans l'garage et Fait le fucké, avec une chorégraphie dont même Rihanna ne peut égaler.
Voici la preuve qu'il est possible de construire et de jouer sur une guitare à 8 manches. Bien sûr, il faudra 16 mains et un peu de pratique mais ça donne un résultat vraiment bien.
Liste des manches :
- mandoline
- ukulele
- guitare 6 cordes
- basse fretless
- basse
- guitare 12 cordes
- guitare bariton
- guitare 7 cordes
Comme quoi ce n'est pas la longueur du manche qui compte, mais bien le nombre que vous avez entre les mains!
Si vous voulez passer une commande, DNG Custom Guitars se fera un plaisir de répondre à vos besoins.
En reconfigurant mon nouveau PC Windows 7, j'ai installé la plus récente version de NotePad++ (5.9.6.2) et juste avant de terminer le processus, j'ai remarqué cette option d'installation :
Use the old, obsolete and monstrous icon.
I won't blame you if you want to get the old icon back :)
Haha!
Quand la merde vaudra de l'or, le cul des pauvres ne leur appartiendra plus.
Retour vers le passé et voyage dans le temps avec Zend_Date
Un client se plaignait d'avoir entré une date et que malgré tout, ça affichait la mauvaise année à l'écran. On croyait avoir affaire à un code 18 de sa part mais comme c'était reproductible, nous avons dû nous creuser les méninges pour trouver la source du problème.
En examinant le code, tout semblait conforme : la valeur de la date, la valeur stockée, la localisation (qui aurait pu jouer des tours) et le format d'affichage spécifié. Pour trouver d'où provenait l'erreur, j'ai utilisé la même méthode décrite à mon dernier billet en faisant des appels en boucle. Avec un peu de chance, peut-être que quelque chose en resortirait.
$locale = new Zend_Locale('fr_CA');Remarquez ce qui se passe dans le calcul lorsqu'on change d'année :
$date = new Zend_Date('2011-12-04', false, $locale);
$i = 0;
do{
echo $date->get('dd MMMM YYYY');
$date->add(1, Zend_Date::DAY);
echo BR; // constante
$i++;
} while($i < 60);
Nom de Zeus! Où est passé le 1er janvier 2012 ? On croirait à une déchirure du continuum espace-temps puisqu'on se retrouve soudainement au 1er jour de 2011 pour ensuite revenir en 2012 à l'itération suivante.
Pourquoi ? Ça m'enrageait un peu car ce n'était pas la première fois que j'avais des mauvaises surprises avec les dates de PHP (@pparadis avait raison). Pour les besoins du projet, le composant Zend_Date avait été retenu pour manipuler et calculer des dates et du temps, configuré avec un type de format autre que celui natif de PHP (plus intuitif que "j F Y"). Et nous ne nous attendions pas à ce type de comportement. À vrai dire, le programmeur aurait eu intérêt à mieux lire la documentation car de ce que j'ai trouvé, il existe une différence minime mais fondamentale entre les formats yyyy écrits en minuscules et majuscules :
- YYYY pour l'année ISO
- yyyy pour l'année réelle
Sinon, voici un autre exemple qui illustre mieux la représentation calendrier. Utilisez le même snippet de code ci-haut et modifiez la date initiale pour "2010-01-01". On s'attendrait que le 1er affichage indique 1er janvier 2010. Pourtant, la même logique s'applique.
Encore une fois, si on se réfère au calendrier, les trois premiers jours de 2010 sont dans la dernière semaine de 2009. Pour faire simple, YYYY retourne l'année du 1er jour de la semaine où se trouve la date demandée. Le format yyyy retourne l'année réelle.
En conclusion, trois choses :
- Lisez toujours la documentation au lieu de prendre pour acquis certaines notions. Les différences entre yyyy et YYYY sont subtiles mais importantes en même temps.
- Évitez-le format ISO pour l'affichage, à moins que vous sachiez exactement ce que vous êtes en train de faire.
- Cette démonstration utilise Zend Framework pour PHP mais comme ISO 8601 est un standard, vous risquez de rencontrer le même problème dans d'autres frameworks et langages de programmation.
Ce matin, je vais vous entretenir à propos d'un bogue que j'ai trouvé cette semaine dans un système qui calcule du temps. Pour faire court, le temps saisi au formulaire était correct, il était ensuite stocké dans une base de données sous forme de nombre à virgule flotante et lorsqu'il était récupéré puis affiché à l'écran, une minute était parfois perdue par rapport à l'heure initiale. Concrètement, 8h25 devenait soudain 8h24! Chaque enregistrement modifiant l'heure décrémentait les minutes. Multiplié par des centaines de manipulations, ça cumulait du temps perdu.
Je soupçonnais la fonction de formatage de l'heure à l'écran.
// simplifiée pour la démonstrationJe l'ai donc isolée et j'ai lancé un jeu de tests couvrant toutes les minutes d'une heure donnée (BR est une constante définie pour imprimer une balise de saut de ligne) :
function format($decimalTime){
$hour = (int)$decimalTime;
$minute = (int)(($decimalTime - $hour) * 60);
return $hour . 'h' . str_pad($minute, 2, '0', STR_PAD_LEFT);
}
echo "Heure\tMinutes\tFormaté\tReprésentation interne" . BR;Selon les résultats retournés, pratiquement 1 affichage sur 2 étaient erronés!
$hour = 8;
foreach( range(0,59) as $minute ){
$time = $hour + ($minute/60);
echo $hour . "\t" . $minute . "\t" . format($time) . "\t" . $time . BR;
}
Comme la partie des minutes est stockée en décimales, l'hypothèse d'une mauvaise conversion se confirmait. Dans certains cas, ça fonctionnait bien pour les fractions simples (8h15 = 8.25, 8h30 = 8.50, etc), alors que pour d'autres valeurs comme 8h12 (8.2 en décimal, 12 min = 1/5 d'une heure, donc 0.2), la fonction retourne la valeur formatée de 8h11 avec une minute en moins. Ce n'est pas le genre d'erreur qu'on peut tolérer (surtout quand le temps, c'est de l'argent).
J'ai ensuite fait quelques tests supplémentaires :
//Pour la portion minutes, si :À cause de la conversion (cast) float à int, la représentation interne de 4.9999999999999 ne conserve que le 4 plutôt que de l'arrondir à 5. Ce qu'il aurait fallu faire :
var_dump(5/1); // int(5)
var_dump(5/60); // float(0.083333333333333)
// remettre les minutes décimales sur une base 60
var_dump((5/60)*60); // devient un float(5)
// exemple
$time = 8.083333333333333; // représentation interne de 8h05
$hour = (int)$time;
$minute = ($time - $hour) * 60;
var_dump( $minute ); // float(4.9999999999999)
var_dump( (int)$minute ); // int(4) et non 5 !
var_dump( (int)round($minute, 0) ); // 5Pour corriger le bogue, je n'ai eu qu'à modifier la fonction en remplaçant une ligne comme ceci :
function format($decimalTime){Ce fût ni long, ni difficile à régler. Mais la cause était incompréhensible pour le client et les conséquences étaient fâcheuses puisqu'il fallait ensuite faire rebalancer les données.
$hour = (int)$decimalTime;
//$minute = (int)(($decimalTime - $hour) * 60);
$minute = (int)round(($decimalTime - $hour) * 60, 0);
return $hour . 'h' . str_pad($minute, 2, '0', STR_PAD_LEFT);
}
Après réflexion, je me demande ce que ça aurait donné si, au lieu d'avoir choisit initialement de stocker les heures en float, on avait plutôt opté pour les conserver en un seul nombre entier représentant le total des minutes plutôt que des fractions d'heures (8h05 = 8h*60 minutes + 5 minutes = 485 minutes) ? Nous n'aurions probablement pas eu de problème de conversion, mais ça aurait certainement occasionné d'autres genres de problèmes.