Bonnes pratiques Rust
Appliquez ces directives lors de l'écriture ou de la révision de code Rust. Basé sur le Rust Best Practices Handbook d'Apollo GraphQL.
Référence des bonnes pratiques
Avant de faire une revue, familiarisez-vous avec les bonnes pratiques Rust d'Apollo. Lisez TOUS les chapitres pertinents en parallèle dans le même tour. Référencez ces fichiers quand vous donnez un retour :
- Chapter 1 - Coding Styles and Idioms: Borrowing vs cloning, Copy trait, Option/Result handling, iterators, comments
- Chapter 2 - Clippy and Linting: Clippy configuration, important lints, workspace lint setup
- Chapter 3 - Performance Mindset: Profiling, avoiding redundant clones, stack vs heap, zero-cost abstractions
- Chapter 4 - Error Handling: Result vs panic, thiserror vs anyhow, error hierarchies
- Chapter 5 - Automated Testing: Test naming, one assertion per test, snapshot testing
- Chapter 6 - Generics and Dispatch: Static vs dynamic dispatch, trait objects
- Chapter 7 - Type State Pattern: Compile-time state safety, when to use it
- Chapter 8 - Comments vs Documentation: When to comment, doc comments, rustdoc
- Chapter 9 - Understanding Pointers: Thread safety, Send/Sync, pointer types
Référence rapide
Borrowing & Ownership
- Préférez
&Tà.clone()sauf si un transfert de propriété est requis - Utilisez
&strplutôt queString,&[T]plutôt queVec<T>dans les paramètres de fonction - Les petits types
Copy(≤24 octets) peuvent être passés par valeur - Utilisez
Cow<'_, T>quand la propriété est ambiguë
Gestion des erreurs
- Retournez
Result<T, E>pour les opérations susceptibles de échouer; évitezpanic!en production - Ne jamais utiliser
unwrap()/expect()en dehors des tests - Utilisez
thiserrorpour les erreurs de bibliothèque,anyhowpour les binaires uniquement - Préférez l'opérateur
?aux chaînes de correspondance pour la propagation d'erreurs
Performance
- Toujours faire un benchmark avec le flag
--release - Exécutez
cargo clippy -- -D clippy::perfpour des conseils de performance - Évitez le clonage dans les boucles; utilisez
.iter()au lieu de.into_iter()pour les types Copy - Préférez les itérateurs aux boucles manuelles; évitez les appels
.collect()intermédiaires
Linting
Exécutez régulièrement : cargo clippy --all-targets --all-features --locked -- -D warnings
Lints clés à surveiller :
redundant_clone- clonage inutilelarge_enum_variant- variantes surdimensionnées (considérez l'encadrement)needless_collect- collection prématurée
Utilisez #[expect(clippy::lint)] plutôt que #[allow(...)] avec un commentaire de justification.
Testing
- Nommez les tests de manière descriptive :
process_should_return_error_when_input_empty() - Une assertion par test si possible
- Utilisez les doc tests (
///) pour les exemples d'API publique - Considérez
cargo instapour les tests de snapshot de sortie générée
Generics & Dispatch
- Préférez les génériques (dispatch statique) pour le code critique en performance
- Utilisez
dyn Traitseulement quand des collections hétérogènes sont nécessaires - Encadrez aux limites de l'API, pas en interne
Type State Pattern
Encodez les états valides dans le système de type pour attraper les opérations invalides à la compilation :
struct Connection<State> { /* ... */ _state: PhantomData<State> }
struct Disconnected;
struct Connected;
impl Connection<Connected> {
fn send(&self, data: &[u8]) { /* only connected can send */ }
}
Documentation
- Les commentaires
//expliquent pourquoi (sécurité, contournements, rationale de conception) - Les commentaires doc
///expliquent quoi et comment pour les APIs publiques - Chaque
TODOa besoin d'un problème lié :// TODO(#42): ... - Activez
#![deny(missing_docs)]pour les bibliothèques