## Coding Style Le code ne doit pas seulement être "correct" et "performant". Il doit être aussi lisible et compréhensible par un autre être humain. La meilleure façon d'écrire du code lisible est de choisir un style cohérent, et de s'y tenir. La suite est un ensemble de conseils. Vous pouvez suivre le ["K&R style"](http://www.cas.mcmaster.ca/~carette/SE3M04/2004/slides/CCodingStyle.html) (de Brian Kernighan et Dennis Ritchie) qui ont créé le langage C, ou le style [GNU](https://www.gnu.org/prep/standards/standards.html#Writing-C). ### Un exemple ```c /** @brief Reverse the characters of src into dst. * @param src the input string to reverse * @param dst the reversed string * @return the length of src */ size_t strreverse(char* dst, const char* src) { assert(dst && src); // neither parameter should be NULL assert(dst != src); // we can’t reverse a string into itself size_t len = strlen(src); for (size_t pos = 0; pos != len; ++pos) { dst[pos] = src[len - pos - 1]; } dst[len] = 0; return len; } ``` - noms de variables courts et parlants, - utilisation des types du C pour fournir des informations sur les arguments `const char *`, - utlisation des types utilisés par les librairies standards (`strlen` renvoie un `size_t`), - utilisation des fonctions standards, - conforme aux conventions des librairies standards (nom de fonction, ordre des arguments), - une description brève de la fonction, - utilisation d'`assert` pour tester des pre-conditions. La règle d'or est d'être cohérent ! #### Formatage - choisir une indentation et s'y tenir. 4 espaces est un standard, - passer à la ligne pour séparer les sections logiques de votre programme, - éviter les longues lignes. 80 caractères est une limite commune, - soyez consistant avec les accolades et les blocs, - soyez consistant avec les espaces entre opérateurs, - les noms de fonctions doivent être clairs et concis. Le nom doit être suffisant pour comprendre le rôle d'une variable/fonction/strucutre. #### Commentaires Commenter son code est une bonne idée. Mais trop de commentaires en est une mauvaise. - le code doit être lisible, - commenter ce qui n'est pas triviale, - commenter chaque fonction sur ce qu'elle fait, ses paramètres, et ce qu'elle retourne. On peut utiliser le standard de Doxygen. - s'il y a plusieurs fichiers sources, écrire un commentaire au début du fichier pour expliquer son rôle. #### Divers - vérifier les retours d'erreurs, - éviter les variables globales, à moins que ce ne soit indispensable, - utiliser systématiquement un fichier d'entête avec les signatures de vos fonctions, - utiliser `errno.h` (appels systèmes, fonctions standards). exemple avec l'appel système `write` : ``` ERRORS These functions shall fail if: EAGAIN The file is neither a pipe, nor a FIFO, nor a socket, the O_NONBLOCK flag is set for the file descrip‐ tor, and the thread would be delayed in the read operation. EBADF The fildes argument is not a valid file descriptor open for reading. EBADMSG The file is a STREAM file that is set to control-normal mode and the message waiting to be read in‐ cludes a control part. EINTR The read operation was terminated due to the receipt of a signal, and no data was transferred. EINVAL The STREAM or multiplexer referenced by fildes is linked (directly or indirectly) downstream from a multiplexer. EIO The process is a member of a background process group attempting to read from its controlling termi‐ nal, and either the calling thread is blocking SIGTTIN or the process is ignoring SIGTTIN or the process group of the process is orphaned. This error may also be generated for implementation-defined reasons. EISDIR The fildes argument refers to a directory and the implementation does not allow the directory to be read using read() or pread(). The readdir() function should be used instead. EOVERFLOW The file is a regular file, nbyte is greater than 0, the starting position is before the end-of-file, and the starting position is greater than or equal to the offset maximum established in the open file description associated with fildes. The pread() function shall fail if: EINVAL The file is a regular file or block special file, and the offset argument is negative. The file offset shall remain unchanged. ESPIPE The file is incapable of seeking. The read() function shall fail if: EAGAIN The file is a pipe or FIFO, the O_NONBLOCK flag is set for the file descriptor, and the thread would be delayed in the read operation. EAGAIN or EWOULDBLOCK The file is a socket, the O_NONBLOCK flag is set for the file descriptor, and the thread would be de‐ layed in the read operation. ECONNRESET A read was attempted on a socket and the connection was forcibly closed by its peer. ENOTCONN A read was attempted on a socket that is not connected. ETIMEDOUT A read was attempted on a socket and a transmission timeout occurred. These functions may fail if: EIO A physical I/O error has occurred. ENOBUFS Insufficient resources were available in the system to perform the operation. ENOMEM Insufficient memory was available to fulfill the request. ENXIO A request was made of a nonexistent device, or the request was outside the capabilities of the device. ```