Документирование Rust-проекта: создание качественной документации

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

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

Начать курс

Написание документации для Rust проекта: от основ до продвинутых техник

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

Основы документирования в Rust

Rust использует особый синтаксис для документации, который основан на Markdown. Документация пишется с помощью doc-комментариев, которые начинаются с /// (для внешней документации) или //! (для внутренней документации модулей).

Рассмотрим базовый пример:

/// Вычисляет факториал числа.
///
/// Эта функция принимает целое неотрицательное число `n`
/// и возвращает его факториал. Если `n` равно 0, возвращается 1.
///
/// # Примеры
///
/// ```
/// let result = factorial(5);
/// assert_eq!(result, 120);
/// ```
pub fn factorial(n: u64) -> u64 {
    (1..=n).product()
}

//! # Модуль математических функций
//!
//! Этот модуль содержит базовые математические операции,
//! включая вычисление факториала и биномиальных коэффициентов.
pub mod math;

Генерация документации с помощью rustdoc

Инструмент rustdoc входит в стандартный набор инструментов Rust и автоматически генерирует HTML-документацию из doc-комментариев. Для запуска достаточно выполнить команду:

cargo doc --open

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

  • --no-deps — не включать документацию зависимостей
  • --document-private-items — документировать приватные элементы
  • --target-dir — указать директорию для выходных файлов

Сгенерированная документация автоматически включает навигацию, поиск, ссылки на типы и функции, а также тесты из примеров кода.

Структура doc-комментариев и специальные секции

Качественная документация в Rust следует определённой структуре. Рекомендуется использовать следующие секции:

  • Краткое описание — первая строка комментария, отображается в списках и поиске
  • Подробное описание — поясняет работу функции, её особенности и ограничения
  • # Examples — один или несколько примеров использования
  • # Panics — ситуации, в которых функция может вызвать панику
  • # Errors — возможные ошибки и их обработка
  • # Safety — для unsafe функций: объяснение предусловий безопасности

Пример полноценной документации функции:

/// Разделяет строку на части по указанному разделителю.
///
/// Возвращает вектор строк, полученных после разделения
/// исходной строки `text` по каждому вхождению `delimiter`.
/// Пустые строки не включаются в результат.
///
/// # Examples
///
/// ```
/// let result = split_string("a,b,c", ',');
/// assert_eq!(result, vec!["a", "b", "c"]);
/// ```
///
/// # Panics
///
/// Функция паникует, если `delimiter` является пустой строкой.
///
/// # Errors
///
/// Эта функция не возвращает ошибок, но может вызвать панику.
pub fn split_string(text: &str, delimiter: char) -> Vec<String> {
    assert!(delimiter != '\0', "Разделитель не может быть нулевым символом");
    text.split(delimiter)
        .filter(|s| !s.is_empty())
        .map(|s| s.to_string())
        .collect()
}

Тестирование документации

Одна из сильных сторон Rust — возможность тестировать примеры кода прямо в документации. Команда cargo test автоматически запускает все примеры из doc-комментариев как тесты. Это гарантирует, что документация всегда актуальна.

Вы можете управлять поведением тестов с помощью атрибутов:

  • ```ignore — не тестировать пример
  • ```no_run — скомпилировать, но не запускать
  • ```should_panic — ожидать панику при выполнении
  • ```compile_fail — ожидать ошибку компиляции

Пример с атрибутами:

/// # Examples
///
/// ```should_panic
/// // Этот пример должен вызвать панику
/// let _v = vec![1, 2, 3];
/// let _x = _v[10]; // выход за границы
/// ```
///
/// ```compile_fail
/// // Этот код не должен компилироваться
/// let x: i32 = "string";
/// ```

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

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

Пример документации структуры:

/// Представляет точку в двумерном пространстве.
///
/// # Fields
///
/// * `x` — координата по оси X
/// * `y` — координата по оси Y
///
/// # Examples
///
/// ```
/// let point = Point::new(3.0, 4.0);
/// assert_eq!(point.x, 3.0);
/// ```
#[derive(Debug, Clone, Copy)]
pub struct Point {
    pub x: f64,
    pub y: f64,
}

impl Point {
    /// Создаёт новую точку с заданными координатами.
    pub fn new(x: f64, y: f64) -> Self {
        Point { x, y }
    }

    /// Вычисляет расстояние от начала координат до точки.
    pub fn distance_from_origin(&self) -> f64 {
        (self.x.powi(2) + self.y.powi(2)).sqrt()
    }
}

Для трейтов также важно указывать контракт, который должны выполнять реализации:

/// Трейт для объектов, которые можно сериализовать в JSON.
///
/// # Implementing
///
/// Реализация должна преобразовывать структуру в корректный JSON-объект.
/// Поля должны быть отсортированы по алфавиту.
pub trait ToJson {
    /// Сериализует объект в строку JSON.
    fn to_json(&self) -> String;
}

Заключение

Написание качественной документации — важный навык для любого Rust-разработчика. Используя rustdoc

Блоги

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