Language

Rails Соглашение

By David Heinemeier Hansson in January, 2016 (Автор перевода Dmitriy Strukov)

The Rails Doctrine

Феноменальная популярность Ruby on Rails в значительной степени обусловлена переходом к новым трендам и технологиям в нужный момент времени. Но, к сожалению, технические преимущества с течением времени становятся не актуальными. Поэтому необходимо подробное объяснение того, каким образом RoR не только продолжает оставаться актуальным, но расширяет свое влияние и сообщество. Мое предположение, что несокрушимым фактором было и остается его противоречивое соглашение.

Соглашение активно развивалось последние десять лет, но большая часть основных идей осталась не тронута. Я не претендую на некую фундаментальную уникальность этих идей. Главное достижение Rails — это объединение вокруг себя сильного сообщества людей с нестандартным подходом и мировоззрением о природе программирования и программистах.

Итак, вот девять самых важных столпов Rails-соглашения и того, как их воспринимает ваш покорный слуга:

  1. Оптимизация на радость программистам
  2. Соглашение над конфигурацией
  3. Меню это омакасе
  4. Отсутсвие парадигм
  5. Культ красоты кода
  6. Острые лезвия
  7. Цените интегрированные системы
  8. Прогресс превыше стабильности
  9. Возведите большую палатку

Оптимизация на радость программистам

Ruby on Rails не существовало бы без Ruby, поэтому логично, что первый столп соглашения появился из самих истоков Ruby.

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

Если Python может похвастаться тем, что есть “один и желательно только один способ реализации чего-либо”, Ruby пришлось по вкусу выразительность и лаконичность. Там где Java активно защищал программистов от самих себя, Ruby сбросил веревку и стартовый набор для первых шагов в изучении. Там, где Smalltalk пробил непорочность установленной культуры, Ruby с прожорством накапливал ключевые слова и конструкции.

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

Ruby был разработан не только для того чтобы осознать, но и вместить в себя всю палитру чувств программиста. Будь то неадекватность, фантазии или радость. Matz обеспечил реализацию идеи поразительной сложности, суть которой в том, что среда разработки должна быть помощником программисту. Ruby это один из тех случаев где, то что кажется простым и понятным на первым взгляд является акробатическим трюком с завязанными за спиной руками. За эти решения приходится платить (спросите об этом команду JRuby, которые пытались сделать реверс инжиринг всего этого), именно поэтому они так сильно заслуживают уважения.

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

Я описал бы погружение в Ruby как находку волшебной перчатки, которая идеально заполнила мое сознание. Лучшее что я мог бы себе представить. Событие, которое стало моим личным переходом от парадигмы ‘создавать программы потому что я в них нуждаюсь’ к ‘созданию программ с любовью и самовыражению через них’. Для тех, кто знаком с работой Mihaly Csikszentmihalyi, тем трудно переоценить его влияние на Ruby сообщество.

Я не преувеличиваю, когда говорю, что Ruby изменил меня и мою жизнь. Для меня это было неким откровением. Он проник в мое сознание и призвал помочь меня выполнять миссионерскую миссию в качестве услуги за творение Matz. С целью помочь распространить его творение и рассказать о его преимуществах.

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

В любом случае, вопрос в том, что такое Ruby on Rails, и как он, руководствуясь своими принципами и идеями продолжает развиваться? Чтобы ответить на данный вопрос, я думаю, уместно будет привести один из принципов, который был часто использован при написании Ruby в первые дни: принцип наименьшего удивления (PoLS). Ruby должен вести себя так, как вы ожидали. Это легко описать на контрасте с Python:

    $ irb
    irb(main):001:0> exit
    $ irb
    irb(main):001:0> quit

    $ python
    >>> exit
    Use exit() or Ctrl-D (i.e. EOF) to exit

Ruby поддерживает обе команды чтобы выполнить ясное и вполне очевидное желание программиста — выход из интерактивной консоли. Python с другой стороны с педантичностью указывает, что программисту следует сделать, хотя очевидно, что он знает намерение программиста (это видно поскольку он показывает сообщение об ошибке). Это довольно простой и наглядный пример работы принципа PoLS.

Причиной тому, что PoLS попал в немилость сообщества Ruby, является его субъективный подход. Но удивительно, кому же он пал в немилость? Что же, этот человек Matz. И люди, которые удивляются таким же образом, как и он. Как только Ruby сообщество пополнило свои ряды, люди стали удивляться несколько разным вещам, что стало причиной бесчисленных писем.

Итак, еще раз, как это связано с Ruby on Rails? Rails разработан с применением такого же принципа PoLS (принцип наименьшего удивления). Принцип широкой улыбки (DHH), который гласит: API интерфейсы разработаны с таким пристальным вниманием, что заставляют меня улыбаться все больше и шире. Когда я излагаю это таким образом, это звучит комично и самовлюбленно, даже мне трудно возразить первому впечатлению.

