В прошлом году я принял решение, что не буду больше использовать Rails, и не буду поддерживать Rails в своих гемах. Кроме того, я буду делать все возможное, чтобы мне никогда не пришлось снова столкнуться с Rails на работе.
Так как я вовлечён во множество Ruby-проектов, люди часто спрашивают меня, почему я не люблю Rails, какие проблемы у меня есть с ним и так далее. Поэтому я решил написать этот длинный пост, чтобы подвести итоги и все объяснить.
Статья частично техническая, частично личная и, к сожалению, частично гневная. Я пишу это не для того, чтобы привлечь внимание, получить посетителей и т.п., у меня нет никакого интереса в этом. Я пишу это, потому что я хочу закончить мои дискуссии о Rails и чтобы было место, куда давать ссылки каждый раз, когда я слышу одни и те же вопросы.
Я также хотел бы рассказать вам пару историй, которые "начинающие Rails-разработчики", вероятно, никогда не слышали, и осветить некоторые вопросы, которые являются достаточно важными, чтобы по крайней мере, подумать о них.
Хорошая часть
Я не буду делать вид, что все в Rails плохо, неправильно, и фреймворк является воплощением зла. Это было бы не справедливо, да и просто глупо. О Rails можно сказать очень много хорошего. И я упомяну пару (очевидных?) вещей для поддержания баланса.
Итак, Rails сделал Ruby популярным. Это факт. Я стал Ruby-разработчиком, что в свою очередь изменило мою карьеру и дало мне много удивительных возможностей, именно благодаря Rails. Многие рубисты тех дней прошли по тому же пути. Мы все здесь благодаря Rails. Во многих случаях, Rails на самом деле оказал огромное влияние на людей, и буквально улучшил им жизнь. Люди получили лучшие рабочие места, лучшие возможности и хорошие деньги. Это было радикальной сменой условий "игры" для многих из нас.
На протяжении многих лет Rails & DHH вдохновили многих людей, в том числе людей из других сообществ, на переосмысление того, что они делают. Например, я уверен, что Rails способствовало улучшению PHP сообщества (вы можете попытаться доказать, что я ошибаюсь, но у меня есть довольно яркие воспоминания как Symfony подчерпнул кучу вдохновения от Rails). То же самое произошло в Java, фреймворк Play является примером.
Есть и другие фантастические аспекты. Rails был всегда нацелен на простоту использования и возможность быстро создавать веб-приложения, что позволило преуспеть таким инициативам, как Rails Girls. Rails доказал людям, что они способны создать что-то самостоятельно, без какого-либо опыта программирования, в относительно короткий промежуток времени. Это удивительно, так как это легко может стать воротами в мир программирования для людей, которые в противном случае даже не рассматривали возможность стать программистом.
Мое путешествие
Позвольте мне рассказать вам немного о моем бэкграунде и как я пришёл к Rails.
Я начал работать с Ruby в конце 2006 года, поскольку моя дипломная работа была о Rails. Я изучал язык в то время, как писал свой диплом. Это было весело, это было интересно, это было что-то новое для меня. Тогда я еще работал в качестве PHP-разработчика. И как типичный PHP-программист в ~2005-6, я делал все эти типичные вещи: писал SQL-запросы в шаблонах представлений, писал в процедурном стиле, а затем разрабатывал свой собственный фреймворк и свой собственный ORM, разочаровывался и выгорал. Несмотря на некоторые знания C, C++, Java и Python, я решил перейти на Ruby, из-за Rails. Я выбрал их для своего диплома и совершенно случайно наткнулся на предложение о работе от местного магазина на Rails. Я ответил и они наняли меня. Это было в марте 2007 года.
Итак, с марта 2007 года я начал работать с Ruby профессионально, и где-то с 2009-го я начал вносить вклад в OpenSource проекты на Ruby. С тех пор я работал в консалтинговой компании в течение 3.5 лет, в основном c большими и сложными проектами. Потом работал фрилансером в течение нескольких лет, работал с кучей клиентов, открыл свою собственную компанию, а затем вернулся на полный рабочий день, а затем снова на фриланс, и теперь я вновь штатный сотрудник. Я создавал Rails-приложения с нуля, и участвовал в разработке относительно больших Rails-приложений.
Позвольте мне рассказать вам одну историю. Однажды я присоединился к существующему проекту. Это было огрооомное приложение, которое управляло веб-сайтом торгового он-лайн сообщества. Сложные модели продаж, сложные промо-акции, затейливые конфигурации товаров, купоны, группы пользователей, сообщения — в нём было всё это. Я присоединился к ним, чтобы помочь добавить несколько новых фич. Одной из моих первых задач было… добавить ссылку на что-то на какой-то странице. Мне потребовалось несколько дней, чтобы добавить эту глупую ссылку. Почему? Приложение было большим шаром сложной логики предметной области, раскатанным по нескольким слоям и с настолько сложными вьюхами, что было не просто даже найти нужный шаблон, в котором добавить ссылку. Так как мне нужны были некоторые данные из заказа для того, чтобы создать эту ссылку, не было очевидно, как я должен получить их. Недостаток внутренних API приложения и опора исключительно на ActiveRecord сделали эту задачу чрезвычайно трудной. Я не шучу.
Мои первые фрустрации с Rails начались довольно рано. Я испытал недовольство от ActiveRecord примерно после 6 месяцев его использования. Также мне никогда не нравилось, как Rails подошел к работе с JavaScript и AJAX. В случае, если вы не помните, или не застали версии до того, как Rails принял UJS подход (который был хитом обсуждений в 2007-2008 годах), Rails использовал inline JavaScript в шаблонах, порожденный связкой противных хелперов. Как и всё с Rails, это было "легко и приятно в начале", а затем превращалось в неподдерживаемое дерьмо. В конце концов, Rails принял UJS в версии 3.0 и, кажется, сообщество согласилось, что это лучший подход. Это было, когда Merb был убит влит в Rails. О, вы не знаете, что такое Merb? Хорошо, давайте поговорим об этом.
Почему я был восхищён Merb & DataMapper
Merb — проект, созданный Ezra Zygmuntowicz. Он начался как хак, чтобы сделать загрузку файлов быстрее и потокобезопасной. И он прошёл интересный путь от этого хака до модульного, потокобезопасного, быстрого full-stack фреймворка для разработки веб-приложений. Я помню, как люди начали говорить о Merb в 2008-м и это было удивительное чувство, что происходит что-то новое, и это будет здорово!
Вы возможно обрадовались, когда в Rails появился режим API, не так ли? Хм, а Merb имел 3 режима: режим полного стека, режим API и микро-режим, в котором он был урезан до минимума, и я до сих пор помню, что это было самой быстрой вещью когда-либо существовавшей в Ruby мире. Это было более 7 лет назад. Вдумайтесь в это.
В то же время еще один проект привлёк внимание сообщества — DataMapper. Он стал частью Merb стека, являясь его выбором для ORM. Я был очень возбуждён тем, как он решал многие проблемы, которые были в ActiveRecord. DataMapper уже в ~2008-9 имел определения атрибутов в моделях, пользовательские типы, ленивые запросы, более мощный DSL запросов и так далее. В 2008 году Yehuda Katz был одним из Core-разработчиков проекта, он активно продвигал его и был большой ажиотаж по этому поводу. DataMapper в конечном счете был лучшим ORM, чем ActiveRecord в 2008-9. Было бы несправедливо не упомянуть о том, что Sequel появился примерно в то же время и до сих пор он используется гораздо меньше, чем ActiveRecord, несмотря на то, что является более хорошим решением.
Я был восхищён Merb и DataMapper так, как они принесли надежду, что мы можем сделать что-то лучше и создать здоровую конкуренцию для Rails. Я был взволнован, потому что оба проекта поощряли модульный подход и потокобезопасность, не говоря уже о таких вещах, как просто более хорошие стандарты написания кода.
Оба проекта были в конечном счете убиты Rails, так как Merb был "влит" в Rails, что вылилось в огромный рефакторинг Rails для версии 3.0. DataMapper потерял внимание сообщества и без особой поддержки проект не смог развиваться, как это могло бы быть, если Merb не был бы "влит" в Rails.
С этим решением экосистема Ruby потеряла кучу важных проектов и только Rails выиграли от этого. Является ли решение убить Merb хорошим или нет, это вопрос личного мнения, мы можем только предполагать, что могло бы произойти, если бы решение не было принято. Тем не менее, есть простая истина о конкуренции — это здорово. Отсутствие конкуренции означает монополию, и есть простая истина о монополии — это не здорово. Конкуренция способствует прогрессу и инновациям, конкуренция создает здоровую экосистему, она позволяет людям сотрудничать больше, чтобы поделиться тем, что распространено, чтобы создавать лучший фундамент. Это не то, что происходит в сообществе Ruby.
После того, как Merb & DataMapper были практически уничтожены (в долгосрочной перспективе), создать нечто новое в экосистеме Ruby оказалось крайне сложно. Поскольку внимание людей сфокусировано на Rails, новые проекты были под его сильным влиянием. Прорваться с новыми идеями было трудно, если не сказать больше… так как каждый раз, когда вы что-то демонстрируете, люди просто хотят, чтобы это было похоже на Rails и хорошо работало с Rails. Делать проекты, которые работают с Rails, — трудно, но я вернусь к этому вопросу позже.
После всех этих лет мы в конечном итоге пришли к одному фреймворку, подчиняющему всю нашу экосистему, влияя на тысячи разработчиков и создание стандартов, которые… весьма спорны. Мы потеряли разнообразие экосистемы, которая начала расти в 2008 году и была подавлена Rails.
Эй, я знаю, как это звучит почти как теории заговора, но не относитесь к этому так. То, что я сказал здесь, — это факты с примесью моих личных чувств. Я начал участвовать в DataMapper в конце 2009 года и, видеть как он рушится было очень грустно.
Сложность!
Сложность является нашим самым большим врагом. Люди стали проявлять меньше энтузиазма к Rails, поскольку быстро оказалось, что имея дело с растущей сложностью, он оставляет нас с большим количеством вопросов без ответа. То, что предлагают DHH & co. никогда не было достаточно, чтобы решить многие проблемы, с которыми тысячи разработчиков начали бороться ещё в 2007-2008 гг. Некоторые люди надеялись, что, возможно, Merb/DataMapper принесут улучшения, но теперь вы знаете, что произошло, так что мы все вернулись обратно к Rails в 2010 году, когда Rails 3.0 был выпущен.
Пару дней назад кто-то запостил на /r/ruby ссылку на статью об организации кода с помощью "Service объектов". Это одна из многих подобных статей. Если вы думаете, что это своего рода тенденция последнего времеми, взгляните на статью James Golick от марта 2010 — "Crazy, Heretical, and Awesome: The Way I Write Rails Apps".
Мы говорим о путях совершенствования архитектуры наших Rails приложений в течение примерно 6 лет. Я пытался внести свой вклад в эту дискуссию насколько я мог — статьями, выступлениями на конференциях и работой над многими проектами с открытыми исходниками, которые стремятся решать различные сложные задачи.
Однако подобные аргументы и идеи всегда высмеиваются членами Rails Core Team, и особенно DHH. Это было отпугивающим и обескураживающим для меня, и это причина почему я никогда не пытался внести свой вклад в Rails. Я чертовски уверен, что мои предложения будут в конечном итоге заминусованы. Monkey-patches? Да ладно, не проблема, мы любим нашу 10.years.ago! Новые абстракции? Кому это нужно, Rails — это просто! TDD? Не проблема, она мертва, не беспокойтесь! ActiveRecord раздутая — ну и что, это же так удобно, давайте добавим больше возможностей!
Экосистема Rails, особенно вокруг своей Core Team, никогда не производила на меня хорошее впечатление, и для меня не проблема признать, что я просто боюсь предлагать любые изменения. Это особенно актуально, так как первое, что я хотел бы предложить "Пожалуйста, удалите ActiveSupport" (ха-ха… представьте себе это!).
Ладно, давайте перейдем к некоторым техническим деталям.
Удобство-ориентированное проектирование Rails
Как я уже говорил, Rails был построен с прицелом на удобство использования. Не путайте это с простотой. Только вчера я наткнулся на этот твит, который говорит об этом всё:
Вот как работает Rails, классический пример:
User.create(params[:user])
Вы видите простую строку кода, и вы можете сразу сказать(если вы знаете, является ли User моделью ActiveRecord), что она делает. Проблема здесь заключается в том, что люди путают простоту с удобством. Эту строку удобно/легко написать в вашем контролере и всё сразу заработает, не так ли?
Однако, эта строка кода не является простой, её легко написать, но код "под капотом" чрезвычайно сложен, так как:
- params должны пройти через СУБД-специфические приведения типов
- params должны быть валидированы
- params могут быть изменены с помощью колбеков, включая потенциальные вызовы внешних систем, вызывающие побочные эффекты
- невалидное состояние приводит к установке сообщений об ошибках, которые зависят от внешних систем (например I18n)
- валидные params должны повлиять на состояние объекта, и возможно изменить состояние ассоциированных с ним объектов
- один объект или весь граф объекта должен быть сохранен в базе данных
Это нехватка разделения ответственности, которая всегда наносит ущерб любому сложному проекту. Это увеличивает связывание(coupling) и затрудняет изменение и расширение кода.
Но в Rails мире это не является проблемой. В Rails мире основные принципы дизайна такие как SRP (и SOLID в целом) высмеивают и представляют как "раздутые, ненужные абстракции, увеличивающие сложность". Когда вы говорите, что предпочитаете моделировать варианты использования приложения, используя свои собственные объекты и делать сложные части явными, лидеры Rails скажут вам YAGNI. Когда вы говорите, что вы предпочитаете использовать композицию, которая делает ваш код более надежным и гибким, лидеры Rails, за исключением tenderlove, скажут вам “use ActiveSupport::Concerns”.
Для Rails-разработчика не проблема, что данные, поступающие из веб-формы направляются в глубины ActiveRecord, где Бог знает, что произойдет.
Действительно сложная часть в этой дискуссии — быть в состоянии объяснить, что это первоочередная проблема. Людей привлекает Rails, потому что он дает вам ложное чувство простоты, в то время как то, что происходит на самом деле, заключается в том, что сложность спрятана за удобными интерфейсами. Эти интерфейсы основаны на многих предположениях о том, как вы собираетесь писать и проектировать ваше приложение. ActiveRecord является лишь одним типичным примером, но Rails полностью построен на этой философии, каждая часть Rails работает аналогично.
Я должен упомянуть, что я знаю об огромных усилиях сделать ActiveRecord лучше, таких как введение Attributes API (сделано с помощью серьезного внутренного рефакторинга, который улучшил кодовую базу). К сожалению, до тех пор пока ActiveRecord поставляется с более чем 200 публичными методами и поощряет использование колбеков и concerns, это всегда будет ORM, которая не в состоянии справиться с растущей сложностью.
Изменится ли эта философия в Rails? Я так не думаю. У нас нет никаких признаков того, что что-то улучшится в этом отношении, так как лидеры Rails просто против этого. Простое доказательство — недавнее спорное дополнение ActiveRecord.suppress
, которое было предложено самим DHH. Обратите внимание на то, как он в очередной раз подшучивает над обычными Ruby классами, говоря: "Да, вы можете добиться того же, создав отдельную фабрику CreateCommentWithNotificationsFactory". Ну-ну!
ActiveCoupling
Должен ли Rails являться вашим приложением? Это был важный вопрос, который задают многие после просмотра выступления дядюшки Боба, где он в основном предлагает более сильное разделение между веб-частью и вашим основным приложением. Отбросив технические детали, это хороший совет, но Rails не был разработан с учетом этого факта. Если вы делаете это с Rails, вы теряете всю суть этого фреймворка. По факту, взгляните на то, что сказал DHH об этом:
Его мысли на этот счёт предельно ясны, не так ли? Важной частью является "конечно, является". И знаете, что? Я полностью согласен!
Rails является вашим приложением, и всегда будет так, покуда вы не прилагаете огромные усилия, чтобы использовать его таким образом, для которого этот фреймворк не был предназначен.
Подумайте об этом:
- ActiveRecord призван стать центральной частью логики вашей предметной области. Вот почему он предоставляет гигантский интерфейс с большим количеством функций. Вы можете иногда извлекать часть логики в отдельные компоненты, когда это имеет смысл. Но Rails философия заключается в том, чтобы поместить всё в ActiveRecord, а не беспокоиться о SRP, не беспокоиться о LoD, не беспокоиться о тесной связи между логикой предметной области и слоем сохранения и так далее. Вот как вы можете эффективно использовать Rails.
- Весь "слой" представления в Rails связан с ActiveModel, и как следствие он связан и с Active Record ORM (это может быть и Sequel, но это не имеет значения)
- Контролеры являются неотъемлемой частью Rails-приложения, и сильная связанность имеет место и здесь
- Хелперы также являются неотъемлемой частью Rails-приложения, сильная связанность ещё раз
- Все в Rails, и во множестве сторонних gems, созданных для Rails, происходит через наследование (либо mixins, либо на базе классов). Rails и сторонние gems обычно не предоставляют автономных, повторно используемых объектов, они предоставляют абстракции, от которых наследуют ваши объекты — это еще одна форма сильной связанности.
Имея это в виду, было бы сумасшествием считать, что Rails — не ваше приложение. Если вы пытаетесь избежать этого типа связанности, можно себе представить, какие усилии придётся приложить и сколько из встроенной функциональности вы потеряете. И именно поэтому демонстрация альтернативных подходов в Rails создают впечатление раздутых, ненужных абстракций, напоминающих людям об их "страшных" Java днях. Rails не был построен с ориентацией на низкую связность и компонентно-ориентированный дизайн.
Не боритесь с этим. Примите это.
Нежеланная часть
Несмотря на всё вышесказанное, моя самая большая жалоба на Rails — это ActiveSupport. Так как я уже писал об этом, я не чувствую, что мне нужно повторяться. Я также рекомендую почитать комментарии в той статье.
Единственное, что я хотел бы добавить, что именно из-за ActiveSupport я не считаю Rails желанной частью экосистемы Ruby. Эта библиотека является квинтэссенцией всего неправильного в Rails для меня. Отсутствие фактических решений, отсутствие чётких абстракций, просто куча воркэраундов для решения проблемы под рукой, воркэраунды, которые превращены в официальный API, и карго-культ в результате. Чудесно!
Rails является закрытой экосистемой, и это накладывает плохие требования на другие проекты. Если вы хотите заставить что-то работать с Rails, вы должны позаботиться о таких вещах, как работоспособность при подключенном ActiveSupport, или что ничего не сломается от зверской перезагрузки кода в режиме разработки, или что объекты предоставляются глобально, потому что, ну вы знаете, в Rails всё должно быть доступно везде, для вашего удобства.
То, как работает Rails, требует много дополнительных усилий от разработчиков, создающих свои гемы. Прежде всего, следует ожидать, что ваши гемы могут работать с Rails (потому что, очевидно, все будут использовать их с Rails), и это само по себе является непростой задачей. У вас есть библиотека, которая работает с базами данных, и вы хотите заставить её работать с Rails? Ну вот, теперь вы должны заставить её работать, как ActiveRecord, более или менее, поскольку интерфейс интеграции — ActiveModel, изначально основан на ActiveRecord времён Rails 3.0.
Есть множество ограничений, которые делают интеграцию с Rails весьма трудной задачей.
Вы понятия не имеете, со сколькими проблемами вы можете столкнуться при попытке заставить код работать с горячей перезагрузкой кода в режиме разработки. Rails ожидает глобальную, изменяемую среду выполнения. Для того, чтобы сделать всё еще труднее, они ввели Spring. Этот гем открывает целую категорию потенциальных новых багов, с которыми ваши гемы могут столкнуться, когда вы пытаетесь заставить их работать с Rails. Я настолько задолбался с этим, друзья мои, что мне больше нечего сказать. Мало того, что перегрузка кода в Ruby работает ненадежно, так это к тому же добавляет кучу совершенно ненужной сложности для наших гемов и приложений. Это влияет на всех, кто разрабатывает гемы, которые должны работать с Rails. Никто из команды ядра Rails, несмотря на критику на протяжении многих лет, даже не думал, что было бы хорошей идеей, посмотреть, как это можно было бы сделать лучше. Если бы кто-нибудь просто сосредоточился на повышении скорости загрузки приложения, мы могли бы положиться просто на перезапуск процесса. Кроме того, вы должны действительно использовать автоматизированное тестирование, чтобы удостовериться, что изменение, которое вы только что сделали, на самом деле работает, а не жать F5. Просто к вашему сведению.
Я знаю, это звучит, как будто я жалуюсь, хотя по сути так и есть! Я пытался поддерживать Rails и это было слишком разочаровывающим опытом для меня. Я сдался, я не хочу делать это больше.
Посколько моё решение проблем подразумевало выдирание ActiveSupport, удаление ActiveRecord и добавление нормального слоя представления, который был бы отделен от любого ORM, я понял, что неразумно думать, что это когда-нибудь произойдет в Rails.
Уход от Rails
В результате девяти грёбанных лет работы с Rails и активной работы над многими OpenSource проектами на Ruby, я сдался. Я больше не верю, что нечто хорошее может случиться с Rails. Это моя личная точка зрения, но многие люди разделяют те же самые чувства. В то же время, есть много других, которые по-прежнему счастливы с Rails. Рад за них! Честно! Rails вошёл во всеобщее употребление, у него есть своя сфера применения, он по-прежнему помогает людям и это зрелый, хорошо поддерживаемый, стабильный веб-фреймворк. Я не пытаюсь убедить кого-либо, что Rails в конечном счете плохой! Он просто очень плохой для меня.
Впрочем это имело свои последствия. Именно поэтому я оказался вовлечён в такие проекты, как dry-rb, hanami and trailblazer и поэтому я давно работаю над rom-rb. Я хочу помочь построить новую экосистему, которая, мы надеемся, вернёт тот же самый энтузиазм, который мы все чувствовали во времена Merb и DataMapper.
Нам нужна разнообразная экосистема, нам нужно больше маленьких, целенаправленных, простых и надёжных библиотек. Нам нужны рубисты, которые чувствуют себя комфортно, используя фреймворки совместно с небольшими библиотеками.
Уход от Ruby
Правда в том, что уход от Rails — также начало моего следующего путешествия — ухода от Ruby в качестве основного языка. Я вдохновился функциональным программированием в последние пару лет. Вы можете видеть, что в этом стиле я пишу теперь и на Ruby. Я наблюдаю за ростом Elixir с большим воодушевлением. Я также изучаю Clojure, который в данный момент находится на вершине моего списка "языки для изучения". Чем больше я узнаю, тем больше я люблю его. Моя конечная цель состоит в том, чтобы изучить ещё и Haskell, поскольку я заинтригован его статической типизацией. В настоящее время на работе я программирую на Scala. Я смог очень быстро оценить преимущества статической типизации в нём, несмотря на то, что это была жёсткая перестройка моего рабочего процесса разработки, включая компиляцию и TypeError ошибки. Это освежающий опыт — видеть как мой редактор говорит мне, что я сделал ошибку, прежде чем я добрался до выполнения каких-либо тестов.
Чем больше я погружаюсь в функциональное программирование, тем больше я вижу насколько отстаёт Rails, когда дело доходит до современного дизайна приложений. Monkey-patching, опора на глобальное изменяемое состояние, сложный ORM — эти вещи рассматриваются в качестве основных проблем в функциональных языках.
Я знаю, многие скажут "но Ruby является объектно-ориентированным языком, используй это в свою пользу, вместо того, чтобы пытаться сделать из него то, чем он не может быть". Но это не так. Прежде всего, Ruby является объектно-ориентированным язык с функциональными особенностями (блоки, лямбды и т.д.). Во-вторых, избегание изменяемого состояния является общим, хорошим советом, который вы можете применить в своем Ruby-коде. Устранение глобального состояния и изолирование его, когда вы не можете его избежать, — также очень хороший общий совет.
Как бы там ни было, я покидаю Ruby. Я уже начал этот процесс. Он займёт годы, но это мой путь. Я буду продолжать работать и поддерживать rom-rb, dry-rb, помогать с hanami и trailblazer. Так что не волнуйтесь, эти проекты очень важны для меня, и я счастлив наблюдать рост их сообществ.
Наиболее частая обратная связь
Это заранее подготовленный список обратной связи и вопросов, но он основан на реальной обратной связи, которую я получал.
Заткнись. Rails великолепен и работает очень хорошо для меня.
Это является наиболее распространенным вариантом обратной связи, которую я получаю. Прежде всего, меня беспокоит, что многие люди так реагируют. Мы обсуждаем инструмент, а не человека, нет необходимости воспринимать это так эмоционально. Не поймите меня неправильно, я понимаю, что это естественно "защищать" что-то, что помогло вам, или то, что вам просто нравится, в то же время здорово иногда выходить за рамки привычного мышления, быть открытым к критике и спокойно анализировать её. Если вы счастливы с Rails, это здорово, на самом деле.
Ты просто жалуешься, ты не помогаешь, ты ничего не сделал, чтобы помочь Rails стать лучше, ты не предложил никаких решений описанных проблем
Этот тип обратной связи раньше меня очень злил и огорчал. В момент написания этой статьи, в соответствии с GitHub, я сделал 2435 коммитов в OSS прошлом году. Это было в моё свободное время. Да, я не способствовал улучшению непосредственно Rails из-за причин, которые я объяснил в этой статье. Там слишком много того, с чем я не согласен, и это было бы пустой тратой времени для обеих сторон. Я вносил свой вклад через статьи в блогах, доклады на конференциях и тысячи строк OpenSource кода, которые вы можете найти на GitHub.
Это OSS, просто форкни Rails
Это абсолютно мимо кассы. Нам необходимо разнообразие в экосистеме с хорошим выбором библиотек, а также несколько фреймворков с их уникальным набором фич, делающим их пригодными для различных вариантов использования. Форк Rails не будет иметь никакого смысла. Никто не будет форкать Rails, чтобы пройти через такие испытания, как удаление ActiveSupport и устранение высокой связности от таких концептов как ActiveRecord и т.д. Проще и быстрее создать что-то новое, что другие люди уже и делают (см. Hanami).
Комментарии (398)
VovanZ
24.05.2016 00:53-5> Оба проекта были в конечном счете убиты Rails
Как можно убить open-source проект? Не нравится — форкайся и продолжай пелить так, как нравится.Source
24.05.2016 01:04+9Автор использует несколько драматичный слог, когда вспоминает о Merb и DataMapper, но по большому счёту так и было. Более полное понимание можно получить прочитав статью по ссылке из статьи «Rails and Merb Merge». Если вкратце, то Rails Core Team обещала реализовать модульность и низкую связность, в частности легкость отказа от ActiveRecord в пользу DataMapper или Sequel. По факту всё оказалось не так радужно, как в обещаниях.
А чтобы форкаться и продолжать пилить нужны команда и ресурсы, а команда Merb как раз распалась в результате того «объединения».VovanZ
24.05.2016 13:08-2Но сами Merb и DataMapper никуда не делись ведь. Можно взять последнюю версию до слияния и продолжить работу с этого места.
Если недовольных вроде автора — больше одного, то они вполне могут этим заняться.saboteur_kiev
24.05.2016 19:27+3Вы считаете, что если создатели и основатели Merb и DataMapper опустили руки, и распались, забросив свое родное детище, то посторонние люди внезапно объединяться, схватят и начнут внезапно пилить качественный продукт?
Форки это хорошо, но редко какие форки превосходят оригиналы.
erlyvideo
24.05.2016 15:56команде мерба дали возможность сохранить лицо, разрешив им «объединиться». На самом деле они просто попрогали что-то и бросили, но поскольку все друзья, решились иммитацию сливания.
spotifi
24.05.2016 13:34+1OpenSource без масштабности — ничто. Rails всасывает в себя разработчиков, не оставляя сил другим проектам.
Не обязательно, что другие проекты хуже. А и потом что Rails слишком авторитетен.
Это и не дает развивать другие проекты в RubyVovanZ
24.05.2016 18:49Вы так говорите, как будто чуваки из Rails приходят к разработчикам домой, направляют им пистолет в голову, и под угрозой смерти заставляют использовать только Rails и контрибутить только в Rails.
getElementById
24.05.2016 19:06Речь идет о написании библиотек, которые могли бы пригодиться большому количеству людей. Вам нужно их продвигать, чтобы они действительно стали общепринятым решением. Вам может быть это непонятно, если вы не писали их, но у меня есть пример под рукой: гем dry-types, который занимается приведением типов. Это абсолютно общая и при этом конкретная задача. Но он из коробки не работает с рельсами из-за горячей перезагрузки кода, а если вы захотите подружить его с ActiveSupport, то вас ждет веселый вечер (если вы опытный руби-разработчик, иначе шансов ноль), результатом которого будет запутанное и ненадежное решение.
Source
24.05.2016 23:01гем dry-types, который занимается приведением типов
стоит упомянуть, что это как раз один из многих гемов автора статьи :-)
nemilya
25.05.2016 17:19Надо отметить — что именно (и только) благодаря такому проекту как Rails (и по сути, лично DHH) — мир веб-разработок узнал про Ruby. И по причине, что ruby стало пользоваться на несколько порядков людей чем во времена «до-rails» — Ruby улучшился (по крайней мере по направлению производительности).
Terras
24.05.2016 02:16-2Если учитывать число вакансий в РФ, то я наблюдаю следующую картину:
— число проектов на рельсах снижается (старые все еще поддерживаются, а вот с новыми уже нет).
— растет число проектов на python (django).]
— растет число проектов на js-фреймах.
foxmuldercp
24.05.2016 11:30-5js кросплатформенный, nodejs можно завести хоть на своём телефоне под android (Если там заводили полноценный VoIP Asterisk, то завести nodejs явно проще). Что бы не писалось на js оно может быть использовано в телефоне, телевизоре, VoIP терминале, да даже на десктопе с «полноценным» UI конкретной платформы, внешне не отличимым от привычных контролов, поэтому естесственно, количество проектов на нём будет расти.
2ord
24.05.2016 11:53Хорошо бы перевести эту картину в плоскость цифр, чтобы было ясно где рост замедлился, а где — ускорился.
j_wayne
24.05.2016 08:20+8В статье меня ничего не удивило) Хотел написать длинный и пространный комментарий, но холиварить очень не хочется.
Поэтому только факты.
Стараюсь использовать рельсы, как запчасть, как завещал дядюшка Боб.
Через полтора года новый разработчик с ходу сделал довольно сложное задание.
Сами рельсы довольно продуманы и удобны в мелочах — миграции, ассеты, сиды, енв и пр. инфраструктурные штучки.
Есть с чем сравнить, Play, Spring Boot и т.п. Быстрый релоад в отличии от Play + Scala. Работа с ассетами в Spring Boot напомнился времена голого JSP и сервлетов).
Я не отказываюсь даже от Active Record, но работаю с ним очень осторожно, практически не применяя магии и скрыв за слоем репозиториев.
Стараюсь не использовать гемы, засоряющие глобальное пространство или сильно сорящие в ActiveController/ActiveRecord::Base. Они дают быстрый старт, но большое количество проблем в будущем. Как пример — karmi для elasticsearch. Работать с ним через модель поначалу удобно, но шаг в сторону (скажем маппинги сильно отличаются от схемы бд) — и ты получаешь массу проблем.
Если сначала потратить немножко времени, и написать сервис, используя более низкоуровневый механизм того же karmi, то в дальнейшем все находится под контролем и времени написание функционала уже особо не занимает. Гораздо экономнее, чем потом дебажить и писать воркэраунды.
Многие клиенты на эти практики реагируют довольно нервно. Чем менее привязан к rails community клиент, тем больше шансов, что он отнесется к ним позитивно.vayho
24.05.2016 11:08> Работа с ассетами в Spring Boot напомнился времена голого JSP и сервлетов).
Можно подробнее? Стало интересно в чем проблема.j_wayne
24.05.2016 11:26В основном упреки касаются практически стокового thymeleaf.
Неуклюжие layouts. Еще подключение css/jss (тут скорее отсутствие asset pipeline, он в принципе для Spring Boot имеется, но мне неясно его качество и статус). Сурово как то все. Если вы наведете на средства сделать лучше, буду рад и признателен.
По поводу шаблонов — есть надежда, что jade спасет, но опять же неясно, насколько прямо он реализован именно для Spring Boot.
Оффтоп — а по миграциям — flyway уж очень суров.
Ни в одном веб-фреймворке я не видел миграций, сделанных хотя бы так же удобно, как в рельсах(foxmuldercp
24.05.2016 11:33+2Я пару лет назад изучил и написал веб-бухгалтерию простенькую на Asp.Net MVC 4, и там как мне кажется, тоже много взято из идеологии рельс, по крайней мере оно там очень похоже. Но сменил работу и уишел в хостмастера юникс систем. Но это в будущем дало мне сейчас большой плюс в понимании работы с рельсами теперь — пишу свою панель управления хостингом приложений.
Пробовал еще Perl + Mojolicious, но там слишком много надо реализовывать из того, что в рельсах идет из коробкиSource
24.05.2016 13:54+1Да, Asp.Net MVC 1 — это по сути порт Rails 2.x под .NET
Насколько далеко они разошлись сейчас я не в курсе, но в 2008-2010 годах был настоящий бум — фреймворк аля Rails писали на всех популярных языках :-)Renius
24.05.2016 17:44+1Только не очень понятно почему никто кроме рельсовиков не воспринимает AR нормально, видимо он нигде толком не получился?
Source
24.05.2016 23:05+2Про это ещё Фаулер писал в EAA Patterns писал… Если вкратце, то AR — это одновременно и паттерн и антипаттерн, так как совершенно внаглую нарушает SRP.
Renius
25.05.2016 12:55-2Существует масса вещей которые в наглую нарушают христианство например. Конечно Фаулер молодец, да и вообще святой, с этим трудно спорить. Но есть десятки тысяч счастливых разработчиков использующих AR на успешных проектах.
Source
28.05.2016 02:39А причём тут религия? Вы же сами написали, что AR нигде толком не получился. Я только добавил, что он by design не может толком получиться и неизбежно будет доставлять проблемы в нетривиальных случаях.
Renius
28.05.2016 10:03Это метафора — такой литературный прием.
Ну и AR получился в Rails, 99% задач решаются через AR.Source
28.05.2016 11:01Т.е. Вы с проблемами от использования AR не сталкивались? И никаких неудобств от того, что логика предметной области находится в моделях AR не испытывали?
Renius
28.05.2016 11:40Сталкивался, в детстве. Уже давно бизнес логика не хранится в моделях. Но статьи про «thin controllers fat models» продолжают выходить с завидной регулярностью — это саботаж!
Source
28.05.2016 12:16По-моему важно понимать, что если модели предметной области(классы, содержащие бизнес-логику), у вас не наследуют ActiveRecord::Base, то у вас нет паттерна ActiveRecord в проекте. Возможно вы используете рельсовый AR в качестве странной реализации паттерна Repository, возможно ещё как-то… но только не в качестве ActiveRecord.
Renius
28.05.2016 14:34Наследуют, все что хранятся в базе, но это вовсе не означает, что эти классы должны отвечать за бизнес логику в обязательном порядке.
Source
29.05.2016 00:58это вовсе не означает, что эти классы должны отвечать за бизнес логику в обязательном порядке.
Ну вообще-то это следует напрямую из определения паттерна. Просто у Вас своё оригинальное видение ActiveRecord… поэтому мы тут тёплое с мягким сравниваем.
Renius
29.05.2016 10:19Погодите, нигде не же сказано, что бизнес логика должна быть реализована через AR?
Объект AR не должен знать как снимать деньги со счета, но он должен знать как аз balance вычесть 10.
И нет в этом ничего оригинального, на AR возложены конкретные узкие обязанности.Source
29.05.2016 11:23+1AR — это когда логика сохранения данных помещена в модель предметной области, в ту самую в которой бизнес логика. Тупо по определению:
"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"Renius
29.05.2016 12:29«An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.»
Я не вижу тут диррективы: «все должно быть так и только так», это пример
PaymentService
def withdraw(user, amount)
validate business logic here
user.withdraw!(amount)
end
end
PaymentService.withdraw(user, 10)
Вот я не знаю точно user.withdraw!(amount) — domain logic? помоему не очень но это AR
Логика доступа сохранена, не вижу противоречий
Source
29.05.2016 13:45+4Я не вижу тут диррективы: «все должно быть так и только так»
Такой директивы нет ни у одного паттерна. Но если что-то не совсем так, то это уже не этот паттерн. Всё просто, в AR нет никаких Service, по сути AR — это и есть fat models. Всё остально — это не AR. Не усложняйте.
Renius
29.05.2016 13:53Не вижу никаких усложнений, одни упрощения.
Я не предлагаю вмешивать в AR Services.
AR занимается своими обязанностями. Все остальное занимается своим делом.
Всем добра и Single Responsibility.
У юзера есть метод withdraw, но на юзера нельзя возлагать обязанности соблюдения бизнес логики всей системы, это не его обязанности.
Снять деньги у юзера — не обязанность юзера, а обязанность сервиса банка. Причем банк как сущность может вообще не иметь AR сущностей.
И это не усложнение, это — напротив — упрощение, сегрегация интерфейсов проще, чем порождение франкенштейнов. Собственно и в реальном мире с реальной бизнес логикой пользователь не может снять деньги со своего счета непосредственно.Source
29.05.2016 15:23И это не усложнение, это — напротив — упрощение
Это упрощение кода, но усложнение понятий. Паттерны хороши тем, что дают названия вместо длинных определений. Вместо того чтобы говорить "Каждый класс соответствует одной таблице в БД. Строка таблицы соответствует объекту класса. Логика работы с БД помещена в модель предметной области.", мы говорим одно название — ActiveRecord. И всем понятно, о чём это и чем это плохо в нетривиальных случаях. Когда Вы вводите свою интерпретацию понятия ActiveRecord вместо общепринятого определения, и пытаетесь строить свои выводы на ней, это выглядит очень странно.
Renius
29.05.2016 17:02Подождите
В моем примере AR кладет в БД, и логика работы в БД там же. Но категорически нельзя Генератору светящихся лампочек просить AR что-то делать, но можно Генератор Светящихся Лампочек попросить Модель данных AR попросить что-то сделать.
Вы же предлагаете всю предметную область положить в AR, как быть с сущностями сервисами, которые не хранят свои данные в AR а являются сервисами?
Вот поэтому и получаются жирные модели, когда у нас юзер становится монстром делающим не свойственные ему вещи и отвечающим за не свойственные ему операции, никакой патерн не заставит и _не_заставляет_ меня это делать, и даже не рекомендует. Всему должна быть мера.Source
29.05.2016 18:02Вы же предлагаете всю предметную область положить в AR
Я в этом треде вообще ничего не предлагаю. Я просто констатирую определение этого паттерна и прямые следствия из него.
А то, что Вы по факту не используете паттерн Active Record — это даже хорошо. Путаница возникает из-за того, что Вы думаете, что Вы успешно и повсеместно применяете данный паттерн, хотя по факту отходите от него безумно далеко, и при этом пытаетесь других убедить, что 2+2=5.Renius
29.05.2016 18:14Не понимаю почему вы сделали такой вывод.
Добрая половина документов в проектах обычно AR классы. Но они делают свое AR-ное дело, абстрагируют меня от СУБД, хранят бизнес логику своего поведения. 2+2 все еще 4 для меня.
develop7
31.05.2016 10:15Вы же предлагаете всю предметную область положить в AR
Рельсы «предлагают». Чуть менее, чем все кодогенераторы, примеры в гемах, примеры в литературе, в остальных интернетах и на презентациях предлагают держать бизнес-логику в модели или предполагают, что она лежит в модели.
raacer
28.05.2016 12:22А что Вы делаете, если два далеких друг от друга контроллера выполняют одинаковые действия с какой-то моделью?
Renius
28.05.2016 12:48Я не люблю когда контроллеры выполняют действия над моделями, если они сложнее чем CRUD. В сложном случае, это не работа контроллеров. Стащили у питонистов form_objects, есть сервисы, есть куча всяких чужих паттернов, мы же не в вакууме?
foxmuldercp
24.05.2016 17:53+2mvc 1/2/3 прошли мимо меня, но они всяко лучше asp.net webforms, которые, оспади прости, битрикс в мире дотнета, судя по тому «коду» что я видел и мое счастье, что я ЭТО не застал
Source
24.05.2016 23:08Хаха, а я застал «краешком»… серьёзные проекты на WebForms я не делал, но там реально была жесть, он генерировал совершенно дикий HTML, а AJAX работал через UpdatePanel, т.е. тупо обновлял практически всю страницу… Так что да, ASP.NET MVC в сравнении с WebForms был крут уже с первой версии.
vayho
24.05.2016 12:57Мы намучавшись с thymeleaf в итоге ушли на простенький написанный одним человеком twig подобный шаблонизатор.
Скрипты собираются с помощью Maven, настроили один раз и больше не трогаем.
Ну в целом понятно о чем вы, соглашусь есть неудобные места.
Source
24.05.2016 13:50+3Такой подход не плох и безусловно имеет право на существование. Только фишка в том, что Rails разнообразно сопротивляется такому использованию (как запчасть). Поэтому это требует хорошей дисциплины от всей команды разработки и дополнительных усилий. Впрочем, на этом пути помогают такие проекты, как trailblazer.
Droy
24.05.2016 09:16+2Я, как человек недавно познавший быстрое прототипирование Rails, в когнитивном диссонансе. Только недавно пришел к мысли о том, что вот оно — будущее (в сравнении с PHP). Конечно, я не занимался ничем крупным и толком не работал на Rails, я лишь где-то в начале пути, и понимаю, что эта статья не призыв к действию, но ладно бы это было только мнение автора, он то уже потратил не мало времени и знает о чем говорит. Более того, комментаторы что здесь, что к оригинальной статье, все поголовно соглашаются. И теперь, продолжая изучать Ruby, я мысленно просто буду ждать какого-то подвоха, который ждет меня прям здесь — за углом.
j_wayne
24.05.2016 09:50+4Серебряной пули, как известно, нет. Критическое мышление это хорошо, нужно трезво оценивать плюсы и минусы инструментов. К сожалению, сообщество последователей DHH сильно догматично.
Droy
24.05.2016 10:03Я согласен. Но это я описал свою ситуацию, а не мнение о статье.
С одной стороны, когда отзываются о чем-то плохо, значит это что-то есть с чем сравнить. Потому что в моей ситуации, я сейчас не вижу ничего криминального, что описывает автор. И у меня еще больший диссонанс от того, что вроде бы автор работает долго с Rails и ему, возможно, просто уже он надоел, а возможно, что он попробовал что-то другое.
Сейчас я вижу это так: автору статьи надоели автомобили. Надо стоять в пробках и ездить только по дорогам с определенными правилами. Отсюда возникает мысль: или у автора в гараже стоит летающее авто и он так пытается сам себя убедить, что оно то лучше, или ему просто надоели машины и он собирается ходить пешком. Насколько я понял, летающие машины = elixir и scala по мнению автора?j_wayne
24.05.2016 10:09+2Я думаю, что дело в этом:
> Одной из моих первых задач было… добавить ссылку на что-то на какой-то странице. Мне потребовалось несколько дней, чтобы добавить эту глупую ссылку.
У меня те же самые мотивы «нестандартного применения» рельсов. С чем сравнить есть — я нативно из java. Поддался на то самое «быстрое прототипирование». В этом рельсы хороши, слов нет. Настоящие проблемы начинаются после N месяцев разработки и эксплуатации.
В принципе зная и обходя минусы, можно вполне успешно работать. К сожалению, у клиентов особого понимания такой подход не встречает. Поэтому проще отползти.foxmuldercp
24.05.2016 11:36+2> Одной из моих первых задач было… добавить ссылку на что-то на какой-то странице. Мне потребовалось несколько дней, чтобы добавить эту глупую ссылку
Мне кажется, что это мог быть, например, просто не очень качественный проект, с первых версий рельс, и с большим историческим наследованием, как например, виденная мною ЦРМ с 10+ летней историей разработки с нуля под компанию и тоннами кода, удаление которого может поломать всё в очень и очень неожиданном месте.
prostofilya
24.05.2016 10:11Бросьте это дело, это даже не какая-нибудь захудалая статистика, это просто мнение одного человека. Конечно, не каждый день публикуются статьи по руби, но всё же — просто не обращайте внимания. Программирование оно в целом уже вещь индивидуальная, каждый воспринимает по своему, а кто-то вовсе не воспринимает, а уж отдельный язык — тем более.
Droy
24.05.2016 10:47Я согласен. Но я уже написал, что обратил на эту статью внимание из-за комментариев. Посмотрите, несколько штук здесь, а на оригинальном сайте еще больше, в поддержку автора. Хотя, с другой стороны, вы правы насчет статистики, она бывает и вредна. Может это отписались 1% недовольных, остальные 99% довольных просто игнорируют, потому что не согласны.
foxmuldercp
24.05.2016 11:40Из практики моей работы инженером технической поддержки хостингов в несколько лет — могу с этим согласиться — те, кто доволен — могут привести новых клиентов, но жаловаться «ах вы козлы, у меня ничего не работает, почините быстро» они врядли будут,
А вот с теми, у кого не хватает понимания работы хостинга, например и «шаловливые ручки», и желание кому-то повыносить мозг «быстро сделайте шоб работало а то в суд подам», те звонят и жалуются, но и запоминаются в основном они.
j_wayne
24.05.2016 10:19+1P.S. Для себя, пока что, сайт писал бы исключительно на руби. Просто по другому, см. https://habrahabr.ru/post/301532/#comment_9622742
Cryvage
24.05.2016 13:59+3Насколько я понял из статьи (сам я никогда не использовал, ни Rails, ни Ruby, знаю только самые общие вещи о них, так что, все что я напишу ниже это выводы, сделанные исключительно из данной статьи), проблема в том, что большинство методов и компонентов Rails завязаны на некое глобальное состояние. Еще автор жалуется на засилье наследования. Все это, конечно же, приводит к слишком большой связности между сущностями. В результате это мешает использовать некоторые части Rails независимо. То есть, если используешь, то используешь все полностью. Как следствие, архитектура твоего приложения становится продолжением архитектуры Rails, которую автор считает крайне плохой. Если там действительно все на глобальном состоянии построено, то я с ним полностью соглашусь. Одна вот эта фраза чего стоит: «в Rails всё должно быть доступно везде, для вашего удобства.» — просто убило. Для маленьких проектов это может быть и удобно, но когда проект начнет расти, это будет боль. Ну и, поскольку Rails это главный фреймворк в мире Ruby, всем, кто пишет свои компоненты на Ruby, приходится делать их совместимыми с Rails. Плюс, помимо плохой архитектуры фреймворка, его основные разработчики еще и ведут себя довольно агрессивно, и всем пытаются доказать, что другая архитектура не нужна. Видимо, не хотят все переписывать. Вот это то, что я понял из статьи. В принципе краткое ее изложение получилось.
Droy
24.05.2016 14:10большинство методов и компонентов Rails завязаны на некое глобальное состояние. Еще автор жалуется на засилье наследования. Все это, конечно же, приводит к слишком большой связности между сущностями. В результате это мешает использовать некоторые части Rails независимо.
Мне кажется, что проблема в гемах. Автор, и люди в комментах, это немного затрагивают, намекая, что люди слишком сильно увлекаются ими. Возможно, я неправильно понял.xo8bit
24.05.2016 14:47+1Проблема гемов тоже есть, также как и проблема зависимостей. Сама рельса тянет за собой кучу гемов, плюс для любого проекта наверняка нужно будет добавить еще парочку
(десятков)гемов, вот и выходит зависимости от огромного количества библиотек, у которых в свою очередь свои зависимости, которые могу конфликтовать с другими. И вот да тогда начинается настоящий ад.
Source
24.05.2016 16:40+2Проблема не в гемах, а в том, что гемы должны быть написаны с прицелом на Rails. Т.е. по-большому счёту гемы зависят от Rails. Именно это и не нравится автору. Он, как и многие другие программисты, хочет чтобы гемы были независимыми и простыми библиотеками.
Source
24.05.2016 14:30+2Я, как человек недавно познавший быстрое прототипирование Rails, в когнитивном диссонансе. Только недавно пришел к мысли о том, что вот оно — будущее (в сравнении с PHP).
Не волнуйтесь. У автора статьи в 2007 году были такие же мысли о Rails, что и у Вас. Да и у меня было такое же ощущение в 2008-м.
Просто у Rails есть свои границы применимости, за которыми вся его магия оборачивается против программиста. С накоплением опыта участвуешь во всё более сложных проектах и всё чаще натыкаешься на эти границы. Поэтому со временем эта борьба с фреймворком утомляет и хочется иметь инструмент простой и предсказуемый.
Но Rails в ближайшие годы никуда не денется. И на простых проектах Вы вполне можете оставаться в рамках Rails Way и не испытывать никаких неудобств. А для сложных — посмотрите сразу в сторону trailblazer.Droy
24.05.2016 14:34Спасибо. Я особо не переживаю. Всегда хочется учиться чему-то новому, а в наши дни количество языков/фреймворков растет неутомимо быстро и каждый день появляется что-то новое, да не факт, что стоящее. И тут дело даже не в Rails, а в общей тенденции. За чем гнаться?
spotifi
24.05.2016 14:38Хочется надеятся, что серьезные проекты вы получите, только став опытным разработчиком.
А к тому времени будете уже и сами знать. Не парьтесь понапрасну.Droy
24.05.2016 14:40Так в том и дело, что сейчас для меня Rails отдых/хобби, которое может перерасти в работу. В работе мне приходится использовать PHP.
Хочется надеятся, что серьезные проекты вы получите, только став опытным разработчиком.
Не совсем понял к чему это? К тому, чтобы сам себя не замучал костылями?Source
24.05.2016 17:01+1В качестве хобби и работы на ближайшее время Rails вполне подойдёт. Если говорить о России, то в ближайшие 3-4 года Вы скорее найдёте работу именно c Rails, а не с «летающими машинами», как Вы выразились.
Однако, основная мысль статьи в том, что не стоит идеализировать Rails. Он симпатично выглядит снаружи, но внутри никогда особо не блистал понятностью или удобством. К тому же фреймворк оброс кучей функционала, часть из которого весьма спорна, и стал медленно развиваться в плане действительно важных вещей… В чём-то он уже пытается догнать конкурентов, к примеру, наконец-то добавляя поддержку веб-сокетов.
На тему самого Ruby тоже спохватились и пытаются угнаться за языками, на которые идёт массовый переход: Ruby 3x3, Concurrent Ruby
Fedcomp
24.05.2016 09:51На самом деле очень странная статья. Автор буквально ругает те плюшки рельс за которые его очень сильно любят пытаясь сделать из него строгий фреймворк которым он сам по себе никогда не являлся и не собирался. А по высокой связанности это здравая мысль, тут уже каждый сам выбирает для себя.
Source
24.05.2016 17:20+2Эти плюшки хороши, когда Вам надо сделать блог за 10 минут. Но чем сложнее становится проект, тем больше сложности они в него добавляют.
Очень рекомендую всем, кто имеет дело с Rails, книгу «Rails Anti-Patterns». В ней описаны многие анти-паттерны, на которые в какой-то мере провоцирует сам Rails.
murr
24.05.2016 11:34Продолжайте изучение инструмента и на этом этапе меньше слушайте подобных «особых мнений». Не стоит превращать инструмент в идеологию. Идеальная архитектура — это не решение задачи, к а один путей к ее решению, зачастую достаточно дорогой для компании и, в целом, очень субъективный.
Тут кто-то писал про Coldfusion, мол «фе». Пару лет назад я работал в прибыльной компании из штатов с 10М+ пользователей, добротной архитектурой приложений (не идеальной, но достаточно понятной для внесения изменений и поддержки меняющихся требований бизнеса), все на распоследних версиях фреймворков, в том числе Rails. И вот в один прекрасный момент нас купила фирма-конкурент, которая клонировала изначальную идею нашей фирмы (геймификация ритейла + персональные рекомендации), повела более грамотную маркетинговую политику, набрала больше инвестиций и выкупила нашу компанию (по сути покупался бренд и база пользователей). Весь наш чудесный код выкинули на помойку и заменили ужасным и кривущим кодом на Coldfusion (практически никто из нашей dev-команды не захотел работать с этим ужасом дальше и все уволились). Компания по прежнему процветает. Код по прежнему на Coldfusion. Делайте выводы, господа идеалисты. Рынку не нужна идеальная архитектура приложения, да никто про нее и не знает даже, кроме инженеров.Droy
24.05.2016 11:39+2Спасибо за мнение. Я и не собирался никуда уходить. Статья лишь подтолкнула посмотреть, а что там еще есть интересного в нашем мире. Например, открыл для себя elixir.
Весь наш чудесный код выкинули на помойку и заменили ужасным и кривущим кодом на Coldfusion
Какая жестокая, но реальная правда. Такой «коммерческий» подход я часто встречал в русских компаниях. Команда зарубежная?murr
24.05.2016 11:44> Статья лишь подтолкнула посмотреть, а что там еще есть интересного в нашем мире. Например, открыл для себя elixir.
Это здорово, на самом деле, знать много подходов.
> Команда зарубежная?
Да, все это происходило в LA.
j_wayne
24.05.2016 11:47Если контора большая и есть ресурсы тратить несколько дней на вставку ссылки, почему бы и нет.
Maintainability это одно из качеств проекта, и если его отсутствие можно решить в лоб, ковбоями, да флаг им в руки.
Остальным же это экономит время.murr
24.05.2016 12:30+1> Maintainability это одно из качеств проекта, и если его отсутствие можно решить в лоб, ковбоями, да флаг им в руки.
Я рассмотрел крайний случай, обычно дела с поддерживаемостью обстоят намного лучше, рельсы как раз помогают с этим хотя бы на уровне «что где должно примерно лежать».
alsii
24.05.2016 14:36+1"Компания по прежнему процветает. Код по прежнему на Coldfusion." — ситуация, хорошо знакомая онкологам.
shir
24.05.2016 11:39+7Занимаюсь Рельсами уже… эээ… тоже где-то лет 9. А до этого и на C писал и на Java, и даже на ассемблере доводилось.
Как написали ниже, основная проблемы с рельсами начинаются после нескольких месяц разработки. И, на самом деле, многие проблемы возникают от того что кто-то плохо знает рельсы и попросту делает костыли, эти костыли обрастают своими костылями и т.д. Либо от того что заложил неправильную архитектуру. И дальше уже повезет или нет. Рано заметешь что не так, и есть время на рефакторинг — исправил и проблемы нету. Но чаще бывают, что проблемы живут неосознанными достаточно долгое время чтоб пустить корни, и так просто от них не избавиться, да и клиент со сроками подгоняет, на рефакторинг времени не остается.
А вот тут параллельно решил React.js изучить. Redux'ы там всякие и т.п. Казалось бы вот оно «счастье» с точки зрения архитектуры. И что? Я форму логина делаю уже неделю. Простой логин по email и паролю. Перечитал уже тонну тутариалов. Просмотрел кучу примеров. Вот только для того чтоб понять примеры нужно прочитать еще тонну туториалов. И до сих пор кстати не доделал. Осталось сделать переход на новую страницу. Пытаюсь второй день понять откуда по правильному я должен вызывать это переход. Вы можете представить такую проблему в рельсах? Что там автор про простоту говорит? Что про модульность? Может где-то там и есть в рельсах лишняя связанность которая не дает автору жить и спокойно спать ночами, вот только разрабатывать на рельсах на порядок быстрее чем на других фрэймворках. Быстрее разрабатываешь, быстрее получаешь деньги. У тебя стало 100500 пользователь и рельсы не справляются? (хотя я лично поддерживал проект на рельсах с 10к запросами в минуту, и не сказал бы что это было очень сложно) Вот теперь время подумать и нанять разработчиков которые напишут тебе с нуля под высокую нагрузку хоть на хаскеле, избавившись от кучи костылей…
Это вот мои немного сумбурные мыслиDroy
24.05.2016 11:45+2Спасибо за мнение. Первое, что мне бросилось в глаза в rails-community — это перфекционизм. Я обратил внимание, что разработчики rails как никто другие любят делать красиво. Отсюда у меня сложилось мнение, что rails в первую очередь любят за удовольствие, которое он приносит. И такие комментарии как ваш только подкрепляют мое мнение.
И что? Я форму логина делаю уже неделю. Простой логин по email и паролю.
Как это знакомо! Иногда кажется, что подобные технологии просто навязывают
j_wayne
24.05.2016 11:52+1Мне все же кажется react + redux это несколько edge и поэтому такая кривая входа, в дальнейшем будет проще (может уже и не в react-redux, а в чем то новом).
А что для роутинга используете?shir
24.05.2016 11:57Да, я тоже думаю (надеюсь) что это просто технология еще не устоялась. Но после рельсов все очень сложно. На каждом шаге.
> А что для роутинга используете?
react-router пытюась использовать.j_wayne
24.05.2016 12:01Сам до роутеров еще не дошел, рекомендовать не могу, но посмотрите, может лучше что-то специализированное?
https://github.com/reactjs/react-router-redux
https://github.com/acdlite/redux-routershir
24.05.2016 12:24Так эти библиотеки призваны работать в связке с react-router.
А вот то что мне надо вроде как вот-тут обсуждается. https://github.com/reactjs/redux/issues/297
voicer
31.05.2016 23:52+2Йо
Как известный в очень узких кругах эксперт по реакту, хотелось бы подсказать.
Сначала несколько общее замечание:
React.js — это, все таки, буква V в паттерне MVC. То есть все остальные части (например, бизнес-логика) — она как бы и не должна быть проблемой реакта.
А конкретный хороший рецепт типа из самых последних трендов — используйте redux-saga. Самое то для авторизации.
Ну и последнее, в целом:
Если вы хотите простоты и понятности, смотрите скорее в сторону Angular.js с его богатейшим API на все случаи жизни и огромной коллекцией пакетов.
Если проводить аналогии между Ruby и Front-End JS, то, скорее:
Angular.js == Ruby on Rails
React.js + Redux == Sinatra (скорее, даже Padrino)
Если вам нравится вариант, когда вы с нуля тщательно отбираете только нужные вам либы и сами ваяете архитектуру, которую вам надо — лучше брать React.js
Если вам нравятся примеры типа "блогчат за 10 минут" — это к Angular.jsshir
01.06.2016 11:45Спасибо за ссылку, посмотрю.
А вот angular и прочие ember'ы как-то пробовал и сбежал от них нафик. По мне там никакого упрощения нету, только сложности лишние добавляет, и код еще более запутанный становится. Вот React мне сразу понравился своей идеей.
Razaz
01.06.2016 12:21А не могли бы вы привести примеры больших приложений на связке React+[Some Flux like stuff].
Сейчас в раздумьях по поводу миграции с Angular 1.3. Пока смотрим на Angular 2.0(+Typescript) и Ember.js.voicer
01.06.2016 13:55+1Ну, например:
Facebook, Instagram и AirBnB использует React.js и React Native весьма активно.
По заявлению инженера Facebook, у них больше 20 000 компонентов уже используется. Но исходники закрыты.
Khan Academy использует реакт для большей части рендера. Код открыт:
https://github.com/Khan/perseus
Марафон использует реакт:
https://github.com/mesosphere/marathon
Насколько я знаю, Atom (текстовый редактор от Github) использует React для рендера, код открыт.
Что же по поводу самой проблемы «Angular.js v2 vs Ember.js vs React.js» — так-то все хороши, тут подсказать не могу, самому все нравится. Смотрите куда хочется двигаться.Razaz
01.06.2016 14:13Интересует аналог Discourse, Taiga и тд. У марафона маловат UI :)
То есть фронт не для конечного потребителя, где обычно мало ресурсов и вьюх, а UI для администрирования серверов со сложной UI логикой и тд. Что нить типа 200+ actions с Flux и как это вообще живет и поддерживается :))voicer
01.06.2016 14:45Ну, проблема в том, что если Discource и Taiga уже есть и здравствуют, то какой смысл писать их клоны? :)
А так на реакте дофига всего пишется. В гугл-трендах запрос react.js обогнал angular.js
Общий список: https://github.com/facebook/react/wiki/Sites-Using-React
Те, что конкретно мне нравятся:
Razaz
01.06.2016 16:06Я не про клон. Пример — админка серверного приложения. 50+ ресурсов, вьюх и компонентов за сотню. В связке Angular 1.3 + ui-router + свой слой для REST живет отлично. И поддерживается достаточно легко. По сложности Jira или VisualStudio Online.
Просто хотел посмотреть как очень большое приложение живет от и до.
По sprintly: https://github.com/sprintly/sprintly-kanban/tree/master/app/actions вот тут получается 50+ файлов будет жить?voicer
01.06.2016 16:14Ну я например писал онлайн-бухгалтерию на React.js + Backbone.js: http://imboss.ru/.
По размеру там в районе 1000 компонентов.
Но вот так, чтобы выложить вам ссылку на открытый код — боюсь, не знаю таких.
Про srpintly — вообще сами actions спорная инициатива, я бы не так сделал, но получается да, у них там и будет жить. Возможно по подпапкам еще разнесут, не знаю уж, на какой базе — каждому отдельно или будут группировать по смыслу.Razaz
01.06.2016 16:57Нашел:) Вдруг кто наткнется на вопрос.
WP Calypso
В целом близко к тому, что хотелось посмотреть и организация проекта норм.
voicer
31.05.2016 23:55Вот еще хорошую ссылку хочется подкинуть: https://github.com/mxstbr/react-boilerplate/
Это типа boilerplate для Universal App на базе React.js + Redux + Reselect.
Примечателен тем, что все используемые библиотеки типа bleeding edge.
Вам будет полезно посмотреть, как делается авторизация с unidirectional data flow.
Envek
24.05.2016 14:09+1Если вам нравятся Рельсы, не обязательно с них уходить. Просто следует помнить, что они заточены под быстрое создание несложных приложений. Более сложные приложения на них писать можно, но нужно добавлять к Rails другие инструменты, которые будут помогать масштабироваться. Например, Trailblazer.
См. https://habrahabr.ru/post/301532/#comment_9623484
yaBliznyk
24.05.2016 18:09+3Находясь в подобной ситуации могу вас заверить, что изучение руби вам не повредит. Сам язык очень хороший, автор статьи даже указывает на то, что будет саппортить некоторые библиотеки на Руби.
Из личного опыта — написание парсера на руби было очень веселым и быстрым. Книги по руби читаются легко. Все, что не касается напрямую Rails — очень удобно и просто.
Rails так-же имеет смысл установить, по играться, развить своё восприятие данного фрэймворка. Очень многое вам покажется правильным и вы решите использовать подобные схемы решения задач на PHP.
Используйте Руби в качестве трамплина для вашего развития как программиста в целом.
caballero
24.05.2016 09:42-3Создается впечатление что рельсы ждет судьба ColdFusion. Тоже в свое время выглядел круто.
sl_bug
24.05.2016 09:53+5Комментарии к статье от Yehuda Katz
https://twitter.com/wycats/status/734991937862795264
https://twitter.com/wycats/status/734992848987258880
https://twitter.com/wycats/status/734993723029868544
Virviil
24.05.2016 10:05+13Статья просто потрясная! Очень коррелирует с моими мыслями по поводу Rails.
Показушная "простота" работает хорошо только до тех пор, пока не надо чуток выйти за рамки. В тот момент когда это происходит, совершенно теряется понимание "что делать", код превращается в макароны из грязных хаков и теряет полностью свою простоту и привлекательность.
ЗА адептами Рельсов очень интересно наблюдать тогда, когда они пытаются написать что-то на… Ruby! ActiveSupport — это по сути новый язык программирования.
По моим ощущениям, создание rails приложения — это сборка камней/гемов — как в лего, только вся сложность начинается в тот момент, когда эти кубики надо собрать вместе. Когда гем подключается одной строчкой и делает кучу вещей — я его просто боюсь! А такие "батарейки" — везде.
Самое главное, API Рельсов не очевидное, не однозначное, и разработчика на Рельсах по сути ничего не заставляет его как то изучать и понимать. Можно создать десяток сайтов на Рельсах и так и не узнать, что скрывается за волшебным словом Rack, и чем middleware гемы отличаются от "не middleware"!
Ничего не имею против ActiveRecord, если чувствовать пределы, его использовать очень удобно. Но когда можно забрать модель из формы через :params и сохранить как есть одной строчкой как в статье — это рождает миллионы вопросов на SO — "Почему сохраняет пустую модель/не сохраняет ничего" которые просто нереально чинить — там всего одна строка!)
Очень бы хотелось обсудить предыдущую статью автора, в которой он осуждает monkey patching: если не ActiveSupport, то как? Если многим это удобно, то писать RFC к самому Руби? 10.years.ago — возможно это должно быть в стандартной библиотеке?
А что касается проблем ООП — мне кажется Руби — не показатель плохости такой парадигмы. Monkey patching и вся рефлексия — это по сути нарушение инкапсуляции. И это то, что самое крутое в руби, с его method_missing, символами и открытиями классов в любом месте вашего кода. А ведь именно на этом строится такая "классная" ActiveRecord, роутинг, ActiveSupport. Оставь в Рельсах "чистое" ООП — и от всей прелести Релься ничего не останется.
Source
24.05.2016 23:19Очень бы хотелось обсудить предыдущую статью автора, в которой он осуждает monkey patching: если не ActiveSupport, то как?
Нет ничего плохого в отдельных модулях для подобных методов, не обязательно их добавлять к базовым классам. По началу это даёт определённый вау-эффект, но не даёт реальных преимуществ, а вот весёлый дебаг временами обеспечивает.
igrishaev
24.05.2016 10:14+15Чел перерос технологию и закономерно направился в функциональное программирование. Все с порядке вещей.
LifeKILLED
24.05.2016 10:45+1Спасибо за перевод. Интересная статья. Никогда не программировал на Ruby, было очень интересно сложить хотя бы такое поверхностное представление о достоинствах и недостатках Rails. Автора я понимаю, сам не люблю ограничивать себя набором готовых функций, особенно, если они вызывают проблемы с не интуитивным решением (виной тому моя криворукость или желание выйти за рамки — решайте сами).
Я так понял, главная проблема автора не столько в самом Rails, сколько в сообществе. Поскольку всё-таки можно сделать проект по всем правилам, создать обёртки вокруг функционала Rails, нагородить собственных классов и организовать всё так, чтобы проект был масштабируемым. Но любители Rails просто привыкли пользоваться готовыми функциями и мириться с возникающими проблемами. Конечно, с такой разницей во взглядах работать с этими людьми — одно мучение.
"… дает вам ложное чувство простоты, в то время как то, что происходит на самом деле заключается в том, что сложность спрятана за удобными интерфейсами"
Эта фраза актуальна вообще для всего, и не только в компьютерном мире :)j_wayne
24.05.2016 12:06> Поскольку всё-таки можно сделать проект по всем правилам, создать обёртки вокруг функционала Rails, нагородить собственных классов и организовать всё так, чтобы проект был масштабируемым. Но любители Rails просто привыкли пользоваться готовыми функциями и мириться с возникающими проблемами. Конечно, с такой разницей во взглядах работать с этими людьми — одно мучение.
Точные у вас формулировки)
Можно. И да, так и есть, мучение, борьба Дон Кихота с ветряными мельницами.LifeKILLED
24.05.2016 19:38Извините, ничего конкретнее написать не мог. Но поскольку прочитал статью с интересом (пусть и отнесясь к ней, как к поучительной истории из жизни), решил выразить переводчику благодарность, отписавшись под ней :)
«Борьба с ветряными мельницами», кстати, очень интересное занятие, сравнимое с поиском сокровищ по пиратской карте.
Source
24.05.2016 23:25Спасибо за отзыв :-)
Я так понял, главная проблема автора не столько в самом Rails, сколько в сообществе.
Автор хочет привлечь внимание сообщества к тому, что есть жизнь за пределами Rails. Как на Ruby, так и на других языках. В частности он является автором более чем десятка полезных гемов для Ruby.
raidhon
24.05.2016 10:45+1Вот сидел я тут и подбирал себе фреймворк под новый проект. Удобство или Скорость. Rails или Beego. Или вообще на Django опять писать. А может вобще на Sails.js ведь за асинхронностью будущее.
Решил старый конь борозду не испортит.
Развернул значит я Rails 5, конфиги уже прописал, даже web socket новый успел подергать.
И тут прочитал эту статью +_=dmitry_ch
24.05.2016 11:00+1А что мешает теперь? Ведь раз вы все себе под задачу выбрали, то кто после статьи вам мешает так же хорошо ваш проект реализовать?
Я куда чаще видел, когда человек, поначитавшись, бросает привычную технологию, строит что-то на новом (плюясь, разбираясь, но, в общем, радуясь), а потом понимает, что но новом он писал не так круто, как знаток нового (наоборот, прорывались подходы старого, уже отвергнутого), и что новое также нужно поддерживать.
В общем, «старый конь», пока он решает задачи, почему бы и не поработал? Тем более что выбирать сегодня инструмент, которые закроет все проблемы проекта на долгие годы — это нереально, и в чем-то безответственно. Даже банальный движок форума можно писать на php+mysql (и поиметь в будущем более-менее понятные проблемы — но «потом»), а можно на oracle+хранимые процедуры+веб-приблуды от уважаемого Oracle — будет круто до небес, никто никогда себе это не поднимет (стек сильно не массовый), и проект не взлетит, поддержка станет до небес дорогой, и будет вопрос «а зачем».raidhon
24.05.2016 13:01В среде описанных фреймворков мне не нужно разбираться. Проверено и пройдено.
Rails выбран из за банальной лени, быстро и без заморочек собрать проект.
Но у Rails низкая производительность и эту проблему придется решать почти сразу. Первая тысяча пользователей онлайн и начнется.
Кеширование, рефакторинг кода, оптимизация запросов. Здравствуй Raw Sql прощай Active Record. Привет Turbolinks и тд.
Когда на Beego этот момент настанет ой как не скоро. Но это компилируемый язык писать дольше, модулей к фреймворку почти нет, шаблонизатор со странной точкой в переменной ( но это я уже докапываюсь его можно заменить на Pongo2 ).
Да и поддержка Golang это вам не в Ruby ковырятся.
Ещё есть Sails.js удобный websocket из коробки ( а он мне понадобится ), встроенный Grunt ( Pipeline тут даже рядом не валялся ), большое количество модулей и бодрая производительность. Но опять же это Node, асинхронный код, не спасёт даже async.
После Ruby это смотрится и читается как адов ад.
Я напоминаю себе маленького ребенка которому предложили несколько конфет, а взять можно только одну )).
Лень побеждает уже начал делать на Rails, поздно пить боржоми почки уже отказали!XimikS
24.05.2016 14:38Если у вас 1000 активных пользователей, то вам придётся озаботиться кешированием в любом случае.
Spiritschaser
24.05.2016 18:06По-моему, вы доросли до микрофреймворков. Например, я сейчас на python использую flask + peewee + pyjade + webassets (css сразу в sass, html сразу в jade), хочу прикрутить marshmallow для работы с json и angularjs, а виджеты angular'a делать автоматом с помощью flask-triangle… будут нужны сокеты или асинхронные запросы — просто добавить.
raidhon
24.05.2016 22:07За 15 лет разработки я думаю я уже вырос из них )
Из микрофреймворков в Python я работал и c Flask и с Bottle, а ещё с Falcon и даже Muffin (повелся на слово async ) успел помучать.
Когда нужно что простое и времени на эксперименты хватает, то да можно.
Но времени нет почти всегда, поэтому Full-stack фреймворк и вперед к деньгам!
А для экспериментов я предпочитаю Node.js там есть Express, Koa и Hapi к ним в NPM столько пакетов для извращений до конца жизни хватит.
unabl4
24.05.2016 20:40Это ещё бабушка на двое сказала, что у проекта будет 1000+ пользователей онлайн.
Если так и будет (дай-то Бог каждому проекту) — то просто кидай в него железом и всё, а потом перепишешь на чём-то более высокопроизводительном (если это вообще нужно будет к тому моменту). Большенство проектов не взлетит так и так и смысла делать всё круто с самого начало — нуль ))raidhon
24.05.2016 22:14Тут все просто это не замшевелый стартап с 5 рублями.
Когда есть деньги они и из контекста столько приведут не первый раз с ними работаю.unabl4
24.05.2016 23:44В людом случае, рельсы хоть и не самый высокопроизводительное решение (GIL и всё такое) в конечно счёте все решит выстроенная архитектура, имхо. Можно разбить приложение на части (микросервисы) и самые медленные переписать на чём-то другом.
А вообще, как мне кажется, чем дальше в сторону хайлоада, тем больше общих решений будет у всех языков и фреймворков — кэширование, низкоуровневое ковыряние и т.д.
Source
24.05.2016 23:28+1Начали и начали. От ещё одного проекта на Rails никому хуже не станет )))
А на будущее посмотрите ещё и в сторону Elixir+Phoenix. Конфет много не бывает xDvoicer
01.06.2016 00:16+1А там и вовсе в сторону чистого Erlang можно глянуть, ну и в качестве веб-фреймворков «Chicago Boss» или «N2O».
Красивейший язык, в самом деле.
За один синтаксис в стиле пролога можно уже простить многое.
Хотя, непонятно, зачем я это пишу — любой человек, изучающий эликсир, как минимум, погуглит, что такое Erlang ;)develop7
01.06.2016 01:33+1А там и вовсе в сторону чистого Erlang можно глянуть
глянуть — и обратно, к pipe operator, макросам, ecto и прочей прелести
voicer
01.06.2016 02:36+1/me Поднимает руки
Извините, спорить не буду. Мне нравится и elixir, и erlang. И, кроме того, я искренне считаю, что изучение erlang как минимум не повредит, а как максимум сильно расширит горизонты и возможности изучающего.raacer
01.06.2016 08:12А что бы Вы все-таки порекомендовали предпочесть разработчику, переходящему с Python/Django? Мне нравится Python своей четкостью и гибкостью, и Django своим порядком и ОО стилем. В Ruby и Rails я усмотрел какой-то хаос, оттого и предпочел Python/Django. Что будет ближе в таком случае?
voicer
01.06.2016 14:33+2Эм. Сложно что-то подсказать при такой постановке задачи. Разработчик переходит с Python/Django — а куда? :)
Вообще, я так понял из ваших комментариев ниже, вы уже много лет в вебе, поэтому первое что я посоветую — серьезно задумайтесь о смене фокуса. Неужели вам совсем неинтересны, например, IoT, VR? С вашим опытом на них реально найти вакансию джуниора как минимум, а в этих областях даже джуниоры получают вполне достойную плату, не меньше чем senior в вебе. Ну и кроме того, часто в этих проектах нужны как минимум веб-странички, а то и полноценные приложения, написанные на базе Electron.
По поводу же смены технологии именно для веба… Настоятельно рекомендую посмотреть и попробовать функциональный язык вроде Erlang|Closure|Haskell, крайне освежает. Тут нужно заметить, что перечисленные языки — они, вообще-то, очень сильно разные, с разной концепцией, и лучше посмотреть каждый.
Возможно, вы и не перейдете на них, но очень много полезного для себя найдете.
Не бойтесь тратить время на какой-нибудь Erlang, работы конкретно под функциональщину хватает: https://functionaljobs.com/.
Еще из неплохих вариантов в вебе я бы посоветовал Go и JS. Первый предлагает большую производительность и очень крутой параллелизм, второй мультипарадигменный, с возможностью писать и в ООП и функциональном стиле по желанию пользователя. И там и там есть работа, есть живая экосистема с огромным количеством библиотек.
Ну и чисто для вдохновения и расширения горизонта, хотелось бы посоветовать глянуть на вот эти два языка:
- Фунциональщина под веб, пока что очень новый язык, использовать осторожно, но заложенные концепции просто офигенны: http://elm-lang.org/
- Настоящее ООП в стиле SmallTalk. Как и в Ruby, все объект. После знакомства с этим языком вам динамичный руби с открытыми классами (вы еще называете это хаотичным) покажется заскорузлым монстром, на котором нельзя толком метапрограмминг писать. К сожалению, из-за своей динамической природы этот язык довольно медленный, так что годится скорее для изучения в академических целях, писать на нем реальные программы я бы не стал. Но для расширения сознания, получения нового опыта и оттопыривания чакр крайне рекомендую взглянуть.
raacer
01.06.2016 16:16+1Спасибо!
Вопрос не в деньгах и вакансиях, а в продуктивности использования того или иного языка. Меня в основном интересует веб и сетевые приложения.
Вы предлогаете три разных языка: Erlang|Closure|Haskell — я них сейчас в основном и смотрю, и еще Scheme, Comron Lisp и Elixir тоже привлекают внимание. Дело в том, что мне нужно решать реальные задачи, и хотелось бы начинать сразу с практичного и мощного языка. Среди прочих равных выбрал бы тот, что можно компилировать в JS. А проблема в том, что я не могу среди них выбирать, так как совершенно не разбираюсь в ФП. Когда выбирал между Python и Ruby — было гораздо проще, так как я знал, что именно меня не устраивает в других императивных языках с поддержкой ООП: строгая типизация, негибкие списки параметров функций, отсутствие множественного наследования, отсутствие хорошей поддержки метапрограммиравания, нечитабельность или громоздкость языка, непоследовательный синтаксис.
Теперь же я просто не знаю, как выбирать. Стоит ли промянять мощные макросы лисп-подобных языков на декларативность полностью функциональных языков? Не будет ли мешать статическая типизация так же как в ООП? Нужна ли мультипарадигменность и поддержка ООП, и какую проблему они решают? И т.д.vlad72
01.06.2016 17:04+1А на Nim не смотрели? Вроде и компиляция в JS, и ФП есть, и мощный, даже серия статей здесь была про то, чем он хорош.
Мне даже интересно потом Ваше мнение будет…raacer
01.06.2016 17:43Не могу ничего про него сказать кроме того, что он меня не привлекает, разве что кажется любопытным. На вид он кажется больше объектно-ориентированным, чем функциональным. А то, что там есть поддержка ФП — так это и в Python есть, и в Ruby, и в JS. Только эта поддержка весьма слабая.
Меня лично сейчас интересует прежде всего ФП в чистом виде, а также его сочетание с метапрограммированием.
Source
01.06.2016 21:08+1Nim логичнее сравнивать с Go, Rust, Crystal.
Язык интересный, но стабильной версии пока нет, да и библиотек пока тоже немного. Причём ощущение, что разработчики слегка подзабили в этом году… После выхода версии 0.13 уже 5 месяцев никаких новостей от них не слышно. Коммиты есть, но активность в разы меньше, чем в прошлом году.vlad72
01.06.2016 22:09Знаю, что platoff сравнивал его с Go и Rust (не в пользу последних), других статей пока не встречал. Столько он на него надежд возлагал. Интересно было бы узнать его впечатления после почти года знакомства.
platoff
02.06.2016 00:14почему возлагал? все прекрасно — вот первая ласточка от наших ребят — обернули Unreal Engine 4 — и игрушку пишут: https://github.com/pragmagic/nimue4, но это, как говорится только начало, на подходе еще сервер сайд и веб/десктоп приложения на Nim
Source
02.06.2016 11:52Почему возлгал то? На офф.сайт зайдите, там последняя новость в январе была. По-моему, это маркетинговая недоработка… мало что-то делать, надо не забывать об этом писать.
Source
01.06.2016 21:26+1Вообще для всех кто выбирает язык для веб-разработки, я бы посоветовал такой алгоритм:
- определяете наиболее популярный веб-фреймворк
- ищете актуальную книгу "Programming НазваниеФреймворка" или "Web Development with НазваниеФреймворка" или "Web Development with НазваниеЯзыка"
- Бегло читаете https://learnxinyminutes.com/ по языку, а затем найденную книгу
- По результатам прочтения книг делаете осознанный выбор что вам ближе
- Изучаете сам язык и вдумчиво перечитываете понравившуюся книгу
Source
01.06.2016 21:37+1По вышеназванным языкам это книги:
Elixir — Programming Phoenix
Erlang — N2O — No Bullshit Sane Framework for Wild Web
Clojure — Web Development with Clojure
Haskell — Developing Web Applications with Haskell and Yesod
foxmuldercp
24.05.2016 11:44+1Вот кстати, про вебсокеты на 5х рельсах — я пытался осилить официальный гайд с этим примером чатика, но так и не осилил — нет ли у Вас желания по горячим следам написать статью, думаю, многие бы оценили
raidhon
24.05.2016 13:12Желания нет. Но могу помочь ссылками.
Прочитал тут http://www.rusrails.ru/action-cable-overview, запустил этот пример https://github.com/rails/actioncable-examples.
Да ещё пример запустил на свежей Rails — 5.0.0.rc1 на beta 3 что то не завелось.
hardtop
24.05.2016 13:17+2А что не так с Django?
dromanow
24.05.2016 15:07+1С Django в принципе много чего не так, но применительно к задаче автора комментария думаю ключевое это отсутствие вебсокетов в 2016 году.
hardtop
24.05.2016 17:09Ну, вебсокеты — они ж не всем нужны (игры и чаты — там да). А что именно Вас не устраивает в Django? (не для разжигания бесплодных споров, но информации для)
Envek
24.05.2016 17:42А как же оповещения о новых комментариях и прочих обновлениях на всех социально-ориентированных сайтах? На хабре, вон, вручную кнопку «обновить» нажимать надо. А в том же гитхабе новые комменты в ленте сами появляются.
dromanow
24.05.2016 18:28+1Это вопрос для целый статьи :) Если очень кратко из последнего наболевшего: очень не нравиться «тупая» орм, тяжелые и непредсказуемые FormSet, нарушение одного из важных принципов дзена питона «явное лучше чем не явное».
Я понимаю что скорее всего это вопрос не столько к Django сколько к его области применимости. Но дело в том что начиная долгоживущий проект я вряд ли могу предсказать как он будет развиваться и как скоро мы упремся в границы Django-песочницы. И я не готов рисковать своим временем и деньгами выбирая столь ограниченный инструмент для долго живущих проектов. Если дело касается классического контент сайта (лендинга, страницы компании, какого-нибудь блога, вот этого всего) то к Django вопросов нет, отрабатывает на все деньги. Просто я такими проектами не занимаюсь.hardtop
24.05.2016 18:39Спасибо! А что используете в качестве «тяжёлой артиллерии» для догло живущих проектов? Ну, или, что стоит из нового рассматривать?
dromanow
24.05.2016 22:20Как раз то "тяжелой артиллерии" стараемся избегать в последнее время, предпочитая легкие компоненты со слабой связанностью. Сейчас в основном строим на базе tornado, т.к. активно используем вебсокеты, и планируем переход на асинхронную работу с бд и чистый sql. До этого вполне успешно использовали Flask. Когда кодовая база бизнес логики гораздо больше чем непосредственно веба преимущества Django совсем не очевидны, а гибкость Flask решает. Захотели, подтянули монго, не понравилось, поменяли на sqlalchemy.
Так же смотрим за рамки питона, интересны Java Spark или, чем черт не шутит Clojure Luminus ))
raidhon
24.05.2016 22:23С Django все отлично и к комментариям ниже по поводу сокетов.
django-websocket-request и вопрос решен причем в формате моего любимого Sails.js.
Rails и Django самые ленивые фреймворки, отличный синтаксис языков и быстрая разработка без напряга.
Не было бы Rails пилил бы на Django.
Envek
24.05.2016 14:00+5Продолжайте использовать Rails. Просто помните, что одних Rails не достаточно. Точнее, недостаточно трёх букв MVC, которые есть в них.
Пока у вас приложение маленькое (5-10 моделек) и с не очень большой логикой, всё будет окей. Когда число моделей перевалит за 50, а просто список функциональности перестанет помещаться в голове одного человека (а ещё помножьте на скорость разработки) — вы запутаетесь и будете погребены под приложением.
Решения есть, их много, но, к сожалению, ни одно из них пока не стало стандартом. Посмотрите на Trailblazer (мы его используем) — он добавляет новых уровней абстракции и этим снимает нагрузку с существующих букв MVC. Посмотрите, какие проблемы, решает этот инструмент — если они вас не волнуют, то вам ещё рано. Я же когда читал книжку по нему, плакал над каждой, потому что мы страдали просто от всех: к примеру — у нас было 500+ строк коллбэков в некоторых основных моделях, например.
AndreyHenneberg
25.05.2016 11:54Про коня в контексте данной статьи и комментариев выше. Просто ассоциация, поскольку на Ruby никогда не писал, но с описанными проблемами сталкивался в нескольких других «местах». Так вот, полностью эта пословица звучит так: «Старый конь борозды не испортит, но и глубоко не вспашет». Мне кажется, что это стоит помнить, выбирая навороченные «коробочные» фрэймворки Rails или Django, потому что иногда лучше собрать свою «коробочку», как это делают во Flask.
eugzol
01.06.2016 20:38На Phoenix и Elixir ещё посмотрите. Обещают продуктивность Рельсов с производительностью почти на уровне компилируемых языков.
Anton_Zh
24.05.2016 10:45+4Многие из перечисленных здесь недостатков характерны для Yii/Yii2
samizdam
24.05.2016 23:00+1Насколько я могу судить, Yii немало и концепций позаимствовал из Rails, и задачи аналогичные решает в той же нише. Итог, как говорится, предсказуем.
После нескольких лет работы с Yii, на проекте сложнее среднее много усилий начинает уходить на борьбу с «удобствами» ActiveRecord, которую нельзя выкинуть из приложения и нагромождения собственных абстракций чтобы разбавить изкоробочную связанность компонентов фрейворка.
И да, начинаешь мечтать о DataMapper =)Anton_Zh
25.05.2016 02:46+1Да, совершенно согласен. Сам сталкиваюсь с этими же проблемами. Пытаюсь решать с помощью паттерна «Репозиторий» поверх ActiveRecord
erlyvideo
24.05.2016 11:48+1>DataMapper в конечном счете был лучшим ORM, чем ActiveRecord в 2008-9.
тут и кроется отличие профессиональных программистов от веселых хипсто-хакеров. Датамаппер никогда не работал. Я сделал один проект на этом кошмаре и слава богу он разорился и закрылся до того, как кто-то начал его поддерживать.
Рельсы в некоторых вопросах огорчают, так что поменьше гемов пожалуйста, их итак слишком много.develop7
24.05.2016 14:05+2Ну не знаю, я в 2014 работал в проекте с Datamapper. И оно вполне себе работало, даже несмотря на отсутствие поддержки разработчиком. Так или иначе, ползать по его коду было всяко приятнее, чем по AR.
Envek
24.05.2016 14:19+1ActiveRecord в 2008-м (2-е рельсы?) и ActiveRecord в 2016-м (5.0) — это две большие разницы.
В 2.х ActiveRecord был ужасен, в 4.х он уже был хорош (в первую очередь благодаря arel'у). И все 4-е рельсы он продолжал сильно перепиливаться (помнится, один мой pull request пришлось сильно переделывать с 4.1 на 4.2).
erlyvideo
24.05.2016 16:00ужасен — это не совсем то слово, которое отражает реальность.
Читать один файл на 3 экрана гораздо проще, чем 10 файлов на пол-экрана каждый.
Простое распиливание кода на куски, которые вроде как должны быть в разных файлах по сути только ухудшает читаемость и не дает из коробки расширяемость кода.
Source
24.05.2016 17:46Ох, не напоминайте мне про Arel. Надо было мне как-то раз его подружить с PG-функциями без скобок, типа current_date.
Для тех, кто не знает, у Arel есть возможность вызывать SQL-функции, но только со скобками
Account.where{created_at == :now.func()} # работает Account.where{created_at == :current_date.func()} # не работает
В общем, пока я воркэраунд писал, достаточно ознакомился с его исходниками. Мягко говоря, там реальный треш. Если не согласны, попробуйте решить вышеописанную задачу. У меня на тот момент была версия arel-4.0.2.sl_bug
24.05.2016 17:52+1А зачем тут arel?
Account.where('created_at::date = current_date')
Source
24.05.2016 23:42Ахах, ну видимо придётся контекст задачи описывать…
Нужно было предоставить пользователю возможность создавать сегменты по определённым моделям. Т.е. пользователь накидывает критерии в интерфейсе, а мы по этим критериям с помощью Arel генерируем SQL-запрос. Естественно давать пользователю вводить raw SQL в планы не входило. Переписывать без Arel было бы долго, потому что для заказчика это выглядило просто «а давайте добавим ещё 1 тип критериев в форму». При этом требования к скорости результирующего запроса были очень высокими, т.е. обернуть current_date в SQL-функцию тоже не прокатывало.
Envek
24.05.2016 19:00+1В вашем случае, может, не стоило тогда даже и рассматривать
current_date
как функцию?
Arel — это, ИМХО, вещь не для прикладных разработчиков, а для разработчиков ActiveRecord'а и прочих вещей, напрямую общающихся с базой. В его исходный код не заглядывал, но простым он точно не будет, ведь его задача — генерить разный SQL для разных БД с их особенностями. Например, oracle_enhanced адаптер вместе с последним arel'ом научились генерить разные SQLи типа SELECT для 11-го и 12-го Ораклов.
Но ваша правда, даже документации толковой к нему нет, а чем хардкорнее вещь, тем она нужнее.
Source
24.05.2016 23:49Я чуть выше описал зачем это было нужно. Именно как построитель запросов он и использовался, т.е. по самому прямому назначению.
не стоило тогда даже и рассматривать current_date как функцию?
Как не рассматривай, а как-то надо было её запихнуть в результирующий SQL и обойдясь при этом без raw SQL. Реальнее оказалось запихнуть как функцию )))
erlyvideo
26.05.2016 09:52+2потому что они все как писали под мускль без индексов, так и продолжают под него писать.
dima007
24.05.2016 14:11-1Автор использует вполне ожидаемые аргументы. Active Record заменить на DataMapper. Но насколько знаю, по производительности один другому не проигрывает. Это просто вопрос вкуса
dromanow
24.05.2016 14:11+3Местами ловил себя на мысли что читаю про Django. Похоже это болезнь всех мега фреймворков…
Anton_Zh
24.05.2016 14:52+1Что насчет Symfony2?
dromanow
24.05.2016 15:09Не знаю, не приходилось использовать на практике, если с ним все хорошо то я за него рад ))
dima007
24.05.2016 15:51Там в основном споры об архитектурных решениях в Doctrine2 и версионность пыха для Symfony3
Phantaminuum
24.05.2016 18:06Symfony2 (и 3), ИМХО, противоположность рельсам. Мало чего работает по одной команде из коробки, что-то приходится делать руками, что-то докручивать, донастраивать. В общем, полная противоположность принципу convention over configuration. Но это окупается в крупных проектах, проще дается построение правильной архитектуры, легко выкинуть и заменить не устраивающий модуль хоть из ядра фреймворка — огромная гибкость. И конечно за это приходиться платить сложностью освоения и скоростью начальной разработки, в итоге для небольших проектов не особо оправдано выбирать symfony.
raacer
25.05.2016 08:16Какие из описанных проблем Вы наблюдаете в Django?
dromanow
25.05.2016 10:13+1Большое количество «магии» (Explicit is better than implicit явно не про него). Перегруженность основных компонентов, как из коробки, так и базовых батареек (при этом, что удивительно, они откровенно не дотягивают до аналогов из параллельных вселенных). Сильная связанность. Тотальная привязка к ORM.
Я не хейтер Django, я работаю с ним много лет, и до сих пор поддерживаю на нем проекты, но это крайне не гибкий инструмент. И на долгоживущих проектах с не полностью определенным фичелистом я его не использую.raacer
25.05.2016 10:34Я что-то не нахожу в статье ничего про магию.
По поводу перегруженности — субъективно несогласен. Постоянно чего-то не хватает, и со временем функционал расширяют и улучшают, что радует. Наверное, это зависит от задач.
Не могу понять, где там тотальная привязка к ORM. Мало того, все компоненты легко расширяемы и заменяемы.
О гибкости — это вообще странно слышать. Огромная структура классов дает возможность переопределить почти все, что угодно. Только с админкой раньше было очень плохо, она как буд-то посторонним человеком делалась. Но и ее в последнее время заметно улучшили.
Единственный реальный минус — это сложность. Изменить можно почти любой аспект поведения, но для этого может понадобиться очень серьезное изучение всех потрохов. Чтобы эффективно работать с Django на любых сложных проектах, надо быть настоящим гуру, а не просто юзером фреймворка.
Похоже, невозможно одновременно достичь функциональности, гибкости и простоты. Чем-то одним надо пожертвовать. Хотелось бы, чтобы это было не так.dromanow
25.05.2016 11:29+2Сложность за простыми интерфейсами это всегда магия, в Django с этим еще хуже, так как интерфейсы заменили соглашениями.
Про перегруженность я так сразу и сказал, куча невнятных мелочей есть, а нормальный явный left outer join или темплейт таг добавляющий класс к форме сделать уже который год не могут.
Если из Django выкинуть орм то останется уродливый парсинг урлов, половина форм и cbv и тормозной шаблонизатор. А админка, единственное в чем Django на голову превосходит аналоги, превратиться в тыкву. Зачем мне тогда вообще тянуть в проект Django если для всего этого есть более внятные инструменты?
Django гибкий на столько на сколько любой другой открытый проект. Понятно что при нужде все можно допилить, докостылить и т.д., исходный код открыт, гит в руки, «пилите Шура, пилите»… только Вы совершенно правильно сказали это требует серьзный уровень знания потрохов, потому что связанность высокая, интерфейсы магические и как только ты начинаете что то модифицировать под себя, в другом, неожиданном, месте что то начинает отваливаться. Зачем мне все это? Я выберу более подходящий инструмент, благо выбор есть.raacer
25.05.2016 12:01Не-не, Вы явно не поняли мою мысль… В Джанго функционал очень грамотно разбрит по методам классов. Вас не устраивает какой-то класс — вы его наследуете, переопределяете какой-то метод — и все. Это не то же самое, что форкнуть и пилить под свои нужды, и даже не манки-патчи. Это грамотная разработка с использованием всей мощи языка.
Я не хочу сказать что Джанга идеальна. Но там другие проблемы, имхо. И они уж точно не в гибкости.
Про админку Вы правы, конечно. А как иначе-то? Потому и нет аналогов.
Шаблоны «тормознутые» только потому, что они делают всю грязную работу за программистов, которую те часто забывают делать сами. Так что джанго-шаблоны — одни из самых надежных шаблонов, и гнать на них не нужно :) А плата за это — производительность. Не бывает ничего бесплатного. Если работу не делает программист — ее делает компьютер. НО! Не устраивает скорость — всегда можно было использовать Jinja2, а теперь, к тому же, его поддержка хорошо интегрирована, да и ничто не мешает подключить любой другой шаблонизатор. Джанго постепенно все больше открывает двери для сторонних решений.dromanow
25.05.2016 14:52Не хочу я с Вами спорить, это спор ни о чем. Если в Вашем бекграунде Django не приносил вам боли и сожаления о бесцельно потраченном времени, я искренне за Вас рад, я лично брать на себя эти риски больше не хочу. Django хорош для своего, весьма ограниченного, круга задач которых я в последнее время не касаюсь.
А так же я не хочу тратить время на «серьезное изучение всех потрохов» что бы стать «настоящим гуру» этих потрохов. Если молоток требует знаний металлургии и сопромата для использования я не бросаюсь их изучать, я просто меняю молоток.raacer
25.05.2016 15:19Согласен, тут не о чем спорить. Если нет желания тратить время на глубокое изучение всей архитектуры, Django — не самый лучший выбор. Лучше выбрать какой-то простой «молоток». Потому что Django — это целый «комбайн-конструктор», если можно так выразиться. Мало того, что надо понимать внутреннюю структуру, так еще и очень желательно понимать и уметь использовать метаклассы, которые по своей сути — хоть и простая, но довольно мозговзрывательная концепция.
vlad72
24.05.2016 14:18+1Сложность задач увеличивается. То, что создавалось ранее, уже не так просто развивать — вылазят ранее не видимые недостатки подхода и реализации. Люди ищут замену…
UncleAndy
24.05.2016 14:32+3Думаю, автор немного не прав в том смысле, что Rails надо оценивать сравнивая с другими фрэймворками, а не просто перечисляя что в нем плохо. Если это хорошо в других фрэймворках, может оказаться что в них плохо что-то другое. Это не вопрос того, что Rails лучше. Это вопрос того, что Rails лучше для автора статьи в задачах, которые он решает. Вполне возможно, что ему просто надоело и ему банально хочется развития. Вполне естественный процесс, правда, ничего не говорящий о недостатках Rails.
phoenixweiss
24.05.2016 14:37+3Очень интересная статья но просто ужасный перевод. Я понимаю что текста много, но мне кажется что автор перевода не перечитывал текст перед публикацией. Читать сложно и неудобно.
nemilya
24.05.2016 15:48+9Мне вот эта картинка понравилась (12 лет прогресса веб-разработки):
У меня есть один проект (первый) — дак он всё ещё крутится на Rails 1.0 (был переписан с Access) — и заказчик вполне доволен до сих пор (прошло уже почти 10 лет). Изучать новые технологии необходимо, но и понимать, что в конечном итоге надо решать бизнес задачи.
А автору спасибо за DataMapper — использовал (совместно с Sinatra) в нескольких проектах.
sl_bug
24.05.2016 15:55+3Source
25.05.2016 12:32+1Хороший ответ. Akita справедливо отмечает, что у Rails есть своя сфера применения (Basecamp-like apps) и большинство веб-проектов в эту сферу попадают. Также как есть Wordpress для блогов.
И если вы пытаетесь сделать какой-то проект на инструменте, который для этого проекта не предназначен, например, магазин на Wordpress или веб-приложение, архитектурно не похожее на Basecamp, на Rails, то вы будете страдать. Однако, он забывает, что когда Rails только набирал обороты, многие говорили «Зачем нужен фреймворк, для большинства проектов достаточно CMS», «Зачем нужны Ruby и Python, большинство крупных проектов написаны на PHP». Так что текущая ситуация — просто очередной виток истории.
Также он отмечает, что слишком сильная дефрагментация сообщества, как у PHP и JS, — это ещё хуже, чем монополия. С этим я тоже согласен.
blazer
24.05.2016 16:28В-основном претензии автора касаются ActiveRecord, который элементарно оттуда удаляется и заменяется Mongoid :) В такой связке, рельсы прекрасны и актуальны.
getElementById
24.05.2016 18:23+2Это не так. Основная претензия к ActiveSupport, которые делает большое количество безответственных вещей. ActiveRecord — это просто ограниченный паттерн ОРМ, в который напихано много откровенно дурных вещей, которые постоянно используются некорректно. ActiveRecord можно удалить, а ActiveSupport — нет.
defaultvoice
24.05.2016 22:41+3А если монго не нужен? Что за мода пихать NoSQL решения куда попало?
blazer
25.05.2016 08:18А почему нет? Для небольших и средних проектов Монго на порядок сокращает время разработки, да и работать с ним приятней намного, нежели с Active Record и всеми этими беспонтовыми миграциями
defaultvoice
25.05.2016 15:40+4Что-то мне подсказывает, что вы просто не осилили SQL.
blazer
26.05.2016 22:16-2Что-то мне подсказывает, что вы просто не осилили Mongo))) Я работал c php+sql до рельсов ;)
guai
24.05.2016 19:59-3Странные претензии. Руби — это рельсы, а рельсы — это руби. Рельсы сделаны максимально рубивэйно. Другое дело, что все эти претензии уже к рубивэю можно выдвигать и к дизайну языка (его отсутствию) в целом.
Надо ли писать на руби нерубивэйно; вводить дополнительные административные ограничения на команду; переносить туда шаблоны, почерпнутые в других языках? Или может лучше взять другой язык?
Имхо, второе. Язык должен отражать стиль программиста. Если руби уже тесноват, то это не руби виноват, а просто пора двигаться дальше.
Ну а про ActiveSupport чистая правда, он монструозен.raacer
25.05.2016 08:26Ruby не знаю, но полностью с вами согласен. Не понимаю, за что меня сейчас заминусуют в этой теме. Есть ведь гораздо более продуманные языки и фреймворки, такие как, например, Python и Django.
Tab10id
25.05.2016 11:51+3Если Вы не знаете Ruby, то как можете оценить его «продуманность»?
raacer
25.05.2016 12:27-3Эммм… Ладно Вы меня подловили! Ни то, ни другое не является в полной мере правдой :)
Я делаю выводы о продуманности прежде всего из того, как создавался язык и какие принципы в него закладывались, а также по результатам языка (таким как рельсы, хехе). Например, сравним документ под названием «PEP 20 — The Zen of Python» с… даже не знаю, с чем, может подскажете… Вот из Вики о философии Ruby:
Мацумото, фанат объектно-ориентированного программирования, мечтал о языке, более мощном, чем Perl, и более объектно-ориентированном, чем Python.
Более объектно-ориентированном, чем Python? Чем он более?.. Отсутствием множественного наследования, которые заменили примесями? А что по поводу Perl? Неужели, его write-only свойств недостаточно? Отталкивания от перла сильно настораживает.
потребность создавать полезные и красивые программы как причина программирования
Вообще очень странное определение. Потребность программировать как причина программирования.
Вот так примерно я оцениваю.
Хочу оговориться: я понимаю, что питон тоже не идеальный. Но все-таки, не хотелось бы сводить разговор к взаимному метанию какашками, это ведь тема о RoR, а не о питоне… Так что, давайте сосредоточимся на метании какашками в руби и рельсы!
А вообще, я в последнее время расстраиваюсь из-за всех этих сложностей, связанных с хранением состояний, и хочется опробовать функциональный подход в каком-то серьезном проекте. Вот только не уверен, есть ли вообще жизнь без состояний? Ладно, на сервере их в БД можно спрятать. А на клиенте с его событийностью — это боль. Извините за оффтоп. Наболеле :) Вдруг кто подскажет верный путь (джедая).
Sega100500
25.05.2016 12:54+5В Мире нет совершенства! А уж тем более совершенства нет в сфере программирования! За свой более чем 25-летний опыт программирования я научился относиться к этому философски. «Чюдисов на свети ни бываит!». Либо ты программист, и сам можешь реализовать какие-то механизмы, коих нет в используемой тобой библиотеке (фреймворке) или реализация этих механизмов тебя не устраивает, либо… можешь поставить перед собой зеркало и «пинять на него».
Важно принять для себя принцип разумной достаточности, а не тратить время на поиски святого грааля — той библиотеки, того инструмента, где все будет ну прям все-все-все идеально, все будет чудесным образом реализовано на все случаи жизни! Не трать свою жизнь на это! Есть базис, который тебя устраивает, вот и пользуйся им! Есть множество механизмов, реализованных за тебя — пользуйся ими! Все остальное можно реализовать самому. Я вообще не лезу глубоко в дебри Rails, использую базовые механизмы, и, знаете, меня все устраивает и прекрасно все работает! А Ruby — это вообще идеальный язык из тех, с которыми мне довелось познакомиться за время своей карьеры.
Сообщество Ruby и Ruby on Rails как раз и отличается тем, что без лишних разговоров, пафоса, споров, холиваров просто делают свою работу, занимаются своим любимым делом, и делают это грамотно и хорошо — видимо, менталитет такой. Ну а если кто-то решил уйти, вот так шумно хлопнув дверью, то не велика потеря.raacer
25.05.2016 13:05+2О, первый вменяемый комент. Уважуха.
На самом деле, человек пытался сделать руби лучше, в том понимании, как он видит. А сообщество его фактически отторгло своим большинством. Логично уйти в более подходящее сообщество, туда, где твои идеи будут понимать и ценить. А хлопать дверью — это от неоправданных ожиданий. Он не получил того, чего ожидал, вот и расстроился. Просто нужно изначально быть более внимательным и гибким в своем выборе, и готовым к ошибкам.
Source
25.05.2016 13:28Ну, за 25 лет Вы явно успели попрограммировать не только на Ruby, не так ли? Т.е. причины со временем менять базис существуют в том числе и лично для Вас.
У любой технологии есть свой цикл развития:
Rails сейчас очевидно находится на этапе «Late Majority». И вполне объяснимо, что Пётр, как один из лидеров Ruby-сообщества, чувствует социальную ответственность и соответственно потребность описать свою точку зрения.Sega100500
25.05.2016 15:20+1Естественно, не только Ruby, но «А Ruby — это вообще идеальный язык из тех, с которыми мне довелось познакомиться за время своей карьеры.». И говорить о каком-то закате инструментария разработчика совершенно неуместно, пока этот инструмент востребован и прекрасно выполняет свои функции. В последние времена наблюдается очень плохая тэнденция в программировании, которую можно охарактеризовать как и «пинять на зеркало», и «а вы, друзья, как ни садитесь, все ж...» — наблюдаются постоянные какие-то метания от одного инструмента к другому, от одной технологии к другой. Уважаемые, да везде лучше, где нас нет! Но вполне есть возможность сделать то место, где вы здесь и сейчас, вполне себе лучшим — своей светлой головой и золотыми руками. Ни одна технология, ни один инструментарий не сделает из вас профессионала чудесным образом!
Source
25.05.2016 16:10Так почему же Вы ушли с предыдущих языков программирования, с предыдущих фреймворков, а не сделали их лучшими для себя?
Автор 9 лет программировал на Ruby — в каком месте тут «постоянные метания»?
И говорить о каком-то закате инструментария разработчика совершенно неуместно, пока этот инструмент востребован и прекрасно выполняет свои функции
Речь не о закате, а о насыщении. Все, кто хотел использовать Rails, — уже используют. Теперь добавляться будут только начинающие программисты. А профессионалы будут постепенно уходить в категории «Innovators» и «Early Adopters» других технологий. И это не тенденция последнего времени, так было всегда.
Если тот же Hanami наберёт популярность, то для Ruby никакого заката не будет, даже наоборот.Sega100500
25.05.2016 17:04Начнем с того, что я не занимаюсь проектированием и разработкой языков программирования, библиотек, фреймворков, а использую их в качестве инструментов. Улучшать их? Какой смысл? Я уже сказал о принципе разумной достаточности. Если язык устраивает меня по большей части, то я использую его, а то, чего мне в нем не хватает — реализую самостоятельно. Я не пытаюсь менять Миры! Да, сейчас стало более возможным просить разработчиков языков и иных инструментов об их улучшении, вносить свои правки, но верить в то, что прислушаются именно к тебе — совершенно неоправданно.
Автор программировал на Ruby 9 лет. И что с того? Постоянно пытался изменить Ruby? Так он (Ruby) и так постоянно меняется при чем очень даже в лучшую сторону.
Я бы не стал говорить о каком-то насыщении, если речь идет о притоке все новых начинающих программистов. Какое же тут насыщение? Да и с чего бы профессионалам уходить куда-то, если их все устраивает. Профессионал на то и профессионал, что занимается делом, а не мечется в поисках истины в последней инстанции.
В данном конкретном случае более уместно все же говорить о той массе «профессионалов», которые постоянно мигрируют от одной технологии к другой, в каждой из которых им обязательно что-то не нравится.
По своему опыту скажу, что я менял технологии разработки только по мере того, как возникала необходимость переходить на какой-то новый качественный уровень, а предыдущие инструменты уже ну никак не подходили для реализации. Вот ну не стану я сейчас писать веб-приложение на assembler! Хотя раньше программирование на assembler было очень увлекательным занятием! А так, для общего развития, я достаточно много языков программирования изучил, дабы расширить собственный кругозор и границы мышления, но это совершенно не означает, что я их все собираюсь использовать в своей работе.vlad72
25.05.2016 17:26То есть, Вы предлагаете автору статьи и дальше программировать на Rubi? ))
Sega100500
25.05.2016 17:51Я ничего никому не предлагаю, ни за что не агитирую. Дело каждого, что ему делать.
А может, да, вместо Ruby и на Rubi попробовать писать :))))) Вдруг он лучше!
Все мои размышления о том, что смена одной технологии на другую вряд ли чем-то значительно облегчит автору жизнь. Устал он от Rails, ну пусть поищет себя в чем-то другом. Только вот проецировать свое видение на весь фреймворк все же не стоит.vlad72
25.05.2016 19:48-2> Я ничего никому не предлагаю, ни за что не агитирую
Ложь — это один из признаков заблуждения.
> вместо Ruby и на Rubi попробовать писать
Существенное замечание.
>Все мои размышления о том, что смена одной технологии на другую вряд ли чем-то значительно облегчит автору жизнь
Надо же, Вы первый в мире человек, который сказал, что смена технологий не облегчает жизнь.Sega100500
25.05.2016 20:54+1Яркий пример когнитивного диссонанса.
> Ложь — это один из признаков заблуждения.
Ложь — утверждение, заведомо не соответствующее истине и высказанное в таком виде сознательно.
Заблуждение — ошибочное убеждение, представление о чем-либо.
Вы уж определитесь, пожалуйста, либо это ложное утверждение в виде явного, намеренного и сознательного искажения действительности, либо это заблуждение ввиду ошибочного представления о чем-либо.
Судя по вашему утверждению это взаимоисключающее утверждение. Если я в чем-то заблуждаюсь, то как я осознанно могу говорить ложь об этом, а если явно представляю истину, но при этом лгу, то как я в таком случае могу заблуждаться?
Или это у вас несхождение в голове от того, что я вроде ни к чему не призываю, значит, я обязательно должен в чем-то лгать?
> Надо же, Вы первый в мире человек, который сказал, что смена технологий не облегчает жизнь.
В данном контексте акцент надо сделать на «значительно облегчит». Смена технологии, безусловно, изменит жизнь автора, но станет ли она от этого лучше и проще?
«Везде хорошо, где нас нет». Но мы даже понятия не имеем, как бы нам было там, если бы мы там были. Только квантовые вычисления помогут нам побывать сразу во всех состояниях одновременно, а затем выбрать наилучшее! )))))vlad72
26.05.2016 02:07-1Это вам надо определится с тем, зачем высказывать свои мысли вслух.
А то вы похоже привыкли за других решать, что им лучше.
Source
25.05.2016 19:06Начнем с того, что я не занимаюсь проектированием и разработкой языков программирования, библиотек, фреймворков, а использую их в качестве инструментов. Улучшать их? Какой смысл?
Смысл есть, иначе бы развитие технологий совсем остановилось )))
А вот то, что Вы не занимаясь этим и даже не изучив код того же Rails, пытаетесь намекнуть на то, что люди, которые этим занимаются, не являются профессионалами — это как-то странно. Докатились… разработка фреймворков и библиотек — это по-вашему не дело, а метания в поисках истины. Вам самому не смешно?
Автор программировал на Ruby 9 лет. И что с того? Постоянно пытался изменить Ruby?
Автор вносил весьма значительный вклад в экосистему Ruby, если не 9 лет, то на протяжении 5 лет точно. Причём весьма активно.
Я бы не стал говорить о каком-то насыщении, если речь идет о притоке все новых начинающих программистов. Какое же тут насыщение?
Новички, как правило, просто используют то, что есть, и поэтому не добавляют никакой ценности в сообщество. Конечно, они могут со временем набрать квалификацию, выходя за рамки Rails. Но в целом на этой фазе развития идёт неизбежное понижение квалификации в среднем по сообществу.
Да и с чего бы профессионалам уходить куда-то, если их все устраивает.
С чего это Вы решили, что профессионалов всё устраивает?
По своему опыту скажу, что я менял технологии разработки только по мере того, как возникала необходимость переходить на какой-то новый качественный уровень, а предыдущие инструменты уже ну никак не подходили для реализации.
Ну вот, автор тоже перешёл на новый качественный уровень — к функциональному программированию.Sega100500
25.05.2016 21:06> Смысл есть, иначе бы развитие технологий совсем остановилось )))
А они и останавливаются в каком-то смысле. Уповая на чудо-технологии все больше появляется недопрограммистов неспособных самостоятельно писать хорошие программы.
> пытаетесь намекнуть на то, что люди, которые этим занимаются, не являются профессионалами
Не путайте понятия! Те, кто пытаются что-то изменить и улучшить заслуживают уважения, являются двигателями прогресса! Те, же, кто уповают только на смену технологий в надежде на чудесные изменения… в общем, можно долго метаться.
> Но в целом на этой фазе развития идёт неизбежное понижение квалификации в среднем по сообществу.
Благо, что такие просто не осиливают освоение того же Ruby, чем и хорош высокий порог вхождения в подобные системы.
> С чего это Вы решили, что профессионалов всё устраивает?
Преимущественно устраивает. Если человек профессионал, но его что-то не устраивает в готовой системе, то он хотя бы в состоянии собственной реализации недостающих ему механизмов. Я в этом смысле. А в области программирования я вообще не встречал людей, которых бы вообще все устраивало.Source
25.05.2016 21:53+1А они и останавливаются в каком-то смысле.
В каком интересно? Тот же Rails выходит уже в 5-й мажорной версии. IT всё ещё неустоявшаяся отрасль, поэтому тут неизбежно постоянное развитие и изменения на уровне технологий. Стабильными пока остаются только теория и фундаментальные принципы. Назовите хотя бы парочку технологий, которые остановились в развитии, скажем, в 2014 году или раньше и до сих пор актуальны?
Уповая на чудо-технологии все больше появляется недопрограммистов неспособных самостоятельно писать хорошие программы.
Статья отчасти и посвящена тому, что появляется много таких Rails-программистов, которые даже на Ruby в отсутствии Rails не могут программировать.
Вообще раньше моветоном было указывать даже язык программирования перед понятием программист, а теперь везде и всюду НазваниеФреймворка-программист (AngularJS Developer, Magento Developer, Rails Developer). Являются ли люди, которые так себя позиционируют вообще программистами? На мой вгляд, нет. Они — пользователи фреймворков и даже гордятся этим. Для них переключиться и сделать новый проект на другом фреймворке — это целая смена Вселенной, хотя по меркам программирования — это пустяковая задача. Это не хорошо и не плохо, это просто факт. К тому же такие люди тоже нужны отрасли, т.к. программистов на все компании тупо не хватит.
Не путайте понятия! Те, кто пытаются что-то изменить и улучшить заслуживают уважения, являются двигателями прогресса! Те, же, кто уповают только на смену технологий в надежде на чудесные изменения…
Похоже Вы сами запутались… Автор статьи совсем не школьник, который не осилил Rails и ищет замену. В его профессионализме сомневаться не приходится, так же как в профессионализме Steve Klabnik, Jose Valim и многих других. Все они вполне осознанно переходят на другие технологии, потому что пришло время. Профессионалам не нужно надеяться на чудесные изменения, они сами меняют то, что их не устраивает.
P.S. И, кстати, с чего Вы взяли, что у Ruby высокий порог входа?Sna1L
25.05.2016 23:28+1К вопросу о высоте порога.
Хоть у языка и очень красивый синтаксис (на мой личный вкус), но все равно некоторые штуки могут принести боль на начальных этапах.
Например, последний аргумент-хеш. Я когда очень давно познакомился с руби, на какое-то время завис над чем-то вроде:
object.method { key1: 1, key2: 2 }
Тема с блоками кода вообще достаточно сложная, мне кажется.
Например, у меня есть предположение, что далеко не все начинающие rails-программисты смогут провести разницу между лямбдой и обычным блоком.
Плюс к тому, знаю людей, для которых первое время вызывало некую боль отсутствие Си-подбного синтаксиса. Ну, собственно, такие проблемы будут почти у всех людей, которые слишком долго писали на Java и т.п.
Возможно, сами рельсы и являются фреймворком, очень простым для старта, но язык Ruby — нет.
Разумеется, это сугубо мое личное неавторитетное мнение.Source
28.05.2016 02:01После других языков самое непривычное в Ruby — это необязательность скобок (т.н. poetry mode)
Вообще вопросы синтаксиса — это очень субъективно… кто-то синтаксис Python терпеть не может из-за отсутствия
end
или фигурных скобок, кому-тоdef
в Ruby не нравится. Можно от всего этого абстрагироваться для решения какой-то единичной задачи, но при выборе языков для постоянного использования всё-таки важно, чтобы синтаксис был по душе.vlad72
28.05.2016 12:11Требования к синтаксису всегда взаимосвязаны с характером решаемой задачи, ее масштабами и необходимостью дальнейшего поддержания программы и ее модернизации. Это даже не вопрос вкуса, но бизнес-процессов — т.е. объективное требование.
Sna1L
25.05.2016 23:19Мне кажется, или автор не уважает абстракции типа «черный ящик»?
Вроде, главное преимущество рельс в их сложности, которая позволяет, не задумываясь о том, что там внутри, решать задачи.
Да, понятное дело, что порой возникают проблемы, приходится копать глубже, а там уже черная магия. Но не бывает ничего идеального, нужно быть готовым к этому.
Например, думаю, все понимают, что monkey-patching — это плохо. Но ведь это одна из сильнейших фич Руби! Да, ей можно отстрелить себе ногу (или что там обычно отстреливают?), но вы не можете не согласиться с тем, что среди этих патчей есть много хороших решений. Лично мне, например, ну очень нравится простой метод #try(:method). Некоторые вещи из ActiveSupport и вовсе становятся практически неотъемлемой частью жизни разработчиков, это и обуславливает некоторые вопросы на SO, связанные с тем, что вне рельс какие-то методы undefined.
Еще я заметил, что после повального увлечения темой функционального программирования (мне, кстати, она тоже очень интересна), началась повальная критика существующих устоявшихся подходов.
Но ведь все те недостатки, которые перечисляют авторы подобных статей, существовали в нынешних подходах и раньше. Это как «разоблачение», что АНБ следит за людьми.
Нужно задаться вопросом, почему наши подходы имеют такой успех и разделить сферы влияния новых «веяний моды» от «старого доброго».getElementById
25.05.2016 23:44+1У вас сложилось неверное впечатление, но в данном случае виноват автор, не разъяснив свою позицию в статье, но он сделал это позже на реддите. Петр уважает высокоуровневые абстракции, но при условии, что они строятся на продуманном основании. В этом основная претензия к рельсам и особенно к ActiveSupport, потому что решения, реализованные там не имеют под собой почвы. Вы привели очень хороший пример — метод try. Какую проблему он позволяет вам решить? Очень часто люди используют его при работе со вводом из-за отсутствия продуманных средств валидации данных. Вот цитата Петра о новом операторе &. из чата hanami, который упоминался в статье (давность — пара часов):
Piotr Solnica
@solnic
21:30
ie in upcoming hanami-validations you'll be able to do filled(:str?, include?: ".")
that's why I was sad to see this new feature in ruby, as people may not think about proper input validation, if you can make sure that input is in the expected state then lots of complexity in your code won't be needed
Но полбеды само неправильное или неуместное использование, для реализации этого метода AS патчит класс Object, от которого наследуются почти все объекты в руби. Что может пойти не так?Sna1L
25.05.2016 23:57+1Как я и сказал, за все нужно платить:)
Я им почти не пользуюсь (воспользовался пару раз, когда в чужих костылях нужно было что-то поправить. Собственно, как раз тот случай, который вы описали: непродуманная валидация данных), но сама идея мне нравится. В упомянутом мною случае (правки в костылях) оно сократило количество изменений и при этом в diff все было очень ясно и четко (хоть сам код и говно, прямо скажем).
Подобные удобства, ясное дело, порождают проблемы. Но ведь они все равно остаются удобствами.
Да, я понимаю, что к языкам программирования и технологиям основным требованием является ограждение программиста от возможных ошибок, но нельзя ведь бросаться в крайности.
Упомянутый Haskell, возможно, шикарный язык (не могу оценить его в силу слабого владения ФП и всеми этими математическими штуками в целом), но сомневаюсь, что с его помощью можно быстро обучить команду программистов и делать продукты с той же скоростью и легкостью (до поры до времени), как в Rails.
Мне кажется, что если сейчас провести эксперимент и заставить всех программистов писать на Clojure, то код превратится в императивную кучу скобочек. И это проблема не языка, это проблема программиста.
Камнем преткновения является человеческий фактор. ФП может быть сколько угодно крутым, но оно не становится повсеместно используемым по вполне адекватным и понятным причинам. А подобные статьи — это скорее крик души.
IMHO, естественно
getElementById
26.05.2016 00:09Не будьте обмануты идеей, что быстро разрабатывать приложения можно только на рельсах, это не так. Да, у рельс сейчас есть несомненные преимущества в документации, сообщества и всех других важных для опенсорсных проектов вещей. Но это не означает, что с технической стороны там происходит что-то такое, что нельзя сделать по-другому. Можно, даже нужно — вот об этом статья. Но для того, чтобы выстроить грамотную, хорошую архитектуру, нужно много сил, а соответственно много людей. И с этим есть большие проблемы, об этом тоже сказано. Я какое-то время следил за ромом, все ждал, когда он повзрослеет для промышленного применения, но в конце концов просто стал контрибьютором и нисколько не жалею.
И да, читайте книжки по языкам, не обязательно на них программировать, но это даст вам хорошее понимание сильных и слабых сторон у разных решений.Sna1L
26.05.2016 00:19Я изучаю Clojure в данный момент;)
Вы, очевидно, решили, что я считаю рельсы панацеей. Напротив, я бы с радостью хотел попробовать что-нибудь еще.
Несколько раз сталкивался с тем, что приходилось лезть в код самого фреймворка, чтобы понять, почему что-то работает неправильно. В такие моменты задаешься вопросом: это со мной что-то не так или с фреймворком. Что ж, без лишней скромности считаю, что фреймворк виноват :)
Однако, как Вы сами упомянули, рельсы имеют очень развитую инфраструктуру: множество гемов (и не только rails-специфичных!), множество накопленной информации и, как многие считают, достаточно низкий порог вхождения. И работы по рельсам очень много, что тоже не маловажно.
Мне нравится, что есть такой прекрасный фреймворк (который я иногда называю: "одна большая DSL") и что я с ним работаю (а не с 1С-битрикс, как в начале карьеры, упаси боже). Когда представится возможность, и я с ним распрощаюсь, потому что люблю изучать новые штуки (и мода на ФП меня тоже коснулась). Но распрощаюсь без какой-либо критики:)
getElementById
26.05.2016 00:47+1Тут просто заголовок некорректно переведен, в оригинале было: «My time with Rails is up», что можно грубо перевести как «Хватит с меня рельсов». И тогда все встанет на свои места — автор статьи написал много гемов и его достало поддерживать совместимость с рельсами, а кроме рельсов ничего толком не появилось, вот весь сказ. Вот если вы начнете писать свои гемы (к чему Петр открыто призывал в твитере), тогда может распрощаетесь с рельсами с такой же статьей :)
Ну а Clojure — это правильно, не забудьте посмотреть выступления Рича Хикки.Sna1L
26.05.2016 00:52Спасибо за продуктивный диалог, оставили мне пищу для ума:)
За сим считаю разговор оконченным.
Source
26.05.2016 12:33можно грубо перевести как «Хватит с меня рельсов»
По-моему это более эмоциональный перевод, а по сути то же самое. Хотя все по-разному воспринимают… не исключаю, что кто-то мог «Пришло время попрощаться с Rails» воспринять как «Прекратите использовать Rails!», несмотря на то, что в заголовке никакого призыва нет и посыл другой.Sna1L
26.05.2016 12:50Лично я так и воспринял. Может, просто невнимательно прочитал.
Думаю, имеет смысл выносить ссылки на оригиналы статей в начала постов, все-таки чем хорош Хабр, так это тем, что помимо самих переводов можно узнать о существовании статьи вообще.
raacer
26.05.2016 04:08> ФП может быть сколько угодно крутым, но оно не становится повсеместно используемым по вполне адекватным и понятным причинам.
А можете уточнить, что за причины?
Я использую Python/Django, но столкнулся с проблемой отсутствия подобного решения на клиенте, и JS для меня превращается в ад. Давно интересовался Clojure. Кроме откровенных недостатков JS, меня в последнее время утомляет работа с состояниями в Django, так как их то и дело приходится протаскивать куда-то в труднодоступные места. К тому же, постоянно возникают задачи-головоломки внедрения своего функционала в сложную иерархию классов и запутанную цепочку вызова методов. Сейчас думаю, не запилить ли следующий проект на Clojure и ClojureScript. Поэтому пытаюсь оценить их потенциальную пригодность к сложным проектам: насколько легко это использовать и сопровождать, и достаточно ли развита инфраструктура. А тут еще Haskell, Elixir — глаза разбегаются, не знаю за что хвататься. Буду признателен, если сможете развернуто поделиться своим мнением.Sna1L
26.05.2016 08:28+1Мое мнение, как я уже упомянул, нельзя считать авторитетным:)
Под очевидными причинами я имел в виду:
- приученность к императивной парадигме (если заставить школьника, который писал на паскале, писать на лиспе, то он будет писать на нем точно так же, как на паскале, просто со скобочками)
- сложность обучения (частично вытекает из первого пункта).
- отсутствие (пока что) развитой инфраструктуры. По Rails/Django/etc можно найти ответ практически на любой вопрос на SO, документация в рельсах достаточно неплоха (т.к. проект опенсорсный и при этом популярный, то понятное дело, что она постоянно улучшается), количество плагинов/гемов/модулей просто зашкаливает. Может этим похвастаться Haskell/Elixir? Сомневаюсь. Говоря о плагинах, можно упомянуть JVM, но:
- по тому, что я успел увидеть в Clojure, у меня сложилось мнение, что использование Java-библиотек выглядит не очень естественно.
- а Scala, видимо превращается в Scala-Java, что тоже по сути не ФП. Но это лишь предположение
На Хабре где-то была статья, где автор рассказал, что их компания отказалась от Scala в пользу Go. Всю статью не помню, но запомнил следующие тезисы:
- Код был слишком разношерстный (кто-то писал функционально, кто-то писал в стиле Scala-Java)
- Некоторые конструкции невозможно было гуглить из-за "странных" символов (это не проблема ФП, но все равно интересный факт. Я не в курсе, но, возможно, у Haskell могут быть похожие проблемы)
- Сложно было нанимать новых программистов
Мне кажется, что перечисленные мною причины действительно имеют место быть я являются вполне очевидными. Наверняка, есть множество подводных камней, но, в виду отсутствия опыта в ФП, говорить о них не решусь. Но я вангую, что со временем появится куча статей "разоблачающих" ФП. Кто знает, может быть, в будущем будет популярно логическое программирование?
Source
26.05.2016 12:58+1приученность к императивной парадигме (если заставить школьника, который писал на паскале, писать на лиспе, то он будет писать на нем точно так же, как на паскале, просто со скобочками)
Вот в этом основная проблема «моды на ФП», по сути то это просто ещё 1 инструмент и надо понимать как им пользоваться. Вот неплохая статья на эту тему: http://degoes.net/articles/fp-is-not-the-answer
По Rails/Django/etc можно найти ответ практически на любой вопрос на SO, документация в рельсах достаточно неплоха (т.к. проект опенсорсный и при этом популярный, то понятное дело, что она постоянно улучшается), количество плагинов/гемов/модулей просто зашкаливает. Может этим похвастаться Haskell/Elixir?
Те, кто помнят экосистему Rails и Django времён 2008-2010 годов, могут оценить, что в том же Elixir ситуация с экосистемой уже гораздо лучше. Конечно по кол-ву пакетов/гемов обогнать Ruby не просто, но нет каких-то прям стоп-факторов от использования. Про экосистему Haskell я не в теме, честно говоря.Sna1L
26.05.2016 13:01Те, кто помнят экосистему Rails и Django времён 2008-2010 годов, могут оценить, что в том же Elixir ситуация с экосистемой уже гораздо лучше.
Возможно, но суть в том, что сейчас уже не 2010 год и многое уже пройдено и установилось. Это не стоп фактор, но в данный момент это одна из причин, почему его не используют повсеместно. Все хотелось использовать слово "сыро", но не поворачивается язык, а словарного запаса для более удачного выражения, увы, не хватает.
Source
26.05.2016 16:48+1Более подходящее выражение: выход из зоны комфорта. Если для Rails у Вас уже есть набор привычных гемов. То тут придётся этот набор заново подбирать и возможно что-то самому писать. Я просто застал время, когда и используя Rails надо было самому писать гемы. Поэтому не вижу в этом ничего страшного :-)
erlyvideo
26.05.2016 20:08вы так говорите, будто сейчас не прийдется руками править каждый первый скачанный из интернета гем.
Source
26.05.2016 23:22Зачем править, когда есть monkey-patching :-D
А если серьёзно, то всё-таки ситуация получше, каждый первый точно править не надо. В основном в допилке нуждаются не особо популярные гемы типа интеграций со всякими сервисами. Случаи, когда нужно влезть в исходники того же Arel или kaminari, не так уж часто встречаются.
raacer
26.05.2016 15:41Почему выбор пал на Clojure, а не на Haskell или Elixir? Что Вы думаете о разнице между этими языками? Встречал мнение, что Elixir вообще гораздо более современный чем тот же Clojure.
Sna1L
26.05.2016 15:49+1Если честно, без особых объективных причин. Просто захотелось.
За Clojure стоит JVM, за Elixir, если не ошибаюсь, Erlang. Я встречал мнение, что чтобы использовать Erlang, нужно четко знать, в чем его преимущества и нужны ли они вам.
К тому же немаловажным фактором является то, что мне нравится Лисп с его простотой и однородной структурой. Можно сказать, что Clojure — это современный диалект Лиспа. А так работу можно найти и по тому, и по тому (видел таких людей). Тем более, что со временем количество вакансий будет только увеличиваться, имхо, причем в случае Clojure это будет происходить быстрее, поскольку некоторые компании, которые работают с Java начинают все чаще смотреть в сторону Scala, а там и Clojure недалеко.
TheShock
26.05.2016 16:18+1> ФП может быть сколько угодно крутым, но оно не становится повсеместно используемым по вполне адекватным и понятным причинам.
А можете уточнить, что за причины?
Как на меня основная причина в том, что, по сути, почти все программирование ПО — про сайд-эффекты. Запись в базу, вывод на экран, етс. Потому чистоты не добиться и приходится прибегать к костылям. А в итоге получается иммутабельность ради иммутабельности, абсолютно нечитаемые конструкции и тонны копипасты. И, конечно, никакой декларативности на практике. Потому что обычно программа по своей сути является последовательностью нескольких изменений состояния. Обычно на ФП пишут в императивном стиле и в нечитабельной форме. Пример:
https://habrahabr.ru/post/279715/#comment_8812695raacer
26.05.2016 16:58+1Кстати да, я вот всех сторонников ФП спрашиваю, как же им удается избавиться от ненавистных им состояний. И пока никакого внятного объяснения…
Source
26.05.2016 17:52+1Если коротко, то состояние передаётся от функции к функции. Каждая функция его меняет (или не меняет, если надо пропустить шаг обработки) и передаёт следующей.
TheShock
26.05.2016 19:38Ну теорию то мы знаем, а вот на практике почему-то так не получается ни у кого ;) Ну вот покажите какой-то крупный опен-сорс проект. Бложик там, или движок игровой, или форум, который написан таким подходом. Потому что пока примеры маленькие — рассуждать очень легко. А когда появляется куча зависимостей и когда сайд-эффект заложен в бизнес-требования (а это всегда так в практической разработке) — появляются костыли, куча копипасты и нечитаемый код.
develop7
26.05.2016 19:40RabbitMQ или pandoc подойдут?
TheShock
26.05.2016 19:52Простите, не могу понять, как RabbitMQ клиент на ерланге запустить. А то тут: https://www.rabbitmq.com/erlang-client.html только либы для общения с сервером.
pandoc — просто математическая либа. Функции получают что-то на вход и возвращают. это не программа.develop7
26.05.2016 20:01А то тут: https://www.rabbitmq.com/erlang-client.html только либы для общения с сервером.
ну да. а что именно ещё нужно?
pandoc — просто математическая либа
не, вот этот http://pandoc.org/
TheShock
26.05.2016 20:05ну да. а что именно ещё нужно?
Емс. Я могу его вот взять и запустить на клиентской машине? Залогиниться, написать сообщение. Принять. Увидеть его в трее.
не, вот этот http://pandoc.org/
Да, я понял. Математическая — неправильно выразился. Суть такой либы в том, чтоб в функцию принять данные и вернуть новые. Но она еще не программа, которую можно поставить на компьютер и пользоваться. Такие либы вообще все-равно на чем писать — особой бизнес сложности они не имеют.IvaYan
26.05.2016 22:32+1Но она еще не программа, которую можно поставить на компьютер и пользоваться.
Почему? Pandoc — программа для преобразования форматов текстовых файлов. Можно поставить и пользоваться. Для той же windows есть msi-инсталлер.
Я могу его вот взять и запустить на клиентской машине? Залогиниться, написать сообщение. Принять. Увидеть его в трее.
Из коробки — нет. RabbitMQ это не мессенджер и не чат. Это система передачи сообщений между компонентами программного комплекса. У этой системы есть серверная часть (написанная на Erlang) и клиентские библиотеки, которые можно встроить в любую программу.
raacer
27.05.2016 14:05Это не интересные примеры. Никакого функционала кроме связи с сервером, никакого временного хранения данных. Вопрос-ответ, и все.
develop7
27.05.2016 21:06+2не интересные примеры
ну извините
никакого временного хранения данных
https://www.rabbitmq.com/tutorials/amqp-concepts.html#queue-durability а?
во-вторых, ну что поделать, если у «настоящих программистов» от одного вида erlang/haskell медвежья болезнь случается.
raacer
28.05.2016 06:21+1Извините, думал речь о клиенте, а не о сервере. Причем тут медвежья болезнь? Я просто хочу понять, как это использовать в реальных проектах.
develop7
29.05.2016 12:33Причем тут медвежья болезнь?
наблюдение, к слову пришлось, к вам отношения предположительно не имеет.
как это использовать в реальных проектах.
ФП вообще или конкретно RabbitMQ?
raacer
29.05.2016 14:59+1ФП конечно, о нем же речь. А RabbitMQ вроде как должен служить примером. Только я примеров из жизни не просил, это для меня слишком сложно :) Но тема интересная. Вон выше товарищ TheShock дал ссылку на забавный случай (где специалист по FP и RP предлагал сообществу свои, так сказать, уроки, и в своем же примере ошибку исправить не смог). Мне больше нравятся примеры такого объема. А понять я хочу, как в реальных проектах, где состояние необходимо как требование, использовать преимущество ФП, заключающееся в программировании без сайд-эффектов. Вот ниже мы с товарищем Source это и обсуждаем.
TheShock
30.05.2016 20:48ну извините
Обьясню. Примеры очень узкие. При чем все — для использования программистами, не конечными юзерами. Феникс — фреймворк, Пандок — либа (хоть и с консольным интерфейсом), Реббит — либа. Интересно увидеть многогранный продукт. Я не сомневаюсь, что для некоторых (довольно узких) целей ФП очень удобен. Когда в бизнес-требованиях есть вход и выход. Но он далек от серебрянной пули и уж точно не замена ООП, как любят покричать. Потому он и «не становится повсеместно используемым по вполне адекватным и понятным причинам». Он банально не рассчитан на большинство задач программирования, а только очень узкий спектр, а на остальные задачи натягивается с треском и костылями. В то время, как другие подходы более приближены к реальности разработки.raacer
30.05.2016 21:38+1Поясните пожалуйста, на чем основывается Ваше мнение? Вы делаете довольно громкое заявление, а аргументируете его только выводами от обратного. Так можно доказать, что PHP лучше чем Python или Ruby.
ФП мало кто умеет, а оупен сорс требует немало ресурсов. Так что отсутствие таких проектов в изобилии — это не показатель. Если кто-то не осилил — это тоже не показатель. Даже кажущаяся нечитабельность не вляется доказательством, ведь даже обычный цикл в C без пояснений хрен поймёшь.
У меня лично ощущение, что научиться ФП — все равно, что заново научиться программированию. Сильно разные подходы. Для императивного программирования нужно научиться мыслить алгоритмически. Для функционального — не знаю как правильно назвать, но явно не «пошагово». Точнее, не только. Может быть, проблема в пороге вхождения?TheShock
30.05.2016 22:08У меня есть предположение, что:
1. Использование ФП ограничено довольно узким кругом специфических задач
2. Большинство, в том числе апологеты ФП не умеют его готовить (как, кстати, множество апологетов ООП не умеет его готовить)
Такие выводы у меня из следующих предпосылок:
1. Известные мне программы на ФП довольно узки
2. Большинство примеров ФП в статьях, что лично я видел — обычная императивщина просто записана навыворот.
— Я понимаю, что теоретически ФП круто паралелится (наверное, клево было б шейдеры писать), но как оно будет параллелиться когда у функций будут сайд-эффекты?
— Более того, когда появляется сложный стейт и нетривиальные зависимости, я часто вижу, что в много функций приходится передавать не какие-либо чистые данные, а что-то вроде: `mySmallFn(wholeAppState)`, что, по сути просто использование глобальной переменной, хоть и с притворством, что она локальная — связи очень сложно проследить, особенно ввиду утиной типизации. (а кто вообще может прочитать `id`, который я верну из функции?)
— функция, которая возвращает функцию, которая возвращает функцию, которая зависимо от аргумента возвращает результат. Как такое прокрыть юнит-тестами? В том же ооп все довольно просто. Вызвал метод — должен вернуться результат или измениться состояние. Методы очень атомарны.
— другая проблема — дебагинг. Кто кого вызывает и почему? Путь кода становится абсолютно неконтролируемым и отладка сводится к обычным `print(currentData)`.
Так вот — у меня вопрос. Может, я ошибаюсь? Но если так и ФП действительно очень удобен, то я хочу научиться делать такие проекты. Покажите мне примеры, статьи, научите. Расскажите, как обходите такие принципиальные вопросы? Давайте я приведу контр-примеры. А что с действительно сложными и комплексными проектами? Не обработка текстовых данных, а игры, графические редакторы?
Просто с таким агрессивным пиаром и такой слабой базой через пару лет от ФП все будут плеваться (непонятный, запутанный, невозможно поддерживать, тормозной и так далее, обязывает к копи-пасте) и вполне возможно, что незаслуженно и есть способы на нем программировать легко и кльово. Но люди, которые умеют делать — сидят тихонько и всем говорят, что их ААА-игры написаны на попсовом С++, чтоб не спалиться.getElementById
31.05.2016 01:47+1Вы правда думаете, что кто-то всерьез примется вас учить? Вы серьезно? Могу вас заверить, ни у какого специалиста после прочтения таких призывов такого желания не возникнет. Если вам это нужно, то дерзайте, если нет, то к чему это все?
TheShock
31.05.2016 02:08Та меня учить не надо. Я этой темой не первый год интересуюсь. Прекрасно знаю когда хороша иммутабельность и когда мутабельность и что для каждой из них есть свое место. И что иногда функциональный подход реально удобнее для обработки данных.
Я просто искренне надеюсь, что как можно больше людей прочитав мои комметарии решат не лезть в то болото, которое сейчас пропагандируется как ФП и не будеть видеть в нем серебрянную пулю и, конечно, что перестануть писать бред из серии «ООП — отстой, все клевые пацаны давно фигачат в ФП», при этом не иметь в своем коде ни декларативности, ни чистоты и пародию на иммутабельность с её минусами, но без её плюсов.getElementById
31.05.2016 02:14К сожалению, комментариями в интернетах вы этого не добьетесь, ложитесь спать :)
raacer
31.05.2016 07:32-2Ну, с ООП ведь так и есть: на него плюются все, кто освоил хотя бы пэхапэ. Никто ведь не хочет чувствовать себя дураком. Вот и сваливают всё на ООП. Не вижу, что должно защитить ФП от такого отношения.
Есть, кстати, и игры, написанные на Ф языках (на вики видел списки).
ОК, в общем, я постараюсь попробовать и затем написать, что из этого получилос. :)
develop7
31.05.2016 10:21Но он далек от серебрянной пули и уж точно не замена ООП, как любят покричать.
Я совершенно уверен, что лет 5 назад думал буквально эту же мысль, и не исключаю, что даже и где-то писал.
на остальные задачи натягивается с треском и костылями
Допустим, как например?
TheShock
31.05.2016 23:35Я совершенно уверен, что лет 5 назад думал буквально эту же мысль, и не исключаю, что даже и где-то писал.
А сейчас считаете, что таки серебрянная пуля и замена ООП?
Допустим, как например?
Я уже описывал в комментариях к топику неоднократно. Вы принципиально не читаете то, что вам не нравится?develop7
01.06.2016 10:56А сейчас считаю, что серебряной пули нет, и ФП очень даже замена ООП — при прочих равных позволяет проще и надёжнее реализовывать более высокоуровневые абстракции.
Я уже описывал в комментариях к топику неоднократно.
Если я ничего не упустил, то конкретный пример вы привели только один — ваше же недовольное ворчание в топике про FRP.
Ну и да, функциональные ЯП являются полными по Тьюрингу, поэтому трещат разве что шаблоны Настоящих Программистов.
raacer
01.06.2016 11:08конкретный пример вы привели только один — ваше же недовольное ворчание в топике про FRP.
Не надо передергивать. Пример — код, а ворчание там вполне уместное. Тут я уже писал подробнее об этом коде. Просто пример не показательный, и доказывает лишь то, что ничего не доказывает.
raacer
31.05.2016 13:06Он банально не рассчитан на большинство задач программирования, а только очень узкий спектр, а на остальные задачи натягивается с треском и костылями
На вики про Erlang пишут много интересного, в том числе о сферах приминения и примерах использования. Чем не примеры? И где там можно заподозрить «треск»?
Cryvage
31.05.2016 13:09+2Ну почему же прямо для очень узких. К примеру сервер любой можно написать. Там как раз есть вход (запрос) и выход (ответ). А это, хоть и частный случай, но в то же время очень частый. Клиент-серверная архитектура распространена повсеместно. Графический интерфейс, как мне кажется, тоже можно писать в функциональном стиле. Для GUI вообще удобней всего использовать реактивное программирование, а оно очень хорошо реализуется с помощью ФП. Сюда же можно отнести любой рендеринг. В том числе и 3D рендеринг в играх. Физика в играх тоже хорошо в эту парадигму вписывается.
Вот уже получается, что ФП может найти свое применение, и на сервере и на клиенте, и в играх. И это не какие-то редкие случаи, не какой-то специфичный софт, а самые общие вещи: сервера, графический интерфейс, рендеринг, расчет физики.
Но будущее, на мой взгляд, за гибридным подходом. Сплав ООП и ФП, на мой взгляд, наиболее удобен с практической точки зрения.raacer
31.05.2016 13:14Как Вы себе представляете такой сплав? У меня промелькнула такая мысль, но углубляясь в ФП я подумал, это вообще довольно противоречивые подходы. Разве использовать ФП и ООП на разных уровнях абстракции, например ФП внутри отдельно взятого метода, где это подходит. Но это ж совсем микроФП, не имеющее отношения к архитектуре приложения.
getElementById
31.05.2016 13:33Ответ на поверхности — объекты без состояния. Создаете объект один раз, у него есть только один метод, который принимает аргументы и возвращает результат. Вот, почитайте: https://habrahabr.ru/company/latera/blog/301338/
raacer
31.05.2016 13:45Ничего не понял. Там нет введения в проблему. Зачем это нужно? Чем такой объект принципиально отличается от функции первого класса?
Cryvage
31.05.2016 14:29+1Про объекты без полей, а следовательно и без состояния, я кстати уже упоминал где-то в этой теме. Да и метод, при этом, не обязательно должен быть один. Еще, как вариант, может быть неизменяемый объект. В этом случае, для методов объекта, его поля будут фактически константами.
Source
31.05.2016 13:48А чего его представлять то, на самом деле полно мультипарадигмальных языков.
Особо отличился Oz — он одновременно поддерживает 7 парадигм программирования :-)
И Вы правы, разные парадигмы не должны мешаться друг с другом, но их можно использовать в разных частях программы.raacer
31.05.2016 13:54Преобразовать одни данные в другие можно вполне успешно на любом неэзотерическом языке. Гораздо сложнее построить архитектуру приложения, чтобы это все работало без ошибок и при необходимости легко исправлялось, расширялось и модифицировалось. Как тут смешать парадигмы? В той же Django используется ФП довольно много где, но на верхнем уровне она ОО.
Cryvage
31.05.2016 14:11+1Просто, как язык, позволяющий писать в обоих стилях. Да хотя бы тот же JS. Аргументы функции — объекты. Функция — тоже объект. В итоге, как хочешь, так и пиши. Ну или взять хотя бы MVC с активной моделью. View можно написать в функциональном стиле, а Model — в объектном. Controller, в зависимости от задачи, либо в функциональном, либо в объектном. Противоречия, они в основном идеологические. А чрезмерная идеологизированность на пользу не идет. Нужно искать компромиссы. К тому же, многое зависит от того, как вещи рассматривать. Можно ведь считать поля объекта неявными параметрами его методов. А сам объект, на протяжении его жизненного цикла, от конструктора до деструктора, можно воспринимать как функцию. В то же время переменные объявленные во внешней функции, для замыкания будут теми же полями. В некотором смысле внешняя функция, для замыкания является объектом, а само замыкание аналогично методу объекта. А раз, и объект можно считать функцией, и функцию можно считать объектом, то значит никакого противоречия между ООП и ФП нету. Это просто две разные абстракции, вокруг одних и тех же сущностей.
raacer
31.05.2016 14:58Противоречие есть. В ФП параметры передаются по значению, т.к. все преимущество строится в том числе вокруг иммутабельности данных. В ООП объекты обычно мутабельные. Чтобы не было противоречий, надо использовать исключительно иммутабельные объекты, а иначе это не ФП уже, а процедурное программирование.
Source
31.05.2016 15:21@Cryvage пишет о том, что можно ОО-язык использовать в функциональном стиле. Т.е. данные о состоянии объекта передавать только конструктору и объявлять на них только геттеры, чтобы даже у методов объекта не было возможности повлиять на его состояние. Тогда получится своеобразное замыкание как в ФП.
Но чтобы так писать на ОО-языке всё равно надо уже расширить своё мышление функциональной парадигмой :-)raacer
31.05.2016 15:29Я понимаю. Но будет ли это называться ООП, или содержать ООП частично? И зачем это вообще делать? Кто-то в реальной жизни это использовал с успехом, решил таким образом какие-то проблемы?
Source
31.05.2016 15:58Нет, это будет называться ФП на ОО-языке. Нужно, если у Вас задача идеально подходящая для ФП, а язык проекта позволяет только ООП.
Source
31.05.2016 15:12Вы во многом правы, но не считаете ли Вы, что функциональные примеси в ООП демонстрируют слабость ОО-парадигмы? По сути даже создатели языков программирования, признают чистое ООП недостаточно удобным. Остался ли хоть один современный ЯП, в котором есть только чистое ООП и ничего больше? Так чтоб никаких лямбд (только Strategy), никаких foreach (только Iterator) и т.д.
Cryvage
31.05.2016 17:21+4Функциональные примеси, они не в ООП. Они в языках программирования. Это говорит лишь о том, что ОО-парадигма не является ответом на все вопросы. Тут вступает в силу старая добрая истина: «Используйте инструмент, подходящий под задачу.»
Языки программирования добавляют функциональные примеси для того, чтобы сделать язык более универсальным и удобным. Это вполне логично с их стороны. По этой же причине во многих языках высокого уровня можно делать ассемблерные вставки. По этой же причине, в C# можно добавить unsafe код.
Если топор не подходит для того, чтобы копать землю, и человек берет с собой, и топор, и лопату, чтобы сначала срубить дерево, а потом выкопать пень, разве это говорит о слабости топора?raacer
31.05.2016 17:46Я вот тоже самое хотел сказать Вам, но решил дождаться вашего ответа )))
Посмотрите чуть выше, как Source интерпретирует Ваше предложение. Примерно так же понял и я. Разве Вы не о том писали, что можно использовать объекты как параметры функций? А тогда выходит, что их надо делать иммутабельными (или следить за иммутабельностью), чтобы это был действительно ФП.Cryvage
31.05.2016 19:58Но в случае смеси ООП и ФП, иммутабельными придется делать не все объекты в программе, а только те, которые участвуют во взаимодействии между объектной и функциональной частью. Как-то так я себе это представляю.
raacer
01.06.2016 09:25Я понял. То есть, это пока просто идея? Интересно было бы посмотреть на попытку использования такого подхода. И все же, мы вроде как говорим о реалиях, а в них ФП уживается с ООП только будучи внутри последнего, по большому счету очень слабо участвуя в архитектуре.
Source
31.05.2016 17:57Функциональные примеси, они не в ООП. Они в языках программирования.
Верно, я имел в виду ООП-языки.
Это говорит лишь о том, что ОО-парадигма не является ответом на все вопросы
+1, у любой парадигмы есть свои границы применимости.
И даже там где одна парадигма применима, другая может иметь более удобные средства. Так что по-хорошему программист должен быть знаком с многими парадигмами, чтобы делать осознанный выбор под конкретную задачу, а не просто по привычке.
Source
31.05.2016 14:24+3Но он далек от серебрянной пули и уж точно не замена ООП
Что Вы как ребёнок всё в серебряные пули верите…
ФП — это парадигма программирования и она предоставляет свои инструменты для решения задач. ООП — другая парадигма, в идеале их области применения могли бы не пересекаться, но на практике одну и ту же задачу можно решать в рамках и той и другой парадигмы.
Мы тут обсуждаем конкретно веб-разработку, а не всё подряд. Если вспомнить как ООП попало в веб-разработку, то очевидно, что это было мотивированно больше всего модой на ООП, т.к. весь практический смысл этой парадигмы теряется для программ, которые отрабатывают за долю секунды.raacer
31.05.2016 15:16Я не знаю, как ООП попало в веб, но я знаю, как я попал в ООП. Я всю (взрослую) жизнь программирую под веб. Про ASP на VBScript и JScript я просто промолчу. На C# было интересно, но статическая типизация и закрытые исходники превращали программирование в боль. Отсутствие множественного наследования и манки-патчинга превращали простые задачи в мегатрудозатратные. PHP — глоток свежего воздуха в плане открытости платформы, но спагетти трудно сочетаемых функций и, в лучшем случае, синглетонов быстро утомляли. Python же (как, вероятно, и Ruby) — это как скинуть с себя мешок с цементом, развязать руки и начать-таки работать, а не ковырять палкой дерьмо (простите). Это благодаря развитому ООП с множественным наследованием и метапрограммированием, динамической типизации, и прочим плюшкам. Само по себе ООП — не решение. Важно то, как оно реализовано в конкретном языке. Я бы не рискнул запилить что-то серьезное, скажем, на Java или том же C#, хоть они и продвинулись значительно. Так же как не рискнул бы писать на питоне большие проекты в процедурном стиле — это тупо и непродуктивно. Другое дело, что в ООП тоже есть предел, когда трудозатраты начинают расти нелинейно по отношению к объему работ. Можно ли это решить, и чем — вот в чем вопрос. Функциональным программированием Хаскелля или Эрланга? Метапрограммированием Лиспа/Кложуры? Но говорить, что ООП не подходит вебу — вы уж извините, сколько абстракций он держит в той же Джанге, и, наверное, в этих ваших рельсах… Возможно ФП еще лучше, возможно нет, но ООП в вебе — не случайность, и время жизни время обработки страницы здесь не аргумент, т.к. за долю секунды происходит столько всего, что в голове не удержишь.
develop7
31.05.2016 15:37Можно ли это решить, и чем — вот в чем вопрос.
да, можно
Функциональным программированием Хаскелля или Эрланга?
ну эм Haskell от Erlang отличаются, мягко скажем, сильно, но в целом да, именно им
ООП не подходит вебу
сложный софт в ОО-парадигме пишется с существенно большими трудозатратами, чем в функциональной
raacer
31.05.2016 15:46ну эм Haskell от Erlang отличаются, мягко скажем, сильно, но в целом да, именно им
Их отличие — это уже второй вопрос. Основной мой вопрос в том, что Лисп соблазняет своей силой макросов, когда код можно изменять как данные (это ж вам не какие-то чахлые макросы предпроцессора в C), и при этом он вроде как поощряет программирование в функциональном стиле. Чем он тогда хуже, если должен быть лучше?
сложный софт в ОО-парадигме пишется с существенно большими трудозатратами, чем в функциональной
Это другой разговор. Все познается в сравнении и зависит от сложности задачи. Для динамической странички подойдет PHP. Для бложика — Джанго или Рельсы. Более сложные проекты на них конечно сложно пилить.
TheShock
31.05.2016 23:43сложный софт в ОО-парадигме пишется с существенно большими трудозатратами, чем в функциональной
Как раз ФП вполне ничего для легкого софта, прототипчиков всяких, где мало связей. Крупную игрушку или графический редактор на ФП написать? Увольте.raacer
01.06.2016 09:27+1Крупную игрушку или графический редактор на ФП написать? Увольте.
Так а Вы пробовали? Расскажите, на чем пробовали, и с какими проблемами столкнулись. Очень интересно ведь. А то люди и игры, и графические редакторы пишут — вроде как пруф. Хотя, конечно, история умалчивает о том, что им пришлось пережить.
Source
31.05.2016 15:53Само по себе ООП — не решение. Важно то, как оно реализовано в конкретном языке.
Насколько я помню, есть всего 3 реализации ООП — на основе классов, на основе прототипов и на основе акторов.
C# ранних версий — это шикарный пример реализации ООП на основе классов, а вот начиная с 3-й версии туда начали добавлять ФП и прочие не ООП-концепции.
Из различий реализаций ООП на основе классов, Вы упомянули только множественное наследование, которое по холиварности не уступает goto, поэтому в большинстве реализаций отсутствует )))
сколько абстракций он держит в той же Джанге, и, наверное, в этих ваших рельсах…
А задумайтесь сколько из этих абстракций реально нужны, чтобы обработать запрос? именно из-за усложнения простых вещей "за долю секунды происходит столько всего, что в голове не удержишь". Вы догадываетесь сколько объектов создаётся для обработки тривиального GET /page/permalink? Хотя по сути Вам нужен 1 объект класса Page и то он сам Вам нафиг не нужен, Вам нужны данные из БД, но как же, без ORM никуда..
raacer
31.05.2016 16:35Я использую большую часть классов, и благодарен каждому методу в Джанге, т.к. они реально облегчили мою жизнь. Появились вьюхи на основе классов — жить стало еще легче.
Чему Вы противопоставляете ООП? Если ФП — так я ж не спорю, я о нем вообще пока мало что знаю. Я в данном случае противопоставляю ООП процедурному стилю, так как речь зашла о том, место ли ему в вебе. Возможно, ФП еще более подходит, но нельзя говорить, что ООП обязан только моде. ООП прежде всего легче изучается теми, кто владеет императивным программированием, поэтому с коммерческой стороны он может быть выгоднее чем ФП, по крайней мере в несложных проектах.
Из различий реализаций ООП на основе классов, Вы упомянули только множественное наследование
А еще — утиная типизация.raacer
31.05.2016 16:38А еще метаклассы.
Source
31.05.2016 17:44Я возможно Вас слегка расстрою, но утиная типизация — это часть парадигмы обобщённого программирования, к ОО-парадигме она никаким боком не относится :-)
Метапрограммирование — это тоже не ООП, строго говоря. Вообще рекомендую ознакомиться со списком парадигм программирования, там много интересной информации.
Что касается ООП, попробуйте хотя бы для себя, абстрагируясь от привычек, ответить на вопрос: при каких условиях неудобно применять ООП?
raacer
31.05.2016 17:55Нет, не расстроили. Дело не в обобщении алгоритмов, а в том, как определяется тип объекта. Нате вам тоже ссылочку про утиную типизацию :-P Википедию я, знаете ли, читать умею.
Что касается ООП, попробуйте хотя бы для себя, абстрагируясь от привычек, ответить на вопрос: при каких условиях неудобно применять ООП?
На очень маленьких и на очень больших проектах, имхо.Source
31.05.2016 18:11Я понимаю, хотя списочек там реально заслуживающий внимания, я несколько новых для себя нашёл.
Дело не в обобщении алгоритмов, а в том, как определяется тип объекта.
Дело как раз в том, что можно написать обобщенный метод/функцию, без явного указания типа/интерфейса параметров в сигнатуре метода. В ООП для подобных методов придётся использовать явные интерфейсы.
raacer
31.05.2016 18:21Ну, я постоянно с ним сверяюсь в последние дни )) Спасибо, тем не менее. Вот например интересная вещь: функциональное программирование относят к декларативному. Как тогда Lisp стал функциональным — не вполне ясно.
А интерфейсы в ООП — это тоже обобщение. Вот по вашей же ссылке написано:
Вместо описания отдельного типа в обобщённом программировании применяется описание семейства типов, имеющих общий интерфейс и семантическое поведение (англ. semantic behavior).
Все это — и интерфейсы, и утиная типизация — обеспечивает полиморфизм (и тут по ссылке написано про обобщение, кстати), а следовательно имеет непосредственное отношение к ООП. Обобщение — все же, более широкое понятие.
В общем, не всё так однозначно, различные парадигмы могут иметь общие техники и подходы.Source
31.05.2016 19:20+1Как тогда Lisp стал функциональным — не вполне ясно.
Lisp появился ещё до того как все эти парадигмы были сформулированы. Формально, он в первую очередь гомоиконный. Но всё ФП началось именно с него.
В общем, не всё так однозначно, различные парадигмы могут иметь общие техники и подходы.
В принципе, да, остаётся их разделять разве что по обязательности к-л части.
TheShock
31.05.2016 23:42бы не рискнул запилить что-то серьезное, скажем, на Java или том же C#, хоть они и продвинулись значительно
эмс. А на чем бы рискнули?raacer
01.06.2016 08:35На Python — вполне. По моему мнению, для веба в 99% случаев требуется язык с динамической типизацией, по крайней мере если в ОО стиле писать. А дальше уже надо на сам язык смотреть, насколько он удобен и лаконичен. Я, к сожалению, не так много языков знаю. Ruby, очевидно, тоже вполне хорош, это уже дело вкуса, и он мне просто не по вкусу. JS, PHP, Perl — сильно сомнительный выбор в виду различных ограниченностей этих языков. А больше я ничего и не знаю.
Из функциональных — пока не пробовал. Смотрю вот, выбираю… :)
TheShock
31.05.2016 23:41Что Вы как ребёнок всё в серебряные пули верите…
Так я как раз и не верю. Я прекрасно комбинирую, ФП — для мелкой обработки данных, ООП — для глобальной архитектуры. Это адепты ФП пытаются убить ООП и кричат, что ФП — серебрянная пуля, что приводит к фейспалму.
весь практический смысл этой парадигмы теряется для программ, которые отрабатывают за долю секунды.
При чем ООП к времени жизни программы? О, оSource
01.06.2016 01:12При чем ООП к времени жизни программы? О, о
При том, что ООП хорош для задач, где нужно управлять глобальным состоянием программы в оперативной памяти. Взять тот же GUI, как его инстанцировали при открытии программы, так он и продолжает существовать пока программу не закроешь, и у каждого контрола свои атрибуты и обработчики событий. Удобно для ООП? Конечно!
Проблема в том, что ООП превратили в культ карго и создают объекты везде где ни попадя, просто потому что так принято.raacer
01.06.2016 09:08+2ООП хорош для задач, где нужно управлять глобальным состоянием программы
Из этого совершенно не следует, что ООП плох там, где нужно управлять локальным состоянием.
1. ООП с классами позволяет хорошо структурировать и подготовить к повторному использованию любой более или менее сложный код. Не важно, что объект живет миллисекунды, это не аргумент. Важно то, что с помощью классов можно быстро приготовить подходящее тебе поведение объекта. Возможно, ФП решает эту задачу проще, но если забыть на секундочку ФП, то без ООП становится совсем сложно.
2. Даже в случае малого времени жизни обработчика, ООП успешно дает доступ к долгоживущему глобальному состоянию, такому, как база данных, такими средствами, как ORM.
3. Вы так говорите, как буд-то миллисекунды — это так же мало и для компьютера, как и для Вас. За эти миллисекунды веб-приложение успевает пропустить запрос по конвейеру прослоек различных предварительных обработчиков, определить смысл и суть запроса и выбрать подходящую реакцию, преобразовать поступившие данные в удобный для дальнейшей работы вид, проверить их на валидность, обработать информацию в соответствии с бизнес-логикой, произвести взаимодействие с базами данных путем построения соответствующих запросов и упаковки данных, собрать данные для ответа, привести их в пригодный для ответа вид, сформировать ответ, отправить все это обратно и отчитаться о выполненных действиях. И звучит это гораздо проще, так как в каждой задаче есть уйма проблем. Давайте лучше измерять сложность хотя бы в количествах строк кода, а не в миллисекундах. Это будет неточно, но гораздо ближе к правде.
4. Вы все время говорите о какой-то проблеме культа и создании объектов где ни попадя. Это мне очень напоминает выпад в сторону простой библиотеки для отправки имейлов, которую я написал для Django. Стороннему наблюдателю из мира ФП не видно, зачем там объект, когда можно было написать функцию send_mail. Но если подумать немного наперед (а ведь это публичная либа, здесь надо думать не только о себе), то становится очевидным, что многим понадобится ставить сообщение в очередь, обработчик которой совершенно не знает ничего о том, как его отправлять. ООП здесь помогает упаковать все в удобный объект. Если Вы не поняли, зачем был создан объект, или в вашем случае он просто не нужен — это ведь не значит, что он не нужен никому? Мы ведь хотим повторно использовать код, делиться им с другими, чтобы те его тоже повторно использовали. А если закрыться в своей коморке и ни с кем не общаться, то да, можно не использовать никаких абстракций и каждый проект писать с нуля. Потом получаются интернет-магазины, в которых ссылки на картинки нужно вставлять ручками.
Когда Вы говорите о культе — я вообще, честно говоря, удивляюсь. В чем он состоит? В том, что 90% веб-программистов пишет код на синглетонах? Не надо ругать ООП за кривые руки программиста. В Django использование ООП оправдано везде, я уже писал об этом, Вы не видели, видимо. Даже добавление ООП во вьюхи существенно упростило жизнь. Про рельсы не скажу ничего, может там и переборщили — хз.Source
01.06.2016 12:25+1но если забыть на секундочку ФП, то без ООП становится совсем сложно
Это от масштаба проекта зависит на самом деле. 80% сайтов вообще просты до безобразия… просто мы тут их не обсуждаем :-)
ООП успешно дает доступ к долгоживущему глобальному состоянию, такому, как база данных, такими средствами, как ORM
По факту, ORM — это ещё одно следствие моды на ООП. Данные в реляционной БД — это данные, а не объекты. Как следствие OR impedance mismatch и разнообразные статьи типа "ORM is an anti-pattern".
За эти миллисекунды веб-приложение успевает пропустить запрос по конвейеру прослоек различных предварительных обработчиков...
И вот Вы перечислили больше десятка действий и ни одного объекта. Когда задача описывается через действия — это как раз признак того, что она больше подходит для ФП, чем для ООП. В случае обработки веб-запросов объекты создаются только чтобы вызвать какие-то их методы, а потом напрячь GC. Советую Вам книгу Programming Phoenix, чтобы посмотреть как эта задача решается без объектов.
ООП здесь помогает упаковать все в удобный объект.
точнее вместо того, чтобы функцию поставить в очередь, требует сначала обернуть её в класс
А если закрыться в своей коморке и ни с кем не общаться, то да, можно не использовать никаких абстракций и каждый проект писать с нуля.
Абстракции и повторное использование — это вещи, слабо связанные с ЯП и с парадигмами программирования. И возможны они везде, было бы желание. А если нет желания, то и в ООП их не будет.
raacer
01.06.2016 14:12Спасибо за ссылку.
Вы сразу обсуждаете две темы в одной. Определитесь пожалуйста, о чем речь?
1. ФП лучше ООП.
2. ООП не решает проблем, а просто является модой.
То, что ФП лучше, не мешает ООП быть полезным и решать конкретную проблему: писать понятный код в императивном стиле, который большинство программистов понимают изкоробки. ФП — это следующий уровень развития, до него еще надо дорасти.
Абстрагирование — одна из базовых концепций в ООП, так что абстракции таки имеют прямое отношение к ООП. С любой парадигмой возможно абстрагирование, но не любая парадигма поддерживает это напрямую.
То, что я перечислил действия, было сказано к тому, что за миллисекунды решается куча задач. Вы перескакиваете и увиливаете.
Поставить функцию в очередь — это уже отчасти ФП. Я не говорил, что нельзя решить задачу средствами ФП, я сказал, что ООП тут решает конкретную проблему.
ORM — это то, к чему естественно тянутся все ООП программисты, чтобы упростить себе жизнь. Какждый ООП программист мечтал или даже пытался изобрести ORM, чтобы автоматизировать рутинную работу по связыванию программы с базой данных. Но языки без поддержки метапрограммирования дают вполне посредственный результат. Хорошая ORM позволяет забыть о преобразовании типов, проверки данных, и т.д. — это ускоряет разработку.
Перестанье смешивать две разные темы: ФПvsООП и ООПненужен — и тогда все встанет на свои места. ООП решает конкретные проблемы, он не просто мода. ООП может быть вполне оправдан с экономической точки зрения. С технической стороны, возможно, ФП лучше, чем ООП. Но это две разные темы, и из одного совершенно не следует другое.Source
01.06.2016 17:35ООП не решает проблем, а просто является модой.
Я этого и не говорил. Я говорил про то, что веб-разработка пошла сначала по пути ООП, а не сразу по ФП, и это во многом было именно веяние моды. Сейчас мода поутихла и появляются более уместные решения. Ну не является обработка потока изолированных входящих запросов задачей, подходящей для ООП, т.к. у них тупо нет никакого shared state в памяти.
raacer
01.06.2016 17:58Понятно. Ну так бы и сказали :)
Мне думается, что причина в этом лишь отчасти. Не забывайте о более высоком пороге вхождения в ФП. ООП легче изучать, когда уже есть навыки процедурного программирования. Это тупо дешевле.
И вообще, на сколько я могу судить, ООП пробрался в веб относительно недавно вместе с Rails и Django, тогда какмодуизвестность он приобрел гораздо-гораздо раньше. До этих фреймверков в вебе был в основном только PHP и Perl, на которых мало кто пытался использовать ООП. Программисты на PHP, коих в вебе долгое время большинство, вообще всегда были лютыми хейтерами ООП.Source
01.06.2016 22:45Ну, как ни странно, ООП начала активно пробираться в веб как раз через PHP 5, ещё 12 лет назад. А потом уже Ruby и Python подтянулись )))
ООП действительно появилось гораздо раньше и на момент, когда веб-сайты стали превращаться в веб-приложения и им стал нужен нормальный бэкенд в ходу были C++, Delphi, Java, C#. Все ООЯП.
И по сути был двусторонний процесс, с одной стороны разработчики популярных языков для обычных приложений заметили веб. А с другой стороны веб стал усложняться и требовать подходов для борьбы с этой сложностью. Поэтому недолго думая решили, что и для web ООП пойдёт не хуже, чем для desktop. Ну и экономический фактор тоже сыграл роль, дело даже не в пороге входа, а в том, что ОО-языки уже много кто знал по работе с desktop-приложениями.raacer
02.06.2016 07:55В этой теме, конечно, нельзя быть категоричным, и во многом Вы правы. Но по поводу PHP я не промолчу! :)
О да, я помню эту историю 12 лет назад… Ужасно медленная и неудобная реализация классов. Это при том, что задача PHP-кода — как можно быстрее отработать и умереть. ООП в PHP категорически не рекомендовали использовать. Я на всю жизнь запомнил, как на какой-то конфе по PHP докладчика спросили, когда же наконец в PHP будет нормальное ООП. На что докладчик посмеялся в стиле «ООП — говно и никому не нужно», и весь зал отреагировал одобрительными усмешками. И все бы ничего, если бы это было какое-нибудь сообщество лисперов. Только функций первого класса у них даже не предвиделось, а метапрограммирование было только на уровне разыменовывания переменных и медленного eval, если это можно вообще так назвать. Процедурное программирование на синглетонах выглядело в этой среде, как что-то очень профессиональное. Такое невежественное отношение к парадигмам — это просто позор.
Я много общался с PHP-шниками, потому что сам на нем долго писал. И по моим наблюдениям, немногочисленные разработчики тянулись к ООП не благодаря PHP, а вопреки ему, потому что хотелось писать красивый понятный код, а тут вроде как появилась возможность. И каждый раз это заканчивалось разочарованием: слишком медленно, слишком деревянно. Так что, появление классов в PHP вовсе не дало толчок развитию ООП в вебе, это было действительно больше похоже, как Вы говорите, на дань моде, типа «смотрите, мы не хуже, но нам это нафиг не нужно» или " — а ты знаешь ООП? — конечно, даже знаю паттерн Синглетон!" Достаточно посмотреть на все те знаменитые оупен-сорсные проекты на PHP, типа WP, Drupal и прочие, чтобы понять, какими парадигмами принято мыслить на PHP. Именно с появлением рельсов и джанги ООП в вебе приобрела массовый и практический характер.
Это наталкивает на серию интересных вопросов, связанных с темой ООП vs ФП. Почему именно специалисты по ООП создали рельсы и джангу (функциональщина на нижнем уровне не в счет)? Почему подобный инструмент не создали функциональщики? Почему последние не создали еще более удобного инструмента, который сделал бы разработку настолько быстрой, что рельсы и джанги остались бы в стороне? А если создали — почему такая тишина? Может быть дело в том, что для ФП до сих пор не было удобных языков, а теперь, когда есть Elixir, дело попрёт?Source
02.06.2016 12:38+1Да, реализация там была действительно неважная. Хотя говорят, что сейчас уже лучше.
Вы больше говорите о программистах, которые сразу начали с PHP, мой опыт не сильно репрезентативен, но я таких почти не встречал. Разве что видел их по вопросам на форумах.
Когда ООП добавили в PHP, это была уже знакомая для многих парадигма. Поэтому наверно и добавили.
Даже фреймворки типа CodeIgniter стали появляться. Хотя он тоже отличался весьма оригинальным видением ООП.
По поводу вопросов, специалистов по ООП в начале 00-х было на порядки больше, чем специалистов по ФП. Опять же благодаря моде, т.к. именно ООП преподавали во всех ВУЗах, а ФП касались на редких факультетах. Да и до сих пор ФП в виду непопулярности остаётся тем конкурентным преимуществом, про которое писал Пол Грэм. Инертность мышления ещё долго будет останавливать людей от изучения чего-то кроме ООП.
raacer
02.06.2016 17:10Похоже, C++ и Java потянули за собой ООП. Интересно еще было бы узнать, почему оба эти языка пошли именно по этому пути.
raacer
01.06.2016 09:12Я прекрасно комбинирую, ФП — для мелкой обработки данных, ООП — для глобальной архитектуры.
Так делают многие. Вопрос в том, возможно ли ФП использовать для глобальной архитектуры.
vlad72
01.06.2016 13:13+1Ветка очень интересная, спасибо!
Только вот теперь непонятно, зачем такое громкое название было давать — ФП, когда большинство улучшений (по сравнению с ООП) можно было бы реализовать в рамках несколько видоизмененного ООП, применяя например объекты с явным указанием вроде «с сайд-эффектами» / «без сайд-эффектов»?
Есть ли какие-то вещи, которые принципально не вписываются в ООП?raacer
01.06.2016 14:16Тут уже предлагали иммутабельные объекты. Но, походу, никто так не пробовал. Имхо, ООП — это о мутабельных состояниях. Методы объекта производят различные действия с ним. Ума не приложу, зачем может понадобиться иммутабельный объект. В таком случае это уже не ООП. Но, попробовать конечно можно, никто ж не мешает. У кого получится — пусть напишет. А пока это какая-то абстрактная теория, решающая лишь одну задачу: примирить сторонник ООП и ФП )))
Дело в том, что это совершенно разные парадигмы, и они предполагают совершенно разные способы мышления.vlad72
01.06.2016 14:35+1Так в том-то и дело, что в реальной жизни необходимы и мутабельность и иммутабельность, поэтому вопрос не в примирении сторонников разных подходов, а в том — зачем нужна была революция, если и эволюция вполне себе бы справилась (иммутабельный объект — это просто как вариант «с ходу»)?
В чем ФП-парадигма не могла быть интегрирована в существующие ОО-ЯП? Да, они бы не были уже чисто оопешными, ну и что, какая разница, если такие «фичи» бы появились?Source
01.06.2016 17:17Только вот теперь непонятно, зачем такое громкое название было давать — ФП, когда большинство улучшений (по сравнению с ООП) можно было бы реализовать в рамках несколько видоизмененного ООП
1) ФП появилось лет на 10-15 раньше, чем ООП
2) то, что на ОО-ЯП можно писать в функциональном стиле не меняет ОО-парадигму, просто код перестаёт ей следовать
3) Интеграция обеих парадигм в рамках одного языка и так уже идёт, причём давно ужеvlad72
01.06.2016 17:39Спасибо за ответ! Просто слишком много шума вокруг «чистого» ФП, что несколько напрягает ))
raacer
01.06.2016 18:03Может просто ФПшники негодуют, потому что для них превосходство их методологии очевидно, а остальные никак не могут оценить. Я вот тоже долго негодовал из-за тотальной процедурности вместо ООП, ведь преимущество последнего для меня было очевидно :)
А вы читали «Lisp: побеждая посредственность»? Почитайте, может еще больше заинтересуетесь этим шумом ;) Там, конечно, скорее про Lisp, чем про ФП как таковой, но тем не менее, выводы можно экстраполировать и на ФП.vlad72
01.06.2016 19:37Да, статья знакомая, спасибо, еще раз с удовольствием прочитал!
Интересно, что в Вики Ruby не сильно отстает по внедрению функциональности от например Common Lisp / Erlang / F# / Scala. А вот по Вашим словам разница существенная.
И еще вопрос в том, насколько чистые Ф-языки приспособлены для выполнения разных задач (как это уже здесь обсуждалось), не будет ли универсальность принесена в ущерб мощи.
Почему я и вопрос задал — не проще ли «допилить» уже существующие ОО-языки, сфера применения которых известна и отработана, привнеся в них Ф-парадигмы.
Ну это наверное холивар уже с моей стороны ))raacer
01.06.2016 20:15+1Поговаривают, Пол Грэм — вообще класнный чувак, и написал еще много других интересных статей.
Интересно, что в Вики Ruby не сильно отстает по внедрению функциональности от например Common Lisp / Erlang / F# / Scala. А вот по Вашим словам разница существенная.
Честно, я в этом пока почти не разбираюсь. На сколько я понял, чистый функциональный язык отличается иммутабельностью параметров функций и переменных (если таковые вообще есть) и наличием возможности программировать в декларативном стиле, описывая входные и выходные данные различных функций. Это должно упрощать жизнь и программисту, и компилятору.
И еще вопрос в том, насколько чистые Ф-языки приспособлены для выполнения разных задач
Вот я и хочу попробовать. Чисто технически, функции первого порядка должны решать задачу абстрагирования, так что можно обойтись и без ООП. Как это будет выглядеть на практике — жизнь покажет.
Почему я и вопрос задал — не проще ли «допилить» уже существующие ОО-языки
Ну ведь сделали уже, полно мультипарадигменных языков. Только я лично ничего не слышал о какой-то смешанной парадигме. Только видел как разные парадигмы используются на разных уровнях абстракции, что, в общем-то, совсем не то. И вообще, зачем Вы ищете какие-то легкие пути? Учите ФП и будет вам счастие :)
Пошел учить Elixir.vlad72
01.06.2016 22:03+1О-о, за ссылку спасибо! Та да, лень — мать пороков… А еще хочется не прогадать с серебряной пулей. А от Вас ждем статью Elixir vs Python ;)
Sna1L
26.05.2016 20:45Как я успел осознать, неизменяемое состояние в ФП — это миф. Без изменения состояния невозможно что-либо "напрограммировать" (я не математик, поэтому не возьмусь доказывать это свое утверждение, а просто с умным видом поставлю восклицательный знак) !
Просто состояние сохраняется не так, как мы привыкли (в переменных), а с помощью использования лямба функций, замыканий и т.п.
Как минимум, думаю, Вы не будете спорить, если я скажу, что даже в императивной программе, чем меньше мутабельности, тем проще и, возможно, лучше.
Source
26.05.2016 23:45+1А где вы вообще вычитали про неизменяемое состояние в ФП? В ФП есть неизменяемость данных, но причём тут состояние?
Любая функция, если она что-то делает изменяет состояние, это вроде очевидный факт касаемо ФП.
Даже чисто математические функции изменяют состояние:
y(x) = x*x
y(5) => 25 // было состояние: 5, стало: 25.
Разница в том, что в ФП это состояние передаётся в качестве аргумента функции, а в ООП состояние — это отдельная «сущность», на которую 2 метода могут влиять параллельно.Sna1L
27.05.2016 00:02Возможно, я что-то не то подразумеваю под состоянием.
Давайте разберемся. Я предполагаю, что в данном контексте состоянием является некоторый переменный(upd.) набор данных, принадлеащий системе.
Например, при добавлении значения в стек мы меняем его состояние, а именно:
- количество элементов в нем
- "верхний" элемент*
- и т.д.
- и т.п.
Функция-квадрат сама по себе никакого состояния не меняет. Функция — просто правило, по которому элементы одного множества сопоставляются другому. О каком состоянии может быть речь?
Теперь касательно ФП.
Когда мы говорим о том, что данные неизменяемые, мы, по моей логике, немного лукавим, поскольку в нашей системе есть только одна вещь — вычисляемое значение. А вот сам процесс его вычисления — уже имеет некоторое состояние в разном виде. Например, в изменяющихся аргументах при хвостовой рекурсии (как-то странно я ее назвал, но Вы меня поняли) либо в изменении функции (правила сопоставления одного элемента другому) с помощью замыканий и пр.
Поэтому данные все же меняются, просто не те, к которым мы привыкли. Лично я привык к тому, что состояние системы зависит от ее переменных, которые являются хранилищем данных, к которому мы имеем прямой доступ (привет, оператор присваивания). В случае ФП мы не имеем такого прямого доступа, но достигаем нужного результата, воздействуя на него косвенно способами, которые я уже частично перечислил.
Примерно так выглядит мое понимание такого явления как функциональное программирование. Как же выглядит Ваше? Буду признателен, если поделитесь или укажите, где я не прав.
Source
27.05.2016 00:32Я предполагаю, что в данном контексте состоянием является некоторый переменный(upd.) набор данных, принадлеащий системе.
В таком определении у Вас состояние — это вся база данных + redis + ещё что-то. Слишком глобально и внешне к самому приложению.
Давайте возьмём для примера веб-приложение, оно обрабатывает входящие HTTP-запросы. Задача приложения обработать запрос и выдать HTTP-ответ. Для простоты рассмотрим один поток выполнения. Получив запрос, приложение создаёт некоторую структуру данных, описывающую запрос. Теперь эта структура данных и есть состояние. Дальше оно передаётся от функции к функции, сначала проходит через middleware-функции, потом в роутинг-функцию, потом в action-функцию контролера и т.д. пока эта структура-состояние не станет ответом.Sna1L
27.05.2016 00:41В таком определении у Вас состояние — это вся база данных + redis + ещё что-то. Слишком глобально и внешне к самому приложению.
Ну это уже в крайность. Все-таки, система взаимодействует с БД/редисом/чем-то еще, а не включает их в себя. (upd. да, видимо, я еще и неправильно пользуюсь термином "система")
Воспользуюсь Вашим примером с веб-приложением.
По моей логике, входные данные не являются состоянием. Это как параметр X квадратичной функции. Он, конечно, влияет на результат, но состоянием обладать будет в данном случае будет именно вычисление этого результата.
Грубо говоря, вычисление выглядит так:
f(g(h(k(x))))
, гдеx
— параметры запроса. Собственно, нас слабо волнует, что именно за запрос, нас волнует то, как в зависимости от этого запроса будет вычисляться результат. Например, k(x) может обращаться к БД и извлекать оттуда данные (params[:id]), h — как-то обрадабывать эти данные, например, преобразовать их в список чисел, следующая функция может возвести их в квадрат.
Собственно, состоянием в этой цепочке будет обладать именно выполнение какой-то определенной функциии, в которой могут быть какие-то замыкания, например.
Как Вам?
Source
27.05.2016 01:28Ну, крайность, не крайность. А в принципе это глобальное состояние системы, и именно из него она восстановится после жёсткого перезапуска. Просто мы тут о другом состоянии говорим, о том которое находится в ОЗУ и доступно на протяжении процесса обработки запроса.
Например, k(x) может обращаться к БД и извлекать оттуда данные (params[:id]), h — как-то обрадабывать эти данные, например, преобразовать их в список чисел, следующая функция может возвести их в квадрат.
Ну вот, Вы сами описали как функции, одна за другой меняют состояние, которое передаётся по цепочке.
Состояние на уровне отдельной функции тоже можно рассматривать, так сказать, мгновенное состояние… но набор локальных «переменных» нас слабо волнует, интерес представляет только то состояние, которое передаётся по цепочке функций. По поводу всего остального мы просто ожидаем, что половину из этого компилятор нафиг уберёт, а остальное подчистит сборщик мусора )
Cryvage
27.05.2016 01:53По сути состояние это неявный параметр функции. К примеру есть функция f(x), которая что-то делает, например умножает x на 5. f(x){return x*5;} У такой функции нет состояния. Т.к. параметр x передается явно, а число 5 никогда не меняется. Как результат f(7) всегда будет равно 35, сколько бы раз мы ее не вызывали.
Теперь изменим условия. Допустим f1 это метод объекта, и у объекта есть поле y. Пусть метод f1 представляет собой следующую операцию: f1(x) {buf = x; x = x * y; y = buf; return x;}. У этого метода есть состояние. Результат его выполнения зависит от предыдущего вызова. Предположим, изначально y равен нулю. Тогда первый вызов f1(7) вернет ноль. А второй вызов вернет 49. После этого f1(5) выдаст 35. А если повторить вызов, то результат будет уже 25. Зависимость довольно простая, но если не знать потрохов объекта, даже такой простой случай может показаться магией. Вы скажете, что две эти функции f и f1 — разные по своей сути? Но дело в том, что можно реализовать метод f1 избежав зависимости от состояния. Назовем такую функцию f2. Тогда f2(x,y){buf = x; x = x * y; return x, buf;}. Здесь мы получили и новое значение x и новое значение y. При желании можем использовать возвращенное значение y, для повторного вызова f2. Но теперь мы знаем что и откуда берется, т.к. явно это указываем. То есть речь тут скорее не об отсутствии состояния, а о явной его передаче от вызова к вызову. В то же время, мы всегда можем разорвать эту зависимость, вызвав функцию с другими параметрами. Разумеется, отсутствие состояния можно реализовать и в ООП. И в какой-то степени, к этому надо стремиться. Чем меньше состояний у объектов, тем универсальнее и гибче будет объект. Хотя, если дойти в этом до крайности, то объект превратиться просто в набор методов, а полей в нем не останется. Во всем нужна мера, как и всегда.
Из примеров выше видно, что состояние несет в себе те же риски, что и глобальные переменные. Потому что это, в общем-то, и есть глобальные переменные. Поля глобальны для методов объекта. А если поле еще и статическое, то оно глобально для всех объектов данного класса. Если оно при этом будет публичным, то вообще ничем от глобальной переменной отличаться не будет. Следовательно и методы борьбы с состоянием будут такие же, как с глобальными переменными: минимизировать область видимости на сколько это возможно, т.е. сделать глобальные данные локальными. Принимаемый функцией параметр — это как раз и есть локальные данные. Естественно, часть данных из реального мира будет где-то храниться глобально по отношению к программе. Но это не проблема. Просто функции будут принимать эти данные в качестве явных параметров.Sna1L
27.05.2016 02:14+1Наше с Вами видение ситуации, в общем-то, одинаково. Единственное, мне абсолютно не понравилась (или непонятна?) часть про глобальные переменные. Вы, по-моему, пытаетесь глобальной любую переменную, пришедшую извне.
На самом деле, большая часть проблем всех этих дискуссий связана с разной интерпретацией терминов.
Как по мне, в ФП вообще нет переменных (хотя я и использую это слово по привычке).
Например, в функции
f(x) = x*x
x
правильнее называть "параметром" или "аргументом" в зависимости от контекста, что тоже порой может некоторую путаницу вызывать. Когда мы говорим оx
как о чем-то абстрактном, это параметер. Когда мы говорим непосредственно о его значении, это аргумент (f(5) = 25
). Как-то так.
Однако, если вспомнить машину Тьюринга, то там, что состояние, что значение ячейки, что положение "указателя" являются по сути одним и тем же, а именно тупо аргументами функции (коей является сама машина). Собственно, это намекает на то, что в контексте программирования прав все-таки товарищ Source, потому что в программировании важен еще и сам вычислительный процесс, который действительно является сменой состояний, где конечное состояние и будет результатом.
Я почему-то вспомнил какое-то изречение Алана Кея (не вспомню источник). Если совсем коротко, то тезис был примерно таким, что мы слишком усложнили понятие ООП, т.к. изначально он всего-лишь подразумевал такие понятия, как "объект" и "посылка сообщений объекту".
Может быть, мы действительно слишком сильно пытаемся углубиться в высшие замыслы ФП, что отстраняемся от простых вещей вроде "mutability — зло", "side-effects — зло", которые по сути уже очень многое дают сами по себе.
Cryvage
27.05.2016 12:31+1По глобальным переменным могу уточнить. Само понятие глобальности относительно. Например переменная, объявленная внутри функции (я сейчас говорю не про функцию из ФП, а про обычную функцию из императивного ЯП), является локальной для этой функции, т.к. существует только в момент вызова этой функции. И при следующем вызове будет создана новая такая же переменная. Но это будет уже другой ее экземпляр. Однако, если мы внутри функции объявим еще одну, вложенную функцию, то эта же самая переменная, для вложенной функции будет уже глобальной. То же самое с полями объекта. Они существуют все время существования объекта, и являются глобальными для его методов. Единственное, что тут спасает, это, что их область видимости обычно ограничена одним объектом. И между методами объекта существует обязательство, сохранять данные в полях в непротиворечивом состоянии, и учитывать особенности работы остальных методов данного объекта. Это делает объект сильно связной сущностью. В общем-то для того и понадобилось объединить данные и методы в одну сущность, чтобы хоть как-то локализовать взаимную зависимость методов и данных. То есть ООП это компромисс. У объектов есть состояние, но мы работаем с нм максимально аккуратно. Ну это в теории должно быть так. На деле все сильно зависит от компетентности программиста.
В принципе, можно дать некое определение глобальности. Объект «a» является глобальным по отношению к объекту «b», если объект «b» имеет доступ к объекту «a», и при этом время жизни объекта «a» больше, чем время жизни объекта «b».
При этом, если глобальной является некая константа, то с ней проблем нет. Ее значение не меняется. Если же это переменная, и мы можем ее изменить (а как правило, изменить ее можем не только мы, но и чужая функция, что еще хуже), то выполнение нашей функции становится непредсказуемым. Два раза подряд вызвав функцию с одними и теми же параметрами мы можем получить разные результаты. Это вообще противоречит определению функциональной зависимости. Математическая функция обязана для каждого аргумента «x», входящего в область допустимых значений, возвращать определенный, всегда один и тот же результат «y». Только тогда мы имеем право, написать, что y=f(x). То есть сказать, что «y» функционально зависит от «x». Соответственно, чтобы не было противоречий с математикой, мы вынуждены считать, что все глобальные переменные, от которых зависит функция, так же являются ее параметрами. Проблема в том, что эти параметры, во-первых являются неявными, а во-вторых, если несколько функций обращаются к одной и той же глобальной переменной, и хотя бы кто-то в нее пишет, они начинают неявно влиять друг на друга. Возникают побочные эффекты. Такой код крайне сложно поддерживать и масштабировать. А если код еще и может выполняться асинхронно и параллельно, то это вообще ад.
И еще, следует понимать, что под «отсутствием состояния» в ФП подразумевается отсутствие состояния на уровне функции. На уровне же всей программы, всего алгоритма, естественно мы меняем некое состояние. Просто мы передаем его из одной функции в другую с помощью параметров и возвращаемых значений, явно и только тогда, когда нам это нужно. При этом каждая отдельная функция состояния не имеет, и ничего о нашем состоянии не знает. Она универсальна.Source
28.05.2016 02:18+1Само понятие глобальности относительно.
Неа, глобальность — это как раз абсолютное понятие, и подразумевает оно доступность из любого места программы.
А то, что Вы описываете, называя глобальностью, — это по сути про вполне локальную область видимости.
Cryvage
28.05.2016 12:34То что вы говорите это глобальность относительно всех сущностей программы. Но опять же относительно. Просто, когда появилось понятие «глобальная переменная», типичная программа состояла из процедур и функций. В ней не было других элементов абстракции. Переменная могла быть объявлена либо внутри какой-то функции, то есть локально для этой функции, либо вне функции, то есть глобально для всех функций. А поскольку все функции вместе, как раз и представляли собой программу, то она получалась глобальной для всей программы. Сегодня, в типичном ОО языке ситуация несколько сложнее. Уровней видимости и вложенности может быть гораздо больше. Есть пространства имен, классы, модификаторы доступа, объекты, методы. Поэтому говоря о глобальности сегодня, нужно не забывать про уровень этой самой глобальности. Поле является локальным для объекта, т.к. объявлено в нем. Но оно глобально для методов объекта. Приватное статическое поле класса локально для класса, но глобально для всех объектов этого класса. А если статическое поле еще и публичное, то оно глобально для всего пространства имен. Если же и сам класс публичный, то это поле уже глобально для всей программы. Конечно реализация ООП в разных языках может быть сильно разной. То что я написал выше, верно, например для C#. Но сама идея верна для любого языка, в котором уровней видимости больше двух. Даже не обязательно, чтобы это был ОО язык. На одних только замыканиях можно такую вложенность навертеть, что мозг взорвется.
Именно поэтому я считаю не правильным говорить просто о глобальности/локальности данных как о каких-то абсолютных характеристиках. Правильней было бы говорить о степени глобальности/локальности данных. Может это и не совсем верно с какой-то академической точки зрения. Но меня, как программиста, прежде всего интересует практика. А на практике, использование статических полей класса несет в себе всё те же риски и проблемы, что и использование глобальных переменных, хоть они уже и не настолько глобальны, как классические глобальные переменные. Да и простые поля объекта, тоже подвержены тем же рискам. В последнем случае эти риски меньше, потому что и степень глобальности меньше. При этом, чем больше разрастается объект, тем проблем становится больше. Почему? Да потому что растет количество кода, которому доступны поля объекта. Кода для которого эти поля являются глобальными. То есть степень глобальности полей с ростом объекта увеличивается, хотя и уровень, на котором они объявлены не изменился. Отсюда выводы: если в объекте есть поля, нужно делать его как можно меньше. Если полей у объекта нет, то даже будучи довольно большим, его поддержка доставит не так много проблем, как поддержка гораздо меньшего объекта с большим количеством полей и сложным внутренним состоянием. И на практике это подтверждается. Конечно большой объект и без полей может быть сложно поддерживать, но уже по другим причинам. Много кода в одном месте — простоты не добавляет.raacer
28.05.2016 12:44+1Давайте их называть «общими», или «внешними» по отношению к функции. Все-таки, глобальная — это когда на уровне всей программы. Кстати, статические свойства класса — это получается тоже глобальная переменная, если сам класс доступен глобально.
Объект без полей — это смешная шутка :) В питоне это называется «модуль».
Source
27.05.2016 00:45+2Функция — просто правило, по которому элементы одного множества сопоставляются другому. О каком состоянии может быть речь?
Состояние — это один из аргументов функции, например, в той же хвостовой рекурсии при вычислении факториала начальное состояние будет = 1, а итоговое — результат. Просто Вы это называете не состоянием, а вычисляемым значением, хотя, строго говоря, вычисляемое значение — это только конечное состояние.
Когда мы говорим, что данные неизменяемые, мы не лукавим, т.к. они физически не меняются в ОЗУ, в отличии от императивных языков. Насколько я понимаю, именно это помешало распространению ФП в прошлом веке, т.к. программы работали медленнее из-за неизменяемости данных, но со временем это оптимизировали. И теперь людей больше интересует как запустить сотни потоков и не получить ни race condition от доступа к изменяемым данным, ни геммороя с блокировками.Sna1L
27.05.2016 01:11+1писал сейчас большой ответ с примерами кода, но потом понял Ваш "point" и стер.
Собственно, признаю Вас правым, хоть и к некоторым вещам я все равно буду продолжать относиться по-своему (все мы видим мир по-разному, верно? Дайте мне насладиться своим личным безумием:D).
Спасибо, что уделили мне время
Source
27.05.2016 01:33Разумеется у Вас есть право на своё видение :-)
Я, правда, Вам ещё один ответ написал и только потом это сообщение увидел )))
Спасибо за дискуссию.
raacer
28.05.2016 07:44+1В общем, на сколько я понял, суть ФП в том, что:
1) функция всегда получает данные из результата другой функции, так что мы точно знаем, от куда эти данные взялись;
2) функция всегда «изменяет» только возвращаемое значение, так что мы точно знаем, что она влияет только там, где вызывается.
Как результат, связи между функциями легко контролировать, в отличие от императивного стиля, где изменение внешней переменной черт знает на что может повлиять.
Проблема возникает, когда я пытаюсь представить себе использование чистого ФП в приложении с активным вводом-выводом и состоянием как бизнес-требованием. Для примера возьмем толстого веб-клиента. Здесь DOM — это глобальное состояния, которое требуется все время менять. Таймеры и события возникают в совершенно хаотичном и трудно предсказуемом порядке. DOM является и входящим параметром, и результатом обработчиков. Таким образом, обработчики событий влияют друг на друга, изменяя DOM. И проблема в том, что каждый отдельный обработчик на самом деле не является чем-то отдельным и независимым. Они отдельные лишь для того, чтобы осуществить ввод-вывод и ожидание между ними. На самом же деле требуется, чтобы они работали слаженно, иначе на экране начинает происходить белибердень, не имеющая никакого смысла для пользователя.
Вероятно, сторонники ФП, говоря о нелюбви к состояниям, имеют в виду работу с ними как стиль, а не их существование вообще. Ведь все равно в любой программе должно быть какое-то глобальное состояние, а значит и неявная связь между функциями, его использующими. Так что ФП может лишь уменьшить взаимодействие функций через глобальное состояние, а не исключить его полностью.Source
28.05.2016 11:51При функциональном подходе обычно Virtual DOM является и входящим параметром, и результатом обработчиков. А реальный DOM скорее тем самым глобальным состоянием, которое напрямую никто не трогает.
Вероятно, сторонники ФП, говоря о нелюбви к состояниям, имеют в виду работу с ними как стиль, а не их существование вообще.
Да любим мы состояния… проблема не в состояниях, а в работе с разделяемой памятью, особенно когда имеет место конкурентный доступ.
Для этого в функциональном подходе используют STM и Actor Modelraacer
28.05.2016 12:15Глобальное состояние, в общем-то, и хранится в разделяемой памяти. А Virtual DOM не становится намного более локальным от того, что он виртуальный. Речь о сайд-эффектах, которые так или иначе все равно присутствуют.
Ниже Вы уже упомянули, что в Haskell проблема решается изоляцией побочных эффектов с помощью монад. То есть сайд-эффекты никуда не деваются, их просто пытаются спрятать. Ну ладно, пусть хот так, может этого и достаточно — не могу судить в силу слабого понимания. А как с этим делом в других языках, например в том же Elixir?Source
28.05.2016 12:37Просто "сайд-эффект" — это очень расплывчатое понятие. Некоторые даже нагрев процессора к ним относят :-)
С одной стороны можно считать сайд-эффектом любое действие внешнее к программе — запись в БД или в лог.
А с другой — только побочный/неожидаемый эффект от вызова функции. Когда Вы вызываете условноdb.insert!(comment)
, то это вполне ожидаемо приведёт к запросу к БД, а вот то, что этот же код приведёт к отправке email-уведомлений, отправит нотификацию в веб-сокет, а может и ещё что-то… вот это уже нифига неочевидно и обычно имеют в виду избежание именно сайд-эффектов такого типа.
А как с этим делом в других языках, например в том же Elixir?
Если говорить о работе с разделяемой памятью, то используется модель акторов(запускается легковесный процесс, хранящий разделяемое состояние, а все остальные, чтобы повлиять на это состояние, шлют ему сообщения, которые применяются в порядке очереди). Вот тут можно почитать подробнее. Плюс недавно вышла хорошая статья на тему зачем вообще ФП в Erlang и Elixir
raacer
28.05.2016 12:53Не-не, не надо философствовать! :) Сайд-эффект — это очень конкретное понятие. Это когда функция получает доступ к чему-либо кроме параметров, в том числе и модифицирует это — то есть не является чистой функцией. Речь о том, что сайд-эффекты — это неизбежное зло, так как чем их больше, тем сложнее их контролировать. И даже если Вы мамой поклянетесь, это не повод называть Ваши функции чистыми. А иначе я могу сказать, что мой объектно-ориентированный код настолько хорош, что там нет никаких сайд-эффектов :) Но правда в том, что однажды я ошибусь, забуду о чем-то, и сайд-эффект, выйдя из под контроля, станет причиной какой-нибудь новой ошибки.
Отправка сообщения актору — это, к сожалению, тоже сайд-эффектraacer
28.05.2016 18:41Поправочка к определениям, а то я все смешал в кучу. Доступ ко внешним параметрам на чтение, влияющий на результат — это недетерминированность, а на запись — побочный эффект. Чистая функция — детерминированная и без побочных эффектов.
Source
29.05.2016 01:51Я как раз не философствую, а пытаюсь этот вопрос в практическую область перевести. Какой прок от математического факта, что в любой программе есть сайд-эффекты? Но в наших силах разделить эти побочные эффекты на явные и неявные. Если явные — это неизбежность, то неявные — это плохой дизайн.
Отправка сообщения актору — это, к сожалению, тоже сайд-эффект
Вы уже в шаге от определения сайд-эффекта через нагрев процессора… А если серьёзно, то отправка сообщения актору — это то же самое, что вызов метода объекта в ООП. Да и, в принципе, Erlang/Elixir реализуют ООП согласно определению Алана Кея.
raacer
28.05.2016 13:12По обеим ссылкам говорится о том, что данные сделаны неизменяемыми по умолчанию. Это, конечно же, предохраняет от случайных мутаций. Но не там, где они являются дизайном. То есть, это не более, чем защита от дурака.
У меня есть ощущение, что надо подробнее разобраться с монадами. Может быть в них — счастие… :)Source
29.05.2016 01:57Это, конечно же, предохраняет от случайных мутаций. Но не там, где они являются дизайном.
Где это случайные мутации являются дизайном?
raacer
29.05.2016 07:07Предохраняет от случайных мутаций, но не от намеренно используемых.
Прок от математического определения в том, что сам факт наличия не чистых функций говорит о возможности появления ошибок, которые сложно отловить и устранить. С чистыми функциями такая проблема не возможна в принципе. Теоретически, избегая сайд-эффектов можно избегать многих неприятных ошибок. И дело не в явности-неявности, а в том, что в более или менее сложной программе даже явные сайд-эффекты Вы не сможете всегда контролировать, так как не сможете учесть все возможные комбинации этих эффектов, вызванные лагами сети и компа, непоследовательными действиями пользователя и т.д. Но обычно сама задача требует наличия состояния, поэтому без сайд-эффектов не обойтись.
Тогда берешь старый добрый ООП, заворачиваешь состояние и операции с ними в объекты. И тут приходят сторонники ФП, и говорят: «О боже, какой ужас! Здесь везде состояния и сайд-эффекты! Это очень опасный и ненадежный код! Зачем ты используешь ООП, когда можно обойтись простой функцией?!»
После таких слов, если ты не фанатик ООП, появляется серьезный повод задуматься. Залазишь в эти ваши Интернеты, и начинаешь собирать инфу об ФП. И выясняешь, что таки да, сайд-эффекты по своей натуре являются источником многих сложно-отловимых и сложно-исправимых ошибок. Тогда думаешь: «В ФП-прогеры хочу, пусть меня научат!» — и пытаешься выяснить, как же они живут без состояний. Но оказывается, что у них там те же состояния, только в профиль. Вот и получается, что такие функциональщики порождают мифы о жизни без сайд-эффектов. На самом же деле, в любом ООП их не больше, чем в ФП, потому что вызов метода можно выразить через вызов функции со структурой в виде параметра (в том же питоне в метод явно передается self). И, внезапно, большая часть наших методов оказывается чистыми функциями. А глобальные переменные — это зло в любом языке программирования, но, опять же, все равно они будут почти в любой программе: не в коде — так в базе данных. На до же где-то состояние хранить.
Что касается явности-неявности — это вопрос культуры программирования и правильного именования, имеющий место быть при использовании любой парадигмы. Я с Вами согласен, надо писать код так, чтобы из него явно было видно, что он делает. Конечно же это уменьшает количество ошибок. Но не сайд-эффектов.Source
29.05.2016 12:06+2Мне кажется, Вы излишне усложняете… Основная претензия к ООП, касаемо состояний, состоит в том, что состояние спрятано внутри объектов. Соответственно, каждый класс должен сам обеспечивать потокобезопасность. Иначе привет race condition. В ФП потокобезопасность заложена by design, включая защиту от случайных мутаций. Проще говоря, чтобы написать на ОО-языке надёжную программу, которая будет работать в многопоточном режиме, Вам придётся писать в функциональном стиле, просто это будет неудобно. Если Вам самому ещё не приходилось так делать, то понять преимущества ФП сложнее.
Ну а чистые функции — это хорошо, их должно быть большинство, но никому не нужна программа из одних чистых функций, которая не сможет записать результат вычислений ни в БД, ни в файл, ни вывести на экран.raacer
29.05.2016 15:29Просто Вы, очевидно, не фанатик, и, возможно, даже не евангелист ФП. О какой потокобезопасности может идти речь в классе Message, предназначенном исключительно для однопоточной работы с объектами с коротким жизненным циклом. Ну, в крайнем случае, для отправки в конвейер. Даже в этот мелкий проект я поймал критику ООП.
У Вас более рациональная позиция, нежели у тех противников ООП, которые привлекли мое внимание к ФП. Вы — о потокобезопасности, а те — о сайд-эфектах в принципе. Но и смысла тогда в этом вашем ФП намного меньше. За потокобезопасностью я и в ООП прекрасно слежу. Конечно бывает необходимость вынести свойства глобальных объектов в параметры методов, но чтоб прямо полностью в функциональном стиле — не знаю даже зачем. Даже Django вся объекто-ориентированная, и при этом позиционируется как потокобезопасная.
А Вы имеете опыт работы с ООП? Может быть сможете привести еще какие-то преимущества ФП кроме потокобезопасности? (вики уже читал, срачи на форумах тоже).Source
29.05.2016 18:54+2Фанатизм везде плох. Делать из ФП культ — так же плохо, как делать культ из ООП или из Rails :-)
О какой потокобезопасности может идти речь в классе Message, предназначенном исключительно для однопоточной работы с объектами с коротким жизненным циклом.
При разработке на Rails по факту всё подгоняется под однопоточную работу.
Хочешь параллельно обрабатывать запросы — запусти N инстансов однопоточного unicorn, хочешь фоновые задачи — запусти ещё 1 инстанс для sidekiq и т.д. Не знаю, как обстоят дела в Django, но что-то мне подсказывает, что аналогично.
А Вы имеете опыт работы с ООП?
Конечно, 10 лет… А разве сейчас бывают программисты без опыта работы с ООП?
Преимущество ФП ещё в том, что оно проще. В ООП частенько за деревьями не видно леса. Потому что кругом паттерны, замудрённые абстракции и т.д., а что по факту делает код понять сложно. В ФП программу рассматривают как своеобразный конвеер по преобразованию данных, где каждый этап конвеера — это просто функция.
Это очень непривычно после ООП, но когда начинаешь въезжать в идею, понимаешь, что большая часть ОО-паттернов — это костыли, подпирающие изначально непродуманную парадигму.
Чем меньше концепций заложено в код, тем он проще, а значит и надёжнее. Это не значит, что ООП теперь нельзя использовать, просто если Вы можете представить задачу, решаемую вашим кодом, в качестве конвеера по преобразованию данных, то в функциональном стиле ваш код будет гораздо легче и понятнее.raacer
29.05.2016 20:21Не знаю, как обстоят дела в Django, но что-то мне подсказывает, что аналогично.
Django поддерживает многопоточность. Там есть проблема GIL (глобальная блокировка), но она не сильно проявляется в приложениях с активным вводом-выводом. Я обычно запускаю несколько многопоточных процессов.
Конечно, 10 лет… А разве сейчас бывают программисты без опыта работы с ООП?
Большинство программистов, которых я видел, весьма с трудом понимают, зачем ООП, и умеют использовать классы только для создания синглетонов. Например, PHP- и JS-программисты обычно этим страдают. Но в большинстве они, конечно же, считают, что умеют, ибо знают четыре страшных слова из ООП.
В ООП частенько за деревьями не видно леса. Потому что кругом паттерны, замудрённые абстракции и т.д., а что по факту делает код понять сложно.
Я это встречал только в строго-типизированных и не очень хороших языках. В том же Python большинство паттернов вообще не нужны, т.к. ничто не мешает решать задачу влоб. Так что это не преимущество ФП, а недостаток конкретного ОО языка. Хотя, конечно, сложностей хватает и с Python.
Чем меньше концепций заложено в код, тем он проще, а значит и надёжнее.
Согласен. К этому и стремлюсь, на это и надеюсь.
Читаю сейчас про Haskell. Это что-то с чем-то. Он, конечно, математически красив, но за красивой концепцией столько частностей, что я не уверен, что проще. Читаю про Clojure, он в этом плане казался обнадеживающим. Код очень простой: скобки в скобках. Но все равно ничего не понятно, я не могу визуально отделить код от данных. Похоже, это другая крайность. Таки, наверное, придется изучать Erlang или Elixir. Но одно поверхностное знакомство с Erlang ошарашило меня таким количеством фич, что сложно ожидать простоты. Может просто взять любимый Python и нелюбимый JS, и программировать на них в функциональном стиле? :)
в функциональном стиле ваш код будет гораздо легче и понятнее.
Вы может знаете какой-то красноречивый пример, где код в функциональном стиле гораздо легче читается, чем в ОО? Когда-то давно ООП именно этим и влюбил в себя: легкостью чтения, возможностью создавать понятные абстракции. А ФП что ни гляну — какой-то нечитабильный все время.
И, кстати, картинка у вас нечестная. Из ФП можно тоже много паттернов и принципов насобирать. Они там просто другие.Source
30.05.2016 02:25+2Django поддерживает многопоточность.
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
raacer
30.05.2016 07:35
Толк в том, что у меня все приложения на Django успешно крутятся в многопоточном режиме, в том числе с десятками запросов в секунду. Почему в Rails нет толка — здесь уже высказывали предположение.Django поддерживает многопоточность.
Rails сам по себе тоже поддерживает многопоточность, ещё с 2008 года. А толку то?
Ок, спасибо за разъяснения. С ФП пока более или менее ясно. Осталось выбрать язык и попробовать.
Source
30.05.2016 13:34Ну что ж, возможно в Django мире с многопоточностью чуть получше, чем в Rails мире, где Puma ещё только набирает популярность.
Удачи с ФП :-)
TheShock
30.05.2016 23:42+1Потому что кругом паттерны, замудрённые абстракции и т.д., а что по факту делает код понять сложно
Какая миленькая манипуляция) Отсутствие общепринятых паттернов в ФП говорит только о слабой поддержке теорией практики. Есть какие-то теоретические основы, но никто еще не писал достаточно крупного ничего, чтобы пришла Б4 от ФП и сказала, ребята, у нас есть для вас решение.
SRP, DIP вполне себе применяются в ФП как принципы, а Factory, Strategy, Decorator, Visitor в ФП выглядят точно так же. Можно написать такую табличку:
OO pattern / FP Pattern Classes / Functions Classes / Yes, functions Classes / Oh my, functions again! Classes / Function =)
Какие-то сложные паттерны появлялись в ООП в качестве ответа на реальные сложные бизнес-задачи.
В ООП частенько за деревьями не видно леса. Потому что кругом паттерны, замудрённые абстракции и т.д., а что по факту делает код понять сложно
В ФП я встречаю две крайности. Или функция функцию функцией погоняет, или копипаста на копипасте. Вот снова обращусь к этой ссылке. Приведу кусок кода в пример. Мне очень нравится этот пример, ибо он на общезнакомом JS (никаких пугающих, чужеродных конструкций), в нем «показано преимущество fp и rp» и он довольно короткий.
clickItem.pausable(notObs(shiftKey)).combineLatest( clickItem.pausable(shiftKey), unapply(identity) ) .filter(pipe(pluck('timeStamp'), apply(lt))) .map(pipe(pluck('currentTarget'), map(pipe(identity($), invoker(0, 'index'))))) .subscribe(([ai, bi]) => $(".item").slice.apply($(".item"), ai < bi ? [ai, bi + 1] : [bi, ai + 1]).addClass('active'));
И после этого вам кажется, что паттерны, замудренные абстракции и т.д. — это сложночитаемый код?
Этот код мне было бы страшно поддерживать, а веждь я сам писал в подобном стиле (хоть и не столько крайнем) лет пять назад.
А теперь представьте, что у нас баг и неплохо бы было поставить бряку. Или тесты на этот код написать как?
непродуманную парадигму.
Ой, какая глупость там написана.
Functions are understood as black boxes that transform inputs to outputs. If I understand the input and the output then I have understood the function. This does not mean to say that I could have written the function.
Только пока ваша программа достаточно примитивна, чтобы вписываться в эту концепцию
Data structure and functions should not be bound together
Почему? Кроме притянутых за уши сравнений никаких аргументов: «Since functions and data structures are completely different types of animal it is fundamentally incorrect to lock them up in the same cage». Почему б не объеденить данные и способы их обработки в одном месте? Только потому что это животные? Или потому что это не соответствует парадигме ФП? Ну так и не должно.
In an OOPL data type definitions belong to objects. So I can’t find all the data type definition in one place. In Erlang or C I can define all my data types in a single include file or data dictionary. In an OOPL I can’t — the data type definitions are spread out all over the place.
Я правильно понял, что отсутствие свалки в ООПЯ — это их минус?
Let me give an example of this
Он обещает пример, но пример не приводит
Suppose I want to define a ubiquitous data structure. ubiquitous data type is a data type that occurs “all over the place” in a system.
И? Какая проблема с этим?
State is the root of all evil. In particular functions with side effects should be avoided.
Самый распространенный миф. Стейт и сайд-эффекты — не зло, а реальность. Факт. От которого никуда не спрячешься. Ну пока ты, конечно, не подбираешь задачи исключительно под удобную тебе парадигму.
in the real world state abounds
именно!
Pure declarative languages say that there is no state.
Facepalm
The global state of the system is carried into all functions and comes out from all functions
Ага, если глобальная переменная передается первым аргументом (и, по сути, ты можешь повлиять на любую ее часть), то она уже не глобальная, а совсем локальная. Неужели на такую дешевку кто-то покупается?
Mechanisms like monads (for FPLs) and DCGs (logic languages) are used to hide state from the programmer so they can program “as if state didn’t matter” but have full access to the state of the system should this be necessary.
Костыли-костыли. Кто там про непродуманность парадигмы говорил?
Reason 1 — It was thought to be easy to learn.
Да, ибо так и есть.
Reason 2 — It was thought to make code reuse easier.
Да, ибо так и есть.
raacer
31.05.2016 08:00+1Почти совершенно полностью с Вами согласен. Лень было расписывать :) Особенно порадовало о фундаментальной ошибке в парадигме. Пойду скажу жене, что у нее фундаментальная ошибка на кухне: нельзя связывать борщ и кастрюлю — это разные звери. Кастрюля должна стоять на полке, а борщ — в холодильнике.
Про паттерны тоже согласен. Презентация очень полезная, но некоторые вещи откровенно натянуты. Там еще вначале есть о повторно используемом коде, где сишный цикл заменен генератором списка. Не увидел там никакого преимущества, только синтаксис другой.
В общем, критиковать ООП у ФП-шников откровенно не получается.
raacer
31.05.2016 08:42+1Кстати, тот код с FP+RP, на который Вы ссылаетесь — это хороший пример, как не надо писать код. Во-первых, он сразу очень низкоуровневый без каких-либо абстракций. Все, что там можно разглядеть — это всякие служебные функции наподобие: apply, unapply, filter, pipe, pluck, map, slice, subscribe, addClass, removeClass, toggleClass. Все эти функции никак не выражают цели данной программы. А абстракции остались только в голове у автора, но скорее всего и от туда они быстро выветрились. Во-вторых, код не снабжен ни единым комментарием, объясняющим, на кой черт все это нужно. Все, что теперь осталось — это дикая цепочка вызовов функций. Уверен, не видя результат, редкий человек поймет, для чего эта программа была написана. Такой непонятный код можно написать и в императивном стиле. А чтобы исправить ту досадную ошибку в нем, придется теперь понять этот код полностью и восстановить все абстракции. А лучше вообще выкинуть его и написать заново, свой православный код, как это и сделал бы любой нормальный программист :) Этому коду не хватает принципа построения сверху вниз, который, кстати, и в ООП очень важен. Так что, не вините ФП в данном случае, вините автора (надеюсь, он не помрет от икоты).
Source
26.05.2016 17:49+2Вы маленько путаете… Программы, полезные с практической точки зрения, действительно содержат сайд-эффекты, такие как запись в БД. Но из популярных нынче ФП, насколько мне известно, только Haskell радеет за чистоту в этом смысле.
Остальные относятся к этому проще, представляя программу как своеобразный конвеер, у которого на входе — запрос, на выходе — ответ. А внутри цепочка функций, шаг за шагом преобразующих то самое состояние. Некоторые из этих функций могут иметь побочный эффект в виде записи в персистентное хранилище.
Ну а то, что пишут в императивном стиле и в нечитабельной форме, то это ведь не проблема ФП, это проблема с ригидностью мышления автора конкретного кода. ФП — не самоцель, а один из удобных инструментов, если уметь им пользоваться.TheShock
26.05.2016 19:41Ну а то, что пишут в императивном стиле и в нечитабельной форме, то это ведь не проблема ФП, это проблема с ригидностью мышления автора конкретного кода
Покажите мне программу, которая написана в декларативном стиле, где реально ФП использован во всю силу. это как раз проблема ФП, ибо он — глубоко теоретичен и подходит только для узкого списка задач. Использование лямбд для императивного решения задач (типа Linq в C#) я не могу назвать примером использования ФП)
vlad72
26.05.2016 19:47> Ну а то, что пишут в императивном стиле и в нечитабельной форме, то это ведь не проблема ФП
Это проблема стиля. Если ЯП позволяет писать в разных стилях — это плохо. И чем сложней ЯП, чем выше его парадигма, тем это хуже.Source
26.05.2016 23:56Подождите, а как ЯП может запретить писать в каком-то стиле? Я всегда был уверен, что язык может только повысить удобство практического применения какой-то парадигмы, но запретить при этом все остальные… такого как-то не встречал.
Можете пример такого языка привести?vlad72
27.05.2016 01:53Возможно не совсем четко выразил свою мысль: чем больше вариантов решения одного вопроса — тем хуже для читабельности (а значит и для сложных проектов). Особенно, если при этом еще можно применять разные парадигмы. Идеально, конечно, чтобы даже стиль был один, но это наверное слишком идеально будет…
Source
28.05.2016 02:31Спорно. Всё-таки читабельность — это ответственность программиста. И выразительные средства языка ему в этом помогают.
А урезание выразительных возможностей наоборот снижает читабельность в сложных проектах. Для примера можно код крупных проектов на Go посмотреть.vlad72
28.05.2016 12:04> Всё-таки читабельность — это ответственность программиста.
Чеж тогда все Бейсик ругали с его goto? Писали бы ответственно и проблем бы не было…
> А урезание выразительных возможностей наоборот снижает читабельность в сложных проектах.
Согласен, выразительность должна быть большая и безальтернативная.
Source
28.05.2016 12:46Чеж тогда все Бейсик ругали с его goto? Писали бы ответственно и проблем бы не было…
Не знаю, может там был дефицит других управляющих итерациями синтаксических конструкций… я уже с Паскаля начинал… там тоже был goto, но проблем от этого не было )
vlad72
28.05.2016 13:55Так с ростом сложности задач и увеличения возможностей ЯП, требования к читабельности растут быстрее, чем к писабельности.
saboteur_kiev
29.05.2016 22:49> Чеж тогда все Бейсик ругали с его goto? Писали бы ответственно и проблем бы не было…
Убрать goto проще, чем научить миллионы чайников как им грамотно пользоваться…
raacer
29.05.2016 07:38+1Блин, надо было сразу пройти по вашей ссылке. Это эпично.
Для ленивых: https://habrahabr.ru/post/279715/#comment_8812695
vlad72
26.05.2016 08:44> Нужно задаться вопросом, почему наши подходы имеют такой успех и разделить сферы влияния новых «веяний моды» от «старого доброго».
Только после того, как четко разделятся сферы влияния, где и «старого доброго» достаточно, а где лучше применять «веяния моды».
Source
26.05.2016 12:38Но ведь все те недостатки, которые перечисляют авторы подобных статей, существовали в нынешних подходах и раньше. Это как «разоблачение», что АНБ следит за людьми.
Так он и пишет, что 6 лет уже об этих недостатках говорят и пытаются исправить. Но раз Core Team против таких исправлений, то можно уже и закрыть тему.
vehicross
26.05.2016 08:35-1"… это естественно «защищать» что-то, что помогло вам, или то, что вам просто нравится, в то же время здорово быть в состоянии думать за пределами коробки и быть открытым ..."
«Думать за пределами коробки»? Вы говорите серьезно? Я считаю, только блокголова мог так написать в русском языке!Source
26.05.2016 13:08Спасибо, исправил. Переведите тоже что-нибудь интересное… покажите класс :-)
raacer
26.05.2016 15:49Я так понимаю, был странноватый, но близкий к оригиналу перевод? Теперь же получилась отсебятина. :) Лучше уж плохой перевод, чем вольный. Как я понимаю, имелось в виду что-то типа «смотреть шире». Как это перевести — хз. Но уж точно не «нестандартно». Критикующему не мешало бы предложить правильный вариант, а не просто умничать.
thousandsofthem
> User.create(params[:user])
>…
> код «под капотом» чрезвычайно сложен
От сложности никуда не деться, все что перечислено всеравно надо делать. И если сделать вместо одной «ручки» россыпь то код проще не станет. Более того, с россыпью появляется новая проблема: а все ли ручки дернуты.
> Как бы там ни было, я покидаю Ruby
Основной вопрос — а куда? Несмотря на свой почтенный возраст рельсам существует крайне мало альтернатив. Могу вспомнить только elixir/phoenix — кстати от людей из команды rails. И там, кстати, решены многие вопросы упомянутые тут (возможность переписать фреймворк с нуля развязывает руки, да)
printercu
В оригинале в комментах пишут про clojure. Что на нём прототипирование по скорости сравнимо с рельсами. Подробнее не читал, может там и либы предлагают.
Source
Под Clojure сейчас популярен Luminus
Source
где User.changeset — это обычная функция, определенная в модуле User
И всё, никаких скрытых колбеков и никакой магии. Если данные пользователя редактируются через несколько форм с разными требованиями по обязательным полям, то можно создать changeset-функцию для каждой формы. Другими словами валидация полностью отвязана от модели и работа с БД тоже полностью отвязана от модели.
Пётр явно называет Clojure и Elixir, а также Hanami для тех, кто не готов изучать новые языки.
Fedcomp
И сколько еще будет объявлено кастомных функций которые «вроде бы» делают то что там написано? в каждой модели каждый раз и бегать проверять что кто то написал именно то что надо? вместо того чтобы положиться на подобный метод фреймворка?
TheShock
Да, сейчас у некоторых разработчиков мода на копипасту.
Source
Одна дефолтная changeset-функция сгенерируется генератором модели. А остальные по мере необходимости.
В Rails долгим и мучительным путём пришли к тому, что вызывающий код должен преобразовать параметры самостоятельно:
Но куда подобные методы помещать не придумали и пихают пока прямо в контролеры, что в нетривиальных случаях приводит к реализациям user_params, разбросанным по разным файлам.
А вот для создания разных правил валидации одной модели в Rails пока из коробки ничего нет.
sl_bug
А чем такой вариант плох? отдельный класс. Там где вызываете указываете для какой операции нужно. можно еще юзера внутрь передать. Вот тут развитие этой идеи в гем.
Source
Вариант хорош. Но никто и не говорит, что невозможно использовать обычные Ruby-классы совместно с Rails. Автор статьи прекрасно об этом осведомлён, просто устал бороться с тем, что генеральная линия Rails Core Team идёт совсем в другом направлении.
Envek
Именно поэтому появляются проекты, подобные Trailblazer: в них как раз придумывают места, где это должно быть. Конкретно в нём для разных валидаций создаются отдельные форм-объекты, которые используются в операциях (это у них так сервисные объекты). Важно, что валидации выносятся с уровня хранения данных (модели) в отдельное, специальное место. См. http://trailblazer.to/#form
2ord
Пётр несколько раз упоминает о Hanami. Я считаю, что этот фреймворк может стать хорошим ответом Rails.
sl_bug
Когда дорастет до стабильной версии
Arugin
crystal же.
unabl4
Это не фреймворк, он ещё даже до стабильного как язык не дорос, емнип. А так да — хорошее направление, как мне кажется.