# Conseils de codage en C/Facilité de modification

Maintenabilité
* Pour la lisibilité
* Pour la détection des erreurs
* Pour des modifications plus faciles
Fiabilité
* Pour la robustesse
* Pour les performances
* Pour la sécurité
Qualité
* Pour une utilisation plus facile
* Pour la qualité numérique
Maintenabilité
* Pour la lisibilité
* Pour la détection des erreurs
* Pour des modifications plus faciles
Fiabilité
* Pour la robustesse
* Pour les performances
* Pour la sécurité
Qualité
* Pour une utilisation plus facile
* Pour la qualité numérique
Livre
[ Modifier le sommaire ]
Un programme est souvent amené à être modifié, adapté, réutilisé par celui qui l'a écrit ou par un autre, sur une longue durée (correction d'erreur, évolution du logiciel, réutilisation dans une autre application...).
Ces conseils visent à réduire les efforts nécessaires lors d'évolutions.

## Éviter les constantes littérale (c_mod_1)

Les constantes chaîne, numérique doivent être représentées par des symboles. Les constantes littérales sont interdites.

### Justification

Les constantes littérales dupliquées et réparties dans le code source rendent les modifications plus difficiles : risque d'altération, d'oubli d'une occurrence. Il faut les regrouper sous formes de constantes symboliques (définition du pré-processeurs) en tête de fichier source ou dans des fichiers inclus.

### Exemple

* Mauvais : perimetre = 3.14159 * diametre;
* Meilleur : #define PI 3.14159 ... perimetre = PI * diametre;

## Écrire des commentaires fonctionnels (c_mod_2)

Les commentaires ne doivent pas paraphraser le code, ils doivent expliquer la logique de traitement et justifier les choix effectués (pourquoi tel algorithme, telle structure de données, ...).

### Justification

La personne, qui relira le code source en vue de sa maintenance, aura besoin de comprendre les grandes étapes de l'algorithme, les fonctions réalisées par la suite d'instructions du langage.

### Exemple

Mauvais :
Meilleur :

## Pas d'éléments inutiles ou non initialisés (c_mod_3)

Toute fonction définie doit être utilisée et toute variable déclarée doit être initialisée.

### Justification

Évite la présence de code mort qui nuit à la maintenance.
La valeur par défaut d’une variable dépend de facteurs qui peuvent échapper au programmeur. Cette règle évite les fonctionnements aléatoires de certains programmes.

### Outils

Les compilateurs et les outils de vérifications statiques comme splint émettent des avertissements en cas de problème. Certains compilateurs possèdent des options pour générer tous les avertissements sous forme d'erreur, ce qui permet d'interrompre une chaîne de compilation afin de corriger le code.

## Pas de duplication de code source (c_mod_4)

Ne pas dupliquer de grandes parties de code dans plusieurs fichiers source.

### Justification

* La duplication de source oblige à intervenir à plusieurs endroits pour corriger une erreur.
* Rend le code source moins maintenable.
* Lire plusieurs fois le même code ralentit sa compréhension.
Les parties dupliquées doivent être fusionnées en une seule. Le code commun, éventuellement paramétré, deviendra une fonction. Si des contraintes de performance l'impose, l'inlining pourra être utilisé.

### Outils

La recherche des parties dupliquées pourra se faire avec un outil de recherche de chaînes de caractères : sous UNIX grep ou à l'aide d'un éditeur s'il permet la recherche de texte dans plusieurs fichiers.

## Limiter le nombre des variables externes ou globales (c_mod_5)

L'utilisation de variables externes ou globales doit être limité au maximum.

### Justification

Les variables globales peuvent être modifiées par plusieurs unités de compilation, le contrôle des modifications est donc très délicat, les effets de bord sont possibles (modifications non désirées d'une variable ou d'une zone mémoire par du code lié). Un trop grand nombre de variables externes dénote une mauvaise analyse des interfaces entre unités de compilation ou une mauvaise gestion de la portée des variables.
Le mot-clé static en C permet, entre autres, de limiter la portées d'une variable globale ou d'une fonction à son seul fichier source. Il garantit que ces fonctions ou variables ne seront pas utilisées, par erreur, par d’autres unités. Les fonctions locales pourraient être masquées ou masquer d’autres fonctions de même nom, mais définies ailleurs dans le projet ou dans une bibliothèque liée. Le comportement du programme pourrait alors dépendre de l’ordre dans lequel les objets et bibliothèques sont présentés à l’édition de lien. Le respect de cette règle allégera l’édition de lien et évitera certains effets de bord.

