Il y a peu, une annonce était faite comme quoi MySQL travaillait sur un nouveau modèle de release. La trame générale de celui-ci est maintenant fixée et approuvée.

Dans les grandes lignes, on retrouve :

  • Le trunk est toujours laissé dans une qualité de beta
  • Les GA sortiront tous les 12 à 18 mois
  • Pas plus de 2 releases avec un support actif
  • Les milestones commencent lors de beta (jamais lors d’alpha) par un merge entre le trunk et le stage tree.

Pourquoi cet article ? Pas seulement pour relayer l’actualité MySQL, mais aussi pour tenter de sensibiliser un maximum de lecteurs sur l’importance d’un modèle de release adapté. Pour un logiciel prétendant à un minimum d’évolutions et d’activité, il est capital de trouver un compromis entre ce que je nommerai la rétro-utilisabilité et la publication des nouvelles versions. J’entends par « rétro-utilisabilité » le fait d’assurer aux utilisateurs des versions passées un support, un moyen de passer aux versions supérieures efficacement.

Source : Planet MySQL (En)

Ça y’est, vous êtes en train d’écrire vos tests fonctionnels pour votre application Symfony. MAIS votre application – ou une partie – nécessite une identification de la part de l’utilisateur. Il y a bien sûr la solution qui consiste à systématiquement remplir le formulaire dans chaque fichier de test.

Je vous présente ici une solution pour palier à cela. La solution consiste à étendre la classe sfTestFunctional du framework. Ce qui donne, par exemple :

class sfGuardTestFunctional extends sfTestFunctional
{
 public function __construct($browser, $lime = null, $testers = array())
 {
   parent::__construct($browser, $lime, $testers);
   $this->signin(array('username' => 'foo', 'password' => 'bar'));
 }

 /**
  * Perform user authentication
  *
  * @param   array of String         $user_data
  * @return  sfGuardTestFunctional   $this
  */
 public function signin($user_data)
 {
   return $this->info(sprintf('Login as "%s"', $user_data['username']))->
          get('/admin/login')->
          click("S'identifier", array('login' => $user_data))->

          with('form')->begin()->
            hasErrors(false)->
          end()->

          with('user')->begin()->
            isCulture('fr_FR')->
            isAuthenticated(true)->
          end()->

          with('request')->begin()->
            isParameter('module', 'admin')->
            isParameter('action', 'login')->
          end()->

         isRedirected()->
         followRedirect();
 }
}

De cette manière, dans votre fichier de test il vous suffira d’instancier votre browser avec votre nouvelle classe :

$browser = new sfGuardTestFunctional(new sfBrowser('my_vhost'));

Et voilà, vous pouvez vous considérer comme identifié et écrire directement vos tests fonctionnels ! La solution présentée ici est minimale, la mise en forme du code PHP avec Blogspot n’étant pas des meilleure et votre motivation étant sans doute plus grande à déchiffrer 20 lignes de code plutôt que 42.

Une petite mise en oeuvre de ce cette classe, mise en place au sein de Piwam. L’exemple est destiné à la version 1.2 du framework..

Plus que le développement, c’est la conception même du projet qui peut être mise à mal au fil des versions d’un logiciel. Dans bien des cas, l’ajout d’une nouvelle fonctionnalité à un logiciel, aussi anodine soit-elle, peut chambouler très profondément la conception d’une application.
En ce qui concerne les évolutions qui demandent juste un refactoring de la part de l’équipe de développement, on minimise l’impact chez l’utilisateur : il lui suffit de télécharger la nouvelle version, éventuellement de supprimer l’ancienne.

En revanche, tout ce qui a attrait aux données produites par l’utilisateur me semble être un réel problème. Imaginons, par exemple, un système de gestion des droits qui est intégralement reconstruit from scratch.
La version 1 est basée sur un système de groupes prédéfinis (administrateur, modérateur, utilisateur), et la version 2 va être basé sur un système d’ACL (on définit précisément qui a le droit de faire quoi sur quelle partie du produit). L’utilisateur doit alors mettre à jour son logiciel, mais également sa source données (Base de données, fichiers…) !

Premier problème : il y a fort à parier que la manière de stocker ces données (le schéma) ait subit des altérations non néligeables. Il faut ainsi mettre à jour la source de données de l’utilisateur.

Second problème : Je suis également prêt à parier que l’utilisateur s’en verrait frustré s’il perdait toutes ses données. À l’inverse du logiciel lui même qu’il suffit très souvent de remplacer bêtement, la base de données doit évoluer de manière très contrôlée. Cela impose du coup de développer ses propres outils de migration. Que de temps « perdu » ! Sans compter le risque d’introduire des erreurs au niveau de cette évolution.

Quelques solutions : J’ai bien envie de vous laisser sur cette note de poésie :


Mais plus que ça. La moindre évolution doit être pensée et repensée pour éviter de se retrouver face à de nouveaux problèmes ultérieurs. Quitte à fournir une évolution majeure de votre produit qui engendrerait de tels boulversements, essayez de fournir UNE unique nouvelle version intégrant toutes les évolutions possibles, de telle sorte à éviter à l’utilisateur de futures mises à jour trop lourdes. Pour finir – et c’est tout bête – n’oubliez pas d’alerter l’utilisateur quant à ces modifications. Fournissez aussitôt que possible des outils d’import / export des données manipulées par votre application afin de permettre à l’utilisateur, dans le pire des cas (!), de revenir à la version précédente et de récupérer des données opérationnelles.

Cet article était une application directe de ce que j’ai dû subir récemment avec Piwam… La gestion des cotisations a subi un léger changement mais qui imposait une modification de la base de données. Même s’il s’agissait d’une beta, impossible de ne pas fournir d’outils aussi minimes soient-ils pour assurer le bon fonctionnement de la nouvelle mouture.