Документация в Rust: как писать код, который говорит сам за себя

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Почему документация в Rust — это не скучная обязанность, а суперсила

Представьте, что вы открываете чужой crate на Rust, а там — пустота. Ни одного комментария, ни одной строчки документации. Только голый код с дженериками, трейтами и лайфтаймами. Знакомо? Больно? Именно поэтому тема документации в Rust проектах стоит острее, чем когда-либо.

Rust славится своей безопасностью и производительностью, но его система типов может быть сложной для новичков. Хорошая документация превращает ваш код из "китайской грамоты" в понятное руководство. Более того, в Rust документация — это не просто текст. Это исполняемые примеры, которые гарантируют, что ваш код работает так, как вы обещали.

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

Основы: что такое документация в Rust и зачем она нужна

В Rust есть два типа комментариев: обычные (// и /* */) и doc-комментарии (/// и //!). Doc-комментарии автоматически собираются утилитой rustdoc и превращаются в HTML-документацию. Это встроенный инструмент, который идет вместе с компилятором — вам не нужно устанавливать ничего дополнительно.

Зачем тратить время на документацию? Вот три железобетонных причины:

  • Скорость разработки: вы забудете свой код через месяц. Документация — это напоминание себе в будущем.
  • Онбординг новых разработчиков: хорошая документация сокращает время входа в проект с недель до часов.
  • Тестирование в подарок: примеры в doc-комментариях можно запускать как тесты. Это называется doctests.

Давайте посмотрим на простой пример. Вот как выглядит базовая документация функции:

/// Вычисляет факториал числа n
///
/// # Arguments
///
/// * `n` - Неотрицательное целое число
///
/// # Returns
///
/// Возвращает `u64` - факториал числа n
///
/// # Examples
///
/// ```
/// use my_crate::math::factorial;
///
/// assert_eq!(factorial(5), 120);
/// ```
pub fn factorial(n: u64) -> u64 {
    (1..=n).product()
}

Запустите cargo doc --open, и вы увидите красиво оформленную HTML-страницу с этим описанием. А если запустить cargo test, то пример внутри документации тоже выполнится как тест. Удобно, правда?

Структура хорошего doc-комментария: секреты профессионалов

Писать документацию — это искусство. В Rust сообществе сложились определенные стандарты, которые делают документацию полезной и единообразной. Давайте разберем их по косточкам.

Первый абзац — это заголовок

Первая строка doc-комментария должна быть кратким описанием того, что делает функция, структура или модуль. rustdoc использует её для создания краткого списка всех элементов. Представьте, что это заголовок новости — он должен сразу дать понять, о чем речь.

/// Сортирует массив методом пузырька (Bubble Sort).
///
/// Подробное описание можно добавить здесь...
pub fn bubble_sort(arr: &mut [i32]) { ... }

Секции: используйте Markdown-заголовки

Rust поддерживает Markdown в doc-комментариях. Используйте стандартные секции, чтобы структурировать информацию:

  • # Examples — примеры использования
  • # Panics — когда функция может вызвать панику
  • # Errors — какие ошибки возвращает (если возвращает Result)
  • # Safety — если функция unsafe, объясните почему
  • # Arguments — описание параметров
  • # Returns — что возвращает функция

Вот пример полноценной документации для функции, которая может паниковать:

/// Извлекает элемент из вектора по индексу с проверкой границ
///
/// # Arguments
///
/// * `vec` - Ссылка на вектор
/// * `index` - Индекс элемента (должен быть меньше длины вектора)
///
/// # Returns
///
/// Ссылку на элемент вектора
///
/// # Panics
///
/// Паникует, если индекс выходит за границы вектора
///
/// # Examples
///
/// ```
/// use my_crate::safe_get;
///
/// let v = vec![10, 20, 30];
/// assert_eq!(safe_get(&v, 1), &20);
/// ```
pub fn safe_get<T>(vec: &[T], index: usize) -> &T {
    if index >= vec.len() {
        panic!("Index out of bounds: {} >= {}", index, vec.len());
    }
    &vec[index]
}

Doctests: документация, которая не врет

Одна из самых крутых фич Rust — это doctests. Примеры кода в doc-комментариях автоматически компилируются и запускаются как тесты. Это значит, что ваша документация всегда актуальна. Если вы измените API и забудете обновить примеры — тесты упадут.

Вот как это работает:

/// Складывает два числа
///
/// ```
/// let result = my_crate::add(2, 3);
/// assert_eq!(result, 5);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

Запустите cargo test, и Rust проверит, что add(2, 3) действительно возвращает 5. Если вы переименуете функцию в sum, тест упадет, и вы узнаете, что документацию нужно обновить.

Совет: старайтесь писать примеры, которые действительно полезны. Не просто "вызов функции", а покажите типичный сценарий использования. Пользователи будут вам благодарны.

Документирование модулей и крейтов

Doc-комментарии можно писать не только для функций, но и для модулей и целых крейтов. Используйте //! (внутренние doc-комментарии) для документирования родительского элемента.

Документация модуля

//! Модуль для работы с математическими операциями
//!
//! Этот модуль предоставляет базовые математические функции:
//! - `add` - сложение
//! - `subtract` - вычитание
//! - `multiply` - умножение
//!
//! # Examples
//!
//! ```
//! use my_crate::math::add;
//!
//! let result = add(10, 20);
//! assert_eq!(result, 30);
//! ```

pub mod math {
    pub fn add(a: i32, b: i32) -> i32 { a + b }
    pub fn subtract(a: i32, b: i32) -> i32 { a - b }
    pub fn multiply(a: i32, b: i32) -> i32 { a * b }
}

Документация крейта

Блоги

Рекомендаций по книгам