Перевод в Эликсир
by Oleg Sovetnik
При выборе языка и фреймворка для реализации умвельта основное внимание было сосредоточено на выборе парадигмы, которая ляжет в основу системы. Для этого я решил остановиться на Elixir, представляющем функциональную парадигму и позволяющим эффективно работать с чистыми функциями потоками данных, акторной моделью и иммутабельностью данных.
Почему Elixir?
- Функциональная парадигма и акторная модель. Умвельт оперирует концептами и фактами, которые представляют собой интерпретацию данных через медиаторы, которые являются не чем иным, как чистыми функциями. Для реализации более сложных процессов, существующих во времени и обладающих жизненным циклом в Elixir используется встроенный GenServer или Agent. Это идеально подходит для моделирования динамичных систем и взаимодействий между агентами.
- Система макросов. Elixir предоставляет мощную систему макросов, которая позволяет создавать высокоуровневые абстракции. Это упрощает работу с синтаксическими структурами, необходимыми для перевода концептов и фактов в код.
- Абстрактное синтаксическое дерево (AST). Встроенная в стандартную библиотеку Elixir система AST упрощает работу с кодом на уровне парсинга и генерации, что является важным для автоматической генерации тестов и кода на основе умвельта.
- Интеграция системы тестирования. Elixir имеет встроенные инструменты для тестирования (ExUnit), что позволяет легко интегрировать процесс тестирования в umwelt. Это упрощает автоматическое создание и запуск тестов на основе сгенерированных спецификаций.
Почему Phoenix?
- Модульная структура. Phoenix поддерживает разделение логики проекта на контексты, что облегчает организацию сущностей и репозиториев. Это создает удобную инфраструктуру для интеграции умвельта как отдельного компонента проекта.
- Лёгкость интеграции с Elixir. Phoenix — это фреймворк, который работает поверх Elixir, что позволяет легко использовать умвельт в веб-приложениях, не теряя преимуществ функциональной парадигмы и мощной системы акторов.
Для того чтобы связать концепты и факты умвельта с кодом на Elixir, необходимо установить чёткие правила перевода. Этот процесс подразумевает трансляцию элементов концептуального дерева в модули, структуры, функции и тесты. Мы определили несколько типов элементов, которые можно преобразовывать в код:
Концепт
В коде концепт превращается в модуль. Модуль находится в контексте корня или другого модуля.
Атрибут
Постоянные атрибуты концепта становятся атрибутами модуля.
Структура
Создается, если в концепте создано хотя бы одно поле. Также определяется тип на основе полей структа.
Пример
Если концепт имеет поля и, соответственно, является структурой, то можно создать примеры, входящие в множество этого типа.
Поле
Если концепт имеет операнды (свойства), то мы можем описать их как поля структуры, указав их тип и значение по умолчанию.
Сигнатура
Заголовок функции или bodyless function, который нужен, чтобы абстрактно описать медиатор. Мы определим аргументы и их типы, и тип результата.
Аргумент
У функции могут быть аргументы для интерпретации. В сигнатурах можно использовать тип any. Если так, то в функции этот аргумент должен быть с более строгим типом. Если же в сигнатуре задан тип, то в функции можно использовать значение.
Функция
Для каждой сигнатуры мы создаем как минимум одну функцию. Смысл функций - интерпретировать какую-то входящую информацию и делать утверждения. Из сигнатуры мы знаем типы аргументов и результата, но в функциях тип any уже недопустим и он должен быть установлен для каждой clause. Способ делать утверждения о связи между предисловием и постусловием. Название этой связи или интерпретации должно быть именем функции.
Утверждение
Для каждой функции мы должны сделать утверждения, которые позволят нам понять смысл функции и протестировать ее. Каждое утверждение содержит конкретные значения для аргументов и результата в соответствии с проверяемым фактом.
Основа умвельта - майндмап - дерево концептов, в котором находятся утверждения о социальных действиях или факты. А факт, в интерпретации теории факта - Утверждение, сделанное в рамках концептуальной схемы. Наша задача - построить такую программу, которая будет эти утверждения делать, сообщая нам о фактах. Тут мы приходим к функциям и вспоминаем о тройках Хоара.
Спецификации из фактов
Как для социологии основным концептом является действие, а основным результатом - факты, так для программирования - функция и ее результат. Рассмотрим процесс получения функции из факта, или перевода с языка концептов и фактов для того, чтобы автоматически получить спецификацию программы в формате тестов.
Так как для реализации умвельта я выбрал Elixir, то и тесты будем писать в формате ExUnit, стандартном фреймворке для тестов в экосистеме Elixir. Но никто не мешает вам сделать то же самое, например, на Ruby и minitest/rspec.
Для описания этих функций мы берем факты и на их основе составляем спецификацию программы. Как мы выяснили ранее, факт представляет собой высказывание вида “bar
— это baz
”, где bar
(предмет) получает характеристику baz
(предикат) через медиатор foo
в контексте концепта Foobar
или assert Foobar.foo(bar) == baz
Теперь мы знаем, какую функцию и где нужно создать, чтобы тест прошел.
умвельт элементы концепты факт программирование