Как стать автором
Обновить

Комментарии 404

> User.create(params[:user])
>…
> код «под капотом» чрезвычайно сложен

От сложности никуда не деться, все что перечислено всеравно надо делать. И если сделать вместо одной «ручки» россыпь то код проще не станет. Более того, с россыпью появляется новая проблема: а все ли ручки дернуты.

> Как бы там ни было, я покидаю Ruby

Основной вопрос — а куда? Несмотря на свой почтенный возраст рельсам существует крайне мало альтернатив. Могу вспомнить только elixir/phoenix — кстати от людей из команды rails. И там, кстати, решены многие вопросы упомянутые тут (возможность переписать фреймворк с нуля развязывает руки, да)

В оригинале в комментах пишут про clojure. Что на нём прототипирование по скорости сравнимо с рельсами. Подробнее не читал, может там и либы предлагают.

Под Clojure сейчас популярен Luminus
И если сделать вместо одной «ручки» россыпь то код проще не станет.
В том то и дело, что код станет именно проще, т.к. всё будет написано в явном виде. Пример из Elixir:

%User{}
|> User.changeset(params["user"])
|> Repo.insert!

где User.changeset — это обычная функция, определенная в модуле User

def changeset(struct, params \\ %{}) do
  struct
  |> cast(params, @allowed_fields)
  |> validate_required(@required_fields)
end

И всё, никаких скрытых колбеков и никакой магии. Если данные пользователя редактируются через несколько форм с разными требованиями по обязательным полям, то можно создать changeset-функцию для каждой формы. Другими словами валидация полностью отвязана от модели и работа с БД тоже полностью отвязана от модели.

Основной вопрос — а куда?
Пётр явно называет Clojure и Elixir, а также Hanami для тех, кто не готов изучать новые языки.
И сколько еще будет объявлено кастомных функций которые «вроде бы» делают то что там написано? в каждой модели каждый раз и бегать проверять что кто то написал именно то что надо? вместо того чтобы положиться на подобный метод фреймворка?
И сколько еще будет объявлено кастомных функций

Да, сейчас у некоторых разработчиков мода на копипасту.
Одна дефолтная changeset-функция сгенерируется генератором модели. А остальные по мере необходимости.
В Rails долгим и мучительным путём пришли к тому, что вызывающий код должен преобразовать параметры самостоятельно:
def user_params(params)
  params.require(:user).permit(@allowed_fields)
end

Но куда подобные методы помещать не придумали и пихают пока прямо в контролеры, что в нетривиальных случаях приводит к реализациям user_params, разбросанным по разным файлам.
А вот для создания разных правил валидации одной модели в Rails пока из коробки ничего нет.
А чем такой вариант плох? отдельный класс. Там где вызываете указываете для какой операции нужно. можно еще юзера внутрь передать. Вот тут развитие этой идеи в гем.
Вариант хорош. Но никто и не говорит, что невозможно использовать обычные Ruby-классы совместно с Rails. Автор статьи прекрасно об этом осведомлён, просто устал бороться с тем, что генеральная линия Rails Core Team идёт совсем в другом направлении.

Именно поэтому появляются проекты, подобные Trailblazer: в них как раз придумывают места, где это должно быть. Конкретно в нём для разных валидаций создаются отдельные форм-объекты, которые используются в операциях (это у них так сервисные объекты). Важно, что валидации выносятся с уровня хранения данных (модели) в отдельное, специальное место. См. http://trailblazer.to/#form

Пётр несколько раз упоминает о Hanami. Я считаю, что этот фреймворк может стать хорошим ответом Rails.
crystal же.
Это не фреймворк, он ещё даже до стабильного как язык не дорос, емнип. А так да — хорошее направление, как мне кажется.
> Оба проекта были в конечном счете убиты Rails

Как можно убить open-source проект? Не нравится — форкайся и продолжай пелить так, как нравится.
Автор использует несколько драматичный слог, когда вспоминает о Merb и DataMapper, но по большому счёту так и было. Более полное понимание можно получить прочитав статью по ссылке из статьи «Rails and Merb Merge». Если вкратце, то Rails Core Team обещала реализовать модульность и низкую связность, в частности легкость отказа от ActiveRecord в пользу DataMapper или Sequel. По факту всё оказалось не так радужно, как в обещаниях.
А чтобы форкаться и продолжать пилить нужны команда и ресурсы, а команда Merb как раз распалась в результате того «объединения».
Но сами Merb и DataMapper никуда не делись ведь. Можно взять последнюю версию до слияния и продолжить работу с этого места.

Если недовольных вроде автора — больше одного, то они вполне могут этим заняться.
Вы считаете, что если создатели и основатели Merb и DataMapper опустили руки, и распались, забросив свое родное детище, то посторонние люди внезапно объединяться, схватят и начнут внезапно пилить качественный продукт?

Форки это хорошо, но редко какие форки превосходят оригиналы.
команде мерба дали возможность сохранить лицо, разрешив им «объединиться». На самом деле они просто попрогали что-то и бросили, но поскольку все друзья, решились иммитацию сливания.
OpenSource без масштабности — ничто. Rails всасывает в себя разработчиков, не оставляя сил другим проектам.
Не обязательно, что другие проекты хуже. А и потом что Rails слишком авторитетен.
Это и не дает развивать другие проекты в Ruby
Вы так говорите, как будто чуваки из Rails приходят к разработчикам домой, направляют им пистолет в голову, и под угрозой смерти заставляют использовать только Rails и контрибутить только в Rails.
Речь идет о написании библиотек, которые могли бы пригодиться большому количеству людей. Вам нужно их продвигать, чтобы они действительно стали общепринятым решением. Вам может быть это непонятно, если вы не писали их, но у меня есть пример под рукой: гем dry-types, который занимается приведением типов. Это абсолютно общая и при этом конкретная задача. Но он из коробки не работает с рельсами из-за горячей перезагрузки кода, а если вы захотите подружить его с ActiveSupport, то вас ждет веселый вечер (если вы опытный руби-разработчик, иначе шансов ноль), результатом которого будет запутанное и ненадежное решение.
гем dry-types, который занимается приведением типов
стоит упомянуть, что это как раз один из многих гемов автора статьи :-)
Напрашивается идиома Язык одного фреймворка =)
Надо отметить — что именно (и только) благодаря такому проекту как Rails (и по сути, лично DHH) — мир веб-разработок узнал про Ruby. И по причине, что ruby стало пользоваться на несколько порядков людей чем во времена «до-rails» — Ruby улучшился (по крайней мере по направлению производительности).
Спасибо за оперативный перевод.
Если учитывать число вакансий в РФ, то я наблюдаю следующую картину:

— число проектов на рельсах снижается (старые все еще поддерживаются, а вот с новыми уже нет).
— растет число проектов на python (django).]
— растет число проектов на js-фреймах.

js кросплатформенный, nodejs можно завести хоть на своём телефоне под android (Если там заводили полноценный VoIP Asterisk, то завести nodejs явно проще). Что бы не писалось на js оно может быть использовано в телефоне, телевизоре, VoIP терминале, да даже на десктопе с «полноценным» UI конкретной платформы, внешне не отличимым от привычных контролов, поэтому естесственно, количество проектов на нём будет расти.
Хорошо бы перевести эту картину в плоскость цифр, чтобы было ясно где рост замедлился, а где — ускорился.
В статье меня ничего не удивило) Хотел написать длинный и пространный комментарий, но холиварить очень не хочется.
Поэтому только факты.

Стараюсь использовать рельсы, как запчасть, как завещал дядюшка Боб.
Через полтора года новый разработчик с ходу сделал довольно сложное задание.

Сами рельсы довольно продуманы и удобны в мелочах — миграции, ассеты, сиды, енв и пр. инфраструктурные штучки.
Есть с чем сравнить, Play, Spring Boot и т.п. Быстрый релоад в отличии от Play + Scala. Работа с ассетами в Spring Boot напомнился времена голого JSP и сервлетов).

Я не отказываюсь даже от Active Record, но работаю с ним очень осторожно, практически не применяя магии и скрыв за слоем репозиториев.
Стараюсь не использовать гемы, засоряющие глобальное пространство или сильно сорящие в ActiveController/ActiveRecord::Base. Они дают быстрый старт, но большое количество проблем в будущем. Как пример — karmi для elasticsearch. Работать с ним через модель поначалу удобно, но шаг в сторону (скажем маппинги сильно отличаются от схемы бд) — и ты получаешь массу проблем.
Если сначала потратить немножко времени, и написать сервис, используя более низкоуровневый механизм того же karmi, то в дальнейшем все находится под контролем и времени написание функционала уже особо не занимает. Гораздо экономнее, чем потом дебажить и писать воркэраунды.

Многие клиенты на эти практики реагируют довольно нервно. Чем менее привязан к rails community клиент, тем больше шансов, что он отнесется к ним позитивно.
> Работа с ассетами в Spring Boot напомнился времена голого JSP и сервлетов).
Можно подробнее? Стало интересно в чем проблема.
В основном упреки касаются практически стокового thymeleaf.
Неуклюжие layouts. Еще подключение css/jss (тут скорее отсутствие asset pipeline, он в принципе для Spring Boot имеется, но мне неясно его качество и статус). Сурово как то все. Если вы наведете на средства сделать лучше, буду рад и признателен.
По поводу шаблонов — есть надежда, что jade спасет, но опять же неясно, насколько прямо он реализован именно для Spring Boot.

Оффтоп — а по миграциям — flyway уж очень суров.
Ни в одном веб-фреймворке я не видел миграций, сделанных хотя бы так же удобно, как в рельсах(
Я пару лет назад изучил и написал веб-бухгалтерию простенькую на Asp.Net MVC 4, и там как мне кажется, тоже много взято из идеологии рельс, по крайней мере оно там очень похоже. Но сменил работу и уишел в хостмастера юникс систем. Но это в будущем дало мне сейчас большой плюс в понимании работы с рельсами теперь — пишу свою панель управления хостингом приложений.
Пробовал еще Perl + Mojolicious, но там слишком много надо реализовывать из того, что в рельсах идет из коробки
Да, Asp.Net MVC 1 — это по сути порт Rails 2.x под .NET
Насколько далеко они разошлись сейчас я не в курсе, но в 2008-2010 годах был настоящий бум — фреймворк аля Rails писали на всех популярных языках :-)
Только не очень понятно почему никто кроме рельсовиков не воспринимает AR нормально, видимо он нигде толком не получился?
Про это ещё Фаулер писал в EAA Patterns писал… Если вкратце, то AR — это одновременно и паттерн и антипаттерн, так как совершенно внаглую нарушает SRP.
Существует масса вещей которые в наглую нарушают христианство например. Конечно Фаулер молодец, да и вообще святой, с этим трудно спорить. Но есть десятки тысяч счастливых разработчиков использующих AR на успешных проектах.

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

Это метафора — такой литературный прием.
Ну и AR получился в Rails, 99% задач решаются через AR.

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

Сталкивался, в детстве. Уже давно бизнес логика не хранится в моделях. Но статьи про «thin controllers fat models» продолжают выходить с завидной регулярностью — это саботаж!

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

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

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

Погодите, нигде не же сказано, что бизнес логика должна быть реализована через AR?
Объект AR не должен знать как снимать деньги со счета, но он должен знать как аз balance вычесть 10.
И нет в этом ничего оригинального, на AR возложены конкретные узкие обязанности.

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

«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
Логика доступа сохранена, не вижу противоречий

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

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

Не вижу никаких усложнений, одни упрощения.
Я не предлагаю вмешивать в AR Services.
AR занимается своими обязанностями. Все остальное занимается своим делом.
Всем добра и Single Responsibility.
У юзера есть метод withdraw, но на юзера нельзя возлагать обязанности соблюдения бизнес логики всей системы, это не его обязанности.
Снять деньги у юзера — не обязанность юзера, а обязанность сервиса банка. Причем банк как сущность может вообще не иметь AR сущностей.
И это не усложнение, это — напротив — упрощение, сегрегация интерфейсов проще, чем порождение франкенштейнов. Собственно и в реальном мире с реальной бизнес логикой пользователь не может снять деньги со своего счета непосредственно.
И это не усложнение, это — напротив — упрощение

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

Подождите
В моем примере AR кладет в БД, и логика работы в БД там же. Но категорически нельзя Генератору светящихся лампочек просить AR что-то делать, но можно Генератор Светящихся Лампочек попросить Модель данных AR попросить что-то сделать.
Вы же предлагаете всю предметную область положить в AR, как быть с сущностями сервисами, которые не хранят свои данные в AR а являются сервисами?
Вот поэтому и получаются жирные модели, когда у нас юзер становится монстром делающим не свойственные ему вещи и отвечающим за не свойственные ему операции, никакой патерн не заставит и _не_заставляет_ меня это делать, и даже не рекомендует. Всему должна быть мера.
Вы же предлагаете всю предметную область положить в AR

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

Не понимаю почему вы сделали такой вывод.
Добрая половина документов в проектах обычно AR классы. Но они делают свое AR-ное дело, абстрагируют меня от СУБД, хранят бизнес логику своего поведения. 2+2 все еще 4 для меня.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Я не люблю когда контроллеры выполняют действия над моделями, если они сложнее чем CRUD. В сложном случае, это не работа контроллеров. Стащили у питонистов form_objects, есть сервисы, есть куча всяких чужих паттернов, мы же не в вакууме?
НЛО прилетело и опубликовало эту надпись здесь
mvc 1/2/3 прошли мимо меня, но они всяко лучше asp.net webforms, которые, оспади прости, битрикс в мире дотнета, судя по тому «коду» что я видел и мое счастье, что я ЭТО не застал
Хаха, а я застал «краешком»… серьёзные проекты на WebForms я не делал, но там реально была жесть, он генерировал совершенно дикий HTML, а AJAX работал через UpdatePanel, т.е. тупо обновлял практически всю страницу… Так что да, ASP.NET MVC в сравнении с WebForms был крут уже с первой версии.
Мы намучавшись с thymeleaf в итоге ушли на простенький написанный одним человеком twig подобный шаблонизатор.
Скрипты собираются с помощью Maven, настроили один раз и больше не трогаем.
Ну в целом понятно о чем вы, соглашусь есть неудобные места.
Такой подход не плох и безусловно имеет право на существование. Только фишка в том, что Rails разнообразно сопротивляется такому использованию (как запчасть). Поэтому это требует хорошей дисциплины от всей команды разработки и дополнительных усилий. Впрочем, на этом пути помогают такие проекты, как trailblazer.
Я, как человек недавно познавший быстрое прототипирование Rails, в когнитивном диссонансе. Только недавно пришел к мысли о том, что вот оно — будущее (в сравнении с PHP). Конечно, я не занимался ничем крупным и толком не работал на Rails, я лишь где-то в начале пути, и понимаю, что эта статья не призыв к действию, но ладно бы это было только мнение автора, он то уже потратил не мало времени и знает о чем говорит. Более того, комментаторы что здесь, что к оригинальной статье, все поголовно соглашаются. И теперь, продолжая изучать Ruby, я мысленно просто буду ждать какого-то подвоха, который ждет меня прям здесь — за углом.
Серебряной пули, как известно, нет. Критическое мышление это хорошо, нужно трезво оценивать плюсы и минусы инструментов. К сожалению, сообщество последователей DHH сильно догматично.
Я согласен. Но это я описал свою ситуацию, а не мнение о статье.

С одной стороны, когда отзываются о чем-то плохо, значит это что-то есть с чем сравнить. Потому что в моей ситуации, я сейчас не вижу ничего криминального, что описывает автор. И у меня еще больший диссонанс от того, что вроде бы автор работает долго с Rails и ему, возможно, просто уже он надоел, а возможно, что он попробовал что-то другое.