### Outils

* Recherche dans les fichiers sources des mots clés extern, des déclarations de variables hors des fonctions.
* L'utilitaire Unix nm et ses options -g et -o permet de connaître les symboles externes dans les résultats de compilation (modules objets .o, bibliothèques .a, .so).

## Ne pas réinventer la roue (c_mod_6)

Utiliser les fonctions et bibliothèques écrites par d'autres programmeurs, principalement dans :
* les bibliothèques standards du langage.
* les bibliothèques de calcul numérique reconnues (LAPACK, LINPACK, BLAS).
* tout autre développement suffisamment fiable.

### Justification

Le respect de ce conseil limite le nombre de lignes de code à maintenir ainsi que les efforts nécessaires aux tests du logiciel.

## Limiter le nombre de sortie (c_mod_7)

Une fonction ne devrait comporter qu'un seul point de sortie.

### Justification

Diminue la complexité du code et facilite l'analyse du déroulement du programme en mise au point.

### Contrôle

Rechercher des instructions return et exit à l'aide d'un utilitaire comme grep.

## Évitez le type union (c_mod_8)

L’utilisation du type union est déconseillé, sauf pour manipuler des champs de bits.

### Justification

Améliore la portabilité.

## Pas de code dans les .h (c_mod_9)

Ne jamais écrire de fonctions ou d'instructions dans les fichiers d’entête .h (excepté les macros instructions).

### Justification

Écrire le corps de fonction dans un fichier .h et l’inclure dans plusieurs sources dupliquerait ce code et pourrait provoquer des erreurs due aux symboles définis plusieurs fois. Plutôt que d’utiliser le pré-processeur, il faut répartir le code source dans différents fichiers .c qui seront compilés séparément et réunit lors de l’édition de lien.

## Seuils pour les métriques déterminant la facilité de modification (c_mod_10)

Les métriques suivantes influent sur la facilité de modification d'un programme (ISO/IEC 9126) :
* AVGS : Taille moyenne des instructions, calculée à partir du nombre d'opérateurs et d'opérandes distincts.
* LEVL : Nombre maximal d'imbrications des structures de contrôle (for, while, if...) de la fonction plus un.
* VOCF : Fréquence d'utilisation du vocabulaire dans un composant, défini par la formule : F_VOC = (N1+N2)/ (n1+n2) avec :
** N1 est le nombre d'occurrence des opérateurs,
** N2 est le nombre d'occurrence des opérandes,
** n1 est le nombre opérateurs distincts,
** n2 est le nombre opérandes distincts.
* CALL : Nombre d’appels distincts : Nombre total d'appels de fonctions effectués dans la fonction analysée.
Seuils pour les métriques :
* AVGS : de 2 à 10
* LEVL : de 1 à 5
* VOCF : de 1 à 4
* CALL : de 0 à 7

### Justification

* AVGS : Les instructions trop longues sont difficiles à modifier. Elles peuvent provoquer des problèmes de priorité des opérateurs, des conversions de type involontaires.
* LEVL : Un trop grand nombre d'imbrication de structures de contrôle pourra être une source d'erreur en cas de modification d'un programme. Il faut déplacer certains niveaux dans une fonction.
* VOCF : Un vocabulaire qui se répète trop pourra être dû à des copiés-collés abusifs de parties de code ou à un programmeur à jeu d'instruction réduit. Les modifications à apporter devront alors s'appliquer à de nombreux endroits. Une solution consiste à factoriser le code à l'aide de fonction paramétrées ou à réutiliser du code externe développé et validé (bibliothèques spécifiques).
* CALL : Une valeur trop élevée montre une mauvaise hiérarchisation dans la fonction. Un nombre élevé de fonctions appelée et de paramètres augmente le nombre de combinaisons possibles dans le déroulement du programme. Il faut limiter le nombre d'appel au besoin en découpant la fonction.