Mots-clé : développement

La tendance python : vivement que la France rattrape l’international !

J’ai eu une discussion avec des fans de Symfony il y a quelques temps. Ils me soutenaient (avec une prétention qui m’a surpris) que Php était de très loin le langage le plus recherché actuellement. Ils se trompaient lourdement. Dire que Php est le langage le plus utilisé, oui. Dire qu’il est le plus demandé, et qu’il le restera, non.

Python est l’avenir

Aucune discussion possible.

Python c’est tout. End of story

Voici le mail que j’ai envoyé récemment à plusieurs de mes clients, et, qui explique la tendance python :

En tapant « most popular development languages » sur google, on voit que :

Enfin je l’ai appris ce matin de la part d’un professeur : deux universités de France retirent Php pour le remplacer par Python cette année (si vous êtes intéressé je vous dirais lesquelles, je n’ai plus en tête les villes de ces universités).

J’imagine les gens de mauvaise foi qui vont aller chercher sur le Web et sortir les deux ou trois sites qui mettent Php devant Python… oui vous allez en trouver, mais en proportion, la plupart des sites expliquent que la tendance d’aujourd’hui c’est Python et JavaScript. Quant à ce dernier, moi qui ai fait quelques sites en NodeJS, je confirme que c’est l’âge de pierre aussi bien côté serveur Web que côté langage JavaScript lui-même… peut être qu’enfin à sa version 6, il fera du scoping normal (lisez ici) déjà rien que ça c’est moisi, sans parler des principes des closures qui empêchent carrément de faire de grosses applications qu’on peut facilement maintenir… là aussi, je ne pourrai jamais convaincre des gens qui ont principalement fait du JavaScript sans avoir essayé aussi intensivement d’autres langages (on ne peut pas comparer dans ce cadre, et toute discussion devient alors impossible)…

Google Nexus 7 : mode développeur

Je recherchais comment activer le mode « développeur » sur ma tablette Nexus 7.
Android 5.1.

Réponse trouvée ici.

  • Aller dans le menu « Paramètres »
  • Aller dans le menu « A propos »

Et là… surprise : ce qui suit mérite de se mettre en titre 1 :

Il faut taper sept fois sur « Numéro de build » pour activer le mode développeur.

Euh ce n’est pas tout : ce qui suit mérite de se mettre en titre 1 aussi :

Il faut activer le mode « Appareil photo » (PTP) pour pouvoir déployer son application en mode débug.

Conclusion qui mérite elle aussi d’être mise en évidence :

WTF ?

WordPress : notes pour les débutants

Petites notes que j’ai apprises lors du développement d’un plugin qui créait des champs entièrement personnalisés :

Les filtres et les actions se ressemblent beaucoup à la fois dans la documentation et dans la déclaration, pourtant :

  • un filtre est une fonction qui reçoit quelque chose en paramètre et qui doit renvoyer quelque chose en paramètre, et s’il n’y a aucune modification du paramètre qui arrive, elle doit obligatoirement renvoyer le paramètre entrant ;
  • par opposition, une action est une fonction qui ne reçoit pas forcément quelque chose en paramètre et surtout, qui n’a pas besoin de renvoyer quelque chose (même si elle renvoie quelque chose, c’est ignoré).

Dans beaucoup de fonctions, il y a deux versions : avec et sans get_ :

  • the_ID(); et get_the_ID();
  • the_category(); et get_the_category();

La version sans le get_ affiche le contenu correspondant (= echo) alors que la version avec get_ renvoie le contenu correspondant, il faut donc utiliser cette dernière en l’assignant à une variable (par exemple : $categorie = get_the_category();).

Enfin dernière astuce : très souvent (voire tout le temps), les fonctions qui commencent par wp_ affichent le contenu, elles font un echo. Exemple de code que j’ai trouvé un peu déroutant quand on ne sait pas ce qu’il en est :

echo '<div class="form-wrap">';
wp_nonce_field(
    'ma_cle_unique',
    'ma_cle_unique_nonce'
);
echo '</div>';

Ici, wp_nonce_field() affiche quelque chose. Les fonctions qui commencent par wp_ affichent quelque chose.

Voilà. En espérant que cela évite à des personnes de perdre autant de temps que cela m’en a fait perdre…

Pourquoi les formats de fichiers de Microsoft Office sont si compliqués ? (Et quelques moyens de contourner les problèmes)

Cet article est apparu sur la page principale de Joel on Software le mardi 19 février 2008.

La semaine dernière Microsoft a publié le format des fichiers binaires d’Office. Ces formats apparaissent à première vue à la limite de l’insulte. Rien que le format de fichier pour Excel 97-2003 est un fichier PDF de 349 pages ! Attendez, ce n’est pas tout ! Il y a, dans ce document, quelques commentaires intéréssants :

Chaque collection de tableaux Excel (workbook) est stocké dans un fichier qui est une « compilation d’objets ».

Oui, vous voyez, les fichiers Excel 97-2003 sont des « compositions » de documents OLE, qui sont principalement plusieurs fichiers réunis en un seul. C’est tellement compliqué qu’il vous faut lire au minimum 9 pages de spécifications pour réussir à comprendre ça. Et ces « specs » ressemblent plus à des structures en C (« struct« ) que ce à quoi on s’attend normalement quand on lit des spécifications. C’est en réalité un système complet hiérarchique de fichiers.