Сейчас я вижу это так: автору статьи надоели автомобили. Надо стоять в пробках и ездить только по дорогам с определенными правилами. Отсюда возникает мысль: или у автора в гараже стоит летающее авто и он так пытается сам себя убедить, что оно то лучше, или ему просто надоели машины и он собирается ходить пешком. Насколько я понял, летающие машины = elixir и scala по мнению автора?
Я думаю, что дело в этом:

> Одной из моих первых задач было… добавить ссылку на что-то на какой-то странице. Мне потребовалось несколько дней, чтобы добавить эту глупую ссылку.

У меня те же самые мотивы «нестандартного применения» рельсов. С чем сравнить есть — я нативно из java. Поддался на то самое «быстрое прототипирование». В этом рельсы хороши, слов нет. Настоящие проблемы начинаются после N месяцев разработки и эксплуатации.
В принципе зная и обходя минусы, можно вполне успешно работать. К сожалению, у клиентов особого понимания такой подход не встречает. Поэтому проще отползти.
> Одной из моих первых задач было… добавить ссылку на что-то на какой-то странице. Мне потребовалось несколько дней, чтобы добавить эту глупую ссылку

Мне кажется, что это мог быть, например, просто не очень качественный проект, с первых версий рельс, и с большим историческим наследованием, как например, виденная мною ЦРМ с 10+ летней историей разработки с нуля под компанию и тоннами кода, удаление которого может поломать всё в очень и очень неожиданном месте.
НЛО прилетело и опубликовало эту надпись здесь
Я согласен. Но я уже написал, что обратил на эту статью внимание из-за комментариев. Посмотрите, несколько штук здесь, а на оригинальном сайте еще больше, в поддержку автора. Хотя, с другой стороны, вы правы насчет статистики, она бывает и вредна. Может это отписались 1% недовольных, остальные 99% довольных просто игнорируют, потому что не согласны.
Из практики моей работы инженером технической поддержки хостингов в несколько лет — могу с этим согласиться — те, кто доволен — могут привести новых клиентов, но жаловаться «ах вы козлы, у меня ничего не работает, почините быстро» они врядли будут,
А вот с теми, у кого не хватает понимания работы хостинга, например и «шаловливые ручки», и желание кому-то повыносить мозг «быстро сделайте шоб работало а то в суд подам», те звонят и жалуются, но и запоминаются в основном они.
P.S. Для себя, пока что, сайт писал бы исключительно на руби. Просто по другому, см. https://habrahabr.ru/post/301532/#comment_9622742
Насколько я понял из статьи (сам я никогда не использовал, ни Rails, ни Ruby, знаю только самые общие вещи о них, так что, все что я напишу ниже это выводы, сделанные исключительно из данной статьи), проблема в том, что большинство методов и компонентов Rails завязаны на некое глобальное состояние. Еще автор жалуется на засилье наследования. Все это, конечно же, приводит к слишком большой связности между сущностями. В результате это мешает использовать некоторые части Rails независимо. То есть, если используешь, то используешь все полностью. Как следствие, архитектура твоего приложения становится продолжением архитектуры Rails, которую автор считает крайне плохой. Если там действительно все на глобальном состоянии построено, то я с ним полностью соглашусь. Одна вот эта фраза чего стоит: «в Rails всё должно быть доступно везде, для вашего удобства.» — просто убило. Для маленьких проектов это может быть и удобно, но когда проект начнет расти, это будет боль. Ну и, поскольку Rails это главный фреймворк в мире Ruby, всем, кто пишет свои компоненты на Ruby, приходится делать их совместимыми с Rails. Плюс, помимо плохой архитектуры фреймворка, его основные разработчики еще и ведут себя довольно агрессивно, и всем пытаются доказать, что другая архитектура не нужна. Видимо, не хотят все переписывать. Вот это то, что я понял из статьи. В принципе краткое ее изложение получилось.
большинство методов и компонентов Rails завязаны на некое глобальное состояние. Еще автор жалуется на засилье наследования. Все это, конечно же, приводит к слишком большой связности между сущностями. В результате это мешает использовать некоторые части Rails независимо.
Мне кажется, что проблема в гемах. Автор, и люди в комментах, это немного затрагивают, намекая, что люди слишком сильно увлекаются ими. Возможно, я неправильно понял.
Проблема гемов тоже есть, также как и проблема зависимостей. Сама рельса тянет за собой кучу гемов, плюс для любого проекта наверняка нужно будет добавить еще парочку (десятков) гемов, вот и выходит зависимости от огромного количества библиотек, у которых в свою очередь свои зависимости, которые могу конфликтовать с другими. И вот да тогда начинается настоящий ад.
Проблема не в гемах, а в том, что гемы должны быть написаны с прицелом на Rails. Т.е. по-большому счёту гемы зависят от Rails. Именно это и не нравится автору. Он, как и многие другие программисты, хочет чтобы гемы были независимыми и простыми библиотеками.
Я, как человек недавно познавший быстрое прототипирование Rails, в когнитивном диссонансе. Только недавно пришел к мысли о том, что вот оно — будущее (в сравнении с PHP).
Не волнуйтесь. У автора статьи в 2007 году были такие же мысли о Rails, что и у Вас. Да и у меня было такое же ощущение в 2008-м.
Просто у Rails есть свои границы применимости, за которыми вся его магия оборачивается против программиста. С накоплением опыта участвуешь во всё более сложных проектах и всё чаще натыкаешься на эти границы. Поэтому со временем эта борьба с фреймворком утомляет и хочется иметь инструмент простой и предсказуемый.
Но Rails в ближайшие годы никуда не денется. И на простых проектах Вы вполне можете оставаться в рамках Rails Way и не испытывать никаких неудобств. А для сложных — посмотрите сразу в сторону trailblazer.
Спасибо. Я особо не переживаю. Всегда хочется учиться чему-то новому, а в наши дни количество языков/фреймворков растет неутомимо быстро и каждый день появляется что-то новое, да не факт, что стоящее. И тут дело даже не в Rails, а в общей тенденции. За чем гнаться?
Хочется надеятся, что серьезные проекты вы получите, только став опытным разработчиком.
А к тому времени будете уже и сами знать. Не парьтесь понапрасну.
Так в том и дело, что сейчас для меня Rails отдых/хобби, которое может перерасти в работу. В работе мне приходится использовать PHP.
Хочется надеятся, что серьезные проекты вы получите, только став опытным разработчиком.
Не совсем понял к чему это? К тому, чтобы сам себя не замучал костылями?
В качестве хобби и работы на ближайшее время Rails вполне подойдёт. Если говорить о России, то в ближайшие 3-4 года Вы скорее найдёте работу именно c Rails, а не с «летающими машинами», как Вы выразились.
Однако, основная мысль статьи в том, что не стоит идеализировать Rails. Он симпатично выглядит снаружи, но внутри никогда особо не блистал понятностью или удобством. К тому же фреймворк оброс кучей функционала, часть из которого весьма спорна, и стал медленно развиваться в плане действительно важных вещей… В чём-то он уже пытается догнать конкурентов, к примеру, наконец-то добавляя поддержку веб-сокетов.
На тему самого Ruby тоже спохватились и пытаются угнаться за языками, на которые идёт массовый переход: Ruby 3x3, Concurrent Ruby
На самом деле очень странная статья. Автор буквально ругает те плюшки рельс за которые его очень сильно любят пытаясь сделать из него строгий фреймворк которым он сам по себе никогда не являлся и не собирался. А по высокой связанности это здравая мысль, тут уже каждый сам выбирает для себя.
Эти плюшки хороши, когда Вам надо сделать блог за 10 минут. Но чем сложнее становится проект, тем больше сложности они в него добавляют.
Очень рекомендую всем, кто имеет дело с Rails, книгу «Rails Anti-Patterns». В ней описаны многие анти-паттерны, на которые в какой-то мере провоцирует сам Rails.
Продолжайте изучение инструмента и на этом этапе меньше слушайте подобных «особых мнений». Не стоит превращать инструмент в идеологию. Идеальная архитектура — это не решение задачи, к а один путей к ее решению, зачастую достаточно дорогой для компании и, в целом, очень субъективный.

Тут кто-то писал про Coldfusion, мол «фе». Пару лет назад я работал в прибыльной компании из штатов с 10М+ пользователей, добротной архитектурой приложений (не идеальной, но достаточно понятной для внесения изменений и поддержки меняющихся требований бизнеса), все на распоследних версиях фреймворков, в том числе Rails. И вот в один прекрасный момент нас купила фирма-конкурент, которая клонировала изначальную идею нашей фирмы (геймификация ритейла + персональные рекомендации), повела более грамотную маркетинговую политику, набрала больше инвестиций и выкупила нашу компанию (по сути покупался бренд и база пользователей). Весь наш чудесный код выкинули на помойку и заменили ужасным и кривущим кодом на Coldfusion (практически никто из нашей dev-команды не захотел работать с этим ужасом дальше и все уволились). Компания по прежнему процветает. Код по прежнему на Coldfusion. Делайте выводы, господа идеалисты. Рынку не нужна идеальная архитектура приложения, да никто про нее и не знает даже, кроме инженеров.
Спасибо за мнение. Я и не собирался никуда уходить. Статья лишь подтолкнула посмотреть, а что там еще есть интересного в нашем мире. Например, открыл для себя elixir.
Весь наш чудесный код выкинули на помойку и заменили ужасным и кривущим кодом на Coldfusion
Какая жестокая, но реальная правда. Такой «коммерческий» подход я часто встречал в русских компаниях. Команда зарубежная?
> Статья лишь подтолкнула посмотреть, а что там еще есть интересного в нашем мире. Например, открыл для себя elixir.

Это здорово, на самом деле, знать много подходов.

> Команда зарубежная?

Да, все это происходило в LA.
Если контора большая и есть ресурсы тратить несколько дней на вставку ссылки, почему бы и нет.
Maintainability это одно из качеств проекта, и если его отсутствие можно решить в лоб, ковбоями, да флаг им в руки.
Остальным же это экономит время.
> Maintainability это одно из качеств проекта, и если его отсутствие можно решить в лоб, ковбоями, да флаг им в руки.

Я рассмотрел крайний случай, обычно дела с поддерживаемостью обстоят намного лучше, рельсы как раз помогают с этим хотя бы на уровне «что где должно примерно лежать».
НЛО прилетело и опубликовало эту надпись здесь
Занимаюсь Рельсами уже… эээ… тоже где-то лет 9. А до этого и на C писал и на Java, и даже на ассемблере доводилось.

Как написали ниже, основная проблемы с рельсами начинаются после нескольких месяц разработки. И, на самом деле, многие проблемы возникают от того что кто-то плохо знает рельсы и попросту делает костыли, эти костыли обрастают своими костылями и т.д. Либо от того что заложил неправильную архитектуру. И дальше уже повезет или нет. Рано заметешь что не так, и есть время на рефакторинг — исправил и проблемы нету. Но чаще бывают, что проблемы живут неосознанными достаточно долгое время чтоб пустить корни, и так просто от них не избавиться, да и клиент со сроками подгоняет, на рефакторинг времени не остается.

А вот тут параллельно решил React.js изучить. Redux'ы там всякие и т.п. Казалось бы вот оно «счастье» с точки зрения архитектуры. И что? Я форму логина делаю уже неделю. Простой логин по email и паролю. Перечитал уже тонну тутариалов. Просмотрел кучу примеров. Вот только для того чтоб понять примеры нужно прочитать еще тонну туториалов. И до сих пор кстати не доделал. Осталось сделать переход на новую страницу. Пытаюсь второй день понять откуда по правильному я должен вызывать это переход. Вы можете представить такую проблему в рельсах? Что там автор про простоту говорит? Что про модульность? Может где-то там и есть в рельсах лишняя связанность которая не дает автору жить и спокойно спать ночами, вот только разрабатывать на рельсах на порядок быстрее чем на других фрэймворках. Быстрее разрабатываешь, быстрее получаешь деньги. У тебя стало 100500 пользователь и рельсы не справляются? (хотя я лично поддерживал проект на рельсах с 10к запросами в минуту, и не сказал бы что это было очень сложно) Вот теперь время подумать и нанять разработчиков которые напишут тебе с нуля под высокую нагрузку хоть на хаскеле, избавившись от кучи костылей…

Это вот мои немного сумбурные мысли
Спасибо за мнение. Первое, что мне бросилось в глаза в rails-community — это перфекционизм. Я обратил внимание, что разработчики rails как никто другие любят делать красиво. Отсюда у меня сложилось мнение, что rails в первую очередь любят за удовольствие, которое он приносит. И такие комментарии как ваш только подкрепляют мое мнение.
И что? Я форму логина делаю уже неделю. Простой логин по email и паролю.
Как это знакомо! Иногда кажется, что подобные технологии просто навязывают
Мне все же кажется react + redux это несколько edge и поэтому такая кривая входа, в дальнейшем будет проще (может уже и не в react-redux, а в чем то новом).
А что для роутинга используете?
Да, я тоже думаю (надеюсь) что это просто технология еще не устоялась. Но после рельсов все очень сложно. На каждом шаге.

> А что для роутинга используете?

react-router пытюась использовать.
Сам до роутеров еще не дошел, рекомендовать не могу, но посмотрите, может лучше что-то специализированное?

https://github.com/reactjs/react-router-redux
https://github.com/acdlite/redux-router
Так эти библиотеки призваны работать в связке с react-router.

А вот то что мне надо вроде как вот-тут обсуждается. https://github.com/reactjs/redux/issues/297
Йо

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

Сначала несколько общее замечание:
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.js
Спасибо за ссылку, посмотрю.

А вот angular и прочие ember'ы как-то пробовал и сбежал от них нафик. По мне там никакого упрощения нету, только сложности лишние добавляет, и код еще более запутанный становится. Вот React мне сразу понравился своей идеей.
А не могли бы вы привести примеры больших приложений на связке React+[Some Flux like stuff].
Сейчас в раздумьях по поводу миграции с Angular 1.3. Пока смотрим на Angular 2.0(+Typescript) и Ember.js.
Ну, например:
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» — так-то все хороши, тут подсказать не могу, самому все нравится. Смотрите куда хочется двигаться.
Интересует аналог Discourse, Taiga и тд. У марафона маловат UI :)
То есть фронт не для конечного потребителя, где обычно мало ресурсов и вьюх, а UI для администрирования серверов со сложной UI логикой и тд. Что нить типа 200+ actions с Flux и как это вообще живет и поддерживается :))
Ну, проблема в том, что если Discource и Taiga уже есть и здравствуют, то какой смысл писать их клоны? :)

А так на реакте дофига всего пишется. В гугл-трендах запрос react.js обогнал angular.js

Общий список: https://github.com/facebook/react/wiki/Sites-Using-React

Те, что конкретно мне нравятся:

Я не про клон. Пример — админка серверного приложения. 50+ ресурсов, вьюх и компонентов за сотню. В связке Angular 1.3 + ui-router + свой слой для REST живет отлично. И поддерживается достаточно легко. По сложности Jira или VisualStudio Online.

Просто хотел посмотреть как очень большое приложение живет от и до.

По sprintly: https://github.com/sprintly/sprintly-kanban/tree/master/app/actions вот тут получается 50+ файлов будет жить?
Ну я например писал онлайн-бухгалтерию на React.js + Backbone.js: http://imboss.ru/.
По размеру там в районе 1000 компонентов.
Но вот так, чтобы выложить вам ссылку на открытый код — боюсь, не знаю таких.

Про srpintly — вообще сами actions спорная инициатива, я бы не так сделал, но получается да, у них там и будет жить. Возможно по подпапкам еще разнесут, не знаю уж, на какой базе — каждому отдельно или будут группировать по смыслу.
Спасибо за ответы :)
Нашел:) Вдруг кто наткнется на вопрос.
WP Calypso
В целом близко к тому, что хотелось посмотреть и организация проекта норм.
Вот еще хорошую ссылку хочется подкинуть: https://github.com/mxstbr/react-boilerplate/

