mardi 6 novembre 2007

Changement de fourrage, tout ça

Comme on dit dans le jargon, je suis officiellement à l'écoute du marché. Le traditionnel CV est par là, ou encore ici.

Je me débrouille en PHP et avec le framework Symfony, j'aime bien concevoir de chouettes applis qui fonctionnent et qui sont maintenables, j'aime beaucoup les petites équipes agiles, j'adore appliquer les bonnes pratiques de conception et respecter les standards du web. Je place au centre de tout le respect du client et les processus de conception collaborative.

Si vous êtes intéressé,vous pouvez me joindre en passant par la case contact :)

Edit : J'ai une extinction de voix carabinée, merci d'éviter le téléphone ou la visioconférence le temps que je me remette d'ici quelques jours ;)

jeudi 1 novembre 2007

Utiliser Symfony pour vos projets

Suite à l'émergence des frameworks web, beaucoup d'équipes de développement ont décidé de leur utilisation sans toujours bien réaliser les tenants et aboutissants liés la démarche, croyant souvent avoir enfin trouvé une méthode miracle pour produire vite et bien. Il peut en résulter de sévères déconvenues, quel que soit le framework, le langage ou la plateforme retenus.

Concernant Symfony, il en va de même ; et si on peut bien entendu trouver énormément d'avantages à son utilisation sur un projet, il faut également bien avoir conscience des contraintes qu'un développement sur sa base implique, sous peine de se retrouver dans le mur assez rapidement.

Symfony n'est pas un CMS

Il est immédiatement tentant de retenir Symfony pour tout type de projet tellement il est agréable de développer sur sa base. Cependant, pourquoi systématiquement réinventer une roue qui tourne peut-être déjà fort bien ailleurs ? L'idée ici est de s'interroger sur la réelle nécessité de recourir à un développement spécifique ; en effet, même si coder en Symfony est très encadré, il n'empêche que la logique métier est entièrement à définir par l'équipe de développement [1]. Plus particulièrement concernant les problématique de gestion de contenus, le besoin métier sur le projet est-il suffisamment conséquent, ou un CMS comme Drupal, SPIP, ezPublish ou Joomla couvre t-il nativement l'ensemble du périmètre fonctionnel cible ? [2]

Un développement spécifique introduira le plus souvent beaucoup plus d'exigences, de compétences et de compléxité qu'une intégration basée sur un outil de gestion de contenus autonome existant (et digne de ce nom). L'idée est bel et bien de renoncer à se faire plaisir à tout prix pour se situer au plus près de la réalité du besoin.

Bien entendu, je me fais aussi ici l'avocat du diable. Pour avoir joué avec les principaux CMS PHP open source du marché et connaissant la propension naturelle d'un client à enrichir au gré de l'avancement projet le périmètre fonctionnel souhaité [3], je préfère allègrement à titre personnel me baser sur un framework comme Symfony afin de rester agile et parer à toute éventualité. Mais je sais aussi quelles sont mes compétences réelles sur le sujet, et dès qu'une équipe dont je ne cerne pas le niveau entre en ligne de compte, généralement les problèmes commencent. Ça tombe bien, c'est justement l'objet du prochain chapitre ;)

Symfony est exigeant

Non, Symfony ne transformera pas magiquement un mauvais développeur en bon développeur... même s'il peut y contribuer à terme ;)

Plus sérieusement, le but réel de l'utilisation d'un framework est bel est bien de vous rendre plus efficace et productif, certainement pas de vous compliquer la vie ou de vous faire perdre du temps.

Il faut bien prendre conscience que le temps de montée en compétence sur l'utilisation du framework - déjà naturellement exigeante - requière également pour certains une montée en compétence en programmation tout court. Et cette dernière, si elle peut se faire sur un projet, peut également allègrement le plomber. Un développeur débutant bidouilleur PHP mettra fatalement plus de temps qu'un codeur expérimenté à appréhender l'ensemble des possibilités introduites par PHP5, la programmation orientée objet, les motifs de conception, mais aussi le respect des bonnes pratiques notamment liées au travail collaboratif ou que sais-je encore.

Le risque à court terme est de voir le code du projet grevé dans sa qualité et sa maintenabilité. À moins bien entendu de prendre en compte en amont cette charge inhérente à la formation, mais on connait tous la réalité professionnelle et commerciale du milieu qui est le notre ;)

Symfony ne vous dispense pas d'organiser votre projet

