Правила для разработчиков от 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 

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

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

ссылка на оригинал статьи http://habrahabr.ru/post/181434/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *