Je suis développeur web freelance et propose des formations à Symfony2 ! Contactez-moi pour en discuter.

Une fonctionnalité très sympa de Sublime Text est pouvoir partager son écran en 2 (View -> Layout -> Columns: 2 par exemple).

Quand on a un écran un peu grand, cela permet par exemple de comparer des bouts de code quand on débuggue, ou pour adapter un exemple trouvé sur le net. Si l’écran est petit, ctrl+k, ctrl+b permet de masquer ou afficher la barre latérale le temps de faire ce que l’on souhaite.

Sur un clavier Azerty, le raccourci pour partager l’écran ne fonctionne pas (avec les produits Apple, il semble que ce soit OK). Le coupable ? Le raccourci. Il faut appuyer sur alt + maj + 2. Hors pour faire 2… il faut appuyer sur Maj. Sur nos claviers, l’éditeur de texte le plus sympa que je connaisse est donc perdu. La solution ? Redéfinir les touches nécessaires pour le binding en question. Allez dans Preferences -> Key bindings – User, et configurez les touches de la manière suivante :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[
    { "keys": ["alt+2"],
        "command": "set_layout",
        "args":
        {
            "cols": [0.0, 0.5, 1.0],
            "rows": [0.0, 1.0],
            "cells": [[0, 0, 1, 1], [1, 0, 2, 1]]
        }
    },
    {
        "keys": ["alt+1"],
        "command": "set_layout",
        "args":
        {
            "cols": [0.0, 1.0],
            "rows": [0.0, 1.0],
            "cells": [[0, 0, 1, 1]]
        }
    }
]

Ici j’ai seulement redéfini les associations de touches pour découper l’écran en 2 verticalement avec alt + 1 et alt + 2. C’est le seul que j’utilise, mais si vous voulez la liste complète (pour découper en 3, 4 parties, horizontalement comme verticalement), vous pouvez chercher la commande set_layout dans Preferences -> Key bindings – Default.

One more thing…

Un autre raccourci que je vous recommande d’ajouter au même endroit que le précédent. Si comme moi vous travaillez sur des gros projets, et naviguez dans l’arborescence à grand coup de cltr+p, vous avez du vous rendre compte qu’on a vite fait de ne plus savoir dans quel répertoire se trouve le fichier avec lequel on travaille.

1
    { "keys": ["ctrl+alt+r"], "command": "reveal_in_side_bar" }

A tout moment, appuyez sur ctrl+alt+r pour sélectionner le fichier courant dans la barre latérale et le mettre en surbrillance, et ainsi le retrouver dans l’arborescence. Des packages (notamment SyncedSideBar) permettent de faire cela, mais leur comportement ne me plait pas.

Ha, et tant que vous y êtes, jetez un oeil dans Preferences -> Settings – Default, et prenez 10mn pour adapter les paramètres de configuration à vos besoins dans Preferences -> Settings – User. Ces quelques détails peuvent vous changer la vie !

Lorsque l’on souhaite écrire du code concis, l’héritage permet de gagner du temps en factorisant le code dans une classe dont plusieurs vont hériter, et se partager les fonctionnalités.

Dans une application AngularJS, il est donc régulièrement nécessaire de faire hériter dans un contrôleur les fonctionnalités d’un contrôleur de base. Je ne parle pas ici d’imbrication, c’est-à-dire d’un « gros » contrôleurs dont une sous partie du DOM est gérée par un ou plusieurs autres contrôleurs, en charge de fonctionnalités restreintes localement. Je vais parler d’héritage au sens objet du terme, bien que cette notion soit un peu floue en JavaScript (j’entends déjà les puristes du fond qui hurlent, mais ça n’est pas l’objet de cet article).

L’héritage de contrôleurs est par exemple utile pour une application de type CRUD, où les divers contrôleurs vont vouloir réaliser des opérations similaires sur différents modèles, avec des particularités pour chacun d’entre elles. On va donc vouloir mettre l’essentiel des fonctionnalités partagées dans un contrôleur de base, et fournir le comportement spécifique dans les fils.

Voici comment je fais pour faire hériter des propriétés, des méthodes, le scope et ce qu’il surveille d’un contrôleur de base vers des contrôleurs fils. Tout part d’un contrôleur de base.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var BaseController = function($scope, DataStorage) {
    this.scope = $scope;
    this.DataStorage = DataStorage;
    this.scope.pageNb = 1;

    var me = this;
    this.scope.$watch ('pageNb', function() {
        me.getList();
        me.scope.isAllselected = false;
    });

    this.scope.displayCreationPopup = _.bind (this.displayCreationPopup, this);
    this.scope.hideCreationPopup    = _.bind (this.hideCreationPopup, this);

    this.scope.showCreationPopup    = false;
}