Si vous avez commencé à lire ces documents avec l’espoir de passer le week-end à écrire rapidos un code qui importe des documents Word dans votre système de blog, ou qui crée des tableaux Internet qui contiennent vos données de comptes bancaires, formattés comme les feuilles Excel de votre suivi personnel, la complexité et la longueur des spécifications vous ont très certainement guéri de ce violent désir. Et vraisemblablement très rapidement. D’ailleurs un développeur normal concluerait que les formats binaires des applications Office :

  • sont volontairement obscurcis ;
  • sont le produit d’un cerveau démentiel ;
  • ont été crée par des développeurs anormalement incompétents ;
  • et sont impossibles à lire ou écrire correctement.

Vous auriez tort sur tous les points. En creusant un peu, je vais vous montrer comment ces formats de fichier sont devenus incroyablement compliqués, pourquoi cela ne reflète pas l’idée qu’on imagine de la « mauvaise programmation made in Microsoft », et ce que vous pouvez faire pour contourner ces problèmes.

La première chose à intégrer est que les formats binaires ont été conçus avec des objectifs complètements différents de ce qu’on imagine aujourd’hui (HTML). Voici ces objectifs, vous allez ainsi mieux comprendre pourquoi les spécifications sont aussi longues :

  • Ils ont été spécifiquement conçus pour être rapides sur les vieux ordinateurs. Dans les premières versions d’Excel pour Windows, 1 méga-octets de RAM était une taille normale de mémoire vive, et un PC 80386 à 20 MHz devait faire fonctionner Excel de manière confortable. Il y a donc plein d’optimisations dans les formats de ces fichiers qui ont pour objectif de les ouvrir et de les fermer beaucoup plus rapidement.
  • Ce sont des formats binaires, donc charger un enregistrement n’est qu’une question de copier directement (« blit ») une séquence d’octets, du disque dur vers la mémoire vive, où vous finissez immédiatement avec un structure de données de type C (« struct« ) qui est utilisable. Il n’y a pas besoin d’analyser ou de parcourir quoi que ce soit lors du chargement. L’analyse syntaxique et le parcours d’un enregistrement sont incomparablement, énormément, atrocement plus longs qu’un simple « blit ».
  • Le format de fichier est un peu tordu là où c’était nécessaire, là où on fait toutes les opérations habituelles, et cela à des fins de rapidité. Par exemple, Excel 95 et 97 ont quelque chose appelé « Sauvegarde Simple » qu’ils utilisent parfois parce que c’est une variante plus rapide sur une partie spécifique du format OLE, parce que dans les cas de sauvegarde normales, ce n’était pas assez rapide. Word a un menu appelé « Sauvegarde Rapide ». Pour sauver rapidement un long document, 14 fois sur 15, seuls les changement sont ajoutés en fin de fichier, au lieu de réécrire entièrement le document en partant de zéro. Sur les disques durs de l’époque, cela se traduisait par le fait qu’un gros document était sauvé en une seconde au lieu de trente. (Cela signifiait aussi que les données effacées dans un document ne l’étaient pas vraiment et étaient toujours présentes dans le fichier. Ce que beaucoup de gens par la suite n’ont pas apprécié).
  • Ils étaient crées dans le but de pouvoir utiliser des librairies. Si vous voulez écrire un « importateur » binaire, vous devez prendre en compte des choses telles que le format de métafichiers Windows (« Windows Metafile Format ») (pour dessiner des formes) et la gestion d’objets OLE embarqués (« OLE Compound Storage »). Si vous êtes sous Windows, il y a une librairie qui gère déjà tout ça et rend les choses triviales…. d’ailleurs, s’en servir a procuré un bon gain de temps à l’équipe de Microsoft. Mais si vous faites tout du début à la fin, vous devrez tout faire vous-même.Office s’accomode parfaitement avec tout ce qui est documents embarqués, par exemple, vous pouvez embarquer une feuille Excel dans un document Word. Un déchiffreur parfait de format Word devrait donc aussi être capable de faire quelque chose avec cette feuille embarquée.
  • Ils n’ont pas été crées avec le mot « interopérabilité » en tête. La supposition à l’époque, et c’était relativement raisonnable de penser ainsi, était que le format Word ne devait être lu et écrit que par Word lui-même. Cela impliquait que lorsqu’un développeur de l’équipe de Word devait prendre une décision sur des changements dans le format du fichier, la seule chose à laquelle il devait faire attention était que ces changements soient (a) rapides à lire et écrire et (b) prennent le moins de code possible dans le programme exécutable Word. Les choses telles que des formats standardisés SGML et HTML, n’ont jamais été pris en compte jusqu’à ce qu’Internet rende indispensable le fait de pouvoir échanger des documents qui soient compatibles entre eux. Et cela, c’est une dizaine d’années après que le format binaire de Microsoft Office n’ait été inventé. De toute façon, il était possible d’utiliser des « importeurs/exporteurs » pour s’échanger des documents. En réalité, Word a vraiment un format crée spécifiquement pour des exports destinés à d’autres programmes, appelé RTF, qui existe d’ailleurs depuis presque le début, et qui est toujours supporté à 100%.
  • Ils devaient pouvoir intégrer toute la complexité du logiciel. Chaque boîte à chocher (« checkbox »), chaque option de formattage, bref, toutes les possibilités offertes par Microsoft Office doivent être représentées quelque part dans les formats de fichier. Cette boîte à chocher (« checkbox »), dans le menu de Word appelée (« Paragraphe solidaire ») qui force un paragraphe à être automatiquement déplacé sur la page suivante si nécessaire afin de rester associé avec le paragraphe qui le suit ? Cela doit être présent dans le format du fichier.Et cela veut dire que si vous voulez développer un clone parfait de Word, qui peut lire correctement les documents Word, vous devez implémenter cette possibilité. Si vous voulez créer un programme destiné à écrire, qui soit compétitif, et qui a la possibilité de charger des documents Word, cela peut vous prendre une minute pour écrire le code qui va charger ce bit dans le fichier proprement dit, mais cela va certainement vous prendre des semaines à réussir à transformer tout l’algorithme de votre affichage pour que ce dernier s’adapte à ce fameux bit. Si vous ne le faites pas, les clients qui voudront ouvrir leurs documents Word dans votre clone vont voir toutes les pages sens dessus-dessous.
  • Ils ne peuvent que refléter l’histoire des applications. La plupart des choses compliquées dans ces formats de fichiers concernent des possibilités ou des options qui sont vieilles, compliquées, pas appréciées et rarement utilisées. Elles sont toujours là par souci de compatibilité, et parce que cela ne coûte rien à Microsoft de laisser du code. Mais si vous voulez vraiment faire un boulot complet et dans le moindre détail, et que vous voulez lire et écrire dans ces formats, vous allez devoir aussi faire le travail qu’un interne de chez Microsoft a fait il y a 15 ans en arrière. Le pire de tout c’est qu’il y a des centaines d’années-homme de développement qui se trouvent à l’intérieur de Word de d’Excel, et si vous voulez clôner ces applications complètement, vous allez devoir faire ces centaines d’années de travail. Un format de fichier et juste un résumé très concis de toutes les possibilités qu’offre une application.Juste pour le fun, voyons un exemple minuscule en détail. Un onglet Excel est un paquet d’enregistrements BIFF de types différents. Je ne vais parler que du premier enregistrement BIFF des spécifications. C’est un enregistrement appelé 1904.

    Les spécifications du format de fichier Excel sont remarquablement obscures sur cet enregistrement. Elles précisent juste que l’enregistrement 1904 indique « si le système de date 1904 est utilisé ». Ah. Super. Un exemple classique de spécification complètement inutilisable. si vous être un développeur qui travaille sur le format Excel, et que vous lisez ça dans les spécifications, vous pourriez tout à fait en conclure que Microsoft essaie de cacher quelque chose. En effet, vous n’avez pas assez d’information. Il vous faut plus de connaissances pour comprendre tout cela, mais je suis gentil et je vais vous l’expliquer. Il y a deux types de feuillets Excel : ceux qui se basent sur la date de base qui est le 1/1/1900 (avec un bogue d’années bissextiles volontairement crée afin d’être compatible avec Lotus  1-2-3, mais c’est trop ennuyeux pour en parler ici), et ceux dont la date de base est le 1/1/1904. Excel supporte ces deux types de dates parce que la première version d’Excel pour Mac se servait de la date de base du système d’exploitation (c’était le plus facile), mais Excel pour Windows devait impérativement pouvoir importer les fichiers Lotus 1-2-3, qui se servaient de la date de base au 1/1/1900. Déjà rien que ça devrait vous faire pleurer de consternation. Tout au long de cet histoire affligeante, pas un seul développeur n’a pensé à faire quelque chose de correct, mais bon voilà : vous avez la chose ici, et il vous faut faire avec.Vous trouverez vraiment ces deux types de fichiers, 1900 et 1904, un peu partout, selon que le fichier soit originaire de Windows ou de Mac. Les convertir de manière silencieuse peut éventuellement générer des problème d’intégrité des données, donc Excel ne changera jamais le type pour vous. Si vous voulez parcourir des fichiers Excel il faut faudra savoir gérer les deux. Ce n’est pas juste une simple question de charger ce petit bit à partir du fichier. Cela veut dire aussi que vous allez devoir réécrire entièrement tout l’affichage des dates avec un paramètre supplémentaire pour pouvoir prendre en compte ces deux types de date de base (epochs). Comptez au minimum plusieurs jours.

    Bien évidemment, lorsque vous travaillerez sur votre clone Excel, vous découvrirez plein de petits détails subtils sur la gestion des dates. A votre avis, quand est-ce qu’Excel fait la conversion de nombres en dates ? Comment fonctionne le formatage ? Pourquoi est-ce que « 31/1 » est interprété comme le 31 janvier de l’année en cours, alors que « 1/50 » est considéré comme le premier janvier de l’année 1950 ? Toute ces petites choses très subtiles qui concernent les comportements ne peuvent pas être complètement documentées à moins d’écrire un document pratiquement aussi long qui le code source d’Excel lui-même.Et c’est juste le premier enregistrement BIFF, alors qu’il y en a plusieurs centaines que vous devrez gérer. Et pour ne rien vous cacher : celui-ci est l’un des plus simples. La plupart des BIFF feront pleurer de rage un développeur expérimenté.

