Introduction : pourquoi le code review en Rust n'est pas qu'une simple formalité
\n\nLe code review est l'un des processus clés dans le développement de tout logiciel de qualité. Mais lorsqu'il s'agit de Rust, ce processus prend une importance particulière. Rust est un langage avec un système unique de propriété (ownership) et d'emprunt (borrowing), que le compilateur vérifie lors de la compilation. Cependant, même si le code se compile, cela ne signifie pas qu'il est bien écrit, sûr et efficace.
\n\nDans cet article, nous allons voir sur quoi se concentrer lors du code review de projets Rust, comment donner un retour constructif sans froisser un collègue, et comment éviter les erreurs typiques que le compilateur ne détecte pas. L'article est destiné aux développeurs qui connaissent déjà les bases de Rust mais souhaitent approfondir leurs compétences en révision.
\n\n1. Sécurité mémoire et gestion des ressources
\n\nRust garantit la sécurité mémoire sans ramasse-miettes. Mais cela ne dispense pas de vérifier comment le développeur utilise les blocs unsafe, les pointeurs bruts et les appels FFI externes.
Que vérifier :
\n- \n
- Utilisation de
unsafe: chaque blocunsafedoit être justifié et accompagné d'un commentaire expliquant pourquoi il est sûr. Si on peut s'en passer, c'est mieux. \n - Fuites de ressources : vérifiez que tous les
Box,Rc,Arcet autres pointeurs intelligents sont correctement libérés. Par exemple, les références cycliques viaRcsansWeaksont un problème fréquent. \n - Ordre de destruction (Drop) : si une structure contient des champs avec une implémentation personnalisée de
Drop, assurez-vous que l'ordre de destruction n'entraîne pas d'erreurs. \n
// Exemple de mauvais code : unsafe sans commentaires\nunsafe {\n let ptr = ...;\n // Aucune explication pourquoi c'est sûr\n *ptr = 42;\n}\n\n// Bon code : commentaire et alternative sûre\n// On utilise unsafe uniquement pour appeler une fonction C qui garantit la validité du pointeur\nunsafe {\n // Le pointeur provient de l'API C, qui garantit sa validité pendant la durée de l'appel\n some_c_function(ptr);\n}\n\n\n2. Idiomaticité du code et style
\n\nRust a ses propres idiomes, qui diffèrent de ceux du C++ ou de Python. Le code review doit vérifier à quel point le code correspond à l'esprit du langage.
\n\nQue vérifier :
\n- \n
- Utilisation de
OptionetResult: évitezunwrap()etexpect()sans raison explicite. Dans le code de production, utilisez la gestion des erreurs viamatch, l'opérateur?ouunwrap_or_else. \n - Pattern matching : préférez
if letetmatchplutôt que des chaînes deis_some()/is_ok(). \n - Utilisation des traits : vérifiez que les traits sont implémentés de manière pertinente. Par exemple, l'implémentation de
Displaydoit produire une sortie lisible, pas simplementDebug. \n - Nommage : en Rust, on utilise
snake_casepour les variables et fonctions,CamelCasepour les types et traits. Les constantes sont enSCREAMING_SNAKE_CASE. \n
// Mauvais : utilisation excessive de unwrap\nlet value = some_option.unwrap();\n\n// Bon : gestion des erreurs\nlet value = match some_option {\n Some(v) => v,\n None => return Err("Valeur non trouvée".into()),\n};\n\n// Encore mieux : avec l'opérateur ?\nlet value = some_option.ok_or("Valeur non trouvée")?;\n\n\n3. Performance et allocations
\n\nRust offre un contrôle de bas niveau sur la mémoire, mais cela ne signifie pas que le code est automatiquement rapide. Lors de la révision, il est important de vérifier les goulots d'étranglement potentiels.
\n\nQue vérifier :
\n- \n
- Allocations inutiles : vérifiez si des
StringouVec