Определение модулей для контроля видимости и конфиденциальности

В этом разделе мы поговорим о модулях и других частях системы модулей, а именно пути(paths), которые позволяют именовать элементы; ключевое слово use, которое приносит путь в область видимости; и ключевое слово pub, чтобы делать элементы общедоступными. Мы также обсудим ключевое слово as, внешние пакеты и оператор glob. А пока давайте сосредоточимся на модулях!

Модули позволяют организовывать код внутри крейта по группам для удобства чтения и простого повторного использования. Модули также контролируют конфиденциальность (privacy) элементов, то есть элемент может использоваться внешним кодом (public) или является деталями внутренней реализации и недоступен для внешнего использования (private).

В качестве примера, давайте напишем библиотечный крейт предоставляющий функциональность ресторана. Мы определим сигнатуры функций, но оставим их тела пустыми, чтобы сосредоточиться на организации кода, вместо реализации кода для ресторана.

В ресторанной индустрии некоторые части ресторана называются фронтом дома, а другие задней частью дома. Фронт дома это там где находятся клиенты; здесь размещаются места клиентов, официанты принимают заказы и оплаты, а бармены делают напитки. Задняя часть дома это где шеф-повара и повара работают на кухне, моют посудомоечные машины, а менеджеры занимаются административной работой.

Чтобы структурировать крейт аналогично тому, как работает настоящий ресторан, можно организовать функции во вложенные модули. Создадим новую библиотеку с именем restaurant выполнив команду cargo new --lib restaurant; затем вставим код из листинга 7-1 в файл src/lib.rs для определения некоторых модулей и сигнатур функций.

Файл: src/lib.rs

mod front_of_house {
    mod hosting {
        fn add_to_waitlist() {}

        fn seat_at_table() {}
    }

    mod serving {
        fn take_order() {}

        fn serve_order() {}

        fn take_payment() {}
    }
}

fn main() {}

Листинг 7-1. Модуль front_of_house содержащий другие модули, которые затем содержат функции

Мы определяем модуль, начиная с ключевого слова mod, затем определяем название модуля (в данном случае front_of_house) и размещаем фигурные скобки вокруг тела модуля. Внутри модулей, можно иметь другие модули, как в случае с модулями hosting и serving. Модули также могут содержать определения для других элементов, таких как структуры, перечисления, константы, типажи или - как в листинге 7-1 - функции.

Используя модули, можно сгруппировать связанные определения вместе и названия. Программистам, использующим такой код, будет легче найти определения, которые они хотели использовать, потому что они могли бы ориентироваться в сгруппированном коде, вместо того, чтобы прочитать все определения. Программисты, добавляющие новые функции в этот код, будут знать, где разместить код для поддержания порядка в программе.

Как мы упоминали ранее, файлы src/main.rs и src/lib.rs называются корнями крейтов. Причина такого названия в том, что содержимое любого из этих двух файлов формируют модуль с именем crate в корне структуры модуля крейта, известное как дерево модулей.

В листинге 7-2 показано дерево модулей для структуры, показанной в листинге 7-1.

crate
 └── front_of_house
     ├── hosting
     │   ├── add_to_waitlist
     │   └── seat_at_table
     └── serving
         ├── take_order
         ├── serve_order
         └── take_payment

Листинг 7-2: Дерево модулей для кода в листинге 7-1

Это дерево показывает, как некоторые из модулей вкладываются друг в друга (например, hosting находится внутри front_of_house). Дерево также показывает, что некоторые модули являются наследниками (siblings) друг друга, то есть они определены в одном модуле (hosting и serving определены внутри front_of_house). Чтобы продолжить метафору про семейства, если модуль A содержится внутри модуля B, мы говорим, что модуль A является потомком (child) модуля B, а модуль B является родителем (parent) модуля A. Обратите внимание, что все дерево модулей укоренено в неявном модуле с именем crate

Дерево модулей может напомнить вам дерево каталогов файловой системы на компьютере; это очень удачное сравнение! Так же, как каталоги в файловой системе, для организации кода используются модули. И так же, как для файлов в каталоге, нужен способ найти модули.