Une seule conclusion s’impose : c’est très gentil à Microsoft de fournir officiellement un document décrivant le format de leurs fichiers Office, mais ça ne va pas pour autant vous rendre la vie super facile si vous décidez d’écrire quelque chose qui importera ou sauvera sous le format Office. Ces applications sont affreusement complexes et subtiles, pleines de possibilités et vous ne pouvez pas simplement implémenter 20 % des fonctions les plus populaire et espérer que 80 % de votre clientèle sera satisfaire. La spécification du format binaire vous aidera à gagner quelques minutes, tout au plus quelques jours, et vous évitera de faire du reverse engineering. Rien de plus.

OK, je vous ai promis quelques solutions de contournement. La bonne nouvelle c’est que pour la plupart des applications qui veulent lire ou écrire au format Office ne font pas un bon choix. Il y a deux alternatives qu’il vous faut immédiatement étudier : soit laisser Office faire ce travail, soit écrire dans un format plus facile (ce qui ne veut pas dire moins puissant).

Laissez Office faire le boulot pour vous. Word et Excel ont des modèles objet extrêmement complets, disponibles via l’automation COM, qui vous donne la possibilité de faire tout par programmation. Dans plein de cas il est beaucoup plus pertinent de réutiliser le code dans Office plutôt que d’essayer de le ré-implémenter. Voici quelques exemples.

  1. Vous avez une application Web qui doit transformer des documents Word en PDF. Voici comment je le ferais : quelque lignes de VBA Word pour charger le fichier et le sauver au format PDF en utilisant le convertisseur PDF intégré de Word 2007. Vous pouvez appeler ce code directement, même en ASP ou ASP.NET sous IIS. Cela fonctionnera. La première fois, il y aura un chargement de Word et ça prendra quelques secondes. Les fois suivantes, Word sera gardé en mémoire par le sous-système COM pendant quelques minutes au cas où vous en auriez besoin. C’est suffisamment rapide pour n’importe quelle application Web de taille moyenne.
  2. Même chose que précédemment, mais vous êtes hébergé sur du Linux. Achetez un serveur Windows 2003, installez une copie de Word avec une licence pro, et mettez en place un petit Webservice qui fait ce travail. Une demi journée de travail avec C# et ASP.NET.
  3. Même chose que précédemment, mais il vous faut être plus réactif : votre application a grossi. Mettez un « load balancer » en face de plusieurs PC que vous aurez mis en place de la même manière qu’à l’étape précédente. Aucun code supplémentaire.

