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

Ruby on Rails соглашение. Часть 3

Время на прочтение 7 мин
Количество просмотров 2.9K
Автор оригинала: David Heinemeier Hansson


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


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

В 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 со временем начинают оспариваться “слишком много свободы”. Но один пример, который в настоящее время является самым популярным, является апогеем. Это тонкий слой синтаксического сахара вокруг встроенной в Ruby функции модулей и предназначен для того, чтобы один класс мог инкапсулировать несколько связанных с ним классов, но самостоятельных, concerns (отсюда и название).

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

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

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

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

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

Теги:
Хабы:
-2
Комментарии 5
Комментарии Комментарии 5

Публикации

Истории

Работа

Программист Ruby
15 вакансий
Ruby on Rails
17 вакансий

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн