CocoaPods qui permet de les externaliser dans un projet dépendant.
Tout comme l'organisation des sources, la présentation du code permet d'influer sur sa clarté et sa compréhension. Une répartition par blocs logiques espacés permet une compréhension d'ensemble avant même d'avoir lu une ligne de code ! Un exemple simple permet de le montrer :
Dans le premier cas, notre cerveau reconnait immédiatement un poème, sait facilement extraire le contenu de chaque strophe. Il ne reste qu'à lire pour en comprendre le sens. Dans le deuxième cas, seuls les connaisseurs sauront identifier les Correspondances de Baudelaire. Ils devront d'ailleurs sans doute le relire plusieurs fois avant d'en comprendre le sens.
Cet effort de segmentation/présentation doit se retrouver dans :
Notons que pour réaliser la décoration des pragmas, ainsi que pour toute action répétitive effectuée, nous utilisons des snippets Xcode.
Dans beaucoup de projets, le passage de nombreux développeurs est visible. En effet, ces derniers n'ont pas les mêmes pratiques : alignement, style d'accolades, espacements... Autant de facteurs qui freinent la bonne compréhension du code par d'autres développeurs.
Bonne nouvelle pour le formatage : il existe maintenant des solutions pour partager un même format dans une équipe et l'appliquer avec Xcode avec un simple raccourci clavier ! Nous avons par exemple développé Xcode Formatter qui se base sur l'outil uncrustify pour avoir un style de code cohérent.
Les raccourcis claviers ⌘-Maj-F et ⌘-Maj-O sont très pratiques pour retrouver du code ou ouvrir une ressource dans son projet. Néanmoins, ils ne doivent pas être le seul moyen d'accéder à l'information !
Comme présenté précédemment, nous utilisons des groupes sur Xcode pour séparer les types de classes et les ressources. Lier chacun de ces groupes à un répertoire du même nom sur le système de fichiers permet de simplifier l'accès et la maintenance de ces données, notamment les images qui évoluent souvent.
Dans ces répertoires, il est important de garder une cohérence dans les fichiers. Une erreur que nous rencontrons souvent est de séparer les xib des classes controllers ou views auxquelles elles sont rattachées. Placer les fichiers xib à côté de leur classe référente et utiliser le même nom pour ces fichiers simplifie grandement leur recherche et édition.
Ou mettre les méthodes privées, les attributs privés, faut-il utiliser des ivars ? Nous proposons une pratique répandue pour laisser dans le .h uniquement les éléments publiques : définir les attributs et méthodes privés dans le .m. Ainsi :
Avec les différentes pratiques présentées précédemment, il est simple de comprendre l'organisation du projet, d'une source, savoir où se trouvent les éléments.
La complexité à appréhender un code n'est pas (souvent) reliée à la complexité de l'algorithme utilisé, mais bien à l'effort nécessaire pour en extraire la logique. Dans cette optique, tout code pouvant générer de l'incompréhension pour un nouveau développeur doit être supprimé ou refactoré.
Par code mort, nous entendons les implémentations par défaut non utilisées et les lignes de commentaires inutiles. Ces quelques lignes dont "on pourrait avoir besoin plus tard" pourront toujours être retrouvées via le gestionnaire de sources ou peuvent être transformées en FIXME ou TODO.
Si l'ordre des sections d'une tableView est clair au moment de son développement, il le sera beaucoup moins lors d'une correction d'anomalie un mois plus tard ou pour un autre développeur. Il en est de même pour toutes les valeurs codées en dur et répétées dans une application qui doivent être présentées avec des constantes.
Nous avons souvent noté une mauvaise utilisation des logs à des fins de debug, qui restent dans le code ensuite et sont visibles en production. Il s'agit de code mort qui doit être supprimé ! Il convient d'ailleurs de définir dans le fichier .pch de l'application une méthode de log qui ne sera utilisée qu'en mode DEBUG :
#ifdef DEBUG #define DLog(...) NSLog(__VA_ARGS__) #else #define DLog(...) /* */ #endif
Cette méthode ne doit être utilisée que temporairement ou pour fournir des logs d'information utiles au développeur qui parcoure l'application. Pour le debug, on préfèrera utiliser des breakpoints dynamiques ou entrer directement des commandes de debug dans la console.
Enfin, et c'est l'un des points les plus importants pour la qualité, le nombre de warnings et d'erreurs d'analyse statique doit être à 0 ! Garder des warnings non corrigés empêche de voir les erreurs ajoutées lors de modifications et pousse l'équipe à ne pas s'en soucier alors que c'est un point très important. Les warnings remontés sont définis dans l'onglet "Build Settings" de l'application. Certains valent d'ailleurs la peine d'être activés en plus de ceux initialement utilisés par Xcode (par exemple "Hidden Local Variables"). Ce site peut aider à choisir les différents flags à activer.
Si la première priorité d'un développeur mobile est de livrer une application de qualité, la seconde est de produire un code fonctionnel compréhensible par n'importe quel autre développeur !
Les noms de variables se doivent d'être cohérents et autoportants ! Pour cela, voici quelques règles qu'il est judicieux de respecter :
De la même manière, les noms de méthodes doivent a minima posséder un verbe et un complément.
Le plus important n'est pas de reproduire les exemples donnés ici, mais bien d'être cohérent dans son application.
Le premier niveau de documentation, c'est le code lui-même ! Nous avons déjà parlé de nomenclature. Dans un second temps, il est possible de séparer les longues instructions monolignes en plusieurs lignes courtes utilisant des variables intermédiaires.
De la même manière, les fichiers xib peuvent rapidement devenir délicats à maintenir si aucun effort n'est réalisé pour nommer les vues. On prendra donc systématiquement la bonne habitude de créer des xib autodocumentés.
La documentation n'a pas été inventée pour excuser les mauvaises pratiques de nomenclature ! Elle est nécessaire pour clarifier des comportements complexes et doit apporter de la valeur au lecteur. Il est conseillé de choisir un formalisme (les plus répandus sont Doxygen et Appledoc) et de s'y tenir.
Nous préconisons de documenter :
Si après refactor un code est toujours mal compris par un autre développeur, il doit être documenté.
Il est souvent tentant de prévoir des optimisations pour la mémoire, les performances d'affichage. Or ces optimisations sont souvent minimes mais complexifient grandement la compréhension du code. Nous conseillons de toujours développer la solution la plus simple, puis analyser ensuite les performances avant d'optimiser.
La meilleure optimisation du code réside dans sa mutualisation : éviter la duplication, la lecture et le maintien de fonctionnalités déjà écrites. Pour ce faire on utilisera à bon escient :
Il faut garder à l'esprit que c'est le code le plus simple à relire et à comprendre qui doit prévaloir. Ainsi, il faut éviter le code générique tant qu'il n'est pas nécessaire.
En appliquant les outils présentés précédemment, nos équipes projets se sont grandement améliorées. Le résultat en vaut la chandelle : une fois une culture de la qualité mise en place, les fonctionnalités sont développées, testées et - en cas d'erreur - corrigées bien plus rapidement. C'est un cercle vertueux que nous souhaitons voir sur chaque projet.
Néanmoins, ces pratiques nécessitent un effort pour être appliquées. Cet effort doit être continu et porté par tous les membres du projet. C'est la Boy Scout Rule : "Toujours laisser l'endroit dans un état meilleur que celui où vous l’avez trouvé". Le premier pas à franchir est de choisir de les suivre et de les afficher dans l'espace de travail :
Notre fiche récapitulative de bonnes pratiques ios
Dans un prochain article, nous aborderons comment mettre en place ces pratiques en accompagnant une équipe de développement : industrialisation, méthodes, rituels, etc. Mais également comment justifier et pousser cette culture de la qualité jusque dans les équipes métier et marketing.