Kévin Subileau

Espace personnel

clock

Debounce et throttle : limiter les appels successifs à une fonction Javascript

Lorsque l'on développe une application Web réagissant à certains évènements en Javascript, comme le redimensionnement de la fenêtre, le mouvement de la souris ou la frappe au clavier, les fonctions rattachées à ces événements risquent d'être appelées très fréquemment. Si le code contenu dans ces fonctions est coûteux en ressources, cela peut ralentir considérablement l'application Web.

Pour améliorer les performances, ou plutôt ne pas les plomber, il existe deux techniques simples, appelées debounce et throttle. Toutes deux permettent de réduire le nombre d'appels à une fonction dans un intervalle de temps donné. En effet, il est souvent inutile d'exécuter ces fonctions à chaque fois que l’événement est déclenché.

Imaginons par exemple que l'on souhaite synchroniser sur le serveur, via des appels AJAX, le contenu d'un champ de saisie au fur et à mesure que l'utilisateur tape le texte (comme le fait Google Docs par exemple). Dans ce cas, plutôt que de solliciter le serveur à chaque caractère saisi ou inutilement lorsque le texte reste inchangé, il peut être plus judicieux de sauvegarder le texte toutes les 5 secondes tant que l'utilisateur le modifie, et de ne plus faire de requêtes lorsque que le texte reste inchangé. Et c'est exactement ce que la fonction throttle permet de faire.

Cependant, bien que ces deux techniques soit assez similaires, il existe une différence fondamentale dans leurs fonctionnements qu'il est important de bien comprendre pour les utiliser correctement.

Je vais donc vous présenter ces deux méthodes l'une après l'autre, en vous expliquant leurs fonctionnements et en vous donnant le code Javascript nécessaire pour les mettre en place.
Lire la suite →

festival-of-colors

Color Thief PHP : extraire les couleurs dominantes d'une image

Color Thief PHP est une classe PHP qui vous permet d'extraire la couleur dominante ou une palette de couleurs à partir d'une image JPEG, GIF, ou PNG. Le projet est disponible sur GitHub, et sur Packagist. Vous pouvez également voir le code en fonctionnement sur cette page de démonstration.

La particularité de cette classe est qu'elle n'utilise pas une simple moyenne arithmétique pour déterminer la couleur dominante, contrairement à de nombreux scripts disponibles sur le web. En effet, cette méthode donne souvent des résultats plutôt aberrants, avec une couleur moche qui ne ressemble à rien de ce que l'on perçoit dans l'image. Ici, un algorithme avancé de quantification de couleurs est utilisé. Cet algorithme, nommé "Modified Mean Cut Quantizer", est comparable à celui utilisé par la compression JPEG. L'avantage est que les couleurs calculées sont le plus souvent visuellement très proches de celles présentes dans l'image d'origine, comme vous pouvez le voir sur l'exemple ci-dessous :

color-thief-example

Un exemple de palette de couleurs obtenue grâce à Color Thief PHP

L'utilisation de la classe est très simple, surtout si vous utilisez Composer, mais peut être assez gourmande en ressources en fonction de la taille de l'image et de la qualité demandée. Je vous conseille donc de conserver le résultat en base de données plutôt que d’exécuter le script à chaque chargement de page. Pour plus d'informations, je vous invite à vous reporter à la documentation sur GitHub.

Les applications de cette classe ne sont limitées que par votre imagination : moteur de recherche par couleur, adaptation des couleurs de l'interface graphique en fonction de l'image affichée... Alex P. Gates a même développé un script PHP capable de modifier la couleur d'une lampe en fonction des couleurs d'une image, en utilisant Color Thief PHP et une lampe Philips Hue.

Enfin, si vous avez besoin de cet outil coté client en Javascript, sachez qu'il s'agit en fait d'un portage d'un script javascript. Vous pouvez donc utiliser le script Color Thief original réalisé par Lokesh Dhakar.

C++

C++ : Déclarer une variable dans un switch

En C++, il est possible de déclarer une nouvelle variable à tout moment dans le code... ou presque !

Ainsi, l'extrait de code ci-dessous est évidemment parfaitement valide et compile sans erreur :

for (int i = 0; i < 10; ++i) {
    std::cout << "Itération n°" << i << std::endl;
    int dummy;
    dummy = i * i;
    std::cout << "Le carré de " << i << " est " << dummy  << std::endl;
}

On note que la variable dummy est définie au milieu du code, sans que cela ne pose problème. Partant de ce constat, on pourrait croire que le code suivant compile également sans problème (en supposant que la variable choix est définie) :

switch (choix) {
    case 1:
        std::cout << "Choix 1." << std::endl;
        int dummy = time(NULL); // Erreur !!
        std::cout << "Il est " << dummy << std::endl;
        break;
    default:
        std::cout << "Choix inconnu." << std::endl;
        // std::cout << "Il est " << dummy << std::endl;
        break;
}

Et bien non ! Si vous compiler un code de ce genre, le compilateur le refusera en indiquant une erreur du type :

error: jump to case label
   crosses initialization of 'int dummy'

ou encore, selon les cas :

error: initialization of 'dummy' is skipped by 'case' label

