[.NET, F#] Пример реального проекта на F#
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
В экосистеме Майкрософт, F# занимает место экспериментального языка, удачные концепты из которого, впоследствии, переносятся в C#. Вместе с тем, во многом благодаря сообществу, фаршик стал реальной альтернативой для прикладных проектов. Под катом описаны ингредиенты бэкенда, фронтенда, тестов, сборки и инфраструктуры проекта, полностью написанного на F#. Исходный код прилагается.
Диаграмма контейнеровSAFeНа выбор ингредиентов, определяющее влияние, оказал SAFe Stack. SAFe представляет собой шаблон dotnet CLI, в котором подобраны необходимые компоненты для гомогенной разработки SPA в связке с бэкэндом. Сайт проекта содержит много обучающих материалов и примеров.SAFе облегчает старт для новичка. На первом этапе можно ничего не менять в шаблоне и сразу переходить к разработке функционала. По мере накопления опыта, вы, скорее всего, отойдете от SAFe. Первая буква акронима - ‘S’ - означает Saturn - идиоматический фреймворк над Giraffe, который, в свою очередь, функциональная обертка над Asp.net. Вторая буква - ‘A’ - означает Azure. Здесь мне было сразу не по-пути с SAFe, а тем, кто использует Ажур, как платформу, пригодится библиотека Farmer, которую пилят те же люди, что и SAFe.Третья буква - ‘F’ - означает Fable - транспайлер из F# в JavaScript - настоящая сдобная булочка в экосистеме фарша.БэкендДля создания API используется библиотека Fable.Remoting. Fable.Remoting скрывает абстракции веб-сервера. Типы, определяющие контракт, помещаются в общий для бэкенда и фронтенда файл (или сборку). Реализовываете API на сервере, все остальное (создание прокси, сериализацию, обработку ошибок, логирование) делает за вас библиотека. Помимо JSON, поддерживается передача бинарных данных.Сейчас, имея такой удобный инструмент, как Fable.Remoting, я не вижу смысла тянуть в бэкенд колбасу Saturn - Giraffe - Asp.Net. Но, по историческим причинам, в проекте остался Giraffe.Если нужно использовать спецификацию OpenAPI, можно посмотреть на GiraffeGenerator.В качестве хранилища данных, в проекте используется NoSql база DynamoDB. За основу реализации слоя доступа к данным была взята библиотека DynamoDb.Ok. В ней используется идиоматический подход на основе монады Reader. В итоге, могу сказать, что этот подход мне не понравился. В будущем хотелось бы вообще не отвлекаться на код в слое доступа к данным. Есть идеи, возможно, об этом выйдет отдельная статья.C реляционными базами из F# работать не приходилось. В чате сообщества замечал нарекания на ограниченную поддержку типов F# в Entity Framework и рекомендации использовать Dapper.В прошлом году сообщество обогатилось серией годных статей по теме внедрения зависимостей: статья 1, статья 2, статья 3. Подход, базирующийся на Flexible Types, применяется и в данном проекте.Для логирования используется библиотека Serilog, у которой есть расширение для Giraffe.Для авторизации используется самописная реализация JWT.Для связи с AWS частично используется дотнетовский AWSSDK, частично HTTP, так как SDK не покрывает весь функционал облака.ФронтендОснова фронтендов на F# - Fable, Ваш код и большая часть стандартной библиотеки переводится в JS. Можно легко взаимодействовать с библиотеками JS. Существует множество обвязок (binding) для популярных библиотек, в т.ч. React и его компонент.Для управления состоянием используется Elmish - реализация Elm-архитектуры. Рендеринг страницы производится с помощью Fable.React и Bulma.Разработка фронта в этой экосистеме доставляет.пример кода
let quizView (dispatch : Msg -> unit) (settings:Settings) (quiz:QuizRecord) l10n = [
br []
figure [ Class "image is-128x128"; Style [Display DisplayOptions.InlineBlock] ] [ img [ Src <| Infra.urlForMediaImgSafe settings.MediaHost quiz.ImgKey ] ]
br []
h3 [Class "title is-3"] [str quiz.Name]
div [Class "notification is-white"][
p [Class "subtitle is-5"][
match quiz.StartTime with
| Some dt -> str (dt.ToString("yyyy-MM-dd HH:mm"))
| None -> str "???"
if quiz.Status = Live then
str " "
span [Class "tag is-danger is-light"][str "live"]
br[]
]
p [] (splitByLines quiz.Description)
if quiz.EventPage <> "" then
a[Href quiz.EventPage][str l10n.Details]
]
]
Отличное введение в экосистему - книга The Elmish Book.Однако, фронтдендеры такие фронтендеры, связка Elmish + Fable.React + Boolma уже вышла из моды. В 2021 году, чтобы быть в тренде, вам нужно освоить Feliz + Fable.React.WebComponent + Material UI и рассмотреть альтернативу - Fable.Svetle. Моя бэкендер страдать.Для взаимодействия с Aws, а именно с брокером сообщений в AppSync, используется библиотека Aws Amplify.ТестыДля проверки нефункциональных требований были реализованы нагрузочные тесты. Без использования сторонних решений (тянуть сюда JMeter показалось перебором). Модульные тесты не писались. Не могу не отметить то чувство защищенности, которое дает система типов F#. Глупые ошибки обычно отлавливаются компилятором. За все время эксплуатации проекта, словил всего один мажорный баг на проде. В других проектах использовал FsUnit и expecto. Первый проще встраивается в инструментарий, второй гибче в синтаксисе, но, как по мне, большой разницы между ними нет.Из прочих решений для тестирования, в моем списке на попробовать:
- FsCheck - для тестирование на основе свойств
- Canopy - фреймворк и DSL для тестирования UI
- NBomber - для нагрузочных тестов
Сборка и развертываниеДля управления пакетами используется Paket. Для сборки используется скрипт Fake. Оба инструмента входят в шаблон SAFe. Судя по обсуждению, в настоящее время есть какие-то проблемы в запуске фейковых скриптов и, в будущем, сборка будет выполняться из консольного приложения. В таком случае, вообще не вижу смысла в фейке.Для обновления инфраструктуры и развертывания используется AWS Cloud Development Kit. Поддержка F# не заявлена, но идет из коробки, вслед за C#. ИнструментарийХорошая новость. В SAFe сконфигурировано горячее обновление клиента и сервера в режиме разработки. К этому быстро привыкаешь и потом не понимаешь, как можно было работать по-другому.Плохая новость. Инструментарий развивается, но он уступает тому, что есть в C#. Проект разрабатывается в VSCode с расширением Ionide. Подвисания, перезагрузки, регулярная необходимость удалять временные файлы - все это по-прежнему присутствует. Есть подозрение, что, в более крупных проектах, это может сильно испортить жизнь разработчику. Альтернативой Ionide является Rider. И там и там недавно вышли обновления, будем надеяться, что ситуация улучшится.Помимо Ionide, используется расширение ILSpy, для того, чтобы понимать логику компилятора.Также, работая с F# необходимо менять привычки отладки. Меньше пошаговой отладки, больше вывода в консоль. Использовать FSI.ИтогоПо состоянию на начало 2021, F# пригоден для прикладных проектов небольшого и среднего размера. Для меня, преимуществами этого языка являются:
- экосистема фронтенд-разработки,
- система типов,
- компактный синтаксис.
До тех пор, пока эти возможности не появятся в C#, при прочих равных, мой выбор будет в пользу фаршика.исходный код проекта
Картинка-поощрение для тех, кто дочитал эту статью до конца.
===========
Источник:
habr.com
===========
Похожие новости:
- [Программирование, .NET, ASP, C#] Фильтры действий, или Как просто улучшить читаемость кода
- [Беспроводные технологии, Гаджеты, Смартфоны, Здоровье] Apple предупредила, что гаджеты с MagSafe нужно держать подальше от кардиостимуляторов
- [.NET, ООП] Наследование в Nuget-пакетах
- [.NET, Проектирование и рефакторинг, C#, Профессиональная литература] Внедрение зависимостей для начинающих (перевод)
- [Администрирование доменных имен, Антивирусная защита, SaaS / S+S, Браузеры, Развитие стартапа] У Google появился новый креативный способ убивать SaaS-стартапы (перевод)
- [.NET, C#] Nuke. Быстрый старт
- [.NET, C#, DevOps] Как установить файл конфигурации в .Net Core Console app для нескольких сред разработки при запуске Docker-контейнера
- [.NET] Когда программисту нечего делать или оптимизируем код при помощи Linq.Expression
- [Беспроводные технологии, Гаджеты, Смартфоны, Здоровье] Медицинское исследование утверждает, что iPhone 12 и MagSafe способны отключать кардиостимуляторы
- [.NET, Системы сборки] xUnit тестирование в TeamCity
Теги для поиска: #_.net, #_f#, #_f#, #_fsharp, #_fable, #_elmish, #_fake, #_paket, #_safe, #_fable.remoting, #_.net, #_f#
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 17:23
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
В экосистеме Майкрософт, F# занимает место экспериментального языка, удачные концепты из которого, впоследствии, переносятся в C#. Вместе с тем, во многом благодаря сообществу, фаршик стал реальной альтернативой для прикладных проектов. Под катом описаны ингредиенты бэкенда, фронтенда, тестов, сборки и инфраструктуры проекта, полностью написанного на F#. Исходный код прилагается. Диаграмма контейнеровSAFeНа выбор ингредиентов, определяющее влияние, оказал SAFe Stack. SAFe представляет собой шаблон dotnet CLI, в котором подобраны необходимые компоненты для гомогенной разработки SPA в связке с бэкэндом. Сайт проекта содержит много обучающих материалов и примеров.SAFе облегчает старт для новичка. На первом этапе можно ничего не менять в шаблоне и сразу переходить к разработке функционала. По мере накопления опыта, вы, скорее всего, отойдете от SAFe. Первая буква акронима - ‘S’ - означает Saturn - идиоматический фреймворк над Giraffe, который, в свою очередь, функциональная обертка над Asp.net. Вторая буква - ‘A’ - означает Azure. Здесь мне было сразу не по-пути с SAFe, а тем, кто использует Ажур, как платформу, пригодится библиотека Farmer, которую пилят те же люди, что и SAFe.Третья буква - ‘F’ - означает Fable - транспайлер из F# в JavaScript - настоящая сдобная булочка в экосистеме фарша.БэкендДля создания API используется библиотека Fable.Remoting. Fable.Remoting скрывает абстракции веб-сервера. Типы, определяющие контракт, помещаются в общий для бэкенда и фронтенда файл (или сборку). Реализовываете API на сервере, все остальное (создание прокси, сериализацию, обработку ошибок, логирование) делает за вас библиотека. Помимо JSON, поддерживается передача бинарных данных.Сейчас, имея такой удобный инструмент, как Fable.Remoting, я не вижу смысла тянуть в бэкенд колбасу Saturn - Giraffe - Asp.Net. Но, по историческим причинам, в проекте остался Giraffe.Если нужно использовать спецификацию OpenAPI, можно посмотреть на GiraffeGenerator.В качестве хранилища данных, в проекте используется NoSql база DynamoDB. За основу реализации слоя доступа к данным была взята библиотека DynamoDb.Ok. В ней используется идиоматический подход на основе монады Reader. В итоге, могу сказать, что этот подход мне не понравился. В будущем хотелось бы вообще не отвлекаться на код в слое доступа к данным. Есть идеи, возможно, об этом выйдет отдельная статья.C реляционными базами из F# работать не приходилось. В чате сообщества замечал нарекания на ограниченную поддержку типов F# в Entity Framework и рекомендации использовать Dapper.В прошлом году сообщество обогатилось серией годных статей по теме внедрения зависимостей: статья 1, статья 2, статья 3. Подход, базирующийся на Flexible Types, применяется и в данном проекте.Для логирования используется библиотека Serilog, у которой есть расширение для Giraffe.Для авторизации используется самописная реализация JWT.Для связи с AWS частично используется дотнетовский AWSSDK, частично HTTP, так как SDK не покрывает весь функционал облака.ФронтендОснова фронтендов на F# - Fable, Ваш код и большая часть стандартной библиотеки переводится в JS. Можно легко взаимодействовать с библиотеками JS. Существует множество обвязок (binding) для популярных библиотек, в т.ч. React и его компонент.Для управления состоянием используется Elmish - реализация Elm-архитектуры. Рендеринг страницы производится с помощью Fable.React и Bulma.Разработка фронта в этой экосистеме доставляет.пример кода let quizView (dispatch : Msg -> unit) (settings:Settings) (quiz:QuizRecord) l10n = [
br [] figure [ Class "image is-128x128"; Style [Display DisplayOptions.InlineBlock] ] [ img [ Src <| Infra.urlForMediaImgSafe settings.MediaHost quiz.ImgKey ] ] br [] h3 [Class "title is-3"] [str quiz.Name] div [Class "notification is-white"][ p [Class "subtitle is-5"][ match quiz.StartTime with | Some dt -> str (dt.ToString("yyyy-MM-dd HH:mm")) | None -> str "???" if quiz.Status = Live then str " " span [Class "tag is-danger is-light"][str "live"] br[] ] p [] (splitByLines quiz.Description) if quiz.EventPage <> "" then a[Href quiz.EventPage][str l10n.Details] ] ]
Картинка-поощрение для тех, кто дочитал эту статью до конца. =========== Источник: habr.com =========== Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 17:23
Часовой пояс: UTC + 5