Создание Ruby on Rails является довольно самовлюбленным начинаем. Оба проекта возникли из ума единого Творца. Но вполне возможно, что я проецирую свои собственные мотивы на Matz, поэтому позвольте воззвать к тому что я знаю: я создал RoR в первую очередь для себя. Чтобы комфортно разрабатывать и основная ценность RoR состоит в том чтобы больше наслаждаться жизнью. Избавить себя от ежедневной рутины.

Как и Matz, я временами заходил в тупик. Один из таких примеров — класс Inflector, который понимает много неточностей английского языка, чтобы преобразовать класс Person в имя таблицы People, Analysis в Analyses и Comment в Comments. Такое поведение системы воспринимается сейчас как неприкасаемая часть Rails, но были времена когда бушевали споры на эту тему, когда соглашение еще только создавалось.

Еще один небольшой пример, который потребует немного меньше усилий для восприятия: о ужас, Array#second #fifth (и как кто-то хорошо подметил #forty_two, хороший троллинг). Эти алиасы были очень оскорбительны для некоторых людей, которые сокрушались по поводу того, что зачем столько наворотов, если можно написать просто Array#[1] Array#[2] и Array#[41].

Оба решения вызывают у меня улыбку и по сей день. Я с удовольствием пишу людям, third как тестовый кейс в консоли. Нет, это не логично. Это не эффективно. Но это заставляет меня улыбаться и следовать принципам для обогащения своей жизни, и оправдывает мой дальнейший вклад в Rails дальнейшие 12 лет.

В отличие от оптимизации производительности, трудно измерить удобство разработки и счастье программиста. Это делало данное начинание почти антинаучным по своей сути. Программистов учат спорить и оперировать измеримыми материями, то в чем можно сделать четкий вывод, там где A категорически лучше чем B.

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

Соглашение над конфигурацией

Один из ранних девизов Rails звучал так: «Ты не красивая и уникальная снежинка». Девиз гласил, что отказываясь от индивидуальности можно обойти решение тривиальных проблем и добиться более быстрого прогресса в областях, которые действительно значимы.

Кого волнует, в каком формате описываются ваши первичные ключи в базе данных? Действительно ли это важно, если речь идет о «id», «postId», «posts_id» или «pid»? Достойно ли это решение постоянного обсуждения? Нет.

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

Мало того, что передача конфигурации в соглашение освобождает нас от обсуждения, она также предоставляет пышное поле для роста более глубоких абстракций. Если у нас есть возможность использовать зависимость класса Person от таблицы people, то мы можем использовать, то же самое преобразование, чтобы отобразить ассоциацию, объявленную как has_many: people, для поиска класса Person. Сила хороших соглашений заключается в том, что они приносят дивиденды в широком спектре использования.

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

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

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

Как и во всем, сила соглашения не лишена подводных камней. Когда с помощью Rails вы делаете все настолько просто, чтобы сделать так много, то легко впасть в заблуждение, что каждый аспект приложения может быть сформирован с использованием только шаблонов. Но в большинстве приложений, есть особые элементы, которые уникальны. Это может быть 5% или 1%, от всего приложения, но такие вещи встречаются.

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

Меню это омакасе

Какое решение вы принимаете, когда не знаете что выбрать из меню в ресторане? Что ж, вполне вероятно, что если вы позволите шеф-повару сделать выбор за вас, то он может приятно вас удивить, до того как к вам придет понимание того, что такое «хорошо». Это омакасе. Способ хорошо поесть, который не требует от вас экспертных знаний и к тому же позволяющий не рассчитывать на слепую удачу при выборе.

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

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

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

Это проблема, подобная ужину в ресторане. Как выбрать из восьми блюд, что ж выбор библиотеки или фреймворка не должно быть работой в одиночку. Цель в обоих случаях — рассмотреть весь вечер или систему.

Таким образом, в RoR мы решили сократить выбор, заменить индивидуальный выбор программиста отдельных инструментов на нечто большее: Лучший набор инструментов для всех. Дивиденды — это легион:

  1. Безопасность кроется в цифрах: когда большая часть людей использует Rails одинаковыми способами по умолчанию, у нас накапливается общий опыт. Это то, что облегчает обучение и помощь новичкам. Это закладывает фундамент для общения. Мы все смотрели одно и то же шоу прошлой ночью в 7, поэтому мы можем поговорить об этом на следующий день. Это способствует более сильному чувству общности.
  2. Люди совершенствуют один и тот же базовый набор инструментов: В Rails в качестве full-stack фреймворка есть много подвижных частей, и то, как они работают вместе, так же важно, как и то, что они делают изолированно. Большая часть проблем в программном обеспечении исходит не от отдельных компонентов, а от их взаимодействия. Когда мы все работаем над облегчением общих проблем от компонентов, которые настроены и падают с ошибкой по разным причинам, у нас возникает меньше проблем.
  3. Замены по-прежнему возможны, но не требуются: хотя Rails — это стек omakase, он все же позволяет вам заменить определенные фреймворки или библиотеки альтернативами. Вам просто это не нужно. Это означает, что вы можете отложить эти решения до тех пор, пока не разработаете четкую персональную палитру “лучших решений”, вместо случайного набора инструментов

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

