Comment DoYouBuzz a réécrit son code sans tout casser

Eric Cambray
DoYouBuzz Open
Published in
8 min readMar 26, 2015

--

Il y a un an, nous avons accouché de la V2 de DoYouBuzz après 9 mois de réécriture intensive de notre code. Au bout du compte : une application beaucoup plus stable, et une mise en production tout en douceur.

Nous vous proposons ici un retour sur notre méthodologie de refonte incrémentale. Attention : cet article peut contenir des termes techniques.

On l’a déjà dit : DoYouBuzz est une vieille startup… Pour le web, “il y a 8 ans” c’est un peu comme parler du paléolithique en histoire : il y a eu du changement depuis ! Nous avons acquis de l’expérience, accumulé des kilomètres de lectures de bonnes pratiques et bien sûr suivi avec attention les avancées techniques dans notre domaine (le développement web, si vous m’avez bien suivi). Notre vision du service s’est aussi considérablement consolidée.

Pour se remettre dans le contexte : en 2007 PHP 5.3 n’est pas encore sorti, jQuery a 1 an, Chrome n’existe pas. C’est comme Lascaux avec un panneau “Peinture Fraîche” écrit en gros. Si nous avions dû lister les bonnes pratiques au niveau du code présent sur DoYouBuzz en 2010 nous n’aurions eu besoin que d’un ticket de métro pour être exhaustif…

Quand nous nous sommes attaqués à la question du refactoring de DoYouBuzz, deux solutions se sont présentées à nous :

  • Le rm -rf. Autrement dit, tout supprimer, nous lancer dans une refonte globale et radicale. Soit des mois et des mois de travail.
  • Faire une refonte graduelle

Vu la taille de l’équipe technique de DoYouBuzz depuis 2011 (2 puis 3 personnes), faire une refonte complète était impossible. D’autant plus que nous souhaitions à tout prix continuer à sortir de nouvelles choses pour faire vivre la plateforme (inimaginable en effet de figer le lancement de nouvelles fonctionnalités pendant un an).

Nous avons donc pris la voie de l’amélioration par palier, pour pouvoir préparer le terrain pour une V2. En fait, même si la V2 de DoYouBuzz a vu le jour en mars 2014, les premiers efforts pour obtenir un code modernisé et maintenable ont commencé en 2011.

Premier effet positif de cette décision ? Cela nous a permis de tester en production par petits morceaux, et donc de pouvoir faire des réglages (ou rétropédalages) si besoin.

Ajout d’une couche d’ORM

Cette première phase a débuté en 2011 et nous a notamment permis d’ajouter une couche d’ORM (ce qui va faire le lien entre les objets PHP et la base de données). Nous sommes passés de ADODB (qui utilise un design pattern en Active Record) à Doctrine2 (qui est lui en design pattern Data Mapper), et nous avons longtemps fait cohabiter les deux (c’est d’ailleurs toujours le cas !).

A partir de ce moment, tous les nouveaux développements se sont fait en utilisant Doctrine2, et petit à petit le code a pu bénéficier des gros avantages d’un ORM (même si beaucoup râlent sur les ORM, quand on fait une utilisation intensive des objets et des liens entre eux c’est un gros plus).

L’avantage d’avoir deux ORM au fonctionnement totalement opposé, c’est qu’il est possible de mixer les deux. Dans notre cas, il a suffit d’ajouter des annotations Doctrine pour que notre entité Turbulences (notre ancien framework) puisse être utilisée comme une entité par Doctrine

/*
*
@Entity
*
@Table(name="users")
*/
class User extends TURB_Object {
..........}

Ensuite dans notre ancien code il est devenu possible d’utiliser l’ancien fonctionnement ou le nouveau (au choix)

// à l'ancienne :
$user->save();
// ou façon Doctrine :
$em->persist($user);

Cela permet, vous l’aurez compris, de migrer progressivement son code et de ne pas voir tout le site s’écrouler si vous avez oublié d’utiliser le nouveau système quelque part.

Nouveau moteur de template