Oui, Symfony fait la part belle aux conventions et prémâche énormément le travail redondant à tout projet de type web. La vie des (bons) développeurs est grandement facilitée, et on peut vraiment gagner rapidement beaucoup de temps. Mais une grave erreur serait de sous-estimer la charge liée à l'organisation et la gestion de la vie du projet.

Par exemple, ce n'est pas en mettant plus de développeurs sur un projet Symfony (ou autre d'ailleurs) que celui-ci sera développé plus vite. Au contraire, même ; tout codeur avec un tant soit peu d'expérience professionnelle a déjà rencontré ce type de cas de figure : on vend un projet de 100 jours de développement, on se fixe un retroplanning ambitieux avec une mise en ligne à 20 jours ouvrés, et on staffe donc arithmétiquement cinq développeurs à plein temps en pensant que le résultat sera totalement équivalent au travail qu'aurait fourni un unique développeur en 100 jours de développement pour concevoir l'intégralité du code de l'application résultante.

Bien entendu, c'est illusoire et généralement, le projet se termine sur des dépassements conséquents et le mécontentement du client [4]. Et pour cause, la déperdition d'énergie utilisée à la communication sur le projet est fonction du nombre d'acteurs présents sur ce dernier. Et on peut staffer trois chefs de projet à plein temps pour canaliser tout ça, c'est d'une part économiquement peu viable et d'autre part totalement inefficace, ces derniers devant perdre également beaucoup de temps à se synchroniser entre eux, puis avec les membres de l'équipe.

Moralité

Non, Symfony n'est pas le remède miracle aux lacunes organisationnelles des structures en charge de la réalisation d'un projet, mais bien un outil exigeant qu'il faut savoir appréhender de la bonne façon en prenant en compte le plus en amont possible ces problématiques. Le gain réel et indiscutable d'efficacité apporté par l'utilisation d'un framework comme Symfony est à ce prix ;)

Notes

[1] Je n'ose pas évoquer ici la notion d'architecte logiciel connaissant la réalité moyenne du monde PHP.

[2] Pour nuancer ce propos, de plus en plus de plugins Symfony tendent à apparaitre pour couvrir ce type de besoins fonctionnels.

[3] Le premier qui me parle du sacrosaint cahier des charges contractuel, je le mords.

[4] Sans parler de la charge de stress portée sur l'équipe, qui du coup va saloper le boulot pour livrer au plus vite.

mercredi 31 octobre 2007

Forum PHP 2007

Juste un petit mot pour vous informer que le Forum PHP 2007 se tiendra les 21 et 22 novembre prochains à Paris dans le 7ème arrondissement.

Au programme, quelques invités prestigieux comme Rasmus Lerdorf et Andrei Zmievski mais aussi un programme de conférences alléchant :

  • Clients riches avec PHP : L'exemple de Flex
  • Optimistations, méthodes, sécurité : retours d'expérience dans les grands comptes
  • Les nouveautés de PHP6
  • Comment Facebook tient la charge avec APC
  • Sécurité : MySQL et PHP sous surveillance

Côté Symfony, Fabien Potencier animera une session sur la simplification du développement des interfaces aux bases de données.

Bref, un événement d'importance dans le petit monde de PHP, venez nombreux :)

mercredi 3 octobre 2007

Dégradabilité javascript et Ajax dans Symfony avec jQuery

Pour un projet, je suis en train d'utiliser la librairie javascript jQuery dans Symfony, en lieu et place du couple prototype et scripaculous dont je vous avait déjà parlé.

L'idée est ici de ne pas avoir à utiliser les helpers fournis par Symfony (qui mettent en oeuvre exclusivement Scriptaculous) et ainsi d'éviter d'utiliser les deux librairies simultanément sur le projet, mais aussi de décoreller le code javascript des templates et de favoriser une meilleure dégradabilité de ce dernier.

Par exemple, au lieu d'utiliser la fonction link_to_remote() dans notre template, on peut tout à fait imaginer d'employer un bon vieux link_to() des familles et de lui appliquer une classe css qu'on va pouvoir cibler depuis jQuery afin d'effectuer un appel AJAX pointant vers l'url présente dans l'attribut href du lien. Avec un exemple, c'est un peu plus clair :

<?php echo link_to('Mon lien', '@maroute?monparam=mavaleur', array('class' => 'ajax_link')) ?>

