Les packages, les crates et les modules
Au fur et à mesure que vous écrivez des programmes de plus en plus grands, l’organisation de votre code deviendra de plus en plus importante. En regroupant les fonctionnalités associées et en séparant le code selon ses différentes responsabilités, vous clarifierez où trouver le code qui implémente une fonctionnalité particulière et où intervenir pour modifier le comportement d’une fonctionnalité.
Les programmes que nous avons écrits jusqu’à présent se trouvaient dans un seul module dans un seul fichier. À mesure qu’un projet grandit, vous devriez organiser le code en le divisant en plusieurs modules puis en plusieurs fichiers. Un package peut contenir plusieurs crates binaires et éventuellement une crate de bibliothèque. Au fur et à mesure qu’un package grandit, vous pouvez en extraire des parties dans des crates séparées qui deviennent des dépendances externes. Ce chapitre couvre toutes ces techniques. Pour les très grands projets comprenant un ensemble de packages interdépendants qui évoluent ensemble, Cargo fournit les espaces de travail (workspaces), que nous aborderons dans [« Les espaces de travail Cargo »][workspaces] au chapitre 14.
Nous aborderons également l’encapsulation des détails d’implémentation, qui vous permet de réutiliser du code à un niveau plus élevé : une fois que vous avez implémenté une opération, d’autre code peut appeler votre code via son interface publique sans avoir à connaître le fonctionnement de l’implémentation. La façon dont vous écrivez le code définit quelles parties sont publiques pour que d’autre code puisse les utiliser et quelles parties sont des détails d’implémentation privés que vous vous réservez le droit de modifier. C’est une autre façon de limiter la quantité de détails que vous devez garder en tête.
Un concept associé est la portée (scope) : le contexte imbriqué dans lequel le code est écrit possède un ensemble de noms définis comme étant « dans la portée ». Lors de la lecture, de l’écriture et de la compilation du code, les développeurs et les compilateurs doivent savoir si un nom particulier à un endroit particulier fait référence à une variable, une fonction, une struct, une enum, un module, une constante ou un autre élément, et ce que cet élément signifie. Vous pouvez créer des portées et modifier quels noms sont dans ou hors de la portée. Vous ne pouvez pas avoir deux éléments portant le même nom dans la même portée ; des outils sont disponibles pour résoudre les conflits de noms.
Rust dispose d’un certain nombre de fonctionnalités qui vous permettent de gérer l’organisation de votre code, notamment quels détails sont exposés, quels détails sont privés et quels noms se trouvent dans chaque portée de vos programmes. Ces fonctionnalités, parfois collectivement appelées le système de modules, comprennent :
- Les packages : une fonctionnalité de Cargo qui vous permet de compiler, tester et partager des crates
- Les crates : un arbre de modules qui produit une bibliothèque ou un exécutable
- Les modules et
use: vous permettent de contrôler l’organisation, la portée et la confidentialité des chemins - Les chemins (paths) : une façon de nommer un élément, comme une struct, une fonction ou un module
Dans ce chapitre, nous aborderons toutes ces fonctionnalités, discuterons de la façon dont elles interagissent et expliquerons comment les utiliser pour gérer la portée. À la fin, vous devriez avoir une compréhension solide du système de modules et être capable de travailler avec les portées comme un pro !