Это типа boilerplate для Universal App на базе React.js + Redux + Reselect.
Примечателен тем, что все используемые библиотеки типа bleeding edge.

Вам будет полезно посмотреть, как делается авторизация с unidirectional data flow.

Если вам нравятся Рельсы, не обязательно с них уходить. Просто следует помнить, что они заточены под быстрое создание несложных приложений. Более сложные приложения на них писать можно, но нужно добавлять к Rails другие инструменты, которые будут помогать масштабироваться. Например, Trailblazer.
См. https://habrahabr.ru/post/301532/#comment_9623484

Находясь в подобной ситуации могу вас заверить, что изучение руби вам не повредит. Сам язык очень хороший, автор статьи даже указывает на то, что будет саппортить некоторые библиотеки на Руби.
Из личного опыта — написание парсера на руби было очень веселым и быстрым. Книги по руби читаются легко. Все, что не касается напрямую Rails — очень удобно и просто.
Rails так-же имеет смысл установить, по играться, развить своё восприятие данного фрэймворка. Очень многое вам покажется правильным и вы решите использовать подобные схемы решения задач на PHP.
Используйте Руби в качестве трамплина для вашего развития как программиста в целом.
Создается впечатление что рельсы ждет судьба ColdFusion. Тоже в свое время выглядел круто.
Комментарии к статье от Yehuda Katz

https://twitter.com/wycats/status/734991937862795264
https://twitter.com/wycats/status/734992848987258880
https://twitter.com/wycats/status/734993723029868544

Статья просто потрясная! Очень коррелирует с моими мыслями по поводу Rails.


Показушная "простота" работает хорошо только до тех пор, пока не надо чуток выйти за рамки. В тот момент когда это происходит, совершенно теряется понимание "что делать", код превращается в макароны из грязных хаков и теряет полностью свою простоту и привлекательность.
ЗА адептами Рельсов очень интересно наблюдать тогда, когда они пытаются написать что-то на… Ruby! ActiveSupport — это по сути новый язык программирования.
По моим ощущениям, создание rails приложения — это сборка камней/гемов — как в лего, только вся сложность начинается в тот момент, когда эти кубики надо собрать вместе. Когда гем подключается одной строчкой и делает кучу вещей — я его просто боюсь! А такие "батарейки" — везде.
Самое главное, API Рельсов не очевидное, не однозначное, и разработчика на Рельсах по сути ничего не заставляет его как то изучать и понимать. Можно создать десяток сайтов на Рельсах и так и не узнать, что скрывается за волшебным словом Rack, и чем middleware гемы отличаются от "не middleware"!
Ничего не имею против ActiveRecord, если чувствовать пределы, его использовать очень удобно. Но когда можно забрать модель из формы через :params и сохранить как есть одной строчкой как в статье — это рождает миллионы вопросов на SO — "Почему сохраняет пустую модель/не сохраняет ничего" которые просто нереально чинить — там всего одна строка!)


Очень бы хотелось обсудить предыдущую статью автора, в которой он осуждает monkey patching: если не ActiveSupport, то как? Если многим это удобно, то писать RFC к самому Руби? 10.years.ago — возможно это должно быть в стандартной библиотеке?


А что касается проблем ООП — мне кажется Руби — не показатель плохости такой парадигмы. Monkey patching и вся рефлексия — это по сути нарушение инкапсуляции. И это то, что самое крутое в руби, с его method_missing, символами и открытиями классов в любом месте вашего кода. А ведь именно на этом строится такая "классная" ActiveRecord, роутинг, ActiveSupport. Оставь в Рельсах "чистое" ООП — и от всей прелести Релься ничего не останется.

Очень бы хотелось обсудить предыдущую статью автора, в которой он осуждает monkey patching: если не ActiveSupport, то как?
Нет ничего плохого в отдельных модулях для подобных методов, не обязательно их добавлять к базовым классам. По началу это даёт определённый вау-эффект, но не даёт реальных преимуществ, а вот весёлый дебаг временами обеспечивает.

Чел перерос технологию и закономерно направился в функциональное программирование. Все с порядке вещей.

Спасибо за перевод. Интересная статья. Никогда не программировал на Ruby, было очень интересно сложить хотя бы такое поверхностное представление о достоинствах и недостатках Rails. Автора я понимаю, сам не люблю ограничивать себя набором готовых функций, особенно, если они вызывают проблемы с не интуитивным решением (виной тому моя криворукость или желание выйти за рамки — решайте сами).

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

"… дает вам ложное чувство простоты, в то время как то, что происходит на самом деле заключается в том, что сложность спрятана за удобными интерфейсами"

Эта фраза актуальна вообще для всего, и не только в компьютерном мире :)
> Поскольку всё-таки можно сделать проект по всем правилам, создать обёртки вокруг функционала Rails, нагородить собственных классов и организовать всё так, чтобы проект был масштабируемым. Но любители Rails просто привыкли пользоваться готовыми функциями и мириться с возникающими проблемами. Конечно, с такой разницей во взглядах работать с этими людьми — одно мучение.

Точные у вас формулировки)
Можно. И да, так и есть, мучение, борьба Дон Кихота с ветряными мельницами.
Извините, ничего конкретнее написать не мог. Но поскольку прочитал статью с интересом (пусть и отнесясь к ней, как к поучительной истории из жизни), решил выразить переводчику благодарность, отписавшись под ней :)

«Борьба с ветряными мельницами», кстати, очень интересное занятие, сравнимое с поиском сокровищ по пиратской карте.
Спасибо за отзыв :-)
Я так понял, главная проблема автора не столько в самом Rails, сколько в сообществе.
Автор хочет привлечь внимание сообщества к тому, что есть жизнь за пределами Rails. Как на Ruby, так и на других языках. В частности он является автором более чем десятка полезных гемов для Ruby.
Полезных в виде virtus? из-за которого боли больше чем от rails?
НЛО прилетело и опубликовало эту надпись здесь
А что мешает теперь? Ведь раз вы все себе под задачу выбрали, то кто после статьи вам мешает так же хорошо ваш проект реализовать?

Я куда чаще видел, когда человек, поначитавшись, бросает привычную технологию, строит что-то на новом (плюясь, разбираясь, но, в общем, радуясь), а потом понимает, что но новом он писал не так круто, как знаток нового (наоборот, прорывались подходы старого, уже отвергнутого), и что новое также нужно поддерживать.

В общем, «старый конь», пока он решает задачи, почему бы и не поработал? Тем более что выбирать сегодня инструмент, которые закроет все проблемы проекта на долгие годы — это нереально, и в чем-то безответственно. Даже банальный движок форума можно писать на php+mysql (и поиметь в будущем более-менее понятные проблемы — но «потом»), а можно на oracle+хранимые процедуры+веб-приблуды от уважаемого Oracle — будет круто до небес, никто никогда себе это не поднимет (стек сильно не массовый), и проект не взлетит, поддержка станет до небес дорогой, и будет вопрос «а зачем».
НЛО прилетело и опубликовало эту надпись здесь
Если у вас 1000 активных пользователей, то вам придётся озаботиться кешированием в любом случае.
По-моему, вы доросли до микрофреймворков. Например, я сейчас на python использую flask + peewee + pyjade + webassets (css сразу в sass, html сразу в jade), хочу прикрутить marshmallow для работы с json и angularjs, а виджеты angular'a делать автоматом с помощью flask-triangle… будут нужны сокеты или асинхронные запросы — просто добавить.
НЛО прилетело и опубликовало эту надпись здесь
Это ещё бабушка на двое сказала, что у проекта будет 1000+ пользователей онлайн.
Если так и будет (дай-то Бог каждому проекту) — то просто кидай в него железом и всё, а потом перепишешь на чём-то более высокопроизводительном (если это вообще нужно будет к тому моменту). Большенство проектов не взлетит так и так и смысла делать всё круто с самого начало — нуль ))
НЛО прилетело и опубликовало эту надпись здесь
В людом случае, рельсы хоть и не самый высокопроизводительное решение (GIL и всё такое) в конечно счёте все решит выстроенная архитектура, имхо. Можно разбить приложение на части (микросервисы) и самые медленные переписать на чём-то другом.
А вообще, как мне кажется, чем дальше в сторону хайлоада, тем больше общих решений будет у всех языков и фреймворков — кэширование, низкоуровневое ковыряние и т.д.
Начали и начали. От ещё одного проекта на Rails никому хуже не станет )))
А на будущее посмотрите ещё и в сторону Elixir+Phoenix. Конфет много не бывает xD
А там и вовсе в сторону чистого Erlang можно глянуть, ну и в качестве веб-фреймворков «Chicago Boss» или «N2O».
Красивейший язык, в самом деле.
За один синтаксис в стиле пролога можно уже простить многое.

Хотя, непонятно, зачем я это пишу — любой человек, изучающий эликсир, как минимум, погуглит, что такое Erlang ;)
НЛО прилетело и опубликовало эту надпись здесь
/me Поднимает руки
Извините, спорить не буду. Мне нравится и elixir, и erlang. И, кроме того, я искренне считаю, что изучение erlang как минимум не повредит, а как максимум сильно расширит горизонты и возможности изучающего.
НЛО прилетело и опубликовало эту надпись здесь
Эм. Сложно что-то подсказать при такой постановке задачи. Разработчик переходит с Python/Django — а куда? :)

Вообще, я так понял из ваших комментариев ниже, вы уже много лет в вебе, поэтому первое что я посоветую — серьезно задумайтесь о смене фокуса. Неужели вам совсем неинтересны, например, IoT, VR? С вашим опытом на них реально найти вакансию джуниора как минимум, а в этих областях даже джуниоры получают вполне достойную плату, не меньше чем senior в вебе. Ну и кроме того, часто в этих проектах нужны как минимум веб-странички, а то и полноценные приложения, написанные на базе Electron.

По поводу же смены технологии именно для веба… Настоятельно рекомендую посмотреть и попробовать функциональный язык вроде Erlang|Closure|Haskell, крайне освежает. Тут нужно заметить, что перечисленные языки — они, вообще-то, очень сильно разные, с разной концепцией, и лучше посмотреть каждый.
Возможно, вы и не перейдете на них, но очень много полезного для себя найдете.

Не бойтесь тратить время на какой-нибудь Erlang, работы конкретно под функциональщину хватает: https://functionaljobs.com/.

Еще из неплохих вариантов в вебе я бы посоветовал Go и JS. Первый предлагает большую производительность и очень крутой параллелизм, второй мультипарадигменный, с возможностью писать и в ООП и функциональном стиле по желанию пользователя. И там и там есть работа, есть живая экосистема с огромным количеством библиотек.

Ну и чисто для вдохновения и расширения горизонта, хотелось бы посоветовать глянуть на вот эти два языка:
  • Фунциональщина под веб, пока что очень новый язык, использовать осторожно, но заложенные концепции просто офигенны: http://elm-lang.org/
  • Настоящее ООП в стиле SmallTalk. Как и в Ruby, все объект. После знакомства с этим языком вам динамичный руби с открытыми классами (вы еще называете это хаотичным) покажется заскорузлым монстром, на котором нельзя толком метапрограмминг писать. К сожалению, из-за своей динамической природы этот язык довольно медленный, так что годится скорее для изучения в академических целях, писать на нем реальные программы я бы не стал. Но для расширения сознания, получения нового опыта и оттопыривания чакр крайне рекомендую взглянуть.
Упс, забыл ссылку для второго языка: IO
НЛО прилетело и опубликовало эту надпись здесь
А на Nim не смотрели? Вроде и компиляция в JS, и ФП есть, и мощный, даже серия статей здесь была про то, чем он хорош.
Мне даже интересно потом Ваше мнение будет…
НЛО прилетело и опубликовало эту надпись здесь

Nim логичнее сравнивать с Go, Rust, Crystal.
Язык интересный, но стабильной версии пока нет, да и библиотек пока тоже немного. Причём ощущение, что разработчики слегка подзабили в этом году… После выхода версии 0.13 уже 5 месяцев никаких новостей от них не слышно. Коммиты есть, но активность в разы меньше, чем в прошлом году.

Знаю, что platoff сравнивал его с Go и Rust (не в пользу последних), других статей пока не встречал. Столько он на него надежд возлагал. Интересно было бы узнать его впечатления после почти года знакомства.
почему возлагал? все прекрасно — вот первая ласточка от наших ребят — обернули Unreal Engine 4 — и игрушку пишут: https://github.com/pragmagic/nimue4, но это, как говорится только начало, на подходе еще сервер сайд и веб/десктоп приложения на Nim
Здорово! А игрушка — это для развития своих навыков?

Почему возлгал то? На офф.сайт зайдите, там последняя новость в январе была. По-моему, это маркетинговая недоработка… мало что-то делать, надо не забывать об этом писать.

Вообще для всех кто выбирает язык для веб-разработки, я бы посоветовал такой алгоритм:


  1. определяете наиболее популярный веб-фреймворк
  2. ищете актуальную книгу "Programming НазваниеФреймворка" или "Web Development with НазваниеФреймворка" или "Web Development with НазваниеЯзыка"
  3. Бегло читаете https://learnxinyminutes.com/ по языку, а затем найденную книгу
  4. По результатам прочтения книг делаете осознанный выбор что вам ближе
  5. Изучаете сам язык и вдумчиво перечитываете понравившуюся книгу
Вот кстати, про вебсокеты на 5х рельсах — я пытался осилить официальный гайд с этим примером чатика, но так и не осилил — нет ли у Вас желания по горячим следам написать статью, думаю, многие бы оценили
НЛО прилетело и опубликовало эту надпись здесь
А что не так с Django?
С Django в принципе много чего не так, но применительно к задаче автора комментария думаю ключевое это отсутствие вебсокетов в 2016 году.
Ну, вебсокеты — они ж не всем нужны (игры и чаты — там да). А что именно Вас не устраивает в Django? (не для разжигания бесплодных споров, но информации для)

А как же оповещения о новых комментариях и прочих обновлениях на всех социально-ориентированных сайтах? На хабре, вон, вручную кнопку «обновить» нажимать надо. А в том же гитхабе новые комменты в ленте сами появляются.

Пожалуй, соглашусь с Вами, что это удобно, и уже назрело.
Это вопрос для целый статьи :) Если очень кратко из последнего наболевшего: очень не нравиться «тупая» орм, тяжелые и непредсказуемые FormSet, нарушение одного из важных принципов дзена питона «явное лучше чем не явное».

Я понимаю что скорее всего это вопрос не столько к Django сколько к его области применимости. Но дело в том что начиная долгоживущий проект я вряд ли могу предсказать как он будет развиваться и как скоро мы упремся в границы Django-песочницы. И я не готов рисковать своим временем и деньгами выбирая столь ограниченный инструмент для долго живущих проектов. Если дело касается классического контент сайта (лендинга, страницы компании, какого-нибудь блога, вот этого всего) то к Django вопросов нет, отрабатывает на все деньги. Просто я такими проектами не занимаюсь.
Спасибо! А что используете в качестве «тяжёлой артиллерии» для догло живущих проектов? Ну, или, что стоит из нового рассматривать?
Как раз то "тяжелой артиллерии" стараемся избегать в последнее время, предпочитая легкие компоненты со слабой связанностью. Сейчас в основном строим на базе tornado, т.к. активно используем вебсокеты, и планируем переход на асинхронную работу с бд и чистый sql. До этого вполне успешно использовали Flask. Когда кодовая база бизнес логики гораздо больше чем непосредственно веба преимущества Django совсем не очевидны, а гибкость Flask решает. Захотели, подтянули монго, не понравилось, поменяли на sqlalchemy.