Dans un fichier javascript (jQuery doit bien entendu être chargé) :

$(document).ready(function() {
  $('a.ajax_link').click(function()
    {
      $.ajax(
        {
          type: 'post',
          url: $(this).attr('href'),
          success: function(msg)
          {
            alert("Résultat: " + msg);
          }
        });
      return false;
    }
  );
});

Avantage supplémentaire, vous continuez à bénéficier du système de routing Symfony (pas d'urls en dur dans les fichiers javascripts externalisés.)

Là où Symfony va également nous aider, c'est au travers de sa gestion native de la décoration d'une vue en fonction du type d'appel HTTP : le framework va detecter si l'action a été appelée ou non depuis une requête XmlHttpRequest et, si c'est le cas, décorer la vue avec le layout global de l'application et donc présenter à vos utilisateur le résultat escompté, qu'ils aient activé javascript ou non pour surfer sur votre site.

Si vous désirez mettre à jour un élément de l'arbre DOM avec le contenu reçu d'une requête Ajax, voici une autre petite astuce ; on va utiliser une ancre dans l'url et s'en servir comme argument décrivant l'id DOM qu'on veut mettre à jour :

<?php echo link_to('Mon lien', '@maroute?monparam=mavaleur#mon_div', array('class' => 'ajax_link')) ?>
<div id="mon_div" style="display:none"></div>

Et en javascript :

$(document).ready(function() {
  $('a.ajax_link').click(function()
    {
      var href = $(this).attr('href');
      var target = href.substring(href.lastIndexOf('#'), href.length);
      $.ajax(
        {
          type: 'post',
          url: href,
          success: function(msg)
          {
            if ($(target))
            {
              $(target).html(msg).show('slow');
            }
          }
        }
      );
      return false;
    }
  );
});

Note : on aurait pu aussi détourner l'attribut target à cette fin mais ce dernier n'est pas valide en XHTML strict.

Bien entendu, ceci n'est qu'un microscopique aperçu de l'étendu des possibilités de jQuery et de son intégration possible avec Symfony (ou d'autre frameworks et langages, bien entendu.)

mardi 2 octobre 2007

Délicieuse Symphonie

Alors ça c'est du lourd : Symfony propulse del.icio.us preview.

Il parait que Symfony rame, sauf chez Yahoo!. Poltergheist ? ;)

mercredi 5 septembre 2007

Release Time (part one)

QOTD :

À trop procrastiner, on s'y casse le nez.

Bon, je suis en train de sortir des cartons tout ce que je n'ai pas encore releasé. Voici une première fournée, sous la forme de deux plugins pour le framework Symfony :

Ces plugins sont releasés sous licence MIT. Enjoy.

Bon, c'est pas fini, d'autres choses vont suivre très prochainement.

mardi 22 mai 2007

Tags faciles avec Propel dans Symfony

Mon camarade de Nespresso Xavier Lacot nous gratifie d'un plugin pour Symfony répondant au doux nom de sfPropelActAsTaggableBehaviorPlugin et permettant de taguer n'importe quel objet Propel très facilement, mais aussi de gérer les requêtes multi-tags et la récupération d'objets de types multiples.

Ce plugin sera notamment utilisé dans un projet qui touchera prochainement de très près ce blog, si les conditions normales de températures et de pression le permettent, comme d'hab.

Du très bon boulot, Xavier !

dimanche 29 avril 2007

Symfony, Admin-Generator et Composants

Dans un précédent billet, nous avons vu comment créer un weblog basique avec l'admin-generator de Symfony. Nous allons reprendre là où nous en étions et ajouter la liste des commentaires à notre back-office de gestion des billets grâce à un simple appel de composant, qui n'est autre qu'un template partiel associé à un contrôleur dédié.

Création du module de gestion des commentaires en back-office

Si ce n'est déjà fait, on crée notre module de gestion des commentaires

# symfony propel-init-admin back comments Comment

Création du composant qui va lister les commentaires d'un billet

Bien. On va maintenant créer un composant postcomments qui affichera la liste des commentaires associés à un objet Post, en créant un nouveau fichier apps/back/modules/posts/actions/components.class.php et en y insérent le contenu ci-dessous :

<?php
class postsComponents extends sfComponents 
{
  