Un webdesigner / intégrateur découvre l’héritage.

En 2012, nous avons aussi rendu un webdesigner heureux ! Nous avons en effet commencé à changer notre moteur de template et nous sommes passés de Smarty à Twig.

Pas besoin d’argumenter ici, avec son héritage et sa facilité d’extension Twig est un must qui reprend les bonnes pratiques vues sur d’autres langages.

Nous avons débuté cette évolution en permettant à nos contrôleur de rendre soit des templates Smarty soit des templates Twig. Pour ce faire, nous avons utilisé une méthode ->render() avec la même signature que les contrôleur Symfony2 (et oui nous pensions déjà au futur) qui selon le type de contrôleur utilisait du Smarty ou du Twig. Pendant cette période nous avons dû maintenir deux layouts identiques mais dans des langages différents.

Une fois Twig pré-dominant dans le code, nous avons fait en sorte de faire un wrapper qui rendait la partie Smarty de la page dans un layout Twig. Un hybride donc, qui évite de tout recoder, et que nous avons baptisé Smartwig. A ce jour il reste encore deux pages utilisant ce système (les préférences emplois et l’export de CV), mais elles devraient vite disparaitre.

Changement de framework

En 2012, nous avons pris la décision de changer de framework. Jusqu’alors, nous étions sur Turbulences, un framework mort né au nom prémonitoire…

Pourquoi changer de framework et pas continuer sur une solution maison ? Pour la stabilité bien sûr, mais aussi pour éviter de recoder des composants et donc accélérer le développement. Autre avantage : la communauté Symfony.

Le choix de Symfony2 (et pas de Zend 2, par exemple) s’est fait dans le temps : nous avons tout d’abord expérimenté le framework en développant plusieurs petits projets sur des versions non stables. Pleinement satisfaits, nous avons ensuite développé un nouveau produit complet (DoYouBuzz Showcase) sur la première version publique du framework.

C’est donc tout naturellement que nous avons commencé à migrer quelques parties du code de DoYouBuzz sur Symfony2 (les formulaires par exemple). A ce moment là, nous avions un véritable framework à 2 têtes. Nous l’avons baptisé Turbofony ☺.

Les tests unitaires et fonctionnels

Le code avant.

En 2013, alors que le code a commencé à ne plus ressembler à un jenga géant, nous nous sommes attaqué à la question des tests. Les tests unitaires tout d’abord : le choix par défaut aurait été PHPUnit, mais nous lui avons préféré Atoum, plus moderne, plus lisible, plus souple au niveau des mocks, et avec une communauté réactive (et tout comme Twig et Symfony2, créé en France. Not bad).

Que dire sur le test unitaire ?
Ne pas en avoir, surtout sur un projet complexe, c’est suicidaire !

Cela permet de répérer les bugs avant qu’il ne soient en prod (vérifier réguliérement). Par ailleurs, vous enlevez le stress de casser quelque chose, quelque part en modifiant une ligne de code.

Nous avons très vite ajouté des test fonctionnels, pour cela nous avons opté pour Behat (oui qui ne sert pas à ça normalement !). C’est une bonne solution qui permet de repérer les bugs parfois très difficiles à détecter. Sur les grosses applis avec beaucoup d’options c’est une sécurité supplémentaire très appréciable.

Refonte de l’éditeur de CV

A partir de mai 2013 a débuté un gros chantier, car oui, même si on a pu faire évoluer par petites touches l’application, il a fallu se retrousser les manches et rentrer dans le tas pour refaire l’éditeur de CV.

Côté serveur

A partir de ce moment, Symfony2 est devenu notre framework par défaut. Bienvenue aux listener, injection de dépendances, bundles, routes, la console en ligne de commande… avec toujours quelques parties sur l’ancien framework (au moment du lancement de la V2 l’achat des comptes Premium ou la gestion des nom de domaine était toujours celle de la V1 par exemple).