Так же смотрим за рамки питона, интересны Java Spark или, чем черт не шутит Clojure Luminus ))
Спасибо за развернутый ответ!
Посмотрите на Java Rapidoid, похож на Spark но еще более минималистичен.
НЛО прилетело и опубликовало эту надпись здесь
Спасибо! Надо глянуть django-websocket-request.

Продолжайте использовать Rails. Просто помните, что одних Rails не достаточно. Точнее, недостаточно трёх букв MVC, которые есть в них.


Пока у вас приложение маленькое (5-10 моделек) и с не очень большой логикой, всё будет окей. Когда число моделей перевалит за 50, а просто список функциональности перестанет помещаться в голове одного человека (а ещё помножьте на скорость разработки) — вы запутаетесь и будете погребены под приложением.


Решения есть, их много, но, к сожалению, ни одно из них пока не стало стандартом. Посмотрите на Trailblazer (мы его используем) — он добавляет новых уровней абстракции и этим снимает нагрузку с существующих букв MVC. Посмотрите, какие проблемы, решает этот инструмент — если они вас не волнуют, то вам ещё рано. Я же когда читал книжку по нему, плакал над каждой, потому что мы страдали просто от всех: к примеру — у нас было 500+ строк коллбэков в некоторых основных моделях, например.

Про коня в контексте данной статьи и комментариев выше. Просто ассоциация, поскольку на Ruby никогда не писал, но с описанными проблемами сталкивался в нескольких других «местах». Так вот, полностью эта пословица звучит так: «Старый конь борозды не испортит, но и глубоко не вспашет». Мне кажется, что это стоит помнить, выбирая навороченные «коробочные» фрэймворки Rails или Django, потому что иногда лучше собрать свою «коробочку», как это делают во Flask.
НЛО прилетело и опубликовало эту надпись здесь
Многие из перечисленных здесь недостатков характерны для Yii/Yii2
Насколько я могу судить, Yii немало и концепций позаимствовал из Rails, и задачи аналогичные решает в той же нише. Итог, как говорится, предсказуем.
После нескольких лет работы с Yii, на проекте сложнее среднее много усилий начинает уходить на борьбу с «удобствами» ActiveRecord, которую нельзя выкинуть из приложения и нагромождения собственных абстракций чтобы разбавить изкоробочную связанность компонентов фрейворка.
И да, начинаешь мечтать о DataMapper =)
Да, совершенно согласен. Сам сталкиваюсь с этими же проблемами. Пытаюсь решать с помощью паттерна «Репозиторий» поверх ActiveRecord
>DataMapper в конечном счете был лучшим ORM, чем ActiveRecord в 2008-9.

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

Рельсы в некоторых вопросах огорчают, так что поменьше гемов пожалуйста, их итак слишком много.
Без «веселых хипсто-хакеров» профессиональные программисты до сих пор бы писали на COBOL.
это опять же миф. Я бы никак не назвал DHH хипстером. Талантливый профессионал с хорошим вкусом и четким пониманием того, что нужно, а что не существенно.
НЛО прилетело и опубликовало эту надпись здесь

ActiveRecord в 2008-м (2-е рельсы?) и ActiveRecord в 2016-м (5.0) — это две большие разницы.


В 2.х ActiveRecord был ужасен, в 4.х он уже был хорош (в первую очередь благодаря arel'у). И все 4-е рельсы он продолжал сильно перепиливаться (помнится, один мой pull request пришлось сильно переделывать с 4.1 на 4.2).

ужасен — это не совсем то слово, которое отражает реальность.

Читать один файл на 3 экрана гораздо проще, чем 10 файлов на пол-экрана каждый.

Простое распиливание кода на куски, которые вроде как должны быть в разных файлах по сути только ухудшает читаемость и не дает из коробки расширяемость кода.
Ох, не напоминайте мне про Arel. Надо было мне как-то раз его подружить с PG-функциями без скобок, типа current_date.
Для тех, кто не знает, у Arel есть возможность вызывать SQL-функции, но только со скобками
Account.where{created_at == :now.func()} # работает
Account.where{created_at == :current_date.func()} # не работает

В общем, пока я воркэраунд писал, достаточно ознакомился с его исходниками. Мягко говоря, там реальный треш. Если не согласны, попробуйте решить вышеописанную задачу. У меня на тот момент была версия arel-4.0.2.
А зачем тут arel?

Account.where('created_at::date = current_date')
Ахах, ну видимо придётся контекст задачи описывать…
Нужно было предоставить пользователю возможность создавать сегменты по определённым моделям. Т.е. пользователь накидывает критерии в интерфейсе, а мы по этим критериям с помощью Arel генерируем SQL-запрос. Естественно давать пользователю вводить raw SQL в планы не входило. Переписывать без Arel было бы долго, потому что для заказчика это выглядило просто «а давайте добавим ещё 1 тип критериев в форму». При этом требования к скорости результирующего запроса были очень высокими, т.е. обернуть current_date в SQL-функцию тоже не прокатывало.

В вашем случае, может, не стоило тогда даже и рассматривать current_date как функцию?


Arel — это, ИМХО, вещь не для прикладных разработчиков, а для разработчиков ActiveRecord'а и прочих вещей, напрямую общающихся с базой. В его исходный код не заглядывал, но простым он точно не будет, ведь его задача — генерить разный SQL для разных БД с их особенностями. Например, oracle_enhanced адаптер вместе с последним arel'ом научились генерить разные SQLи типа SELECT для 11-го и 12-го Ораклов.


Но ваша правда, даже документации толковой к нему нет, а чем хардкорнее вещь, тем она нужнее.

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

не стоило тогда даже и рассматривать current_date как функцию?
Как не рассматривай, а как-то надо было её запихнуть в результирующий SQL и обойдясь при этом без raw SQL. Реальнее оказалось запихнуть как функцию )))
потому что они все как писали под мускль без индексов, так и продолжают под него писать.
Автор использует вполне ожидаемые аргументы. Active Record заменить на DataMapper. Но насколько знаю, по производительности один другому не проигрывает. Это просто вопрос вкуса
Местами ловил себя на мысли что читаю про Django. Похоже это болезнь всех мега фреймворков…
Что насчет Symfony2?
Не знаю, не приходилось использовать на практике, если с ним все хорошо то я за него рад ))
Там в основном споры об архитектурных решениях в Doctrine2 и версионность пыха для Symfony3
Symfony2 (и 3), ИМХО, противоположность рельсам. Мало чего работает по одной команде из коробки, что-то приходится делать руками, что-то докручивать, донастраивать. В общем, полная противоположность принципу convention over configuration. Но это окупается в крупных проектах, проще дается построение правильной архитектуры, легко выкинуть и заменить не устраивающий модуль хоть из ядра фреймворка — огромная гибкость. И конечно за это приходиться платить сложностью освоения и скоростью начальной разработки, в итоге для небольших проектов не особо оправдано выбирать symfony.
НЛО прилетело и опубликовало эту надпись здесь
Большое количество «магии» (Explicit is better than implicit явно не про него). Перегруженность основных компонентов, как из коробки, так и базовых батареек (при этом, что удивительно, они откровенно не дотягивают до аналогов из параллельных вселенных). Сильная связанность. Тотальная привязка к ORM.
Я не хейтер Django, я работаю с ним много лет, и до сих пор поддерживаю на нем проекты, но это крайне не гибкий инструмент. И на долгоживущих проектах с не полностью определенным фичелистом я его не использую.
НЛО прилетело и опубликовало эту надпись здесь
Сложность за простыми интерфейсами это всегда магия, в Django с этим еще хуже, так как интерфейсы заменили соглашениями.
Про перегруженность я так сразу и сказал, куча невнятных мелочей есть, а нормальный явный left outer join или темплейт таг добавляющий класс к форме сделать уже который год не могут.
Если из Django выкинуть орм то останется уродливый парсинг урлов, половина форм и cbv и тормозной шаблонизатор. А админка, единственное в чем Django на голову превосходит аналоги, превратиться в тыкву. Зачем мне тогда вообще тянуть в проект Django если для всего этого есть более внятные инструменты?

Django гибкий на столько на сколько любой другой открытый проект. Понятно что при нужде все можно допилить, докостылить и т.д., исходный код открыт, гит в руки, «пилите Шура, пилите»… только Вы совершенно правильно сказали это требует серьзный уровень знания потрохов, потому что связанность высокая, интерфейсы магические и как только ты начинаете что то модифицировать под себя, в другом, неожиданном, месте что то начинает отваливаться. Зачем мне все это? Я выберу более подходящий инструмент, благо выбор есть.
НЛО прилетело и опубликовало эту надпись здесь
Не хочу я с Вами спорить, это спор ни о чем. Если в Вашем бекграунде Django не приносил вам боли и сожаления о бесцельно потраченном времени, я искренне за Вас рад, я лично брать на себя эти риски больше не хочу. Django хорош для своего, весьма ограниченного, круга задач которых я в последнее время не касаюсь.
А так же я не хочу тратить время на «серьезное изучение всех потрохов» что бы стать «настоящим гуру» этих потрохов. Если молоток требует знаний металлургии и сопромата для использования я не бросаюсь их изучать, я просто меняю молоток.
НЛО прилетело и опубликовало эту надпись здесь
Сложность задач увеличивается. То, что создавалось ранее, уже не так просто развивать — вылазят ранее не видимые недостатки подхода и реализации. Люди ищут замену…
Думаю, автор немного не прав в том смысле, что Rails надо оценивать сравнивая с другими фрэймворками, а не просто перечисляя что в нем плохо. Если это хорошо в других фрэймворках, может оказаться что в них плохо что-то другое. Это не вопрос того, что Rails лучше. Это вопрос того, что Rails лучше для автора статьи в задачах, которые он решает. Вполне возможно, что ему просто надоело и ему банально хочется развития. Вполне естественный процесс, правда, ничего не говорящий о недостатках Rails.
Очень интересная статья но просто ужасный перевод. Я понимаю что текста много, но мне кажется что автор перевода не перечитывал текст перед публикацией. Читать сложно и неудобно.
Мне вот эта картинка понравилась (12 лет прогресса веб-разработки):

image

У меня есть один проект (первый) — дак он всё ещё крутится на Rails 1.0 (был переписан с Access) — и заказчик вполне доволен до сих пор (прошло уже почти 10 лет). Изучать новые технологии необходимо, но и понимать, что в конечном итоге надо решать бизнес задачи.

А автору спасибо за DataMapper — использовал (совместно с Sinatra) в нескольких проектах.
Хороший ответ. Akita справедливо отмечает, что у Rails есть своя сфера применения (Basecamp-like apps) и большинство веб-проектов в эту сферу попадают. Также как есть Wordpress для блогов.
И если вы пытаетесь сделать какой-то проект на инструменте, который для этого проекта не предназначен, например, магазин на Wordpress или веб-приложение, архитектурно не похожее на Basecamp, на Rails, то вы будете страдать. Однако, он забывает, что когда Rails только набирал обороты, многие говорили «Зачем нужен фреймворк, для большинства проектов достаточно CMS», «Зачем нужны Ruby и Python, большинство крупных проектов написаны на PHP». Так что текущая ситуация — просто очередной виток истории.
Также он отмечает, что слишком сильная дефрагментация сообщества, как у PHP и JS, — это ещё хуже, чем монополия. С этим я тоже согласен.
Фрагментация же. :-)
верно, опечаточка вышла :-)
В-основном претензии автора касаются ActiveRecord, который элементарно оттуда удаляется и заменяется Mongoid :) В такой связке, рельсы прекрасны и актуальны.
Это не так. Основная претензия к ActiveSupport, которые делает большое количество безответственных вещей. ActiveRecord — это просто ограниченный паттерн ОРМ, в который напихано много откровенно дурных вещей, которые постоянно используются некорректно. ActiveRecord можно удалить, а ActiveSupport — нет.
НЛО прилетело и опубликовало эту надпись здесь
А почему нет? Для небольших и средних проектов Монго на порядок сокращает время разработки, да и работать с ним приятней намного, нежели с Active Record и всеми этими беспонтовыми миграциями
НЛО прилетело и опубликовало эту надпись здесь
Что-то мне подсказывает, что вы просто не осилили Mongo))) Я работал c php+sql до рельсов ;)
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Если Вы не знаете Ruby, то как можете оценить его «продуманность»?
НЛО прилетело и опубликовало эту надпись здесь
Что касается Django, выше уже отметили, что по большому счёту у него все те же проблемы, что и у Rails.
P.S. Если Вам нравится Python, то посмотрите ещё на Nim.
В Мире нет совершенства! А уж тем более совершенства нет в сфере программирования! За свой более чем 25-летний опыт программирования я научился относиться к этому философски. «Чюдисов на свети ни бываит!». Либо ты программист, и сам можешь реализовать какие-то механизмы, коих нет в используемой тобой библиотеке (фреймворке) или реализация этих механизмов тебя не устраивает, либо… можешь поставить перед собой зеркало и «пинять на него».
Важно принять для себя принцип разумной достаточности, а не тратить время на поиски святого грааля — той библиотеки, того инструмента, где все будет ну прям все-все-все идеально, все будет чудесным образом реализовано на все случаи жизни! Не трать свою жизнь на это! Есть базис, который тебя устраивает, вот и пользуйся им! Есть множество механизмов, реализованных за тебя — пользуйся ими! Все остальное можно реализовать самому. Я вообще не лезу глубоко в дебри Rails, использую базовые механизмы, и, знаете, меня все устраивает и прекрасно все работает! А Ruby — это вообще идеальный язык из тех, с которыми мне довелось познакомиться за время своей карьеры.
Сообщество Ruby и Ruby on Rails как раз и отличается тем, что без лишних разговоров, пафоса, споров, холиваров просто делают свою работу, занимаются своим любимым делом, и делают это грамотно и хорошо — видимо, менталитет такой. Ну а если кто-то решил уйти, вот так шумно хлопнув дверью, то не велика потеря.
НЛО прилетело и опубликовало эту надпись здесь
Ну, за 25 лет Вы явно успели попрограммировать не только на Ruby, не так ли? Т.е. причины со временем менять базис существуют в том числе и лично для Вас.
У любой технологии есть свой цикл развития:
image
Rails сейчас очевидно находится на этапе «Late Majority». И вполне объяснимо, что Пётр, как один из лидеров Ruby-сообщества, чувствует социальную ответственность и соответственно потребность описать свою точку зрения.
Естественно, не только Ruby, но «А Ruby — это вообще идеальный язык из тех, с которыми мне довелось познакомиться за время своей карьеры.». И говорить о каком-то закате инструментария разработчика совершенно неуместно, пока этот инструмент востребован и прекрасно выполняет свои функции. В последние времена наблюдается очень плохая тэнденция в программировании, которую можно охарактеризовать как и «пинять на зеркало», и «а вы, друзья, как ни садитесь, все ж...» — наблюдаются постоянные какие-то метания от одного инструмента к другому, от одной технологии к другой. Уважаемые, да везде лучше, где нас нет! Но вполне есть возможность сделать то место, где вы здесь и сейчас, вполне себе лучшим — своей светлой головой и золотыми руками. Ни одна технология, ни один инструментарий не сделает из вас профессионала чудесным образом!
Так почему же Вы ушли с предыдущих языков программирования, с предыдущих фреймворков, а не сделали их лучшими для себя?
Автор 9 лет программировал на Ruby — в каком месте тут «постоянные метания»?