  /**
   * List comments for a given Post
   * 
   */
  public function executePostcomments()
  {
    $post_id = $this->getRequestParameter('id');
    if (!is_null($post_id))
    {
      $c = new Criteria();
      $c->add(CommentPeer::POST_ID, $post_id);
      $c->addDescendingOrderByColumn(CommentPeer::CREATED_AT);
      $this->comments = CommentPeer::doSelect($c);
    }
  }
  
}

On crée maintenant le template partiel associé au contrôleur, dans le fichier apps/back/modules/posts/templates/_postcomments.php :

<?php if (isset($comments)): ?>
  <?php if (count($comments) > 0): ?>
    <?php use_helper('Comment', 'Text') ?>
    <dl>
    <?php foreach ($comments as $comment): ?>
      <dt>
        <?php echo sprintf('Posté le <strong>%s</strong> par <strong>%s</strong> :', 
                           format_date($comment->getCreatedAt(), 'd/MM/yyyy à H:m'),
                           format_comment_author($comment->getAuthor(),
                                                 $comment->getSite())) ?>
      </dt>
      <dd>
        <?php echo simple_format_text($comment->getContent()) ?>
      </dd>
      <dd>
        [<?php echo link_to('Éditer', 'comments/edit?id='.$comment->getId()) ?>]
        [<?php echo link_to('Supprimer', 
                            'comments/delete?id='.$comment->getId(),
                            'confirm=Êtes-vous sûr ?') ?>]
      </dd>
    <?php endforeach; ?>
    </dl>
  <?php else: ?>
    <p>No comment yet.</p>
  <?php endif; ?>
<?php endif; ?>

Utilisation d'un helper pour des tâches courantes de templating

La fonction format_comment_author est un helper maison, que nous définissons dans un nouveau fichier lib/helper/CommentHelper.php :

<?php
/**
 * Returns a formatted html string for author including website link if any
 * 
 * @param  string   $name
 * @param  string   $site
 * @param  boolean  $nofollow
 * @return string 
 */
function format_comment_author($name, $site=null, $nofollow=true)
{
  if (!is_null($site) && preg_match('/^http/i', $site))
  {
    return sprintf('<a href="%s"%s>%s</a>', 
                   $site, 
                   $nofollow === true ? ' rel="nofollow"' : '',
                   $name);
  }
  else
  {
    return $name;
  }
}

Mise à jour du back-office de gestion des billets

Ceci fait, modifions le fichier de configuration du back-office d'administration des billets créé précemment et situé dans le fichier apps/back/modules/posts/config/generator.yml, afin d'appeller notre nouveau composant postcomments pour la vue d'édition d'un billet :

  [...]

    # Customisation du formulaire d'ajout/édition
    edit:
      
      [...]

      # Affichage d'une sélection de champs
      display:         [author_id, title, excerpt, body, post_sections, ~postcomments]

Vous noterez le caractère ~ précedant le nom du composant : encore une convention Symfony qui nous simplifie la vie :)

Gestion de l'échappement

Vous avez tous déjà entendu parler des failles XSS ? Pour nous en prémunir partiellement, nous allons activer l'échappement automatique des contenus passés à une vue, en ajoutant ces directives dans le fichier apps/back/config/settings.yml :

all:
  .settings:
    escaping_strategy: both
    escaping_method:   ESC_ENTITIES

Ainsi, dans notre cas toutes les chaînes seront échappées en entités HTML pour plus de sécurité. Pour plus d'information, rendez-vous dans la section dédiée de la documentation officielle.

Au final, voici ce que ça donne quand on édite un billet :

Affichage des commentaires d'un billet

Champs virtuels

Notre liste de billets, pour l'instant, ne nous informe pas pour chacun le nombre de commentaires associés. On va y remédier simplement en créant un getter ad-hoc dans notre objet de donnée Post et en appellant le champs virtuel associé. Dans le fichier lib/model/Post.php, on rajoute la méthode suivante :

public function getCommentsNumber()
  {
    return $this->countComments();
  }

Et dans le fichier apps/back/modules/posts/config/generator.yml, on affiche le champs virtuel comments_number dans la vue en liste :

  [...]

    # Customisation des colones de la vue en liste
    list:
      display:         [=title, excerpt, Author, comments_number, created_at, updated_at]

Voici ce que ça donne :

Liste des billets, avec nombre de commentaires associés

En conclusion

Voila, notre application prend forme doucement. On pourrait passez des heures à ajouter des détails par-ci par-là, mais je vous laisse le faire en compagnie de la documentation :)

- page 3 de 5 -