Введение: Почему документация в Rust — это больше, чем комментарии
Экосистема Rust известна своей строгостью и надёжностью. Однако даже самый элегантный код бесполезен без качественной документации. На начальном уровне достаточно написать пару строк /// для публичных функций. Но когда ваш проект разрастается до нескольких крейтов (crates) с десятками модулей, встаёт вопрос о продвинутых техниках документирования.
В этой статье мы рассмотрим инструменты и приёмы, которые помогут вам создавать документацию уровня enterprise: от автоматического тестирования примеров до генерации книг и интеграции с CI/CD.
1. Doctests: документация, которая не врёт
Главная «фишка» rustdoc — возможность встраивать исполняемые примеры кода прямо в комментарии. Такие примеры автоматически компилируются и прогоняются при запуске cargo test. Это гарантирует, что ваша документация всегда актуальна.
Базовый doctest
/// Возвращает сумму двух чисел.
///
/// # Пример
///
/// ```
/// let result = my_crate::add(2, 3);
/// assert_eq!(result, 5);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
Продвинутые приёмы с doctest
Вы можете скрывать строки подготовки, которые не должны отображаться в документации, с помощью # :
/// # Пример с инициализацией
///
/// ```
/// # use std::collections::HashMap;
/// let mut map = HashMap::new();
/// map.insert("key", 42);
/// assert_eq!(map.get("key"), Some(&42));
/// ```
Также можно проверять, что код не компилируется (например, демонстрация ошибок времени компиляции):
/// ```compile_fail
/// let x: i32 = "строка"; // Ошибка: несоответствие типов
/// ```
2. Атрибуты документации: контроль и метаданные
Атрибуты #[doc(...)] позволяют тонко настраивать отображение документации.
Скрытие элементов
/// Внутренняя функция, не предназначена для публичного использования.
#[doc(hidden)]
pub fn internal_helper() {}
Категоризация и поиск
/// Группа утилит для работы с сетью.
#[doc(alias = "net")]
#[doc(alias = "socket")]
pub mod network {
// ...
}
Встраивание документации из другого места
/// Смотрите [документацию модуля](index.html) для общей информации.
#[doc(include = "docs/faq.md")]
pub fn complex_function() {}
3. Cross-references и навигация
Rustdoc поддерживает ссылки на другие элементы документации. Это создаёт связную структуру, удобную для чтения.
Ссылки на функции и типы
/// Используйте [`Config::new`] для создания экземпляра.
///
/// Для более сложной настройки обратитесь к модулю [`config`].
pub struct Config { /* ... */ }
Ссылки на внешние крейты
/// Эта функция использует [serde_json] для сериализации.
///
/// [serde_json]: https://docs.rs/serde_json
pub fn to_json() {}
4. Инструменты для больших проектов: mdBook и документация крейта
Когда одного cargo doc становится недостаточно, на помощь приходит mdBook — утилита для создания книг из Markdown-файлов. Она идеально подходит для написания руководств, туториалов и архитектурной документации.
Быстрый старт с mdBook
# Установка
cargo install mdbook
# Создание проекта
mdbook init my-book
cd my-book
mdbook serve --open
Интеграция с rustdoc
Вы можете встраивать документацию из mdBook в cargo doc с помощью атрибута #[doc = include_str!()]:
/// # Архитектура
///
/// Подробное описание архитектуры библиотеки:
///
#[doc = include_str!("../docs/architecture.md")]
pub mod core {
// ...
}
Заключение: Документация как часть кодовой базы
Продвинутое документирование в Rust превращает комментарии в мощный инструмент поддержки качества. Doctests гарантируют, что примеры работают. Атрибуты дают контроль над видимостью. Cross-references строят навигацию, а mdBook позволяет создавать полноценные книги.
Начните с внедрения doctests в ключевые функции. Затем добавьте атрибуты для скрытия внутренних деталей. И только после этого переходите к mdBook для масштабных проектов. Помните: хорошая документация — это не роскошь, а необходимость для долгоживущего Rust-проекта.
Используйте эти инструменты, и ваша документация станет такой же надёжной, как и сам Rust.