И говорить о каком-то закате инструментария разработчика совершенно неуместно, пока этот инструмент востребован и прекрасно выполняет свои функции
Речь не о закате, а о насыщении. Все, кто хотел использовать Rails, — уже используют. Теперь добавляться будут только начинающие программисты. А профессионалы будут постепенно уходить в категории «Innovators» и «Early Adopters» других технологий. И это не тенденция последнего времени, так было всегда.
Если тот же Hanami наберёт популярность, то для Ruby никакого заката не будет, даже наоборот.
Начнем с того, что я не занимаюсь проектированием и разработкой языков программирования, библиотек, фреймворков, а использую их в качестве инструментов. Улучшать их? Какой смысл? Я уже сказал о принципе разумной достаточности. Если язык устраивает меня по большей части, то я использую его, а то, чего мне в нем не хватает — реализую самостоятельно. Я не пытаюсь менять Миры! Да, сейчас стало более возможным просить разработчиков языков и иных инструментов об их улучшении, вносить свои правки, но верить в то, что прислушаются именно к тебе — совершенно неоправданно.
Автор программировал на Ruby 9 лет. И что с того? Постоянно пытался изменить Ruby? Так он (Ruby) и так постоянно меняется при чем очень даже в лучшую сторону.
Я бы не стал говорить о каком-то насыщении, если речь идет о притоке все новых начинающих программистов. Какое же тут насыщение? Да и с чего бы профессионалам уходить куда-то, если их все устраивает. Профессионал на то и профессионал, что занимается делом, а не мечется в поисках истины в последней инстанции.
В данном конкретном случае более уместно все же говорить о той массе «профессионалов», которые постоянно мигрируют от одной технологии к другой, в каждой из которых им обязательно что-то не нравится.
По своему опыту скажу, что я менял технологии разработки только по мере того, как возникала необходимость переходить на какой-то новый качественный уровень, а предыдущие инструменты уже ну никак не подходили для реализации. Вот ну не стану я сейчас писать веб-приложение на assembler! Хотя раньше программирование на assembler было очень увлекательным занятием! А так, для общего развития, я достаточно много языков программирования изучил, дабы расширить собственный кругозор и границы мышления, но это совершенно не означает, что я их все собираюсь использовать в своей работе.
То есть, Вы предлагаете автору статьи и дальше программировать на Rubi? ))
Я ничего никому не предлагаю, ни за что не агитирую. Дело каждого, что ему делать.
А может, да, вместо Ruby и на Rubi попробовать писать :))))) Вдруг он лучше!
Все мои размышления о том, что смена одной технологии на другую вряд ли чем-то значительно облегчит автору жизнь. Устал он от Rails, ну пусть поищет себя в чем-то другом. Только вот проецировать свое видение на весь фреймворк все же не стоит.
> Я ничего никому не предлагаю, ни за что не агитирую
Ложь — это один из признаков заблуждения.

> вместо Ruby и на Rubi попробовать писать
Существенное замечание.

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

> Надо же, Вы первый в мире человек, который сказал, что смена технологий не облегчает жизнь.
В данном контексте акцент надо сделать на «значительно облегчит». Смена технологии, безусловно, изменит жизнь автора, но станет ли она от этого лучше и проще?
«Везде хорошо, где нас нет». Но мы даже понятия не имеем, как бы нам было там, если бы мы там были. Только квантовые вычисления помогут нам побывать сразу во всех состояниях одновременно, а затем выбрать наилучшее! )))))
Это вам надо определится с тем, зачем высказывать свои мысли вслух.
А то вы похоже привыкли за других решать, что им лучше.
Начнем с того, что я не занимаюсь проектированием и разработкой языков программирования, библиотек, фреймворков, а использую их в качестве инструментов. Улучшать их? Какой смысл?
Смысл есть, иначе бы развитие технологий совсем остановилось )))
А вот то, что Вы не занимаясь этим и даже не изучив код того же Rails, пытаетесь намекнуть на то, что люди, которые этим занимаются, не являются профессионалами — это как-то странно. Докатились… разработка фреймворков и библиотек — это по-вашему не дело, а метания в поисках истины. Вам самому не смешно?

Автор программировал на Ruby 9 лет. И что с того? Постоянно пытался изменить Ruby?
Автор вносил весьма значительный вклад в экосистему Ruby, если не 9 лет, то на протяжении 5 лет точно. Причём весьма активно.

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

Да и с чего бы профессионалам уходить куда-то, если их все устраивает.
С чего это Вы решили, что профессионалов всё устраивает?

По своему опыту скажу, что я менял технологии разработки только по мере того, как возникала необходимость переходить на какой-то новый качественный уровень, а предыдущие инструменты уже ну никак не подходили для реализации.
Ну вот, автор тоже перешёл на новый качественный уровень — к функциональному программированию.
> Смысл есть, иначе бы развитие технологий совсем остановилось )))
А они и останавливаются в каком-то смысле. Уповая на чудо-технологии все больше появляется недопрограммистов неспособных самостоятельно писать хорошие программы.

> пытаетесь намекнуть на то, что люди, которые этим занимаются, не являются профессионалами
Не путайте понятия! Те, кто пытаются что-то изменить и улучшить заслуживают уважения, являются двигателями прогресса! Те, же, кто уповают только на смену технологий в надежде на чудесные изменения… в общем, можно долго метаться.

> Но в целом на этой фазе развития идёт неизбежное понижение квалификации в среднем по сообществу.
Благо, что такие просто не осиливают освоение того же Ruby, чем и хорош высокий порог вхождения в подобные системы.

> С чего это Вы решили, что профессионалов всё устраивает?
Преимущественно устраивает. Если человек профессионал, но его что-то не устраивает в готовой системе, то он хотя бы в состоянии собственной реализации недостающих ему механизмов. Я в этом смысле. А в области программирования я вообще не встречал людей, которых бы вообще все устраивало.
А они и останавливаются в каком-то смысле.
В каком интересно? Тот же Rails выходит уже в 5-й мажорной версии. IT всё ещё неустоявшаяся отрасль, поэтому тут неизбежно постоянное развитие и изменения на уровне технологий. Стабильными пока остаются только теория и фундаментальные принципы. Назовите хотя бы парочку технологий, которые остановились в развитии, скажем, в 2014 году или раньше и до сих пор актуальны?

Уповая на чудо-технологии все больше появляется недопрограммистов неспособных самостоятельно писать хорошие программы.
Статья отчасти и посвящена тому, что появляется много таких Rails-программистов, которые даже на Ruby в отсутствии Rails не могут программировать.
Вообще раньше моветоном было указывать даже язык программирования перед понятием программист, а теперь везде и всюду НазваниеФреймворка-программист (AngularJS Developer, Magento Developer, Rails Developer). Являются ли люди, которые так себя позиционируют вообще программистами? На мой вгляд, нет. Они — пользователи фреймворков и даже гордятся этим. Для них переключиться и сделать новый проект на другом фреймворке — это целая смена Вселенной, хотя по меркам программирования — это пустяковая задача. Это не хорошо и не плохо, это просто факт. К тому же такие люди тоже нужны отрасли, т.к. программистов на все компании тупо не хватит.

Не путайте понятия! Те, кто пытаются что-то изменить и улучшить заслуживают уважения, являются двигателями прогресса! Те, же, кто уповают только на смену технологий в надежде на чудесные изменения…

Похоже Вы сами запутались… Автор статьи совсем не школьник, который не осилил Rails и ищет замену. В его профессионализме сомневаться не приходится, так же как в профессионализме Steve Klabnik, José Valim и многих других. Все они вполне осознанно переходят на другие технологии, потому что пришло время. Профессионалам не нужно надеяться на чудесные изменения, они сами меняют то, что их не устраивает.

P.S. И, кстати, с чего Вы взяли, что у Ruby высокий порог входа?

К вопросу о высоте порога.


Хоть у языка и очень красивый синтаксис (на мой личный вкус), но все равно некоторые штуки могут принести боль на начальных этапах.
Например, последний аргумент-хеш. Я когда очень давно познакомился с руби, на какое-то время завис над чем-то вроде:
object.method { key1: 1, key2: 2 }


Тема с блоками кода вообще достаточно сложная, мне кажется.
Например, у меня есть предположение, что далеко не все начинающие rails-программисты смогут провести разницу между лямбдой и обычным блоком.


Плюс к тому, знаю людей, для которых первое время вызывало некую боль отсутствие Си-подбного синтаксиса. Ну, собственно, такие проблемы будут почти у всех людей, которые слишком долго писали на Java и т.п.


Возможно, сами рельсы и являются фреймворком, очень простым для старта, но язык Ruby — нет.
Разумеется, это сугубо мое личное неавторитетное мнение.

После других языков самое непривычное в Ruby — это необязательность скобок (т.н. poetry mode)


Вообще вопросы синтаксиса — это очень субъективно… кто-то синтаксис Python терпеть не может из-за отсутствия end или фигурных скобок, кому-то def в Ruby не нравится. Можно от всего этого абстрагироваться для решения какой-то единичной задачи, но при выборе языков для постоянного использования всё-таки важно, чтобы синтаксис был по душе.

Требования к синтаксису всегда взаимосвязаны с характером решаемой задачи, ее масштабами и необходимостью дальнейшего поддержания программы и ее модернизации. Это даже не вопрос вкуса, но бизнес-процессов — т.е. объективное требование.

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

Согласен.
Мне кажется, или автор не уважает абстракции типа «черный ящик»?
Вроде, главное преимущество рельс в их сложности, которая позволяет, не задумываясь о том, что там внутри, решать задачи.
Да, понятное дело, что порой возникают проблемы, приходится копать глубже, а там уже черная магия. Но не бывает ничего идеального, нужно быть готовым к этому.
Например, думаю, все понимают, что monkey-patching — это плохо. Но ведь это одна из сильнейших фич Руби! Да, ей можно отстрелить себе ногу (или что там обычно отстреливают?), но вы не можете не согласиться с тем, что среди этих патчей есть много хороших решений. Лично мне, например, ну очень нравится простой метод #try(:method). Некоторые вещи из ActiveSupport и вовсе становятся практически неотъемлемой частью жизни разработчиков, это и обуславливает некоторые вопросы на SO, связанные с тем, что вне рельс какие-то методы undefined.

Еще я заметил, что после повального увлечения темой функционального программирования (мне, кстати, она тоже очень интересна), началась повальная критика существующих устоявшихся подходов.
Но ведь все те недостатки, которые перечисляют авторы подобных статей, существовали в нынешних подходах и раньше. Это как «разоблачение», что АНБ следит за людьми.

Нужно задаться вопросом, почему наши подходы имеют такой успех и разделить сферы влияния новых «веяний моды» от «старого доброго».
У вас сложилось неверное впечатление, но в данном случае виноват автор, не разъяснив свою позицию в статье, но он сделал это позже на реддите. Петр уважает высокоуровневые абстракции, но при условии, что они строятся на продуманном основании. В этом основная претензия к рельсам и особенно к 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, от которого наследуются почти все объекты в руби. Что может пойти не так?

Как я и сказал, за все нужно платить:)
Я им почти не пользуюсь (воспользовался пару раз, когда в чужих костылях нужно было что-то поправить. Собственно, как раз тот случай, который вы описали: непродуманная валидация данных), но сама идея мне нравится. В упомянутом мною случае (правки в костылях) оно сократило количество изменений и при этом в diff все было очень ясно и четко (хоть сам код и говно, прямо скажем).


Подобные удобства, ясное дело, порождают проблемы. Но ведь они все равно остаются удобствами.
Да, я понимаю, что к языкам программирования и технологиям основным требованием является ограждение программиста от возможных ошибок, но нельзя ведь бросаться в крайности.


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


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


Камнем преткновения является человеческий фактор. ФП может быть сколько угодно крутым, но оно не становится повсеместно используемым по вполне адекватным и понятным причинам. А подобные статьи — это скорее крик души.


IMHO, естественно

Не будьте обмануты идеей, что быстро разрабатывать приложения можно только на рельсах, это не так. Да, у рельс сейчас есть несомненные преимущества в документации, сообщества и всех других важных для опенсорсных проектов вещей. Но это не означает, что с технической стороны там происходит что-то такое, что нельзя сделать по-другому. Можно, даже нужно — вот об этом статья. Но для того, чтобы выстроить грамотную, хорошую архитектуру, нужно много сил, а соответственно много людей. И с этим есть большие проблемы, об этом тоже сказано. Я какое-то время следил за ромом, все ждал, когда он повзрослеет для промышленного применения, но в конце концов просто стал контрибьютором и нисколько не жалею.

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

Я изучаю Clojure в данный момент;)


Вы, очевидно, решили, что я считаю рельсы панацеей. Напротив, я бы с радостью хотел попробовать что-нибудь еще.
Несколько раз сталкивался с тем, что приходилось лезть в код самого фреймворка, чтобы понять, почему что-то работает неправильно. В такие моменты задаешься вопросом: это со мной что-то не так или с фреймворком. Что ж, без лишней скромности считаю, что фреймворк виноват :)


Однако, как Вы сами упомянули, рельсы имеют очень развитую инфраструктуру: множество гемов (и не только rails-специфичных!), множество накопленной информации и, как многие считают, достаточно низкий порог вхождения. И работы по рельсам очень много, что тоже не маловажно.


Мне нравится, что есть такой прекрасный фреймворк (который я иногда называю: "одна большая DSL") и что я с ним работаю (а не с 1С-битрикс, как в начале карьеры, упаси боже). Когда представится возможность, и я с ним распрощаюсь, потому что люблю изучать новые штуки (и мода на ФП меня тоже коснулась). Но распрощаюсь без какой-либо критики:)

Тут просто заголовок некорректно переведен, в оригинале было: «My time with Rails is up», что можно грубо перевести как «Хватит с меня рельсов». И тогда все встанет на свои места — автор статьи написал много гемов и его достало поддерживать совместимость с рельсами, а кроме рельсов ничего толком не появилось, вот весь сказ. Вот если вы начнете писать свои гемы (к чему Петр открыто призывал в твитере), тогда может распрощаетесь с рельсами с такой же статьей :)

Ну а Clojure — это правильно, не забудьте посмотреть выступления Рича Хикки.

Спасибо за продуктивный диалог, оставили мне пищу для ума:)
За сим считаю разговор оконченным.

можно грубо перевести как «Хватит с меня рельсов»
По-моему это более эмоциональный перевод, а по сути то же самое. Хотя все по-разному воспринимают… не исключаю, что кто-то мог «Пришло время попрощаться с Rails» воспринять как «Прекратите использовать Rails!», несмотря на то, что в заголовке никакого призыва нет и посыл другой.

Лично я так и воспринял. Может, просто невнимательно прочитал.
Думаю, имеет смысл выносить ссылки на оригиналы статей в начала постов, все-таки чем хорош Хабр, так это тем, что помимо самих переводов можно узнать о существовании статьи вообще.

НЛО прилетело и опубликовало эту надпись здесь

Мое мнение, как я уже упомянул, нельзя считать авторитетным:)
Под очевидными причинами я имел в виду:


  • приученность к императивной парадигме (если заставить школьника, который писал на паскале, писать на лиспе, то он будет писать на нем точно так же, как на паскале, просто со скобочками)
  • сложность обучения (частично вытекает из первого пункта).
  • отсутствие (пока что) развитой инфраструктуры. По Rails/Django/etc можно найти ответ практически на любой вопрос на SO, документация в рельсах достаточно неплоха (т.к. проект опенсорсный и при этом популярный, то понятное дело, что она постоянно улучшается), количество плагинов/гемов/модулей просто зашкаливает. Может этим похвастаться Haskell/Elixir? Сомневаюсь. Говоря о плагинах, можно упомянуть JVM, но:
    • по тому, что я успел увидеть в Clojure, у меня сложилось мнение, что использование Java-библиотек выглядит не очень естественно.
    • а Scala, видимо превращается в Scala-Java, что тоже по сути не ФП. Но это лишь предположение