Ce type d’approche pourrait fonctionner si vous avez pour objectif de faire dans vos applications des appels simples et communs à des objets Office. Par exemple :

  • Ouvrir une fiche  Excel, mettre des informations dans les cellules, recalculer, et extraire des résultat des cellules ;
  • Utiliser Excel pour générer des diagrammes au format GIF ;
  • Extraire presque n’importe quel type d’information de n’importa quelle feuille Excel sans perdre une seconde à réfléchir au format de fichier qu’il y a derrière ;
  • Convertir un fichier Excel au format CSV tabulaire (une autre méthode pratique serait d’utiliser le drive ODBC d’Excel pour aspirer suck data out using SQL queries).
  • Editer des deocuments Word ;
  • Remplir des fiches Word ;
  • Convertir des fichiers entre tous les formats supportés par Office (il y a plein d' »importateurs » qui savent lire les formats de programmes de traitement de texte et de feuilles de calcul).

Dans tous les cas, il y a des façons de dire aux objets Office qu’il ne sont pas en dans une applications interactive, et qu’ils ne doivent pas s’occuper de rafraîchir l’écran et qu’ils ne doivent en aucun cas essayer d’ouvrir une boite de dialogue. Au fait, si vous choisissez cette solution, il y a quelques petites astuces et particularités qu’il faut bien avoir en tête, qui ne sont pas officiellement supportées par Microsoft. Parcourez la base de connaissance de Microsoft sur le sujet avant d’aller plus loin.

Utilisez un format de fichier plus simple pour écrire des fichiers. Si vous devez générer des documents Office par la programmation, il y a presque toujours une façon plus facile et plus pratique que le format binaire Office, que vous pouvez utilisez, et que Word et Excel ouvriront tout de même sans problème, le tout sans rien perdre de vos objectifs.

  • Si vous devez tout simplement générer des données tabulaires pour les ressortir dans Excel, utilisez CSV ;
  • Si vous avez absolument besoin de formules de calcul que CSV ne supporte pas, le format WK1 (Lotus 1-2-3) est incroyablement plus simple que celui d’Excel, et Excel saura le lire ;
  • Si vous devez vraiment, absolument, générer des fichiers natifs Excel, commencez par une très vieille version d’Excel… Excel 3.0 est un bon compromis (c’est le format juste avant que tout ces trucs imbriqués dans des trucs imbriqués n’apparaissent), et sauvez un fichier minimal qui contient uniquement les choses dont vous voulez vous servir. Utilisez ce fichier pour voir le nombre minimal d’enregistrements BIFF que vous devrez ressortir et concentrez vous, dans les spécifications, uniquement sur ces parties ;
  • Pour des documents Word, pensez au format HTML. Word les ouvrira de manière parfaitement transparente.
  • Si vous voulez vraiment générer des documents Word avec des choses particulière et originales dedans, le meilleur moyen sera presque toujours de générer un fichier RTF. Tout ce que Word peut faire peut être écrit dans un fichier RTF, et ce format est un format text simple, pas binaire, et vous pouvez même changer à la main des choses dans le fichier, et Word l’ouvrira toujours certainement sans problème. Vous pouvez créer un document sympa formatté comme vous le désirez, avec des mots-clé que vous voulez remplacer, vous demandez ensuite à Word de sauver le document au format RTF et vous remplacez à la main (ou par programmation) directement dans le fichier RTF ces champs avec les mots-clé à la volée. Et ce document, vous pourrez l’ouvrir sous Word sans aucun problème.

Pour conclure, à moins que vous ne vouliez créer un concurrent d’Office qui peut lire et écrire tous les fichiers Office parfaitement, auquel cas vous aurez des centaines d’années de travail devant vous, il y a de fortes chances que, quel que soit le problème que vous vouliez résoudre, le plus gros de votre travail soit de lire et d’écrire des fichiers Office.

Une bonne interface utilisateur

Voici un site qui donne plein de bonnes idées pour faire une bonne interface utilisateur :

Try a one column layout instead of multicolumns:

Try a one column layout instead of multicolumns.

Try giving a gift instead of closing a sale right away:

Try giving a gift instead of closing a sale right away.

Try merging similar functions instead of fragmenting the ui:

Try merging similar functions instead of fragmenting the ui.

Try social proof instead of talking about yourself:

Try social proof instead of talking about yourself.

Try repeating your primary action instead of showing it just once:

Try repeating your primary action instead of showing it just once.

Try distinct styles between clickable and selected items instead of blurring them:

Try distinct styles between clickable and selected items instead of blurring them.

Try recommending instead of showing equal choices:

Try recommending instead of showing equal choices.

Try undos instead of prompting for confirmation:

Try undos instead of prompting for confirmation.

Try Telling who it’s for instead of targeting everyone:

Try Telling who it's for instead of targeting everyone.

Try being direct instead of indecisive:

Try being direct instead of indecisive.

Try more contrast instead of similarity:

Try more contrast instead of similarity.

Try showing where it’s made instead of being generic:

Try showing where it's made instead of being generic.

Try fewer form fields instead of asking for too many:

Try fewer form fields instead of asking for too many.

Try exposing options instead of hiding them:

Try exposing options instead of hiding them.

Try suggesting continuity instead of false bottoms:

Try suggesting continuity instead of false bottoms.

Try keeping focus instead of drowning with links:

Try keeping focus instead of drowning with links.

Try showing state instead of being state agnostic:

Try showing state instead of being state agnostic.

Try benefit buttons instead of just task based ones:

Try benefit buttons instead of just task based ones.

Try direct manipulation instead of contextless menus:

Try direct manipulation instead of contextless menus.

Try exposing fields instead of creating extra pages:

Try exposing fields instead of creating extra pages.

Try transitions instead of showing changes instantly:

Try transitions instead of showing changes instantly.

Try gradual engagement instead of a hasty sign up:

Try gradual engagement instead of a hasty sign up.

Try fewer borders instead of wasting attention:

Try fewer borders instead of wasting attention.

Try selling benefits instead of features:

Try selling benefits instead of features.

Try designing for zero data instead of just data heavy cases:

Try designing for zero data instead of just data heavy cases.

Try opt-out instead of opt-in:

Try opt-out instead of opt-in.

Try consistency instead of making people relearn:

Try consistency instead of making people relearn.

Try smart defaults instead of asking to do extra work:

Try smart defaults instead of asking to do extra work.

Try conventions instead of reinventing the wheel:

Try conventions instead of reinventing the wheel.

Try loss aversion instead of emphasizing gains:

Try loss aversion instead of emphasizing gains.

Try visual hierarchy instead of dullness:

Try visual hierarchy instead of dullness.

Try grouping related items instead of disordering:

Try grouping related items instead of disordering.

Try inline validation instead of delaying errors:

Try inline validation instead of delaying errors.

Try forgiving inputs instead of being strict with data:

Try forgiving inputs instead of being strict with data.

Try urgency instead of timelessness:

Try urgency instead of timelessness.

Try scarcity instead of abundance:

Try scarcity instead of abundance.

Try recognition instead of recall:

Try recognition instead of recall.

Try bigger click areas instead of tiny ones:

Try bigger click areas instead of tiny ones.

Symfony 2 : avantages et inconvénients

Après bon nombre de commentaires, voire d’insultes (si si), je résume l’article qui suit :


Vous allez toujours entendre le même discours pour ceux qui commencent avec Symfony et qui n’ont jamais vraiment développé d’autres choses, qui est quelque part logique : Symfony c’est génial, c’est super, c’est la réponse à la vie, l’univers, et au reste, il aurait dû s’appeler « Php – 42 » ou quelque chose comme ça (et si vous ne comprenez pas l’allusion c’est qu’on n’a ni le même background, ni le même humour). C’est, de plus, très souvent le genre de personnes qui n’admettent pas qu’ils n’ont pas d’expérience et cela finit à l’insulte ou au pugilat.

S’ils avaient vraiment pratiqué d’autres choses, il verraient qu’il y a plein d’autres trucs ailleurs, et ils verraient qu’à d’autres endroits il y a des choses mieux.

Ceux qui n’ont pas d’expérience mais l’esprit ouvert me demandent ce qu’il y a comme autres choses à tester, et je leur réponds avec plaisir ! Ceux qui n’ont pas d’expérience et ont besoin de justifier leur existence diront « c’est un gros con il est dépassé il n’y comprend rien ». Je ne donne des cours que pour les premiers. Les autres je les laisse faire alt-tab en permanence entre Facebook et Symfony (et si vous saviez tout ce que je pense quand je parle ainsi…).


Après avoir développé deux applications relativement basiques, voici les inconvénients que j’ai relevé de Symfony :

  • Twig : c’est la seule chose qui semble vraiment pratique, utile et optimisée dans Symfony. A tel point que Zend l’utilisera comme moteur de templates, et Drupal 8 aussi. Un bon point pour Symfony, et le seul. Voici la suite.
  • Symfony prône les bonnes pratiques – ce qui est louable – pourtant j’ai dû faire trois fois du copier coller pour que ça fonctionne… Exemple le plus frappant : la bonne pratique (louable) est de séparer totalement la vue du modèle, et du contrôleur. Mieux : ils ont fait un endroit où on écrit toutes les requêtes complexes, afin de les séparer du modèle : ce sont les Repositories. Problème concret : quand on a un type fichier dans un formulaire qui est envoyé, le type « file » est posté. Si on veut écrire le fichier envoyé, ça passe par un contrôleur, et c’est lui qui est censé l’écrire en base de données ? Non ! Donc c’est côté de la base de données, côté modèle donc. Mais… les entités ne peuvent pas accéder à leur propre repository ! Si vous vous retrouvez dans ce cadre (hypra courant) alors vous allez devoir bidouiller, et créer une fonction statique qui renvoie le manager d’entités et demander à ce dernier de récupérer le repository de la classe en cours. Véridique. Bidouillage, bidouillage, bidouillage. Pourtant, j’insiste : Symfony prône les bonnes pratiques et essaie de faire au mieux, mais il échoue assez… attendez je cherche le qualificatif exact… j’ai trouvé : il échoue lamentablement.
  • Je pensais gagner du temps avec le bundle FOSUser. Faux ! En théorie il est censé simplifier la vie à mort et faire gagner énormément de temps. En pratique, c’est comme Symfony, il va vous falloir entrer dans son coeur, comprendre comment il a été écrit afin de pouvoir vous en servir. Exemple concret là aussi : il n’est fait que pour un seul type d’utilisateurs. Si on en veut plusieurs, il va vous falloir installer un bundle supplémentaire : le PUGXMultiUserBundle. Quelques heures plus tard après l’installation et la configuration, on m’a demandé de créer un rôle modérateur, qui doit pouvoir valider les fiches d’inscription, c’est à dire pouvoir afficher n’importe quelle fiche. Je ne peux même pas vous expliquer comment faire, car j’ai demandé aux experts Symfony – ce sont des personnes qui m’ont sous-traité le second travail que j’ai fait sur Symfony, de le faire eux même parce que je n’en pouvais plus de perdre autant de temps inutilement. J’ai beau chercher, mais un bon développeur Php va perdre beaucoup plus de temps à rechercher tout ça, installer, comprendre le fonctionnement, copier coller puis modifier le code, plutôt que de le faire direct à la main, avec des variables dans $_SERVER pour suivre quelques infos.
  • Symfony et le redimensionnement d’images. Je voulais juste, une fois qu’une image est arrivée en base de données, créer une vignette de cette dernière, afin de pouvoir l’afficher plus rapidement. J’ai donc cherché et voici le résultat – vous noterez bien qu’il est affligeant si on veut simplement redimensionner une image : en théorie  :
    • il faudrait mettre en place un service,
    • à partir de ce service, aller chercher des informations,
    • mettre en place toute une configuration, avec un système de hook (les « écouteurs »)

    … bref, refaire des milliers de choses d’une inutilité absolument affligeante, tout ça pour faire un simple resize. Après avoir passé plusieurs heures à installer le LiipImagineBundle : et m’être aperçu que pour faire un resize, il fallait déclarer vouloir utiliser un service dans ‘app/config/config.yml’, je vois qu’il y a un exemple qui est censé fonctionner sur stackoverflow ici. Et puis là le code qui fonctionne utilise getRequest(). Et le container. Moi j’en avais besoin dans l’entité, car c’est ici qu’on écrit les informations en base de données. Pour pouvoir accéder à un container dans une entité, il faut faire un méga hack, ou pire (lire les deux réponses ici). La seule réponse viable c’et de.. créer un service ! Non mais allô quoi ! Juste pour un crop ! Vraiment on est en plein délire. Hop, top chrono : google =» php imageresize, copier coller, et en moins de 5 minutes, tout fonctionnait. Symfony clame haut et fort qu’il vous fait gagner des heures de boulot ? C’est une blague, une grosse blague ! Posez les pieds sur terre, voici la réalité concrète du terrain : Symfony essaie de pousser encore et encore l’abstraction à son maximum mais on arrive à des non-sens comme celui-là : une entité qui appelle deux services différents, surchargés à mort, des centaines de lignes de code totalement inutiles, juste pour faire un resize. C’est tellement grossier comme problème qu’on en arriverait presque à croire que c’est faux… mais c’est vrai, et les liens que j’ai mis sont bien là pour le prouver.

  • Doctrine est quelque chose… que je ne comprends pas. Il a été crée pour « optimiser » les requêtes. Déjà, rien que d’écrire ça, c’est inévitablement un non sens : on n’optimise pas les requêtes via du Php… À moins que je ne me trompe, on n’a jamais besoin d’optimiser les requêtes à ce niveau ! L’optimisation et la mise en cache doit se faire au niveau du moteur de bases de données. Pourtant, là, on doit écrire du SQL, mais pas vraiment. Olivier arrête de dire n’importe quoi me direz vous. Pourtant ça n’est pas une blague, lisez tout ça ici. Tout y est expliqué : ils ont « surchargé » l’écriture de requêtes, afin de… pouvoir optimiser les requête et mieux faire du cache. Si si. Et ils ont même inventé un concept super novateur, que personne ne connaissait avant (grincement de dents cynique), j’ai nommé : l’hydratation (ou en anglais : « hydration »). Non non, j’insiste, arrêtez de rigoler, c’est pas une blague, ils prennent ça très au sérieux là bas, regardez sur la documentation officielle et cherchez « hydration ». Par contre pour bosser il faut absolument savoir ce que ce mot d’une débilité profonde – au sens informatique – signifie : j’ai mené un entretien d’embauche avec une personne (qui se disait expert), et comme je n’ai pas parlé d’hydratation des données, ça ne lui a pas plu. Bon quand je dis « expert », il faut dire qu’il s’était fait dégager à grands coups de pieds au derrière par sa précédente boîte… j’arrête là je vais être méchant 😉
  • Avec Doctrine, on se prend tout le temps la tête sur les requêtes, ce qui fait qu’au final, comme jamais rien ne fonctionne comme on voudrait avec Doctrine, on se retrouve à vouloir connaitre quelle est la vraie requête faite en base. Voir ici. Réponse officielle : on ne peut pas. On ne peut pas voir les requêtes qui sont envoyées au moteur de base de données. Mais si continuez de lire, arrêtez de pleurer de rire ! Allez vous chercher un mouchoir, essuyez-vous les yeux et revenez.
  • Doctrine est censé simplifier la vie en proposant un modèle d’héritage. Exemple de ce que j’ai réalisé : une personne est la classe de base, et de là descendent les professeurs et les étudiants. Pourtant il est lourd. Très lourd. Très (très³²) lourd. Tellement lourd, que même sur la documentation officielle ils reconnaissent que Doctrine est lourd. La preuve sur la documentation officielle. En fait il est censé simplifier la vie du développeur, mais avec Doctrine il faut une machine énorme pour pouvoir faire tourner la moindre requête un tant soit peu complexe.
  • Pire. Encore bien pire (si c’est possible !). Si, comme moi, vous voulez utiliser des requêtes comprenant des calculs de distance, il vous faudra utiliser des fonctions mathématiques et là, de base, Doctrine ne connait rien, et il vous faudra passer quelques heures à installer un bundle dans votre installation, en modifiant pas mal de fichiers un peu partout. Si, là aussi, essuyez vos larmes de rire et lisez bien ce qui suit, car c’est vrai : il est impossible de faire immédiatement cette requête sous Symfony : "SELECT COS(5) as distance;". Non non ça n’est pas une blague, c’est du sérieux. Voir tout mon article détaillé ici.
  • Symfony est tellement complexe qu’il faut absolument avoir un débogueur intégré tel que xdebug et pouvoir faire du pas à pas dans un environnement tel que PhpStorm qui donne la possibilité de suivre tout, avec la pile d’appel. Rendez vous compte : pour développer un site Web simple, des frameworks comme symfony sont tellement complexes qu’il faut obligatoirement pouvoir faire du pas à pas. Ce sont des experts Symfony qui me l’ont expliqué. Sur le coup j’ai sincèrement (honnêtement, ce n’est pas ironique, c’est véridique) cru que c’était une blague. Php est tellement simple et fluide quand il est bien développé que je n’ai jamais eu à utiliser de débogueur pas à pas en plus de dix ans ! Et ma dernière prestation était en tant qu’expert Web chez Business & Décision, prestation pour la banque, et on n’a jamais eu besoin de faire du pas à pas ! D’ailleurs pourquoi je me justifie ? N’importe quel béotien doit se douter de ça…

Je n’ai pas le temps de lister toutes les autres choses qui m’ont fait perdre un temps fou. J’ai vendu un site que je comptais faire en maximum dix jours, et je l’ai fait en un mois. Symfony était tout bonnement un mauvais choix.

En conclusion :

Symfony est censé faire gagner du temps mais en pratique, on est obligé d’apprendre la globalité de tout le framework et au final on ne gagne absolument pas de temps, et bien pire : si le projet est petit, il faut à tout prix éviter des usines à gaz telles que Symfony.

Pour la petite note, les personnes qui m’ont sous traité le projet – qui tourne bien actuellement – ont été déçues parce que je n’ai pas tenu mes délais, et que mes premières livraisons n’étaient pas de bonne qualité – alors que je « semblais » compétent. Je ne jette pas tout sur Symfony, mais bon sang quelle grossière erreur de ma part ! Pour vous donner une idée de comparaison : j’ai terminé en 3 jours un site qui devrait être mis en ligne incessamment sous peu : un site spécialisé la constatation fiable de sites Web. Il contient :

  • Un formulaire d’inscription contenant tout ce qu’il faut (CSRF protection, re-Captcha etc) ;
  • Un CSS full responsive ;
  • Un blog WordPress (évidemment full responsive) ;
  • Un outil complet de capture d’écran basé sur du Webkit (très gros boulot) ;
  • Du code pour gérer un multi-partenariat en marque blanche ;
  • Du templating Smarty pour modifier l’habillage rapidement ;
  • Une documentation entièrement compatible PhpDocumentor ;
  • Une classe (assez longue) pour le traitement des images (archivage, signature chiffrée etc) ;
  • Un ORM qui :
    • ne fait des requêtes que quand c’est nécessaire,
    • fait des requêtes en SQL pur. Ouf, je respire, des heures entières de gagnées.
    • délègue au maximum à la base de données, ce qui est absolument vital pour avoir une application stable, rapide et pérenne sur le temps.
  • Une classe simple d’envoi de mail, avec la possibilité d’envoyer le texte alternatif (= si jamais le client ne peut pas lire du HTML, on peut préciser le texte). Merci PHPMailer, un outil simple, ultra facile d’utilisation, et utilisé dans ma classe, finit par un code ainsi :
    $mail = new ObjetMail(
        EMAIL_DEFAUT_FROM,
        EMAIL_DEFAUT_FROM_NAME,
        EMAIL_DEFAUT_REPLYTO,
        EMAIL_DEFAUT_REPLYTO_NAME,
        $email,
        'Capture bien prise',
        /*... Texte HTML ...*/,
        /*... Texte alternatif ...*/
    );
    try {
        $mail->send();
        array_push(
            $this->_TabResult,
            $this->trad->get(
                'mail_envoye_en_attente_confirmation'
            )
        );
    } catch (Exception $e) {
        $this->addTabErr(
            $this->trad->get('err_envoi_email')
        );
        $ok = false;
    }
  • Tout est tracé et archivé, aussi bien en base que dans les captures d’écran, et tout est prévu pour une grosse évolution : un compte, ce compte pourra avoir plusieurs emails, plusieurs captures, toutes les connexions – réussies ou échouées – sont déjà tracées, ils pourront avoir une ou plusieurs adresses etc.

Faire la même chose avec Symfony ? Je vous laisse estimer le temps de faire les estimations, le cahier des charges, le devis, le développement, mais attention, grâce à Symfony vous allez gagner énormément de temps : Symfony peut générer le CRUD pour l’administration en ligne de commande, regardez ici. Oulah que de temps gagné ! Sachant que je génère un custom getter-setter en 3 touches avec vim, même s’il y a plusieurs centaines de champs, et plusieurs dizaines de tables, je ferais ça « à la main » au maximum en une journée… enfin bon en comparant avec Symfony je peux dire sans éxagérer : sans Symfony, une journée de perdue, mais dix d’économisées ! Mais pourquoi je continue à essayer de prouver que Symfony ne fait jamais gagner de temps, moi ? Même ces personnes expertes Symfony ont décidé de le laisser tomber et de n’utiliser que Silex pour tous leur nouveaux projets à moins qu’ils n’aient vraiment besoin de choses spécifiques à Symfony… et personnellement je n’arrive pas à voir ce que Symfony a de si spécifique dont on ne peut pas se passer 🙂 … A l’inverse, je vois vraiment toutes les raisons pour lesquelles on peut se passer de Symfony.

Apache 2.4 : mod_rewrite et RewriteLog et httpd.conf : du changement

RewriteLog n’existe plus

Vous avez la description ici.

RewriteLog n’existe plus ; il faut mettre LogLevel et ensuite tracer le debug dans le errorlog via la commande :
tail -f error_log|fgrep '[rewrite:'

Mes anciens logs ressemblaient à ceci :
RewriteLog "/web/logs/bonnapizza.rewrite.log"
RewriteLogLevel 9

Maintenant ils sont tous ainsi :
LogLevel alert rewrite:trace2

MySQL : mémo / cheatsheet

Voici quelques astuces dont je me sers souvent, pour ne pas avoir à systématiquement les rechercher, je m’en suis fait une copie dans un petit champ texte :

Création d’une base de données

CREATE DATABASE z DEFAULT CHARACTER SET utf8;

Créer un utilisateur pour une base de données (la manière sale)

Important : d’abord sans le ‘.*’ sinon ça ne fonctionne pas, et puis refaire avec le '.*'.
Très important : ici on autorise tout à l’utilisateur qui va être crée. C’est donc une méthode rapide mais de bourrin et ce n’est pas la bonne méthode si vous voulez faire un utilisateur proprement, destiné à exister pour longtemps. Dans ce cas il faut faire quelque chose de plus précis afin de ne pas tout lui autoriser.
GRANT ALL PRIVILEGES ON bd TO 'nomutilisateur'@'192.168.2.16' IDENTIFIED BY 'motdepasse';
GRANT ALL PRIVILEGES ON bd.* TO 'nomutilisateur'@'192.168.2.16' IDENTIFIED BY 'motdepasse';

Initialisation d’une variable via une requête :

SELECT @MON_ID:= ID FROM matable WHERE CHAMP='champ_recherche';
puis on se ressert de cette variable pour faire une insertion en base de données :
INSERT INTO autre_table (ID_CLE_EXTERNE, DESCRIPTION, DOCUMENT) VALUES
(@MON_ID, 'valeur1', './valeur2');

Relancer le service MySQL

  1. service mysqld stop
  2. attendre une trentaine de secondes afin que le cache soit vidé et que toutes les allocations mémoires soient correctement libérées
  3. service mysqld start

Convertir une table en utf8 :

Très important : si vous tapez ce qui suit avec pour objectif de convertir la table et les données cela ne fonctionnera pas :
ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name;
Ce n’est qu’en utilisant les ordres suivants que la conversion sera faite par MySQL !
ALTER TABLE t1 CHANGE c1 c1 BLOB;
ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8;

Renommer un champ :

Ici, je renomme la clé primaire « ID » et je la passe en minuscules (« id« ) :
ALTER TABLE ville CHANGE ID id int(11) NOT NULL auto_increment;

Modification des AUTO_INC

Pour changer la valeur d’un auto_inc (‘réinitialiser la valeur’, comme on le dit dans MySQL ici) :
ALTER TABLE tbl_name AUTO_INCREMENT = N;