Я часто видел, как растущие компании несколько раз переписывали свое программное обеспечение для бизнес-логики. Например, он может проходить следующие этапы:
- Использование Excel для учета, инвентаризации и т. д.
- Реализация той же бизнес-логики в пользовательской программе с пользовательским интерфейсом и сериализацией данных в JSON или XML.
- Переписать программу для поддержки многопоточности или асинхронной обработки.
- Переписываем программу для использования базы данных SQL.
- Переписываем программу на Java для использования распределенных систем типа Hadoop.
- Переписываем программу на Scala для совместимости со Spark.
- Создание небольшой программы для обработки подмножества данных на рабочей станции для определенного отдела.
- Переписывание части бизнес-логики на JavaScript, чтобы сделать ее доступной для интерфейсных приложений.
Бизнес-логика остается неизменной на всех этапах, но бизнес переписывает ее, потому что программное обеспечение плохо масштабируется. Переписывание бизнес-логики требует больших затрат, чревато ошибками и приводит к несоответствиям между различными частями системы. Этот сценарий подчеркивает одну из самых больших проблем в современной разработке программного обеспечения.
Проблема использования прямого ввода-вывода в библиотеках
Когда библиотеки используют операции ввода-вывода напрямую, это ограничивает возможность повторного использования логики библиотеки. Использование прямого ввода-вывода действует как вирус, делая библиотеку непригодной для использования при изменении системы ввода-вывода. Это создает потребность в решении, которое отделяет бизнес-логику от операций ввода-вывода, позволяя повторно использовать логику и легко интегрировать ее в различные системы.
Вопросы о существующих решениях
Хотя существуют языки программирования без побочных эффектов и прямого ввода-вывода, такие как Haskell, Elm и PureScript, их интеграция с существующими системами может быть очень сложной задачей. Кроме того, не многие программисты знакомы с этими языками. Это поднимает два важных вопроса:
- Как мы можем эффективно интегрировать функциональную бизнес-логику в существующие системы?
- Как мы можем найти программистов, которые хорошо разбираются в чисто функциональных языках программирования?
Знакомство с функциональным скриптом
FunctionalScript — это чисто функциональное подмножество JavaScript, предназначенное для предоставления масштабируемых и многократно используемых компонентов для бизнес-логики. Как подмножество, он поддерживает прямую совместимость с JavaScript, что означает, что любой модуль FunctionalScript можно использовать в любой программе JavaScript без каких-либо модификаций. Эта функция упрощает интеграцию в существующие системы, не требуя дополнительных шагов сборки или инструментов. Он позволяет программистам использовать имеющиеся у них знания JavaScript и опирается на знакомый JavaScript API в качестве стандартной библиотеки.
Одним из существенных преимуществ FunctionalScript по сравнению с другими языками функционального программирования является отсутствие привязки к поставщику. Язык не имеет зависимостей, таких как стандартная библиотека или модули времени выполнения. Если языковой проект будет заброшен, модули FunctionalScript по-прежнему будут работать как обычные модули JavaScript, обеспечивая долговечность вашего кода.
Более того, JavaScript — самый популярный язык программирования в мире, а это означает, что программистам не нужно изучать новый сложный язык, чтобы извлечь выгоду из функционального программирования с помощью FunctionalScript. Это широкое знакомство облегчает поиск и привлечение разработчиков для работы с FunctionalScript, помогая решать проблемы, связанные с другими чисто функциональными языками программирования.
Система типов
FunctionalScript, как и JavaScript, является динамически типизированным языком. Тем не менее, он выигрывает от использования аннотаций типов TypeScript/JSDoc, которые помогают обнаруживать большинство ошибок типов. TypeScript использует структурную систему типов, в отличие от систем номинальных типов, которые можно найти во многих современных языках, таких как C++, Rust, C# и Java. На практике система структурных типов, как правило, вызывает меньше проблем, чем система номинальных типов, что часто приводит к чрезмерному количеству адаптеров между интерфейсами, что в конечном итоге ухудшает возможность повторного использования кода.
Вот пример, иллюстрирующий, как аннотации типов TypeScript/JSDoc можно использовать в FunctionalScript:
/** * @template T * @typedef {T|undefined} Option */ /** @type {<T, R>(f: (value: T) => R) => (value: T|undefined) => R|undefined} */ const optionMap = f => value => value === undefined ? undefined : f(value) // test optionMap { const optionSq = optionMap(v => v * v) const sq3 = optionSq(3) if (sq3 !== 9) { throw sq3 } const sqUndefined = optionSq(undefined) if (sqUndefined !== undefined) { throw sqUndefined } }
Создание приложений с использованием FunctionalScript
- В: Как мы можем создавать приложения с помощью FunctionalScript, если у него нет ввода-вывода?
- A: Это правда, что любая работающая программа требует ввода-вывода. Однако ключевая идея FunctionalScript состоит в том, чтобы как можно дольше задерживать операции ввода-вывода, гарантируя, что основная бизнес-логика остается отделенной от проблем, связанных с вводом-выводом. Такой подход позволяет использовать основные функции повторно и адаптировать их к различным системам ввода-вывода. Следующая диаграмма зависимостей демонстрирует эту структуру:
В этой структуре application.js
служит оркестратором, содержащим только связующий код, который соединяет lib.f.js
(основную бизнес-логику) с вводом-выводом для конкретной платформы. Вот пример простого приложения:
логика.f.js
/** @typedef {(text: string) => undefined} ConsoleOut */ /** @type {(out: ConsoleOut) => undefined} */ const main = out => out('Hello world!') module.exports = { main }
приложение.js
const logic = require('logic.f.js') logic.main(console.log)
FunctionalScript можно использовать в различных типах приложений, в том числе:
- Интерфейсные приложения (веб, мобильные)
- Серверные приложения (Node.js, Deno, Bun)
- Расширения JSON для языков сценариев, такие как инструменты сборки и развертывания.
- Сложные языки запросов для распределенных систем
Используя FunctionalScript в этих сценариях, вы можете обеспечить лучшее разделение задач, более простое обслуживание кода и большую адаптируемость к различным системам ввода-вывода или требованиям.
Как упоминалось ранее, основная цель — иметь масштабируемые и многократно используемые компоненты. Пользователи, формально описывающие бизнес-логику, не должны переписывать ее для новой системы распределенных вычислений или изучать новый язык программирования.
Текущее состояние
FunctionalScript — это проект с открытым исходным кодом, выпущенный под лицензией MIT. Проект все еще находится на ранней стадии разработки, и мы активно работаем над созданием парсера и других необходимых модулей.
Весь код написан на FunctionalScript, что свидетельствует о возможностях языка. Когда синтаксический анализатор завершен, его можно использовать для создания различных инструментов линтера и компиляторов. До тех пор мы вручную проверяем наш код, используя FunctionalScript в качестве соглашения по коду.
Ссылки
- GitHub https://github.com/functionalscript/functionalscript
- Функциональное программирование на JavaScript https://medium.com/bitsrc/purely-functional-programming-in-javascript-91114b1b2dff