Обновить
102
Роман Смирнов@Source

Head of Elixir at Ecom.tech

0,2
Рейтинг
51
Подписчики
Отправить сообщение

Ну что ж, возможно в Django мире с многопоточностью чуть получше, чем в Rails мире, где Puma ещё только набирает популярность.


Удачи с ФП :-)

Django поддерживает многопоточность.

Rails сам по себе тоже поддерживает многопоточность, ещё с 2008 года. А толку то? Вопрос в том какой процент людей пишет сторонние библиотеки и свои приложения в расчёте на многопоточность.


Так что это не преимущество ФП, а недостаток конкретного ОО языка.

Могу с Вами поспорить на эту тему… проблема именно в ООП, а языки подстраиваются, тупо встраивая некоторые паттерны непосредственно в синтаксис. Классический пример — паттерн Iterator от GoF, сейчас уже сложно найти язык в котором не ввели его поддержку на уровне синтаксиса. Что касается, Python, то он, как и Ruby, не является строгим ОО-языком, а поддерживает множество парадигм. Поэтому Вы можете решать на нём задачи в том числе и в функциональном стиле (возможно даже не подозревая об этом). Чисто ОО-подход — это применение паттернов: GoF, PoEAA, Applying UML and Patterns и т.д.


Код очень простой: скобки в скобках. Но все равно ничего не понятно, я не могу визуально отделить код от данных.

это в Lisp-подобном языке то? там в принципе нет разделения на код и данные by design :-)


Но одно поверхностное знакомство с Erlang ошарашило меня таким количеством фич, что сложно ожидать простоты.

Erlang простой, но весьма непривычный язык. Elixir выглядит привычнее, поэтому и осваивать легче.


Может просто взять любимый Python и нелюбимый JS, и программировать на них в функциональном стиле? :)

Почему бы и нет, они это позволяют )))


С примерами не всё так просто… Чтобы ОО-пример был нечитабелен, он должен быть достаточно большой по размеру. Т.е. по-хорошему в качестве примера нужен какой-то OpenSource проект или хотя бы ощутимый кусочек проекта, который переписали с ООП на ФП. К тому же чтобы код на функциональном языке стал для Вас читабельным, надо всё-таки привыкнуть в определённым нотациям.
А то с непривычки даже тривиальный вызов стратегии


(&Strategy.add/2) |> Context.execute(3, 4)

может сложночитаемым оказаться по сравнению с привычным


Context context = new Context();
context.setStrategy(new ConcreteStrategyAdd());
context.executeStrategy(3, 4);

Картинка, кстати, не моя, она как раз из презентации Functional Programming Patterns

Фанатизм везде плох. Делать из ФП культ — так же плохо, как делать культ из ООП или из Rails :-)


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

При разработке на Rails по факту всё подгоняется под однопоточную работу.
Хочешь параллельно обрабатывать запросы — запусти N инстансов однопоточного unicorn, хочешь фоновые задачи — запусти ещё 1 инстанс для sidekiq и т.д. Не знаю, как обстоят дела в Django, но что-то мне подсказывает, что аналогично.


А Вы имеете опыт работы с ООП?

Конечно, 10 лет… А разве сейчас бывают программисты без опыта работы с ООП?
Преимущество ФП ещё в том, что оно проще. В ООП частенько за деревьями не видно леса. Потому что кругом паттерны, замудрённые абстракции и т.д., а что по факту делает код понять сложно. В ФП программу рассматривают как своеобразный конвеер по преобразованию данных, где каждый этап конвеера — это просто функция.
FP pattens
Это очень непривычно после ООП, но когда начинаешь въезжать в идею, понимаешь, что большая часть ОО-паттернов — это костыли, подпирающие изначально непродуманную парадигму.
Чем меньше концепций заложено в код, тем он проще, а значит и надёжнее. Это не значит, что ООП теперь нельзя использовать, просто если Вы можете представить задачу, решаемую вашим кодом, в качестве конвеера по преобразованию данных, то в функциональном стиле ваш код будет гораздо легче и понятнее.

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

Я в этом треде вообще ничего не предлагаю. Я просто констатирую определение этого паттерна и прямые следствия из него.
А то, что Вы по факту не используете паттерн Active Record — это даже хорошо. Путаница возникает из-за того, что Вы думаете, что Вы успешно и повсеместно применяете данный паттерн, хотя по факту отходите от него безумно далеко, и при этом пытаетесь других убедить, что 2+2=5.

И это не усложнение, это — напротив — упрощение

Это упрощение кода, но усложнение понятий. Паттерны хороши тем, что дают названия вместо длинных определений. Вместо того чтобы говорить "Каждый класс соответствует одной таблице в БД. Строка таблицы соответствует объекту класса. Логика работы с БД помещена в модель предметной области.", мы говорим одно название — ActiveRecord. И всем понятно, о чём это и чем это плохо в нетривиальных случаях. Когда Вы вводите свою интерпретацию понятия ActiveRecord вместо общепринятого определения, и пытаетесь строить свои выводы на ней, это выглядит очень странно.

Я не вижу тут диррективы: «все должно быть так и только так»