BaseController.prototype.displayCreationPopup = function (){
    this.scope.showCreationPopup = true;
}

BaseController.prototype.hideCreationPopup = function (){
    this.scope.showCreationPopup = false;
}

Plusieurs choses sont à noter :
– Je définis les propriété (objets et fonctions) à faire hériter dans le prototype. Le prototype définit toutes les propriété communes à toutes les instances de BaseController. C’est donc très bien pour nous dans le cas présent, mais il faut faire attention à ce que l’on met dedans, ce n’est pas toujours ce que l’on va vouloir.
– Bien qu’il s’agisse d’un contrôlleur, on ne l’enregistre pas via angular.module(…).controller. En effet, c’est notre classe abstraite, elle ne contient pas le code métier que l’on souhaite exécuter tel quel, et ne contient pas à proprement parler de code complet.
– D’ailleurs, dans $scope.$watch, on fait appel à la méthode getList() qui n’est pas définie ! Je la définis plus tard, dans les contrôlleurs fils. Mais afin d’éviter de la duplication de code, comme tous les controlleurs font appel à getList lors d’un changement de numéro de page, le code métier correspondant est écrit ici.
– Je fournis le $scope en paramètres du contrôlleur de base, et un service de stockage. Comme le code n’est pas exécuté tel quel, DataStorage n’a pas besoin d’être un vrai service (en fait, il n’a même pas besoin d’être défini). Tous ce dont on a besoin, c’est d’avoir une variable dans laquelle appeler des méthodes. En java ou autre, on aura un type plus précis sur cette variablee, afin d’éviter de pouvoir y mettre n’importe quoi. Dans les divers classes filles, nous injecterons un vrai service, dépendant du contrôlleur dont nous avons besoin afin d’exécuter la logique métier.

Et maintenant, le code métier d’un exemple de classe fille.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// On hérite le contrôleur de celui de base.
var NewsController = function($scope, NewsStorage, $injector) {
    $injector.invoke(BaseController, this, {$scope: $scope, DataStorage:NewsStorage});
   
    this.scope.getList    = _.bind (this.getList, this);
    this.getList();
}
NewsController.prototype = Object.create (BaseController.prototype);

// Une fonction quelconque de récupération de liste de news
// Exemple de ce qu'on pourrait avoir avec de l'asynchrone type requête Ajax :
NewsController.prototype.getList = function (){
    var me = this;
    this.scope.displayLoader = true;
    this.NewsStorage.getList (this.scope.pageNb, function(result){
            me.scope.news = result.data.news;
            me.scope.nbPages = result.data.nbPages;
            me.scope.displayLoader = false;
        }
    );
}

// On injecte le contrôleur dans l'application
var module = angular.module ('myApp.controllers', ['common.controllers', 'common.stores', 'myApp.stores']);
module.controller('NewsController', [
    '$scope',
    'NewsStorage',
    '$injector',
    NewsController
]);

Les 2 lignes importantes d’un point de vue de l’héritage sont
$injector.invoke(BaseController, this, {$scope: $scope, DataStorage:NewsStorage});
et
NewsController.prototype = Object.create (BaseController.prototype);

La première injecte les données présentes dans le $scope du père (en lui fournissant au passage les bons services). Elle fournit aussi tout ce qui s’y rattache : on conserve le $scope.$watch par l’héritage.
La seconde ligne étend le prototype, c’est à dire qu’elle duplique les méthodes dans le contrôlleur fils. Oui, c’est du javascript, pas du C++ ou du Java hein, l’héritage reste ici une notion un peu abstraite (haha).

Cette fois ci, le contrôleur News est bien injecté dans l’application. On le configure, et on lui donne les bons services, c’est eux qui sont fournis au père.
On implémente la méthode getList(), que l’on peut imaginer faire un appel ajax ou dans un cache quelconque (applicatif ou localstorage, soyons fous) pour récupérer les données nécessaires.

Vu que les méthodes sont héritées, depuis la vue, on peut donc appeler showCreationPopup() et hideCreationPopup(). On peut également utiliser les propriété du scope, et rajouter les nôtres.