На Хабре где-то была статья, где автор рассказал, что их компания отказалась от Scala в пользу Go. Всю статью не помню, но запомнил следующие тезисы:


  • Код был слишком разношерстный (кто-то писал функционально, кто-то писал в стиле Scala-Java)
  • Некоторые конструкции невозможно было гуглить из-за "странных" символов (это не проблема ФП, но все равно интересный факт. Я не в курсе, но, возможно, у Haskell могут быть похожие проблемы)
  • Сложно было нанимать новых программистов

Мне кажется, что перечисленные мною причины действительно имеют место быть я являются вполне очевидными. Наверняка, есть множество подводных камней, но, в виду отсутствия опыта в ФП, говорить о них не решусь. Но я вангую, что со временем появится куча статей "разоблачающих" ФП. Кто знает, может быть, в будущем будет популярно логическое программирование?

приученность к императивной парадигме (если заставить школьника, который писал на паскале, писать на лиспе, то он будет писать на нем точно так же, как на паскале, просто со скобочками)
Вот в этом основная проблема «моды на ФП», по сути то это просто ещё 1 инструмент и надо понимать как им пользоваться. Вот неплохая статья на эту тему: http://degoes.net/articles/fp-is-not-the-answer

По Rails/Django/etc можно найти ответ практически на любой вопрос на SO, документация в рельсах достаточно неплоха (т.к. проект опенсорсный и при этом популярный, то понятное дело, что она постоянно улучшается), количество плагинов/гемов/модулей просто зашкаливает. Может этим похвастаться Haskell/Elixir?
Те, кто помнят экосистему Rails и Django времён 2008-2010 годов, могут оценить, что в том же Elixir ситуация с экосистемой уже гораздо лучше. Конечно по кол-ву пакетов/гемов обогнать Ruby не просто, но нет каких-то прям стоп-факторов от использования. Про экосистему Haskell я не в теме, честно говоря.
Те, кто помнят экосистему Rails и Django времён 2008-2010 годов, могут оценить, что в том же Elixir ситуация с экосистемой уже гораздо лучше.

Возможно, но суть в том, что сейчас уже не 2010 год и многое уже пройдено и установилось. Это не стоп фактор, но в данный момент это одна из причин, почему его не используют повсеместно. Все хотелось использовать слово "сыро", но не поворачивается язык, а словарного запаса для более удачного выражения, увы, не хватает.

Более подходящее выражение: выход из зоны комфорта. Если для Rails у Вас уже есть набор привычных гемов. То тут придётся этот набор заново подбирать и возможно что-то самому писать. Я просто застал время, когда и используя Rails надо было самому писать гемы. Поэтому не вижу в этом ничего страшного :-)
вы так говорите, будто сейчас не прийдется руками править каждый первый скачанный из интернета гем.
Зачем править, когда есть monkey-patching :-D
А если серьёзно, то всё-таки ситуация получше, каждый первый точно править не надо. В основном в допилке нуждаются не особо популярные гемы типа интеграций со всякими сервисами. Случаи, когда нужно влезть в исходники того же Arel или kaminari, не так уж часто встречаются.
НЛО прилетело и опубликовало эту надпись здесь

Если честно, без особых объективных причин. Просто захотелось.


За Clojure стоит JVM, за Elixir, если не ошибаюсь, Erlang. Я встречал мнение, что чтобы использовать Erlang, нужно четко знать, в чем его преимущества и нужны ли они вам.


К тому же немаловажным фактором является то, что мне нравится Лисп с его простотой и однородной структурой. Можно сказать, что Clojure — это современный диалект Лиспа. А так работу можно найти и по тому, и по тому (видел таких людей). Тем более, что со временем количество вакансий будет только увеличиваться, имхо, причем в случае Clojure это будет происходить быстрее, поскольку некоторые компании, которые работают с Java начинают все чаще смотреть в сторону Scala, а там и Clojure недалеко.

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

А можете уточнить, что за причины?

Как на меня основная причина в том, что, по сути, почти все программирование ПО — про сайд-эффекты. Запись в базу, вывод на экран, етс. Потому чистоты не добиться и приходится прибегать к костылям. А в итоге получается иммутабельность ради иммутабельности, абсолютно нечитаемые конструкции и тонны копипасты. И, конечно, никакой декларативности на практике. Потому что обычно программа по своей сути является последовательностью нескольких изменений состояния. Обычно на ФП пишут в императивном стиле и в нечитабельной форме. Пример:
https://habrahabr.ru/post/279715/#comment_8812695
НЛО прилетело и опубликовало эту надпись здесь
Если коротко, то состояние передаётся от функции к функции. Каждая функция его меняет (или не меняет, если надо пропустить шаг обработки) и передаёт следующей.
Ну теорию то мы знаем, а вот на практике почему-то так не получается ни у кого ;) Ну вот покажите какой-то крупный опен-сорс проект. Бложик там, или движок игровой, или форум, который написан таким подходом. Потому что пока примеры маленькие — рассуждать очень легко. А когда появляется куча зависимостей и когда сайд-эффект заложен в бизнес-требования (а это всегда так в практической разработке) — появляются костыли, куча копипасты и нечитаемый код.
НЛО прилетело и опубликовало эту надпись здесь
Простите, не могу понять, как RabbitMQ клиент на ерланге запустить. А то тут: https://www.rabbitmq.com/erlang-client.html только либы для общения с сервером.
pandoc — просто математическая либа. Функции получают что-то на вход и возвращают. это не программа.
НЛО прилетело и опубликовало эту надпись здесь
ну да. а что именно ещё нужно?

Емс. Я могу его вот взять и запустить на клиентской машине? Залогиниться, написать сообщение. Принять. Увидеть его в трее.

не, вот этот http://pandoc.org/

Да, я понял. Математическая — неправильно выразился. Суть такой либы в том, чтоб в функцию принять данные и вернуть новые. Но она еще не программа, которую можно поставить на компьютер и пользоваться. Такие либы вообще все-равно на чем писать — особой бизнес сложности они не имеют.
Но она еще не программа, которую можно поставить на компьютер и пользоваться.

Почему? Pandoc — программа для преобразования форматов текстовых файлов. Можно поставить и пользоваться. Для той же windows есть msi-инсталлер.


Я могу его вот взять и запустить на клиентской машине? Залогиниться, написать сообщение. Принять. Увидеть его в трее.

Из коробки — нет. RabbitMQ это не мессенджер и не чат. Это система передачи сообщений между компонентами программного комплекса. У этой системы есть серверная часть (написанная на Erlang) и клиентские библиотеки, которые можно встроить в любую программу.

НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
ну извините

Обьясню. Примеры очень узкие. При чем все — для использования программистами, не конечными юзерами. Феникс — фреймворк, Пандок — либа (хоть и с консольным интерфейсом), Реббит — либа. Интересно увидеть многогранный продукт. Я не сомневаюсь, что для некоторых (довольно узких) целей ФП очень удобен. Когда в бизнес-требованиях есть вход и выход. Но он далек от серебрянной пули и уж точно не замена ООП, как любят покричать. Потому он и «не становится повсеместно используемым по вполне адекватным и понятным причинам». Он банально не рассчитан на большинство задач программирования, а только очень узкий спектр, а на остальные задачи натягивается с треском и костылями. В то время, как другие подходы более приближены к реальности разработки.
НЛО прилетело и опубликовало эту надпись здесь
У меня есть предположение, что:
1. Использование ФП ограничено довольно узким кругом специфических задач
2. Большинство, в том числе апологеты ФП не умеют его готовить (как, кстати, множество апологетов ООП не умеет его готовить)

Такие выводы у меня из следующих предпосылок:
1. Известные мне программы на ФП довольно узки
2. Большинство примеров ФП в статьях, что лично я видел — обычная императивщина просто записана навыворот.

— Я понимаю, что теоретически ФП круто паралелится (наверное, клево было б шейдеры писать), но как оно будет параллелиться когда у функций будут сайд-эффекты?
— Более того, когда появляется сложный стейт и нетривиальные зависимости, я часто вижу, что в много функций приходится передавать не какие-либо чистые данные, а что-то вроде: `mySmallFn(wholeAppState)`, что, по сути просто использование глобальной переменной, хоть и с притворством, что она локальная — связи очень сложно проследить, особенно ввиду утиной типизации. (а кто вообще может прочитать `id`, который я верну из функции?)
— функция, которая возвращает функцию, которая возвращает функцию, которая зависимо от аргумента возвращает результат. Как такое прокрыть юнит-тестами? В том же ооп все довольно просто. Вызвал метод — должен вернуться результат или измениться состояние. Методы очень атомарны.
— другая проблема — дебагинг. Кто кого вызывает и почему? Путь кода становится абсолютно неконтролируемым и отладка сводится к обычным `print(currentData)`.

Так вот — у меня вопрос. Может, я ошибаюсь? Но если так и ФП действительно очень удобен, то я хочу научиться делать такие проекты. Покажите мне примеры, статьи, научите. Расскажите, как обходите такие принципиальные вопросы? Давайте я приведу контр-примеры. А что с действительно сложными и комплексными проектами? Не обработка текстовых данных, а игры, графические редакторы?

Просто с таким агрессивным пиаром и такой слабой базой через пару лет от ФП все будут плеваться (непонятный, запутанный, невозможно поддерживать, тормозной и так далее, обязывает к копи-пасте) и вполне возможно, что незаслуженно и есть способы на нем программировать легко и кльово. Но люди, которые умеют делать — сидят тихонько и всем говорят, что их ААА-игры написаны на попсовом С++, чтоб не спалиться.
Вы правда думаете, что кто-то всерьез примется вас учить? Вы серьезно? Могу вас заверить, ни у какого специалиста после прочтения таких призывов такого желания не возникнет. Если вам это нужно, то дерзайте, если нет, то к чему это все?
Та меня учить не надо. Я этой темой не первый год интересуюсь. Прекрасно знаю когда хороша иммутабельность и когда мутабельность и что для каждой из них есть свое место. И что иногда функциональный подход реально удобнее для обработки данных.

Я просто искренне надеюсь, что как можно больше людей прочитав мои комметарии решат не лезть в то болото, которое сейчас пропагандируется как ФП и не будеть видеть в нем серебрянную пулю и, конечно, что перестануть писать бред из серии «ООП — отстой, все клевые пацаны давно фигачат в ФП», при этом не иметь в своем коде ни декларативности, ни чистоты и пародию на иммутабельность с её минусами, но без её плюсов.
К сожалению, комментариями в интернетах вы этого не добьетесь, ложитесь спать :)
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Я совершенно уверен, что лет 5 назад думал буквально эту же мысль, и не исключаю, что даже и где-то писал.

А сейчас считаете, что таки серебрянная пуля и замена ООП?

Допустим, как например?

Я уже описывал в комментариях к топику неоднократно. Вы принципиально не читаете то, что вам не нравится?
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Ну почему же прямо для очень узких. К примеру сервер любой можно написать. Там как раз есть вход (запрос) и выход (ответ). А это, хоть и частный случай, но в то же время очень частый. Клиент-серверная архитектура распространена повсеместно. Графический интерфейс, как мне кажется, тоже можно писать в функциональном стиле. Для GUI вообще удобней всего использовать реактивное программирование, а оно очень хорошо реализуется с помощью ФП. Сюда же можно отнести любой рендеринг. В том числе и 3D рендеринг в играх. Физика в играх тоже хорошо в эту парадигму вписывается.
Вот уже получается, что ФП может найти свое применение, и на сервере и на клиенте, и в играх. И это не какие-то редкие случаи, не какой-то специфичный софт, а самые общие вещи: сервера, графический интерфейс, рендеринг, расчет физики.
Но будущее, на мой взгляд, за гибридным подходом. Сплав ООП и ФП, на мой взгляд, наиболее удобен с практической точки зрения.
НЛО прилетело и опубликовало эту надпись здесь
Ответ на поверхности — объекты без состояния. Создаете объект один раз, у него есть только один метод, который принимает аргументы и возвращает результат. Вот, почитайте: https://habrahabr.ru/company/latera/blog/301338/
НЛО прилетело и опубликовало эту надпись здесь
Про объекты без полей, а следовательно и без состояния, я кстати уже упоминал где-то в этой теме. Да и метод, при этом, не обязательно должен быть один. Еще, как вариант, может быть неизменяемый объект. В этом случае, для методов объекта, его поля будут фактически константами.

А чего его представлять то, на самом деле полно мультипарадигмальных языков.
Особо отличился Oz — он одновременно поддерживает 7 парадигм программирования :-)
И Вы правы, разные парадигмы не должны мешаться друг с другом, но их можно использовать в разных частях программы.

НЛО прилетело и опубликовало эту надпись здесь
Просто, как язык, позволяющий писать в обоих стилях. Да хотя бы тот же JS. Аргументы функции — объекты. Функция — тоже объект. В итоге, как хочешь, так и пиши. Ну или взять хотя бы MVC с активной моделью. View можно написать в функциональном стиле, а Model — в объектном. Controller, в зависимости от задачи, либо в функциональном, либо в объектном. Противоречия, они в основном идеологические. А чрезмерная идеологизированность на пользу не идет. Нужно искать компромиссы. К тому же, многое зависит от того, как вещи рассматривать. Можно ведь считать поля объекта неявными параметрами его методов. А сам объект, на протяжении его жизненного цикла, от конструктора до деструктора, можно воспринимать как функцию. В то же время переменные объявленные во внешней функции, для замыкания будут теми же полями. В некотором смысле внешняя функция, для замыкания является объектом, а само замыкание аналогично методу объекта. А раз, и объект можно считать функцией, и функцию можно считать объектом, то значит никакого противоречия между ООП и ФП нету. Это просто две разные абстракции, вокруг одних и тех же сущностей.
НЛО прилетело и опубликовало эту надпись здесь

@Cryvage пишет о том, что можно ОО-язык использовать в функциональном стиле. Т.е. данные о состоянии объекта передавать только конструктору и объявлять на них только геттеры, чтобы даже у методов объекта не было возможности повлиять на его состояние. Тогда получится своеобразное замыкание как в ФП.
Но чтобы так писать на ОО-языке всё равно надо уже расширить своё мышление функциональной парадигмой :-)

НЛО прилетело и опубликовало эту надпись здесь

Нет, это будет называться ФП на ОО-языке. Нужно, если у Вас задача идеально подходящая для ФП, а язык проекта позволяет только ООП.

Вы во многом правы, но не считаете ли Вы, что функциональные примеси в ООП демонстрируют слабость ОО-парадигмы? По сути даже создатели языков программирования, признают чистое ООП недостаточно удобным. Остался ли хоть один современный ЯП, в котором есть только чистое ООП и ничего больше? Так чтоб никаких лямбд (только Strategy), никаких foreach (только Iterator) и т.д.

Функциональные примеси, они не в ООП. Они в языках программирования. Это говорит лишь о том, что ОО-парадигма не является ответом на все вопросы. Тут вступает в силу старая добрая истина: «Используйте инструмент, подходящий под задачу.»
Языки программирования добавляют функциональные примеси для того, чтобы сделать язык более универсальным и удобным. Это вполне логично с их стороны. По этой же причине во многих языках высокого уровня можно делать ассемблерные вставки. По этой же причине, в C# можно добавить unsafe код.
Если топор не подходит для того, чтобы копать землю, и человек берет с собой, и топор, и лопату, чтобы сначала срубить дерево, а потом выкопать пень, разве это говорит о слабости топора?
НЛО прилетело и опубликовало эту надпись здесь
Но в случае смеси ООП и ФП, иммутабельными придется делать не все объекты в программе, а только те, которые участвуют во взаимодействии между объектной и функциональной частью. Как-то так я себе это представляю.
НЛО прилетело и опубликовало эту надпись здесь
Функциональные примеси, они не в ООП. Они в языках программирования.

Верно, я имел в виду ООП-языки.


