Пакеты, крейты и модули
Чем больше программа, тем важнее становится организация кода. Если группировать связанную функциональность и разделять код с разными задачами, будет понятно, где искать код, реализующий нужную возможность, и куда идти, чтобы поменять её поведение.
Все программы, которые мы писали до сих пор, умещались в одном модуле в одном файле. Когда проект растёт, код стоит разбивать на несколько модулей, а затем и на несколько файлов. Пакет может содержать несколько бинарных крейтов и, при желании, один библиотечный крейт. По мере роста пакета его части можно выносить в отдельные крейты, которые становятся внешними зависимостями. Обо всех этих приёмах и пойдёт речь в этой главе. Для совсем больших проектов, состоящих из нескольких связанных пакетов, которые развиваются вместе, в Cargo есть рабочие пространства — о них мы поговорим в разделе «Рабочие пространства Cargo» главы 14.
Ещё мы обсудим инкапсуляцию деталей реализации, которая позволяет повторно использовать код на более высоком уровне: реализовав какую-то операцию, вы даёте другому коду вызывать её через публичный интерфейс, и этому коду не нужно знать, как она устроена внутри. То, как вы пишете код, определяет, какие его части публичны и доступны другому коду, а какие — приватные детали реализации, которые вы оставляете за собой право менять. Это ещё один способ уменьшить количество деталей, которые приходится держать в голове.
С этим связано понятие области видимости: у каждого вложенного контекста, в котором написан код, есть набор имён, которые в нём «видны». И программисту, и компилятору нужно понимать, на что указывает конкретное имя в конкретном месте кода — на переменную, функцию, структуру, перечисление, модуль, константу или что-то ещё — и что этот элемент означает. Области видимости можно создавать и решать, какие имена в них будут видны, а какие нет. Двух элементов с одинаковым именем в одной области видимости быть не может, но для разрешения конфликтов имён есть свои инструменты.
В Rust есть ряд возможностей для организации кода: что открыто наружу, что скрыто и какие имена видны в каждой области видимости программы. Вместе их иногда называют системой модулей (module system). В неё входят:
- Пакеты (packages) — возможность Cargo, которая позволяет собирать, тестировать и распространять крейты;
- Крейты (crates) — дерево модулей, из которого получается библиотека или исполняемый файл;
- Модули (modules) и
use— позволяют управлять организацией, областью видимости и приватностью путей; - Пути (paths) — способ назвать элемент, например структуру, функцию или модуль.
В этой главе мы разберём все эти возможности, обсудим, как они взаимодействуют, и объясним, как с их помощью управлять областью видимости. К концу главы у вас сложится твёрдое понимание системы модулей, и вы будете обращаться с областями видимости как профессионал!