Vous pouvez au passage remarquer que je bind régulièrement mes fonctions via la librairie underscore sur l’objet this. Cela permet de ne pas perdre l’objet contrôlleur lorsque les appels se font depuis angular, qui utilise comme objet d’appel le $scope local et non le contrôlleur. Dans cet exemple, tous les bindings ne sont pas nécessaires, mais quand je fais un hideCreationPopup() depuis une vue, c’est le binding dont je viens de parler qui fait qu’on peut changer la valeur de showCreationPopup, et que ce changement se répercute sur la vue.

Cela permet d’isoler le code récurrent dans une classe de base afin d’en faciliter sa réutilisation, ce qui permet, pour les contrôleurs fils, de n’implémenter que la logique spécifique.

Apache bench est un outil qui sert à faire des tests de performances sur une URL donnée.
On l’installe via apt-get install apache2-utils, puis on s’en sert (par exemple) de la manière suivante :

1
ab -n x -c y url

Avec :

  • x le nombre de requêtes à lancer
  • y le nombre de requêtes concurrentes
  • url l’url à tester, qui doit finir par un /

Exemple :

1
ab -n 1000 -c 100 www.google.com/

On obtient ensuite un rapport avec notamment, le temps moyen de réponse, la bande passante consommée, le nombre de requêtes traitées par secondes… D’autres options sont possibles, et vous les trouverez dans les pages man.

Il est important de savoir que cet outil effectue uniquement une requête HTTP GET sur l’url concernée : dans l’exemple donné il va donc uniquement télécharger le HTML, mais pas les fichiers images, js et css externes, et ne les utilisera pas. Cela ne représente donc pas le ressenti réel de l’utilisateur, mais sert pour du dimensionnement.

On peut s’en servir de plusieurs manières. Sur une machine locale (ou la notion de bande passante n’a aucun sens), cela peut servir à tester l’effet de la mise en place d’un système de cache type Memcached ou Redis, ou bien pour voir si la configuration du reverse proxy tient la route. En production ou préproduction, cela permet de voir si la stack fait bien son travail. Mais surtout, Après avec effectué ce genre de requêtes, on regarde les outils de monitoring, et peut surveiller l’état de nombreux éléments : load, accès disques, etat de la base de données…

Attention, comme cet outil fonctionne url par url, il est important d’effectuer des tests sur plusieurs pages différentes, surtout les plus critiques (en terme de temps d’exécution et de fréquentation). Bien que votre home soit probablement la plus visitée, c’est aussi surement une des pages les mieux optimisées. D’autres pages un peu moins visitées peuvent être dangereuses pour les performances (lorsqu’elles ont de lourds calculs par exemples), et la santé de votre serveur.

L’idée de ce genre de d’outil, c’est surtout de regarder à quel moment le serveur va tomber en terme de charge. On effectue plusieurs tests avec des valeurs de plus en plus élevées, et on regarde à partir de quel moment le serveur ne tient plus. On fait ce genre de tests bien avant que le serveur n’atteigne de tels chiffres de fréquentation, ce qui permet d’anticiper les évolutions d’architecture à prévoir.

Je travaille en permanence avec plusieurs machines différentes pour me connecter à des serveurs de développement, de préproduction, à ma machine virtuelle ou à des machines de productions. Après avoir oublié plusieurs fois certains mots de passe, puis m’être planté une fois ou deux de terminal et avoir lanché des scripts sur la mauvaise machine, j’ai commencé à utiliser des codes couleurs pour les différentes machines que j’utilise. Et comme il est pénible de changer les codes couleurs à chaque connection, je me suis finalement mis à utiliser Revelation pour résoudre les deux problèmes en une fois.

L'astuce : une couleur pour chaque machine

L’astuce : une couleur pour chaque machine

Révélation est en effet un gestionnaire de mots de passe, qui sert à les centraliser, et à lancer diverses applications qui les utilisent. Un mot de passe maitre sert à protéger l’accès à des personnes non désirées (dans une certaine mesure). Je m’en sers donc pour me stocker les mots de pass de connection SSH, et pour me connecter directement aux machines distantes en SSH.

L’astuce pour ne pas me tromper de machine, c’est que chacune d’entre elle a une couleur différente. Rouge (comme danger) pour la machine de production, vert pour une VM, et ainsi de suite.

Pour faire pareil, il suffit d’installer Revelation (apt-get install revelation), puis de faire 3 choses :

Créer un profil pour les couleurs des différentes machines :

N'ayez pas peur d'avoir autant de profils que de machine