Ни одна парадигма

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

В Rails — это не так. Это не один, идеальный крой ткани. Это одеяло. Совокупность многих разных идей и даже парадигм. Многие из них, как правило, противоречат друг другу, если их сравнивать друг с другом и один за другим. Но это не то что мы пытаемся сделать. Это не одно большое соревнование, в котором должен быть объявлен один победитель.

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

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

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

Для сравнения, мы обычно рассматриваем модель в MVC как основной бастион объектно-ориентированного подхода. Нахождение только правильных имен для объектов, увеличение согласованности и снижение связанности — это удовольствие от моделирования предметной области. Это очень отличный слой от представления, поэтому мы используем другой подход.

Но даже здесь мы не подходим к одно парадигматической догме. Проблемы с Rails, специализацией Ruby являются миксины, которые часто используются, чтобы дать отдельным моделям очень широкую площадь поверхности. Это хорошо сочетается с шаблоном Active Record, предоставляя связанным методам прямой доступ к данным и хранилищу, с которыми они взаимодействуют.

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

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

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

Это относится и ко многим подязыкам, а также Rails. Мы не пытаемся оградить вас настолько, чтобы вы научились, скажем, JavaScript для представления или SQL для сложных запросов. По крайней мере, чтобы не достичь пика возможностей.

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

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

Культ красоты кода

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

Итак, что такое красивый код? В Ruby зачастую это пересечение нативных Ruby методов и всей мощи DSL. Это незаметная грань, но все же стоит попробовать найти золотую середину.

Вот простой пример из Active Record:

    class Project < ApplicationRecord
      belongs_to :account
      has_many :participants, class_name: 'Person'
      validates_presence_of :name
    end

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

Часть красоты данного примера заключается в том, что это соответствует предыдущим принципам, таким как Конвенция над конфигурацией. Когда мы вызываем belongs_to :account, то предполагаем, что внешний ключ называется account_id и что он находится в таблице projects. Когда нам нужно определить class_name Person для ассоциации participants, нам требуется определить только имя класса. Из этого мы вновь получим внешние ключи и другие точки конфигурации.

Вот еще один пример с миграцией базы данных:

    class CreateAccounts < ActiveRecord::Migration
      def change
        create_table :accounts do |t|
          t.integer :queenbee_id
          t.timestamps
        end
      end
    end

В этом и заключается сила фреймворка. Программист объявляет класс в соответствии с определенным соглашением, например, подкласс ActiveRecord::Migration, который реализует метод #change и фреймворк выполяет все связанные с этим операции и знает, что это метод вызова.

Это дает возможность писать меньше кода. В случае с миграциями это не только вызов rails db:migrate, чтобы обновить состояние базы данных, для добавления новой таблицы, но и позволяет в случае необходимости удалить ее. Это сильно отличается от того, как программист делает все это и объединяет библиотеки, которые вызывают сами себя.

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

Эти два условия делают одно и тоже:

    if people.include? person
      …

    if person.in? people

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

Острые лезвия

В Ruby есть много острых лезвий. Не случайно, а намеренно. Самое известное это monkey-patching: механизм позволяющий изменить существующие методы и классы.

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

Если вы можете изменить что угодно, что остановит вас от переписывания функции String#capitalize и ‘something bold’.capitalize возвращающей ‘Something Bold’ вместо ‘Something bold’? Это сработает в вашем локальном приложении, но сломает всю логику, которая зависит от оригинальной реализации.

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

Потому что обратная сторона monkey patching это возможность делать такие вещи как 2.days.ago (возвращает дату на два дня назад от текущей). Вы можете подумать что это плохая сделка. То что вы лучше откажетесь от использования 2.days.ago, если это будет означать, что программисты не перезаписывают String#capitalize. Если это ваша позиция, то Ruby вероятно не для вас.

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

И не только доверял, но и учил способам использования таких мощных инструментов. Чтобы мы могли поднять уровень профессиональной области, предполагая, что большинство программистов хотели бы стать лучшими программистами, способными овладеть острыми лезвиями не поранив пальцы. Это невероятно вдохновляющая идея и она противоречит интуиции программиста о других программистах.