Это говорит лишь о том, что ОО-парадигма не является ответом на все вопросы

+1, у любой парадигмы есть свои границы применимости.
И даже там где одна парадигма применима, другая может иметь более удобные средства. Так что по-хорошему программист должен быть знаком с многими парадигмами, чтобы делать осознанный выбор под конкретную задачу, а не просто по привычке.

Но он далек от серебрянной пули и уж точно не замена ООП

Что Вы как ребёнок всё в серебряные пули верите…
ФП — это парадигма программирования и она предоставляет свои инструменты для решения задач. ООП — другая парадигма, в идеале их области применения могли бы не пересекаться, но на практике одну и ту же задачу можно решать в рамках и той и другой парадигмы.
Мы тут обсуждаем конкретно веб-разработку, а не всё подряд. Если вспомнить как ООП попало в веб-разработку, то очевидно, что это было мотивированно больше всего модой на ООП, т.к. весь практический смысл этой парадигмы теряется для программ, которые отрабатывают за долю секунды.

НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
сложный софт в ОО-парадигме пишется с существенно большими трудозатратами, чем в функциональной

Как раз ФП вполне ничего для легкого софта, прототипчиков всяких, где мало связей. Крупную игрушку или графический редактор на ФП написать? Увольте.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Само по себе ООП — не решение. Важно то, как оно реализовано в конкретном языке.

Насколько я помню, есть всего 3 реализации ООП — на основе классов, на основе прототипов и на основе акторов.
C# ранних версий — это шикарный пример реализации ООП на основе классов, а вот начиная с 3-й версии туда начали добавлять ФП и прочие не ООП-концепции.
Из различий реализаций ООП на основе классов, Вы упомянули только множественное наследование, которое по холиварности не уступает goto, поэтому в большинстве реализаций отсутствует )))


сколько абстракций он держит в той же Джанге, и, наверное, в этих ваших рельсах…

А задумайтесь сколько из этих абстракций реально нужны, чтобы обработать запрос? именно из-за усложнения простых вещей "за долю секунды происходит столько всего, что в голове не удержишь". Вы догадываетесь сколько объектов создаётся для обработки тривиального GET /page/permalink? Хотя по сути Вам нужен 1 объект класса Page и то он сам Вам нафиг не нужен, Вам нужны данные из БД, но как же, без ORM никуда..

НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь

Я возможно Вас слегка расстрою, но утиная типизация — это часть парадигмы обобщённого программирования, к ОО-парадигме она никаким боком не относится :-)
Метапрограммирование — это тоже не ООП, строго говоря. Вообще рекомендую ознакомиться со списком парадигм программирования, там много интересной информации.


Что касается ООП, попробуйте хотя бы для себя, абстрагируясь от привычек, ответить на вопрос: при каких условиях неудобно применять ООП?

НЛО прилетело и опубликовало эту надпись здесь

Я понимаю, хотя списочек там реально заслуживающий внимания, я несколько новых для себя нашёл.


Дело не в обобщении алгоритмов, а в том, как определяется тип объекта.

Дело как раз в том, что можно написать обобщенный метод/функцию, без явного указания типа/интерфейса параметров в сигнатуре метода. В ООП для подобных методов придётся использовать явные интерфейсы.

НЛО прилетело и опубликовало эту надпись здесь
Как тогда Lisp стал функциональным — не вполне ясно.

Lisp появился ещё до того как все эти парадигмы были сформулированы. Формально, он в первую очередь гомоиконный. Но всё ФП началось именно с него.


В общем, не всё так однозначно, различные парадигмы могут иметь общие техники и подходы.

В принципе, да, остаётся их разделять разве что по обязательности к-л части.

бы не рискнул запилить что-то серьезное, скажем, на Java или том же C#, хоть они и продвинулись значительно

эмс. А на чем бы рискнули?
НЛО прилетело и опубликовало эту надпись здесь
Гляньте phoenix/elixir — язык функциональный, неизменяемые переменные, pattern matching и т д.
Но вот по ощущениям пишется как на рельсах ;)
И все равно что там ооп или фп. Конечно, код отличается, для разных языков совсем по разному структурирование программы происходит, если следовать идеологии языка то все замечательно (шутка про программиста на фортране пишущего на фортране на любом языке). Но вот подход «взял и пользуешься» точно такой же как в рельсах.
Собственно кроме phoenix и rails я ничего даже близко подобного не видел, не зависимо от языка
НЛО прилетело и опубликовало эту надпись здесь
Что Вы как ребёнок всё в серебряные пули верите…

Так я как раз и не верю. Я прекрасно комбинирую, ФП — для мелкой обработки данных, ООП — для глобальной архитектуры. Это адепты ФП пытаются убить ООП и кричат, что ФП — серебрянная пуля, что приводит к фейспалму.

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

При чем ООП к времени жизни программы? О, о
При чем ООП к времени жизни программы? О, о

При том, что ООП хорош для задач, где нужно управлять глобальным состоянием программы в оперативной памяти. Взять тот же GUI, как его инстанцировали при открытии программы, так он и продолжает существовать пока программу не закроешь, и у каждого контрола свои атрибуты и обработчики событий. Удобно для ООП? Конечно!
Проблема в том, что ООП превратили в культ карго и создают объекты везде где ни попадя, просто потому что так принято.

НЛО прилетело и опубликовало эту надпись здесь
но если забыть на секундочку ФП, то без ООП становится совсем сложно

Это от масштаба проекта зависит на самом деле. 80% сайтов вообще просты до безобразия… просто мы тут их не обсуждаем :-)


ООП успешно дает доступ к долгоживущему глобальному состоянию, такому, как база данных, такими средствами, как ORM

По факту, ORM — это ещё одно следствие моды на ООП. Данные в реляционной БД — это данные, а не объекты. Как следствие OR impedance mismatch и разнообразные статьи типа "ORM is an anti-pattern".


За эти миллисекунды веб-приложение успевает пропустить запрос по конвейеру прослоек различных предварительных обработчиков...

И вот Вы перечислили больше десятка действий и ни одного объекта. Когда задача описывается через действия — это как раз признак того, что она больше подходит для ФП, чем для ООП. В случае обработки веб-запросов объекты создаются только чтобы вызвать какие-то их методы, а потом напрячь GC. Советую Вам книгу Programming Phoenix, чтобы посмотреть как эта задача решается без объектов.


ООП здесь помогает упаковать все в удобный объект.

точнее вместо того, чтобы функцию поставить в очередь, требует сначала обернуть её в класс


А если закрыться в своей коморке и ни с кем не общаться, то да, можно не использовать никаких абстракций и каждый проект писать с нуля.

Абстракции и повторное использование — это вещи, слабо связанные с ЯП и с парадигмами программирования. И возможны они везде, было бы желание. А если нет желания, то и в ООП их не будет.

НЛО прилетело и опубликовало эту надпись здесь
ООП не решает проблем, а просто является модой.

Я этого и не говорил. Я говорил про то, что веб-разработка пошла сначала по пути ООП, а не сразу по ФП, и это во многом было именно веяние моды. Сейчас мода поутихла и появляются более уместные решения. Ну не является обработка потока изолированных входящих запросов задачей, подходящей для ООП, т.к. у них тупо нет никакого shared state в памяти.

НЛО прилетело и опубликовало эту надпись здесь

Ну, как ни странно, ООП начала активно пробираться в веб как раз через PHP 5, ещё 12 лет назад. А потом уже Ruby и Python подтянулись )))
ООП действительно появилось гораздо раньше и на момент, когда веб-сайты стали превращаться в веб-приложения и им стал нужен нормальный бэкенд в ходу были C++, Delphi, Java, C#. Все ООЯП.
И по сути был двусторонний процесс, с одной стороны разработчики популярных языков для обычных приложений заметили веб. А с другой стороны веб стал усложняться и требовать подходов для борьбы с этой сложностью. Поэтому недолго думая решили, что и для web ООП пойдёт не хуже, чем для desktop. Ну и экономический фактор тоже сыграл роль, дело даже не в пороге входа, а в том, что ОО-языки уже много кто знал по работе с desktop-приложениями.

НЛО прилетело и опубликовало эту надпись здесь
Я так понимаю, потому что в вебе не крутятся большие деньги, что-бы создавать прорыв в языках. Но теперь и до него очередь дошла.
НЛО прилетело и опубликовало эту надпись здесь

Да, реализация там была действительно неважная. Хотя говорят, что сейчас уже лучше.
Вы больше говорите о программистах, которые сразу начали с PHP, мой опыт не сильно репрезентативен, но я таких почти не встречал. Разве что видел их по вопросам на форумах.
Когда ООП добавили в PHP, это была уже знакомая для многих парадигма. Поэтому наверно и добавили.
Даже фреймворки типа CodeIgniter стали появляться. Хотя он тоже отличался весьма оригинальным видением ООП.


По поводу вопросов, специалистов по ООП в начале 00-х было на порядки больше, чем специалистов по ФП. Опять же благодаря моде, т.к. именно ООП преподавали во всех ВУЗах, а ФП касались на редких факультетах. Да и до сих пор ФП в виду непопулярности остаётся тем конкурентным преимуществом, про которое писал Пол Грэм. Инертность мышления ещё долго будет останавливать людей от изучения чего-то кроме ООП.

НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Ветка очень интересная, спасибо!
Только вот теперь непонятно, зачем такое громкое название было давать — ФП, когда большинство улучшений (по сравнению с ООП) можно было бы реализовать в рамках несколько видоизмененного ООП, применяя например объекты с явным указанием вроде «с сайд-эффектами» / «без сайд-эффектов»?
Есть ли какие-то вещи, которые принципально не вписываются в ООП?
НЛО прилетело и опубликовало эту надпись здесь
Так в том-то и дело, что в реальной жизни необходимы и мутабельность и иммутабельность, поэтому вопрос не в примирении сторонников разных подходов, а в том — зачем нужна была революция, если и эволюция вполне себе бы справилась (иммутабельный объект — это просто как вариант «с ходу»)?

В чем ФП-парадигма не могла быть интегрирована в существующие ОО-ЯП? Да, они бы не были уже чисто оопешными, ну и что, какая разница, если такие «фичи» бы появились?
Только вот теперь непонятно, зачем такое громкое название было давать — ФП, когда большинство улучшений (по сравнению с ООП) можно было бы реализовать в рамках несколько видоизмененного ООП

1) ФП появилось лет на 10-15 раньше, чем ООП
2) то, что на ОО-ЯП можно писать в функциональном стиле не меняет ОО-парадигму, просто код перестаёт ей следовать
3) Интеграция обеих парадигм в рамках одного языка и так уже идёт, причём давно уже

Спасибо за ответ! Просто слишком много шума вокруг «чистого» ФП, что несколько напрягает ))
НЛО прилетело и опубликовало эту надпись здесь
Да, статья знакомая, спасибо, еще раз с удовольствием прочитал!

Интересно, что в Вики Ruby не сильно отстает по внедрению функциональности от например Common Lisp / Erlang / F# / Scala. А вот по Вашим словам разница существенная.

И еще вопрос в том, насколько чистые Ф-языки приспособлены для выполнения разных задач (как это уже здесь обсуждалось), не будет ли универсальность принесена в ущерб мощи.

Почему я и вопрос задал — не проще ли «допилить» уже существующие ОО-языки, сфера применения которых известна и отработана, привнеся в них Ф-парадигмы.

Ну это наверное холивар уже с моей стороны ))
НЛО прилетело и опубликовало эту надпись здесь
О-о, за ссылку спасибо! Та да, лень — мать пороков… А еще хочется не прогадать с серебряной пулей. А от Вас ждем статью Elixir vs Python ;)
НЛО прилетело и опубликовало эту надпись здесь
Двумя руками за такую статью! (и спасибо за ссылки)
НЛО прилетело и опубликовало эту надпись здесь
Так посмотрите тот же Phoenix, у него довольно понятные исходники )
НЛО прилетело и опубликовало эту надпись здесь

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

Как я успел осознать, неизменяемое состояние в ФП — это миф. Без изменения состояния невозможно что-либо "напрограммировать" (я не математик, поэтому не возьмусь доказывать это свое утверждение, а просто с умным видом поставлю восклицательный знак) !


Просто состояние сохраняется не так, как мы привыкли (в переменных), а с помощью использования лямба функций, замыканий и т.п.


Как минимум, думаю, Вы не будете спорить, если я скажу, что даже в императивной программе, чем меньше мутабельности, тем проще и, возможно, лучше.

А где вы вообще вычитали про неизменяемое состояние в ФП? В ФП есть неизменяемость данных, но причём тут состояние?
Любая функция, если она что-то делает изменяет состояние, это вроде очевидный факт касаемо ФП.
Даже чисто математические функции изменяют состояние:
y(x) = x*x
y(5) => 25 // было состояние: 5, стало: 25.
Разница в том, что в ФП это состояние передаётся в качестве аргумента функции, а в ООП состояние — это отдельная «сущность», на которую 2 метода могут влиять параллельно.

Возможно, я что-то не то подразумеваю под состоянием.


Давайте разберемся. Я предполагаю, что в данном контексте состоянием является некоторый переменный(upd.) набор данных, принадлеащий системе.
Например, при добавлении значения в стек мы меняем его состояние, а именно:


  • количество элементов в нем
  • "верхний" элемент*
  • и т.д.
  • и т.п.

Функция-квадрат сама по себе никакого состояния не меняет. Функция — просто правило, по которому элементы одного множества сопоставляются другому. О каком состоянии может быть речь?


Теперь касательно ФП.
Когда мы говорим о том, что данные неизменяемые, мы, по моей логике, немного лукавим, поскольку в нашей системе есть только одна вещь — вычисляемое значение. А вот сам процесс его вычисления — уже имеет некоторое состояние в разном виде. Например, в изменяющихся аргументах при хвостовой рекурсии (как-то странно я ее назвал, но Вы меня поняли) либо в изменении функции (правила сопоставления одного элемента другому) с помощью замыканий и пр.
Поэтому данные все же меняются, просто не те, к которым мы привыкли. Лично я привык к тому, что состояние системы зависит от ее переменных, которые являются хранилищем данных, к которому мы имеем прямой доступ (привет, оператор присваивания). В случае ФП мы не имеем такого прямого доступа, но достигаем нужного результата, воздействуя на него косвенно способами, которые я уже частично перечислил.


Примерно так выглядит мое понимание такого явления как функциональное программирование. Как же выглядит Ваше? Буду признателен, если поделитесь или укажите, где я не прав.

Я предполагаю, что в данном контексте состоянием является некоторый переменный(upd.) набор данных, принадлеащий системе.
В таком определении у Вас состояние — это вся база данных + redis + ещё что-то. Слишком глобально и внешне к самому приложению.
Давайте возьмём для примера веб-приложение, оно обрабатывает входящие HTTP-запросы. Задача приложения обработать запрос и выдать HTTP-ответ. Для простоты рассмотрим один поток выполнения. Получив запрос, приложение создаёт некоторую структуру данных, описывающую запрос. Теперь эта структура данных и есть состояние. Дальше оно передаётся от функции к функции, сначала проходит через middleware-функции, потом в роутинг-функцию, потом в action-функцию контролера и т.д. пока эта структура-состояние не станет ответом.
В таком определении у Вас состояние — это вся база данных + redis + ещё что-то. Слишком глобально и внешне к самому приложению.

Ну это уже в крайность. Все-таки, система взаимодействует с БД/редисом/чем-то еще, а не включает их в себя. (upd. да, видимо, я еще и неправильно пользуюсь термином "система")


Воспользуюсь Вашим примером с веб-приложением.
По моей логике, входные данные не являются состоянием. Это как параметр X квадратичной функции. Он, конечно, влияет на результат, но состоянием обладать будет в данном случае будет именно вычисление этого результата.