N’ayez pas peur d’avoir autant de profils que de machine

Faire la manipulation suivante (sur Ubuntu) pour vos différentes machines :
Ouvrir une console
Edition -> profils -> nouveau
On lui donne un nom (notez le, il va servir plus tard), et le fait se baser sur un profil déjà plaisant
Dans l’onglet couleur, il suffit de décocher « utiliser les couleurs du thème système », et de choisir des couleurs (de texte et d’arrière plan) qui conviennent.

Quand vous avez terminé, vous devriez avoir autant de profils que vous utilisez de machine différente, et chacune d’entre elle aura une couleur différente. Vous pouvez remarquer que je nomme mes profils sous la forme profilXXX, histoire de m’y retrouver.

Configurer les raccourcis dans Revelation :

N'oubliez pas de mettre le nom du profil dans "Domaine"

N’oubliez pas de mettre le nom du profil dans « Domaine »

Une fois qu’on a les différents profils, il faut ensuite configurer les différentes connection SSH, comme dans l’image de droite.
On crée un nouveau raccourci de type shell, avec le nom de son choix, puis on remplit le nom d’hôte, le nom d’utilisateur et le mot de passe nécessaire à la connection à son shell.

L’astuce pour lancer la connection avec le profil désiré, c’est de mettre le nom du profil dans le champ « domaine ». On va ensuite configurer Revelation pour utiliser cette information comme nous le souhaitons.

N’oubliez pas de sauvegarder votre configuration Revelation (ctrl+S, ou le gros bouton enregistrer)

Configurer l’utilisation des profils au lancement des connections SSH :

Dernière étape, il faut préciser à Revelation d’utiliser nos profils lorsque l’on lance un terminal. Pour celà, il suffit d’aller dans Editer -> Préférences -> Commandes de lancement, et dans la ligne SSH, de mettre ce qui suit :

1
gnome-terminal %(--profile=%d%) -x ssh %(-l %u%) %h

Cette ligne parle d’elle même, on lance un terminal avec une connection ssh dont les options sont les paramètres de configuration de la machine donnée, et on choisit le profil correspondant pour le terminal.

Terminé !

L’utilisation est simple : on ouvre sa configuration dans revelation, choisit une machine, et le mot de passe est copié dans le presse papier. Sous Ubuntu, on peut le coller avec clic-molette, on appuie sur entrée, et c’est bon, on est connecté à sa machine. Et voila, fini les pertes de mot de passe, et fini les commandes lancées sur la mauvaise machine. Merci à Antho pour l’astuce !

Des alias git utiles

18 juin, 2013

Depuis quelques temps, j’utilise les alias git pour un certain nombre de taches récurrentes, pour lesquelles je trouve les commandes de bases peu performantes, trop longues à taper, ou parce que je préfère ne pas retenir les nombreuses options qu’elles proposent. Autre avantage : les alias décrits dans le fichier .gitconfig apparaissent dans l’autocompletion de git, ce qui n’est pas les cas si l’on fait un alias bash.

Voici quelques éléments contenus dans la section [alias] de mon fichier ~/.gitconfig:

1
2
[alias]
lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit

Personnellement, je n’ai jamais réussi à me servir de git log. Trop de place occupée pour trop peu d’informations… avec cet alias, chaque commit est sur 1 ligne, les branches sont affichées et colorées, on peut voir de manière pratique qui a réalisé le commit et quand… très pratique donc, comme vous pouvez le voir sur l’image ci-dessous :

screen_better_log

Avant un stand-up meeting, pensez à git lg –since=yesterday, qui vous permet de voir ce que vous avez commité depuis la veille.

1
s = status -sb

L’alias que j’utilise le plus, car il évite de taper git status en entier, ou d’avoir à appuyer sur tab pour compléter. Ca a l’air idiot mais je tape cette commande probablement plusieurs dizaines de fois par jours, donc je revendique ma fainéantise sur la question.
L’option s signifie short (la sortie est épurée), et b permet d’afficher la branche en cours, ce qui permet d’éviter d’avoir un commit sur la mauvaise branche…

1
tryagain = reset –hard HEAD

Parce que des fois, tout ce qui a été fait ne sert à rien et qu’il vaut mieux recommencer à zéro.

1
bv = branch -v

pareil que git branch, mais affiche également le hash court du dernier commit effectué, ainsi que le titre de celui ci.
Dans la même logique, si vous passez votre temps à jongler entre différents remote, vous pouvez penser à ajouter cet alias :

