Note: ce que j'écris ici se rapporte surtout à la documentation technique de librairies et applications Open Source et/ou commerciales, et pas de la documentation pour les utilisateurs.
Écrire de la doc, la hantise du programmeur? Ca dépend beaucoup de comment on s'y prend. Je connais bien trop de librairies Open Source qui n'ont pas de documentation, si ce n'est la inline doc avec les descriptions des fonctions et méthodes - et la plupart du temps, ces informations sont absolument inutiles. Le résultat est que même si on utilise un générateur de documentation comme
phpDocumentor, on a une belle documentation cliquable et tout, mais quand on veut savoir comment utiliser telle ou telle fonction, on n'y trouve que des banalités. Or, c'est une bonne documentation qui va garantir la longévité et le succès d'une librairie ou application.
Exemple de documentation inutile:
/**
* Sets the date
*
* @param string The date
*/
function setDate( $date ) {
// le code
}
Qu'est-ce qui ne va pas? Eh bien pas mal de choses, en fait:
- Dans quel contexte peut-on utiliser cette fonction?
- Quels formats de date accepte-t-elle?
- Comment vérifier que ça a marché?
- Quelles sont les autres fonctions connexes?
Disons que cette fonction est une méthode d'une classe qui permet de gérer un calendrier, et qu'on peut l'utiliser pour définir la date présélectionnée dans celui-ci - la description pourrait alors ressembler à ceci:
/**
* Sets the date that will be preselected in the calendar.
* You have to set this prior to rendering the calendar,
* as it will have no effect otherwise.
*
* Note: For best performance, it is recommended to pass this
* method a PEAR_Date object, as all other date formats are
* converted to a date object anyway.
*
* @param string The date to use: can be an ISO date
string, a timestamp or a PEAR_Date
object
* @return bool|object PEAR_Error True on success, a
PEAR_Error object on
failure
* @see getDate()
* @see render()
* @see $date
* @link http://pear.php.net/date
*/
function setDate( $date ) {
// le code
}
Là, il a toutes les informations essentielles (et plus) pour savoir comment utiliser la fonction. Attention, il n'est pas nécessaire non plus d'écrire un roman pour chaque fonction! Personellement j'ai une liste classée par priorité:
- Description détaillée des paramètres et valeurs retournées
- Description de la fonctionnalité
- Souligner les particularités
- lister les fonctions/propriétés connexes
- Ajouter des ressources d'information externes
Très important aussi: vérifier que la description est toujours correcte après des changements.
C'est bien joli de savoir ce qu'il faut respecter, encore faut-il pouvoir allier ça avec sa méthode de travail. D'un côté il y a un fait établi: à peu près personne ne documente une librairie/application quand elle est finie. De l'autre côté il y a ceux qui prêchent qu'il faut écrire la doc pendant la programmation même. Personellement, je suis un fervent adepte du bon sens, et adapte ma 'stratégie de documentation' à la volée.
Je trouve que cela dépend énormément de ce que je suis en train de faire. Si il s'agit juste d'ajouter une fonction/méthode dans un projet existant, je la documente dès que j'ai fini de la programmer. Quand je développe une nouvelle partie d'une application, j'ai souvent la structure dans la tête - si je commence à documenter pendant que je programme, je perds le fil. Dans ce cas, je finis ce que j'ai commencé et le documente une fois fini. Il faut simplement veiller à ce que ce qui reste à documenter ne devienne pas trop volumineux, sinon on se trouve vite des excuses pour ne pas le faire - surtout si il y a des choses intéressantes à programmer
Note: je connais quelques développeurs qui ne documentent jamais rien de ce qu'ils programment sous le prétexte de toujours pouvoir s'y retrouver sans problème. Je suis avant tout quelqu'un de réaliste: si je devais me replonger dans une application datant de trois ans et qui n'est pas documentée, j'aurais bien du mal. Si ce n'est pas leur cas, chapeau - mais je sais aussi reconnaître un bluff quand j'en vois un.
Après cette petit introduction dans le monde de la inline doc, venons-en au vrai sujet de ce billet: la documentation d'un projet passe aussi par la gestion des erreurs. Pour expliquer, je vais commencer par la fin: l'application XY a trois ans, et près d'un million de lignes de code. Soudain, un petit changement sur le serveur fait qu'elle ne fonctionne plus du tout, et il y a des jolis warning partout ainsi qu'un fatal error final. Après 4 heures de recherche acharnée, on réussit à éliminer le problème - pensait-on. Quelques jours plus tard, le client appelle, de son côté rien ne fonctionne... Apparamment, les changements que l'on vient de faire font que le module XY ne marche plus - mais il ne génère aucun message d'erreur. Malheureusement, cette partie de l'application a été rajoutée il y deux ans, et elle n'a pas été documentée. De plus, les développeurs de l'époque ne sont plus là. Aaaaaaaargh!
Ce qui fait peur, c'est que ce scénario peut sembler exagéré - alors qu'on le retrouve un peu partout. J'ai personellement eu plusieurs vieux projets dans ce genre entre les mains, et cela a conforté ma conviction que la seule chose qui peut vraiment aider dans ce cas, c'est de la bonne documentation - et une gestion des erreurs du tonnerre.
Ce que je veux dire par là, c'est que la documentation en elle-même ne suffit pas. Quand une application grandit, et que sa complexité grandit la documentation technique en vient à ses limites, vu que les erreurs n'y sont pas décrites. C'est pourquoi je mets grand soin dans la gestion des erreurs, et plus particulièrement dans les messages d'erreur. À l'aide d'une gestion des erreurs comme
PEAR_Error ou
patError, chaque erreur est on objet qui contient une multitude d'informations sur l'erreur, qui peuvent être utilisées pour déterminer la cause de l'erreur et aider dans la recherche.
Bien sûr, quand on développe une application il y a les serveurs de débogage et des outils comme le
Zend Studio ont un débogeur intégré - mais il faut tout de même chercher l'erreur, et surtout: une fois l'application installée sur le serveur, ces outils ne sont plus disponibles.
J'utilise principalement patError. Ce qui est bien, c'est qu'en plus du message d'erreur destiné à l'utilisateur de l'application, on peut ajouter un message destiné au développeur qui peut contenir des informations supplémentaires. Pratique si on ne veut être sûr que l'utilisateur du site ne puisse pas avoir accès à des informations qui pourraient compromettre la sécurité. Exemple:
function loadFile( $file )
{
if( !file_exists( $file ) ) {
// créer l'objet d'erreur et le retourner
return patErrorManager::raiseError(
ERROR_CODE,
'The file could not be loaded',
'Tried opening the file ['.$file.'] for reading';
);
}
}
// essayer de lire le fichier
$success = loadFile( 'argh.txt' );
// vérifier si ça a marché
if( patErrorManager::isError( $success ) ) {
// afficher l'erreur. Attention, c'est juste un exemple!
// Normalement on définit un gestionnaire pour faire ça.
echo '<b>Argh! Erreur en vue!</b><br/>'
echo $error->getMessage().'<br/>';
echo $error->getInfo().'<br/>';
}
L'avantage de patError, c'est aussi qu'on peut gérer les erreurs comme on veut - pour le débogage de
SimpleSite, j'ai programmé un gestionnaire d'erreurs qui affiche ces informations avec un backtrace complet. Pour la version live d'un site, le gestionnaire d'erreurs écrit un fichier log et envoie un email avec tous les détails nécessaires.
Erreur en mode débogage de SimpleSite:
Depuis le développement de
Syrocco, j'ai pris l'habitude de mettre beaucoup de soin dans les messages d'erreur, et d'en gérer le plus possible. Ainsi, quand une erreur survient, le message d'erreur va non seulement me dire où se trouve l'erreur, mais aussi directement me donner des indications sur les sources probables avec des solutions envisageables. Ces informations-là, on les a quand on programme, alors il est vrai qu'il faut prendre le temps d'écrire tout ça - mais d'après mon expérience, l'effort en vaut vraiment la chandelle.
Finalement, en alliant la inline doc avec une gestion des erreurs bien compréhensible, und projet peut en grande partie s'auto-documenter. Le chaînon manquant à ce moment-là, c'est de la documentation supplémentaire pour expliquer les mécanismes dans les grandes lignes. Alors n'importe-quel développeur digne de ce nom devrait pouvoir entrer sans difficultés dans des applications même complexes.