Accueil > code > Mieux coder …

Mieux coder …

Je suis en train de lire Clean Code et j’en suis à un peu plus de la moitié et aujourd’hui j’ai codé mieux que jamais!
J’ai appliqué plusieurs conseils distillés par le livre et je pense que mon code est meilleur : plus lisible, plus concis, mieux architecturé, et la testabilité a été grandement améliorée.
Voici ce que j’ai fait en boucle …

Pour vous situer le contexte, je devais réaliser une « portlet » WebTV. Cette portlet doit rechercher une liste de contenus de type LienVideo dans le CMS et afficher au maximum 4 liens hypertextes pointant vers Kewego (site d’hébergement de vidéos). Le premier lien doit afficher une image en dessous de lui.

Après avoir codé en vitesse une première version, j’étais arrivé à un découpage en 3 classes : TagWebTV, LienVideoTransformer, LienVideoComparator. Le code pouvait largement être amélioré.

Méthodes

Pour chaque méthode, je me suis posé la question : Puis-je extraire une sous partie?
C’est trivial, vous voyez ce que je veux dire.

Commentaires

Pour chaque ligne de commentaire, je me suis posé la question : Puis-je remplacer un commentaire par un appel de méthode bien nommée? Principe d’auto-documentation.
Avant : Un commentaire pour expliquer un bloc d’instructions
if (index == 0) {
  // affichage de l'image si on traite le premier lien video
  sb.append("<br/>");
  sb.append("<div style=\"text-align:center;margin-top:10px\">");
  sb.append("<a href=\"").append(lv.getUrl()).append("\" ");
  sb.append("target=\"blank\">");
  sb.append("<img src=\"").append(lv.getImage()).append("\" />");
  sb.append("</div>");
  sb.append("</a>");
}
Après :  Suppression du commentaire, création d’une méthode qui dit exactement ce qu’elle fait
 if (position == 0) {
  insertImage(lv);
}

Paramètres

Pour chaque méthode, je me suis posé la question : Puis-je remplacer au moins un paramètre par un attribut de classe?
Avant : Je passe mon instance de StringBuilder en paramètre de la méthode addLienVideo
for (int i = 0; i w liensVideos.size() && i < MAX_NUM_LIENS_VIDEO; i++) {
    LienVideo lv = liensVideos.get(i);
    addLienVideo(sb, i, lv);

Après : Disparition du paramètre StringBuilder qui rajouté en attribut de classe. J’en profite pour renommer la méthode en insertLienVideo.

for (int i = 0; i < liensVideos.size() && i < MAX_NUM_LIENS_VIDEO; i++) {
  insertLienVideo(i, liensVideos.get(i));
}

Classes

Pour chaque méthode, je me suis posé la question : Serait-elle mieux dans une autre classe? Principe de délégation de responsabilités.
Avant : Deux traitements dans deux méthodes différentes de la même classe, une pour récupérer une liste de Result, la deuxième pour transformer la liste de Result en liste de  LienVideo triée.
// recuperation de la liste des contenus depuis la requete VAP
List<Result> liensVideos = (List<Result>) this.pageContext.getAttribute(TagsUtil.RESULTS_PARAM);
if (liensVideos == null) {
  liensVideos = (List<Result>) getPortalContext().getResults();
}
String webTVCode = buildWebTV(liensVideos);</div>
...
List<LienVideo> liensVideos = LIEN_VIDEO_TRANSFORMER.getLiensVideos(liensVideosResults, getPortalContext());
Collections.sort(liensVideos, LIEN_VIDEO_PRIORITE_DATE_PUBLICATION_COMPARATOR);
Après : Création d’une classe nommée LienVideoService à qui on délègue la récupération des liens vidéos ainsi que le tri par priorité et date de publication, suppression du commentaire car on a désormais un nom de méthode explicite (findAllSortedByPrioriteAndDatePublication)
List<LienVideo> liensVideos = lienVideoService.findAllSortedByPrioriteAndDatePublication();
String webTVCode = buildWebTV(liensVideos);
...
public List<LienVideo> findAllSortedByPrioriteAndDatePublication() {
   List<Result> liensVideosResults = findAllFromCMS();
   List<LienVideo> liensVideos = LIEN_VIDEO_TRANSFORMER.transform(liensVideosResults);
   Collections.sort(liensVideos, LIEN_VIDEO_PRIORITE_DATE_PUBLICATION_COMPARATOR);
   return liensVideos;
}

private List<Result> findAllFromCMS() {
   List<Result> liensVideosResults = (List<Result>) pageContext.getAttribute(TagsUtil.RESULTS_PARAM);
   if (liensVideosResults == null) {
      liensVideosResults = (List<Result>) portalContext.getResults();
   }
   return liensVideosResults;
}

Ce qui est important

Ce n’est pas la liste d’exemples que j’ai collés mais plutôt la démarche. Se poser les questions, plusieurs fois au cours du refactoring pour aboutir au final à quelque chose de pas trop mal 😉

Publicités
Catégories :code Étiquettes : , ,
  1. Aucun commentaire pour l’instant.
  1. No trackbacks yet.

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

%d blogueurs aiment cette page :