Skip to content

Development‐Pattern‐objects

BUYT-1 edited this page Apr 6, 2026 · 2 revisions

Далее представлены некоторые принципы того, как должны представляться объекты закономерностей в коде.

Important

Пока что это является просто сборником мыслей по опыту работы с примерами и простого просмотра получавшегося ранее кода. Детали не проработаны и всё ещё может измениться. Если что-то не понятно сразу, лучше обсудить в чатах.

Что нужно уметь делать

Есть несколько требований к объектам закономерностей и работе алгоритмов с ними. Их внутреннее устройство должно не мешать реализации этой функциональности.

Написанное ниже в основном относится к объектам, которые возвращаются методами типа get_*().

(!)Самостоятельное время жизни

Объект вашей закономерности, который выдаётся в Python, должен иметь самостоятельное время жизни. В идеале он должен быть простым --- строчки да числа. В частности, это означает, что в новых закономерностях RelationalSchema, Column, Vertical мы не используем --- там сложное время жизни через shared_ptr и рекурсивные структуры.

Сериализуемость

Сериализация не должна быть сложной. В идеале что-то типа [](Dep const& dep) { return py::make_tuple(dep.part1, dep.part2); }, где dep.part1 и dep.part2 имеют стандартный плюсовый или забинденный ранее тип.

Работа с контейнерами Python

__eq__, __hash__ должно быть просто реализовать на стороне биндингов. В первом случае использовать py::self == py::self (т. е. operator==).

Вывод для человека

__str__, __repr__. Конструктор хотелось бы иметь, чтобы __repr__ ему соответствовал.

Валидация

Fd <-> FdInput

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

Близко к определению

Смотрим статью, пишем объект так, как там определено, минус, может быть, любовь математиков к множествам.

Удобное обращение

Это больше для валидаторов. Плохой пример --- заставлять пользователя указывать индексов столбцов вместо названий. Для условного дата саентиста в ноутбуке это неудобно.

Unicode

В Python нормальная поддержка Unicode. Постарайтесь её не ломать. Обычно с этим проблем нет.

Предлагаемый вариант

Жёстко разделять классы для представления, внутренние классы, классы для хранения результатов, классы ввода. Третьи нужны, потому что классы представления могут быть большими (строки внутри).

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

Классы представления выдаются пользователю. С ними должно быть удобно работать. Требования выше в основном относятся к ним. Их желательно уметь приводить к классу ввода (если есть).

В валидатор желательно уметь передавать класс представления напрямую. Если класс представления сложно сконструировать или нельзя перетащить сразу классу валидатора, то для последнего стоит завести класс ввода. Его должно быть легко сконструировать.

Класс хранилища нужен, чтобы компактно хранить закономерности и получать (более толстые) классы представления. Например, итерацией (см. std::ranges::views::transform_view). Итераторам можно reference_internal. py::make_iterator. Второстепенная цель --- чтобы алгоритмы не заморачивались с записью. Внутри может быть разумно использовать билдер.

Внутри алгоритма иметь shared_ptr хранилища, который выдавать наружу по вызову метода. При новом запуске просто перезаписывать этот указатель.

За примером того, что может пойти не так, смотрите [TODO: добавить бумагу Шлёнских Алексей, 1 семестр магистратуры]