La raison de cette erreur est que la portée de la variable définie à l'intérieur d'un case s'étend à l'ensemble du switch, et pas seulement à ce case. Le case n'est qu'un label, et ne limite pas la portée de la variable, qui n'est limitée que par les accolades englobantes du switch. Que se passerait il alors si le compilateur ne disait rien et que je décommentais la ligne 9 du code précédent ? Et bien, dans le cas où choix serait différent de 1, l'initialisation de la variable faite à la ligne 4 serait sautée puisque seul le bloc default serait exécuté. La variable dummy serait donc définie (puisque sa portée est globale à tout le switch) mais non initialisée (puisque l'initialisation n'a pas été exécutée). Dans cet exemple, dummy est un entier, il contiendrait simplement une valeur indéterminée. Mais ce pourrait tout aussi bien être un objet, et dans ce cas, le constructeur ne serait pas appelé si choix est différent de 1 ! Ce comportement risqué est donc interdit par le compilateur.

Pour résoudre ce problème, il faut explicitement limiter la portée de la variable en entourant le code du case par une paire d'accolades, comme ci-dessous :

switch (choix) {
    case 1:
    {
        std::cout << "Choix 1." << std::endl;
        int dummy = time(NULL); // Ok !!
        std::cout << "Il est " << dummy << std::endl;
        break;
    }
    default:
        std::cout << "Choix inconnu." << std::endl;
        // Désormais interdit car la variable est hors de portée !
        // std::cout << "Il est " << dummy << std::endl;
        break;
}

La portée de la variable dummy est ainsi limitée au case, et il devient impossible de l'utiliser dans un autre case.

Voilà pour cette petite astuce de programmation en C++ assez simple, il suffit juste d'y penser ! A noter que ce problème et sa solution s'applique aussi lorsque l'on déclare une variable entre un goto et le label ciblé par ce goto. Mais bon, c'est bien connu, plus personne n'utilise le goto de nos jours...

Source

lorem-ipsum

Générer un faux texte en une ligne de PHP

Lorsque l'on développe un site ou une application Web, il est souvent très utile de pouvoir remplir la base de données ou la page Web de faux texte, de type Lorem ipsum. En effet, cela permet de se concentrer sur le design et la mise en page sans pour autant avoir le contenu final de la page et sans que ce contenu ne détourne notre attention.

Mais plutôt que de copier/coller ces faux paragraphes sans cesse, saviez-vous qu'il est possible de le "générer" facilement avec une ligne de code PHP ? C'est plus classe, ça prend moins de place dans le code côté serveur, et surtout vous pouvez l'utiliser pour remplir la base de données et pas seulement pour l'afficher directement !

Le suspens a assez duré, voici le code en question :

$lipsum = simplexml_load_file('http://www.lipsum.com/feed/xml?amount=1&what=paras&start=0')->lipsum;

Bon, ok, j'ai un peu triché. En réalité, on ne génère pas réellement le lipsum en PHP, mais on utilise plutôt l'API du site lipsum.com. Mais peu importe, le but principal est atteint, on a un faux texte en une ligne de PHP !

Pour allez plus loin, vous pouvez transformer cette simple ligne en une fonction un peu plus évoluée qui vous permettra de contrôler un peu plus de paramètres sur le texte généré :

function generer_lipsum($quantite = 1, $type = 'paras', $lorem = false) {
    $url = "http://www.lipsum.com/feed/xml?amount=$quantite&what=$type&start=".($lorem?'yes':'no');
    return simplexml_load_file($url)->lipsum;
}

Où les paramètres sont :

  • $quantite : la quantité de texte à générer.
  • $type : l'unité de comptage de la quantité de texte : paras pour paragraphes, words pour mots, bytes pour octets ou lists pour des listes HTML. Ainsi, si vous définissez $quantite à 5 et $type à words, vous allez générer une phrase aléatoire de 5 mots.
  • $lorem : Si vrai, force le texte généré à débuter par "Lorem ipsum dolor sit amet...".

Voilà pour cette petite astuce qui me plait beaucoup et qui, je l'espère, vous plaira tout autant ! Et si vous en connaissez d'autres de ce style, n’hésitez pas à les partager en commentaire de cet article :D .

Rediriger vers un fichier en conservant l'affichage

Dans un script Bash, il peut arriver que l'on souhaite rediriger la sortie d'une commande vers un fichier tout en conservant l'affichage sur l'écran. L'astuce consiste simplement à utiliser la commande tee. Par exemple, le code :

echo "toto" | tee monfichier

Permet donc d'afficher toto sur l'écran tout en l'écrivant dans le fichier monfichier. Si le fichier n'existe pas il sera créé, sinon son contenu sera écrasé.

Il est également possible de spécifier plusieurs fichiers :

echo "toto" | tee monfichier autrefichier encoreun

Enfin, si l'on souhaite ajouter la sortie aux fichiers indiqués plutôt que de les écraser, il faut spécifier l'option -a ou --append :

echo "toto" | tee -a monfichier autrefichier encoreun

Quelques options supplémentaires sont disponibles, voir le man de tee ! Pour se souvenir du nom de cette commande, on peut faire l'analogie avec un T de plomberie, en sachant que la lettre T se prononce tee en anglais ;) tee