Правила для разработчиков от Sandi Metz

в 6:22, , рубрики: ruby, ruby on rails, Программирование, стиль программирования

Правила для разработчиков от Sandi MetzВ январе этого года, Sandi Metz представила свои правила для разработчиков в эфире подкаста Ruby Rogues. Примерно в это же время, я и моя команда начали новый проект. Эта статья описывает тот опыт, что мы получили, применяя эти правила к своему новому проекту.

Правила

  1. Классы не могут содержать больше чем 100 строк кода.
  2. Методы не могут быть длиннее чем 5 строк кода.
  3. Нельзя передавать больше 4 параметров в метод. Значения хэша также считаются параметрами.
  4. Контроллеры могут инстанциировать только один объект. Следовательно, представление может знать только об одной инстанс переменной и должно только слать сообщения этому объекту (@object.collaborator.value не допустим).

Когда следует нарушать правила

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

Пусть это будет неизменным правилом номер 0.

100-строковые классы

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

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

Мы пришли к выводу, что git diff совсем не обязательно показывает нам, когда мы превысили лимит в 100 строк.

5 строк кода на метод

Ограничение метода пятью строками пожайлуй самое интересное правило.
Мы договорились на том, что ‘if’, ‘else’, ‘end’ тоже считаются. В блоке ‘if’ с двумя ответвлениями, каждое ответвление должно умещаться в одну строку.

Например:

def validate_actor
  if actor_type == 'Group'
    user_must_belong_to_group
  elsif actor_type == 'User'
    user_must_be_the_same_as_actor
  end
end

5 строк гарантируют, что мы никогда не будем использовать ‘else’ с ‘elsif’.

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

Mаксимум 4 аргумента на метод

Применение данного правила в Rails стало для нас большим испытанием, особенно в представлениях.

Хелперы представления, такие как ‘link_to’ или ‘form_for’, могут затребовать много параметров для корректной работы. Мы конечно прилагали усилия для ограничения количества передаваемых аргументов, но порой возвращались к правилу 0 и оставляли их, если не находили лучшего способа.

Инстанциировать максимум один объект в контроллере

Это правило удивило нас больше всего, прежде чем мы приступили к новому проекту. Зачастую нам требовалось больше одного типа объекта на странице. Например, на домашней странице нам нужны были лента активности и счетчик уведомлений.

Мы решили эту проблему через шаблон проектирования Фасад. А выглядело это так:

app/facades/dashboard.rb:

class Dashboard
  def initialize(user)
    @user = user
  end

  def new_status
    @new_status ||= Status.new
  end

  def statuses
    Status.for(user)
  end

  def notifications
    @notifications ||= user.notifications
  end

  private

  attr_reader :user
end

app/controllers/dashboards_controller.rb:

class DashboardsController < ApplicationController
  before_filter :authorize

  def show
    @dashboard = Dashboard.new(current_user)
  end
end

app/views/dashboards/show.html.erb:

<%= render 'profile' %>
<%= render 'groups', groups: @dashboard.group %>

<%= render 'statuses/form', status: @dashboard.new_status %>
<%= render 'statuses', statuses: @dashboard.statuses %>

Класс ‘Dashboard’ предоставляет общий интерфейс для размещения взаимодействующих объектов пользователя, и уже его объект мы передаем в шаблоны представления.

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

def calculate
  @_result_of_expensive_calculation ||= SuperCalculator.get_started(thing)
end

Невиданый успех!

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

Автор: Timrael

Источник

Поделиться

* - обязательные к заполнению поля