Потому что это всегда о других программистах, когда ценность острых лезвий оспаривается. Я еще не слышал, как один программист протянул руку и сказал: “Я не могу доверить себе эту силу, пожалуйста уберите ее от меня!”. Это всегда “Я думаю, что другие программисты злоупотребляли бы этим”. Эта линия патернализма никогда не касалась меня.

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

Множество функций Rails со временем начинают оспариваться “слишком много свободы”. Но один пример, который в настоящее время является самым популярным функционал concerns. Это тонкий слой синтаксического сахара вокруг встроенной в Ruby функции модулей и предназначен для того, чтобы один класс мог инкапсулировать несколько связанных с ним классов, но самостоятельных, concerns (отсюда и название).

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

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

Программисты, которые еще не научились обращаться с острыми лезвиями, пока еще не собираются делать безе. Важное слово здесь: Еще. Я считаю, что у каждого программиста есть путь, если не право, стать полностью полноправным представителем Ruby on Rails сообщества. И говоря полноправным я имею в виду осведомленным, осознающим, когда и в каком контексте следует использовать острые лезвия из набора инструментов.

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

Ruby on Rails — это среда для шеф-поваров и тех, кто хочет стать шеф-поварами. Вы можете начать с посуды, но вы можете поработать над кухней. Не позволяйте никому говорить вам, что вам нельзя доверять лучший инструмент в рамках этого пути.

Цените интегрированные системы

Ruby on Rails можно использовать для разных целей, но его конек — это монолитные интегрированные системы. Такие системы нацелены на решение всей задачи совокупно. Через Rails проходит все, начиная от генерации JavaScript для мгновенного обновления страниц, и заканчивая миграцией базы данных от одной версии к другой, когда проект уже в эксплуатации.

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

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

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

Увы, иногда без распределенной архитектуры не обойтись. Если вашему веб-приложению нужен API-интерфейс, к которому пользователи будут обращаться по HTTP, то ничего не поделаешь — придется решать почти все упомянутые проблемы. Остается порадоваться, что работа со входящими запросами куда проще, чем с исходящими, ведь если ваш интерфейс какое-то время не будет работать, то проблемы будут не у вас, а у потребителя этого интерфейса. По крайней мере в таком случае неудобства, которые вам как разработчику придется претерпеть, не столь велики.

Плохо, когда система преждевременно дробится на сервисы или, что еще хуже, на микросервисы. Бытует мнение, что при разработке «Современного Интернет-Приложения» неизбежно придется строить одну и ту же систему много раз: один раз на стороне сервера, один раз на стороне клиента в виде JavaScript MVC, по одному разу для каждой мобильной платформы, и так далее. Но это требование ничем не обусловлено, так делать совершенно необязательно.

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

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

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

Прогресс превыше стабильности

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

Но, если мы будем слишком внимательно прислушиваться к голосам консерватизма, мы никогда не увидим другой стороны медали. Мы должны иногда брать на себя смелость и изменять условия, по каким все должно развиваться и расти. Именно это развитие сохранит Rails: и его выживание, и процветание в течение десятилетия (десятилетий?) в будущем.

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

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

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

Эта работа — не просто то, что должно произойти исключительно в Rails, но и в более крупном сообществе самого языка Ruby. Rails должен находиться на переднем крае разработки, помогая продвижению Ruby, заставляя его составляющие быстрее использовать более поздние версии.

До сих пор мы очень хорошо справлялись с этим. С того момента, как я начал, мы прошли через Ruby версий 1.6, 1.8, 1.9, 2.0, 2.1, 2.2 и теперь на 2.3. Множество серьезных изменений произошло на этом пути, но Rails непосредственно присутствовал и участвовал в них, чтобы иметь под капотом Ruby, и помочь каждому быстрее осуществлять процесс разработки. Эта отчасти привилегия, а отчасти и обязательство Rails, является основой популяризации Ruby.

Это также верно для вспомогательных инструментов рабочего процесса. Bundler когда-то был спорной идеей, но по настоянию Rails о том, что это будет краеугольным камнем совместного будущего, сегодня это само собой разумеющийся инструмент де-факто. Это так же касается таких инструментов и технологий как asset pipeline (файлопровод) и Spring, предварительный загрузчик приложений Rails. Все три инструмента прошли стадию укоренения, или же продолжали переживать боль роста, но очевидность их ценности в долгосрочной перспективе помогла нам преодалеть это.

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

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

Возведите большую палатку

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

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

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

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

То же самое можно сказать о режиме Rails в качестве HTTP API. В то время, как я лично предан и сосредотачиваюсь на интегрированной системе, включающей в себя виды (представления), несомненно Rails может многое предложить и разработчикам, желающим разделить свое приложение на клиентскую и серверную часть (бекенд и фронтенд). Мы должны принять это, поскольку такие решения могут развиваться в Rails как второстепенные, и я уверен, что это возможно.

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

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

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

← Back to homepage