1
rv = remote -v

Si vous aussi vous avez des alias pour des taches récurrentes ou pour des commandes pratiques, n’hésitez pas à le dire dans les commentaires !

Did you know that Github features a file finder, similar to the one there is in SublimeText ?
It allow to quickly navigate to a file if you know what its filename looks like.

Activate it by typing ‘t’ on a project page, type some of the letters of the filename, then navigate between the results to reach the one you want.

If you know other useful tips for using github, don’t hesitate to share it !


t

 

git_logoQuand on travaille sur un gros projet, on doit parfois identifier l’origine d’une régression. C’est ce qui arrive par exemple lorsque l’on modifie une fonctionnalité pour l’enrichir : quelque chose a été cassé à un autre endroit qui utilisait la même fonctionnalité, en général sans que l’on s’en rende compte lors de la modification.

Une des difficultés, c’est d’identifier l’origine de l’erreur. Car lorsque l’on est plusieurs à travailler sur le projet et qu’il s’est passé plusieurs dizaines (voire centaines, ou plus) de commit entre le moment où la fonctionnalité marchait et celle où elle a été identifié, retrouver le commit à l’origine de l’erreur peut s’avérer être une tâche titanesque.

Sauf que !

Parmi ses nombreuses fonctionnalités sympa, git propose une solution pour ce genre de situations : la recherche dichotomique. Pour ceux qui n’écoutaient pas pendant les cours d’algo, on va partir de l’ensemble des commit, et regarder celui qui se trouve au milieu. On teste le programme, et si la régression est présente, on sait qu’il faut chercher dans les commit qui se trouve avant, sinon dans ceux qui se trouvent après. Et on recommence, jusqu’à ce qu’on ait trouvé l’origine de l’erreur. Bien sûr, git propose un moyen pratique de faire ça, il s’agit de git bisect.

L’avantage ?

La vitesse, et la rigueur ! Quand comme moi on a 85 commits à revoir, au lieu de tester un peu au hasard et n’être pas sûr de trouver après de nombreux essais, avec cette méthode on est certain de trouver l’origine de l’erreur en environ 6 étapes. Et avec cette méthode, le nombre d’étapes augmente lentement : pour 1000 commits, il y aurait seulement une dizaine de commits à revoir !

On fait comment ? Il faut tout d’abord identifier un commit où la fonctionnalité marchait. Ça peut être une ancienne version taggée, un commit… bref, il faut avoir un point de départ. Dans cet exemple, on va dire qu’il n’y avait pas régression lors du commit bacd25e, et qu’on s’en est rendu compte dans la dernière version (sur le HEAD courant).

On démarre le mode de recherche :

1
git bisect start

On indique que le HEAD est une version où la fonctionnalité considérée ne fonctionne pas :

1
git bisect bad

On indique ensuite un commit où ça marche avec git bisect bad [hash du commit]

1
 git bisect good bacd25e

Et c’est parti !

Git nous positionne sur un commit intermédiaire, il faut maintenant tester l’application dans ses différents états.

Après avoir testé, on indique à git si notre fonctionnalité marchait (avec git bisect good) ou ne marchait pas (avec git bisect bad). On obtient alors un nouveau commit à essayer, et ainsi de suite.

gitbisect_goodbad

On continue à tester les différentes versions jusqu’à ce que git nous dise qu’on a fini de chercher.
Git nous présente alors le coupable :

gitbisect_summary

Il ne reste plus qu’à regarder dans les modifications faites lors de ce commit (avec un outil tel que gitk par exemple, pour ne pas galérer dans la console s’il y a eu de grosses modifications), et trouver l’origine de l’erreur. Avant de se mettre au boulot, revenez au bon endroit sur votre branche de travail en quittant le mode de recherche avec :

1
 git bisect reset

Bonus !

La commande log de git est par défaut assez peu pratique. Voici une commande que je trouve assez utile pour gagner de la place, voir les branches et mettre de la couleur :

1
 git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)&lt;%an&gt;%Creset' --abbrev-commit

screen_better_log

 

Bon OK, c’est très flou, mais vous voyez l’idée.

Comme il n’est pas très pratique de taper régulièrement cette commande, le plus simple est d’en faire un alias :

1
 git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)&lt;%an&gt;%Creset' --abbrev-commit"

Désormais, lorsque l’on tape git lg dans la console on a accès à ces logs plus sympa. Merci à Filipe Kiss pour l’astuce !