Nous avons utilisé les routes pour faire le mapping entre URL et contrôleur, et en cas de route non trouvée, l’ancien framework prenait le contrôle. Nous avons donc dû faire un HttpKernel à notre sauce. Le gros du code pour le double framework peut donc se résumer à :

try {
$this->dispatcher->dispatch(KernelEvents::REQUEST, $event);
} catch (NotFoundHttpException $e) {
\TURB_Dispatcher::dispatch();
}

Afin d’améliorer les performances du site, nous utilisons évidemment du cache (memcache par exemple) et surtout un cache HTTP : Varnish. Lorsque vous naviguez sur un CV : si celui ci n’a jamais été visité, il est généré et mis en cache par Varnish, le prochain utilisateur le verra donc (beaucoup) plus rapidement. Evidemment pour chaque modification faite sur un CV, le cache est invalidé directement. Nous sommes donc passés d’un cache fait maison (un simple stockage sur le disque) à une solution éprouvée. Le gain, en faveur de Varnish, est impressionnant : on utilise le protocole HTTP proprement et l’utilisation est transparente.

La gestion du cache par Varnish demande un peu de prise en main mais le résultat vaut le coup.

Coté navigateur

La partie la plus visible est évidemment le changement de design et la partie javascript qui, elle, est passée d’un jQuery qui manipule le DOM à un vrai framework MVC : Angular.

Finies les infos stockées dans le HTML et nous voilà donc avec un vrai modèle de données coté front.

Thomas a très bien détaillé les changements dans sa conférence donnée au Dev Fest nantais que vous pouvez retrouver en vidéo ci-dessous (ou en slides). Pour résumer : c’est un gros plus pour la partie front pour ce qui est de la maintenabilité et la flexibilité apportée.

Passage de JQuery à AngularJS

La mise en ligne de la V2

En mars 2014 la nouvelle version de DoYouBuzz est lancée. Pendant le développement, nous avions volontairement évité toute migration importante de base données (nous avions ajouté quelques champs et nous nous étions limités à des petites changements : il n’y a par exemple aucune nouvelle table ajoutée).

Nous avons donc repoussé les migrations lourdes pour plus tard, parfois en simulant dans le code un schéma de base de données sain.

La mise en production de la V1 à la V2 a donc pu se faire sereinement, sans down (yep!). Le peu de différences de données entre la V1 et la V2 a même permis une beta de la V2 lancée publiquement pour les utilisateurs qui le désiraient, ce qui nous a permis de détecter un bon nombre de bugs avant le lancement à tous.

Et depuis cette V2 ?

Nous avons depuis continué la migration de l’ancien vers le nouveau code, toujours en profitant de nouvelles fonctionnalités pour nous attaquer à une partie du code.

Exemple : nous avions de gros problème de schéma de base de données pour les compétences… Nous avons profité de l’ajout de la notation des compétences pour résorber notre dette technique et apporter une amélioration pour l’utilisateur. Comme nous avions préparé le terrain depuis des années et exposé un schéma propre sur notre API, nos partenaires techniques n’ont eu aucun souci à se faire.

Aujourd’hui, il nous reste encore du travail pour améliorer le code, résorber encore un peu plus la dette technique (notamment au niveau de la base de données) et pouvoir déployer en continu.

Les résultats quant à eux sont déjà là ! Nous pouvons livrer de nouvelles fonctionnalités beaucoup plus rapidement (vous pouvez vous reporter à notre changelog public), la couverture de code testé augmente doucement et nous rend de plus en plus sereins et surtout nous avons une batterie d’outils pour rendre la vie de développeur bien plus agréable ☺.

Et pour pouvoir être agile et sortir des nouveautés en quelques jours c’est évidemment obligatoire !

Au fait, nous recherchons un stagiaire en dév. web pour un stage longue durée. Pour postuler : jobs@doyoubuzz.com ☺.

Crédits photo header : http://gratisography.com/

--

--

Eric Cambray
DoYouBuzz Open

Webmaster & président @Metalorgie , Directeur Technique @doyoubuzz_fr En gros en hastag : #geek #music #unicellulaire