Такой директивы нет ни у одного паттерна. Но если что-то не совсем так, то это уже не этот паттерн. Всё просто, в AR нет никаких Service, по сути AR — это и есть fat models. Всё остально — это не AR. Не усложняйте.

Мне кажется, Вы излишне усложняете… Основная претензия к ООП, касаемо состояний, состоит в том, что состояние спрятано внутри объектов. Соответственно, каждый класс должен сам обеспечивать потокобезопасность. Иначе привет race condition. В ФП потокобезопасность заложена by design, включая защиту от случайных мутаций. Проще говоря, чтобы написать на ОО-языке надёжную программу, которая будет работать в многопоточном режиме, Вам придётся писать в функциональном стиле, просто это будет неудобно. Если Вам самому ещё не приходилось так делать, то понять преимущества ФП сложнее.
Ну а чистые функции — это хорошо, их должно быть большинство, но никому не нужна программа из одних чистых функций, которая не сможет записать результат вычислений ни в БД, ни в файл, ни вывести на экран.

AR — это когда логика сохранения данных помещена в модель предметной области, в ту самую в которой бизнес логика. Тупо по определению:
"An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data."
"Active Record uses the most obvious approach, putting data access logic in the domain object"

Хм, странный эпиграф к статье… Как-будто автор не понял, что юзер реддита имел в виду нашумевшую историю с автором ReiserFS


А по сути статьи — круто! Восхищаюсь вашим упорством и целеустремлённостью.

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

Где это случайные мутации являются дизайном?

Я как раз не философствую, а пытаюсь этот вопрос в практическую область перевести. Какой прок от математического факта, что в любой программе есть сайд-эффекты? Но в наших силах разделить эти побочные эффекты на явные и неявные. Если явные — это неизбежность, то неявные — это плохой дизайн.


Отправка сообщения актору — это, к сожалению, тоже сайд-эффект

Вы уже в шаге от определения сайд-эффекта через нагрев процессора… А если серьёзно, то отправка сообщения актору — это то же самое, что вызов метода объекта в ООП. Да и, в принципе, Erlang/Elixir реализуют ООП согласно определению Алана Кея.

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

Ну вообще-то это следует напрямую из определения паттерна. Просто у Вас своё оригинальное видение ActiveRecord… поэтому мы тут тёплое с мягким сравниваем.

Чеж тогда все Бейсик ругали с его goto? Писали бы ответственно и проблем бы не было…

Не знаю, может там был дефицит других управляющих итерациями синтаксических конструкций… я уже с Паскаля начинал… там тоже был goto, но проблем от этого не было )

Всегда ведь можно сформулировать code convention, исходя из бизнес-требований. Бизнесов много и они разные, поэтому не уверен, что это на уровне разработчиков языка надо делать.

Просто "сайд-эффект" — это очень расплывчатое понятие. Некоторые даже нагрев процессора к ним относят :-)
С одной стороны можно считать сайд-эффектом любое действие внешнее к программе — запись в БД или в лог.
А с другой — только побочный/неожидаемый эффект от вызова функции. Когда Вы вызываете условно db.insert!(comment), то это вполне ожидаемо приведёт к запросу к БД, а вот то, что этот же код приведёт к отправке email-уведомлений, отправит нотификацию в веб-сокет, а может и ещё что-то… вот это уже нифига неочевидно и обычно имеют в виду избежание именно сайд-эффектов такого типа.


А как с этим делом в других языках, например в том же Elixir?

Если говорить о работе с разделяемой памятью, то используется модель акторов(запускается легковесный процесс, хранящий разделяемое состояние, а все остальные, чтобы повлиять на это состояние, шлют ему сообщения, которые применяются в порядке очереди). Вот тут можно почитать подробнее. Плюс недавно вышла хорошая статья на тему зачем вообще ФП в Erlang и Elixir

По-моему важно понимать, что если модели предметной области(классы, содержащие бизнес-логику), у вас не наследуют ActiveRecord::Base, то у вас нет паттерна ActiveRecord в проекте. Возможно вы используете рельсовый AR в качестве странной реализации паттерна Repository, возможно ещё как-то… но только не в качестве ActiveRecord.

При функциональном подходе обычно Virtual DOM является и входящим параметром, и результатом обработчиков. А реальный DOM скорее тем самым глобальным состоянием, которое напрямую никто не трогает.


Вероятно, сторонники ФП, говоря о нелюбви к состояниям, имеют в виду работу с ними как стиль, а не их существование вообще.

Да любим мы состояния… проблема не в состояниях, а в работе с разделяемой памятью, особенно когда имеет место конкурентный доступ.
Для этого в функциональном подходе используют STM и Actor Model

Я для себя лично выбрал Elixir/Phoenix. Клиентской стороной я практически не занимаюсь, но вижу что Elm набирает популярность.

Т.е. Вы с проблемами от использования AR не сталкивались? И никаких неудобств от того, что логика предметной области находится в моделях AR не испытывали?

А причём тут религия? Вы же сами написали, что AR нигде толком не получился. Я только добавил, что он by design не может толком получиться и неизбежно будет доставлять проблемы в нетривиальных случаях.

Информация

В рейтинге
3 083-й
Откуда
Россия
Работает в
Зарегистрирован
Активность