Грубо говоря, вычисление выглядит так: f(g(h(k(x)))), где x — параметры запроса. Собственно, нас слабо волнует, что именно за запрос, нас волнует то, как в зависимости от этого запроса будет вычисляться результат. Например, k(x) может обращаться к БД и извлекать оттуда данные (params[:id]), h — как-то обрадабывать эти данные, например, преобразовать их в список чисел, следующая функция может возвести их в квадрат.


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


Как Вам?

Ну, крайность, не крайность. А в принципе это глобальное состояние системы, и именно из него она восстановится после жёсткого перезапуска. Просто мы тут о другом состоянии говорим, о том которое находится в ОЗУ и доступно на протяжении процесса обработки запроса.

Например, k(x) может обращаться к БД и извлекать оттуда данные (params[:id]), h — как-то обрадабывать эти данные, например, преобразовать их в список чисел, следующая функция может возвести их в квадрат.
Ну вот, Вы сами описали как функции, одна за другой меняют состояние, которое передаётся по цепочке.

Состояние на уровне отдельной функции тоже можно рассматривать, так сказать, мгновенное состояние… но набор локальных «переменных» нас слабо волнует, интерес представляет только то состояние, которое передаётся по цепочке функций. По поводу всего остального мы просто ожидаем, что половину из этого компилятор нафиг уберёт, а остальное подчистит сборщик мусора )
По сути состояние это неявный параметр функции. К примеру есть функция 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. Но теперь мы знаем что и откуда берется, т.к. явно это указываем. То есть речь тут скорее не об отсутствии состояния, а о явной его передаче от вызова к вызову. В то же время, мы всегда можем разорвать эту зависимость, вызвав функцию с другими параметрами. Разумеется, отсутствие состояния можно реализовать и в ООП. И в какой-то степени, к этому надо стремиться. Чем меньше состояний у объектов, тем универсальнее и гибче будет объект. Хотя, если дойти в этом до крайности, то объект превратиться просто в набор методов, а полей в нем не останется. Во всем нужна мера, как и всегда.
Из примеров выше видно, что состояние несет в себе те же риски, что и глобальные переменные. Потому что это, в общем-то, и есть глобальные переменные. Поля глобальны для методов объекта. А если поле еще и статическое, то оно глобально для всех объектов данного класса. Если оно при этом будет публичным, то вообще ничем от глобальной переменной отличаться не будет. Следовательно и методы борьбы с состоянием будут такие же, как с глобальными переменными: минимизировать область видимости на сколько это возможно, т.е. сделать глобальные данные локальными. Принимаемый функцией параметр — это как раз и есть локальные данные. Естественно, часть данных из реального мира будет где-то храниться глобально по отношению к программе. Но это не проблема. Просто функции будут принимать эти данные в качестве явных параметров.

Наше с Вами видение ситуации, в общем-то, одинаково. Единственное, мне абсолютно не понравилась (или непонятна?) часть про глобальные переменные. Вы, по-моему, пытаетесь глобальной любую переменную, пришедшую извне.


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


Например, в функции f(x) = x*x x правильнее называть "параметром" или "аргументом" в зависимости от контекста, что тоже порой может некоторую путаницу вызывать. Когда мы говорим о x как о чем-то абстрактном, это параметер. Когда мы говорим непосредственно о его значении, это аргумент (f(5) = 25). Как-то так.


Однако, если вспомнить машину Тьюринга, то там, что состояние, что значение ячейки, что положение "указателя" являются по сути одним и тем же, а именно тупо аргументами функции (коей является сама машина). Собственно, это намекает на то, что в контексте программирования прав все-таки товарищ Source, потому что в программировании важен еще и сам вычислительный процесс, который действительно является сменой состояний, где конечное состояние и будет результатом.


Я почему-то вспомнил какое-то изречение Алана Кея (не вспомню источник). Если совсем коротко, то тезис был примерно таким, что мы слишком усложнили понятие ООП, т.к. изначально он всего-лишь подразумевал такие понятия, как "объект" и "посылка сообщений объекту".


Может быть, мы действительно слишком сильно пытаемся углубиться в высшие замыслы ФП, что отстраняемся от простых вещей вроде "mutability — зло", "side-effects — зло", которые по сути уже очень многое дают сами по себе.

По глобальным переменным могу уточнить. Само понятие глобальности относительно. Например переменная, объявленная внутри функции (я сейчас говорю не про функцию из ФП, а про обычную функцию из императивного ЯП), является локальной для этой функции, т.к. существует только в момент вызова этой функции. И при следующем вызове будет создана новая такая же переменная. Но это будет уже другой ее экземпляр. Однако, если мы внутри функции объявим еще одну, вложенную функцию, то эта же самая переменная, для вложенной функции будет уже глобальной. То же самое с полями объекта. Они существуют все время существования объекта, и являются глобальными для его методов. Единственное, что тут спасает, это, что их область видимости обычно ограничена одним объектом. И между методами объекта существует обязательство, сохранять данные в полях в непротиворечивом состоянии, и учитывать особенности работы остальных методов данного объекта. Это делает объект сильно связной сущностью. В общем-то для того и понадобилось объединить данные и методы в одну сущность, чтобы хоть как-то локализовать взаимную зависимость методов и данных. То есть ООП это компромисс. У объектов есть состояние, но мы работаем с нм максимально аккуратно. Ну это в теории должно быть так. На деле все сильно зависит от компетентности программиста.
В принципе, можно дать некое определение глобальности. Объект «a» является глобальным по отношению к объекту «b», если объект «b» имеет доступ к объекту «a», и при этом время жизни объекта «a» больше, чем время жизни объекта «b».
При этом, если глобальной является некая константа, то с ней проблем нет. Ее значение не меняется. Если же это переменная, и мы можем ее изменить (а как правило, изменить ее можем не только мы, но и чужая функция, что еще хуже), то выполнение нашей функции становится непредсказуемым. Два раза подряд вызвав функцию с одними и теми же параметрами мы можем получить разные результаты. Это вообще противоречит определению функциональной зависимости. Математическая функция обязана для каждого аргумента «x», входящего в область допустимых значений, возвращать определенный, всегда один и тот же результат «y». Только тогда мы имеем право, написать, что y=f(x). То есть сказать, что «y» функционально зависит от «x». Соответственно, чтобы не было противоречий с математикой, мы вынуждены считать, что все глобальные переменные, от которых зависит функция, так же являются ее параметрами. Проблема в том, что эти параметры, во-первых являются неявными, а во-вторых, если несколько функций обращаются к одной и той же глобальной переменной, и хотя бы кто-то в нее пишет, они начинают неявно влиять друг на друга. Возникают побочные эффекты. Такой код крайне сложно поддерживать и масштабировать. А если код еще и может выполняться асинхронно и параллельно, то это вообще ад.
И еще, следует понимать, что под «отсутствием состояния» в ФП подразумевается отсутствие состояния на уровне функции. На уровне же всей программы, всего алгоритма, естественно мы меняем некое состояние. Просто мы передаем его из одной функции в другую с помощью параметров и возвращаемых значений, явно и только тогда, когда нам это нужно. При этом каждая отдельная функция состояния не имеет, и ничего о нашем состоянии не знает. Она универсальна.
Само понятие глобальности относительно.

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


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

То что вы говорите это глобальность относительно всех сущностей программы. Но опять же относительно. Просто, когда появилось понятие «глобальная переменная», типичная программа состояла из процедур и функций. В ней не было других элементов абстракции. Переменная могла быть объявлена либо внутри какой-то функции, то есть локально для этой функции, либо вне функции, то есть глобально для всех функций. А поскольку все функции вместе, как раз и представляли собой программу, то она получалась глобальной для всей программы. Сегодня, в типичном ОО языке ситуация несколько сложнее. Уровней видимости и вложенности может быть гораздо больше. Есть пространства имен, классы, модификаторы доступа, объекты, методы. Поэтому говоря о глобальности сегодня, нужно не забывать про уровень этой самой глобальности. Поле является локальным для объекта, т.к. объявлено в нем. Но оно глобально для методов объекта. Приватное статическое поле класса локально для класса, но глобально для всех объектов этого класса. А если статическое поле еще и публичное, то оно глобально для всего пространства имен. Если же и сам класс публичный, то это поле уже глобально для всей программы. Конечно реализация ООП в разных языках может быть сильно разной. То что я написал выше, верно, например для C#. Но сама идея верна для любого языка, в котором уровней видимости больше двух. Даже не обязательно, чтобы это был ОО язык. На одних только замыканиях можно такую вложенность навертеть, что мозг взорвется.
Именно поэтому я считаю не правильным говорить просто о глобальности/локальности данных как о каких-то абсолютных характеристиках. Правильней было бы говорить о степени глобальности/локальности данных. Может это и не совсем верно с какой-то академической точки зрения. Но меня, как программиста, прежде всего интересует практика. А на практике, использование статических полей класса несет в себе всё те же риски и проблемы, что и использование глобальных переменных, хоть они уже и не настолько глобальны, как классические глобальные переменные. Да и простые поля объекта, тоже подвержены тем же рискам. В последнем случае эти риски меньше, потому что и степень глобальности меньше. При этом, чем больше разрастается объект, тем проблем становится больше. Почему? Да потому что растет количество кода, которому доступны поля объекта. Кода для которого эти поля являются глобальными. То есть степень глобальности полей с ростом объекта увеличивается, хотя и уровень, на котором они объявлены не изменился. Отсюда выводы: если в объекте есть поля, нужно делать его как можно меньше. Если полей у объекта нет, то даже будучи довольно большим, его поддержка доставит не так много проблем, как поддержка гораздо меньшего объекта с большим количеством полей и сложным внутренним состоянием. И на практике это подтверждается. Конечно большой объект и без полей может быть сложно поддерживать, но уже по другим причинам. Много кода в одном месте — простоты не добавляет.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Функция — просто правило, по которому элементы одного множества сопоставляются другому. О каком состоянии может быть речь?
Состояние — это один из аргументов функции, например, в той же хвостовой рекурсии при вычислении факториала начальное состояние будет = 1, а итоговое — результат. Просто Вы это называете не состоянием, а вычисляемым значением, хотя, строго говоря, вычисляемое значение — это только конечное состояние.

Когда мы говорим, что данные неизменяемые, мы не лукавим, т.к. они физически не меняются в ОЗУ, в отличии от императивных языков. Насколько я понимаю, именно это помешало распространению ФП в прошлом веке, т.к. программы работали медленнее из-за неизменяемости данных, но со временем это оптимизировали. И теперь людей больше интересует как запустить сотни потоков и не получить ни race condition от доступа к изменяемым данным, ни геммороя с блокировками.

писал сейчас большой ответ с примерами кода, но потом понял Ваш "point" и стер.
Собственно, признаю Вас правым, хоть и к некоторым вещам я все равно буду продолжать относиться по-своему (все мы видим мир по-разному, верно? Дайте мне насладиться своим личным безумием:D).


Спасибо, что уделили мне время

Разумеется у Вас есть право на своё видение :-)
Я, правда, Вам ещё один ответ написал и только потом это сообщение увидел )))
Спасибо за дискуссию.
НЛО прилетело и опубликовало эту надпись здесь

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


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

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

НЛО прилетело и опубликовало эту надпись здесь

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


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

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

НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь

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


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

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

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

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

НЛО прилетело и опубликовало эту надпись здесь

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

НЛО прилетело и опубликовало эту надпись здесь

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


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

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


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

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

НЛО прилетело и опубликовало эту надпись здесь
Django поддерживает многопоточность.

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


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

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


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

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


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

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


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

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


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


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

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


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

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

НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь

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


Удачи с ФП :-)

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

Какая миленькая манипуляция) Отсутствие общепринятых паттернов в ФП говорит только о слабой поддержке теорией практики. Есть какие-то теоретические основы, но никто еще не писал достаточно крупного ничего, чтобы пришла Б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.

Да, ибо так и есть.

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

В основном заворачивание побочных эффектов в монады, как попытка их изолировать.

Ну а то, что пишут в императивном стиле и в нечитабельной форме, то это ведь не проблема ФП, это проблема с ригидностью мышления автора конкретного кода

Покажите мне программу, которая написана в декларативном стиле, где реально ФП использован во всю силу. это как раз проблема ФП, ибо он — глубоко теоретичен и подходит только для узкого списка задач. Использование лямбд для императивного решения задач (типа Linq в C#) я не могу назвать примером использования ФП)
Ну, к примеру: веб-сервер cowboy
> Ну а то, что пишут в императивном стиле и в нечитабельной форме, то это ведь не проблема ФП
Это проблема стиля. Если ЯП позволяет писать в разных стилях — это плохо. И чем сложней ЯП, чем выше его парадигма, тем это хуже.
Подождите, а как ЯП может запретить писать в каком-то стиле? Я всегда был уверен, что язык может только повысить удобство практического применения какой-то парадигмы, но запретить при этом все остальные… такого как-то не встречал.
Можете пример такого языка привести?
Возможно не совсем четко выразил свою мысль: чем больше вариантов решения одного вопроса — тем хуже для читабельности (а значит и для сложных проектов). Особенно, если при этом еще можно применять разные парадигмы. Идеально, конечно, чтобы даже стиль был один, но это наверное слишком идеально будет…

Спорно. Всё-таки читабельность — это ответственность программиста. И выразительные средства языка ему в этом помогают.
А урезание выразительных возможностей наоборот снижает читабельность в сложных проектах. Для примера можно код крупных проектов на Go посмотреть.

> Всё-таки читабельность — это ответственность программиста.
Чеж тогда все Бейсик ругали с его goto? Писали бы ответственно и проблем бы не было…

> А урезание выразительных возможностей наоборот снижает читабельность в сложных проектах.
Согласен, выразительность должна быть большая и безальтернативная.

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

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

Так с ростом сложности задач и увеличения возможностей ЯП, требования к читабельности растут быстрее, чем к писабельности.
> Чеж тогда все Бейсик ругали с его goto? Писали бы ответственно и проблем бы не было…

Убрать goto проще, чем научить миллионы чайников как им грамотно пользоваться…
НЛО прилетело и опубликовало эту надпись здесь
> Нужно задаться вопросом, почему наши подходы имеют такой успех и разделить сферы влияния новых «веяний моды» от «старого доброго».
Только после того, как четко разделятся сферы влияния, где и «старого доброго» достаточно, а где лучше применять «веяния моды».

Зачем Вы меня перефразировали?:)

Мне кажется, что еще время для четкого разделения не пришло. Лет через 5, да.
Но ведь все те недостатки, которые перечисляют авторы подобных статей, существовали в нынешних подходах и раньше. Это как «разоблачение», что АНБ следит за людьми.
Так он и пишет, что 6 лет уже об этих недостатках говорят и пытаются исправить. Но раз Core Team против таких исправлений, то можно уже и закрыть тему.
"… это естественно «защищать» что-то, что помогло вам, или то, что вам просто нравится, в то же время здорово быть в состоянии думать за пределами коробки и быть открытым ..."

«Думать за пределами коробки»? Вы говорите серьезно? Я считаю, только блокголова мог так написать в русском языке!
Спасибо, исправил. Переведите тоже что-нибудь интересное… покажите класс :-)
НЛО прилетело и опубликовало эту надпись здесь
Да не, эта идиома переводится именно так: пруф. Другое дело, что дословный перевод был в чём-то яснее, т.к. выражение «из коробки» уже устоялось в IT и понятно о какой «коробке» идёт речь.
НЛО прилетело и опубликовало эту надпись здесь
Я вдохновился функциональным программированием в последние пару лет. Вы можете видеть, что в этом стиле я пишу теперь и на Ruby.
Сколько эмоций! А главное, по-видимому, в этих двух предложениях…

Публикации

Истории