-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixed typos #450
Closed
Closed
Fixed typos #450
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Small fix
Small fix
Fix some words.
The `alias` and `alias_method` chapters translated.
I think you wanted to push in the Russian version, this is the master repository. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Вступление
Один из вопросов, который меня всегда беспокоил как разработчика на Руби,
— это то, что у разработчиков на Питоне есть великолепное руководствo
по стилю оформления (PEP-8), а у нас
никогда не было официального руководства, описывавшего бы стиль оформления кода
на Руби и дающего примеры его успешного применения. Я же уверен, что стиль
оформления крайне важен. Также я верю, что такое замечательное сообщество
разработчиков, которое есть у Руби, вполне имеет силы создать этот давно
назревший документ.
Это наставление появилось на свет в нашей фирме в виде внутреннего руководства
по оформлению кода на Руби (составленного вашим покорным слугой). И в какой-то
момент я решил, что данная работа, которой я тогда занимался, может быть
интересной и другим членам сообщества программистов на Руби и что миру вовсе
не нужно еще одно руководство для внутреннего пользования: окружающий мир может
получить пользу от совместно создаваемого и одобренного сообществом набора
практик, идиом и стилистических предписаний для программирования на Руби.
Со времени опубликования этого руководства я получил многочисленные отклики
от членов сообщества программистов на Руби из разных уголков со всего мира. Я
очень благодарен им за полезные предложения и поддержку! Нашими общими усилиями
мы сможем сделать этот ресурс полезным для всех и каждого разработчика на Руби.
И кстати, если вы работаете с Rails, вы можете взглянуть на дополняющее это
руководство Ruby on Rails 3 & 4: Руководство по стилю оформления.
Руби: руководство по стилю оформления
Это руководство по оформлению кода на Руби дает передовые рекомендации, так что
обычный программист на Руби сможет создавать код, который с легкостью смогут
поддерживать другие обычные программисты на Руби. Руководство по оформлению,
которое отражает повседневную практику, будет применяться постоянно, а руководство,
стремящееся к идеалу, который не принимается обычными людьми, подвергается риску
вообще быть забытым — не важно, насколько хорошим оно является.
Данное руководство разделено на несколько частей, состоящий из связанных по смыслу
правил. В каждом случае я попытался обосновать появление этих правил (объяснение
опущено в ситуациях, когда я посчитал его очевидным).
Все эти правила не появились из пустоты, они по большей части основываются на моем
собственном обширном профессиональном опыте в качестве разработчика ПО, отзывах
и предложениях других членов сообщества программистов на Руби и различных
общепризнанных источниках по программированию на Руби, например,
"Programming Ruby 1.9" и "Язык программирования Ruby"
(в оригинале "The Ruby Programming Language").
Во многих областях до сих пор нет единого мнения в среде разработчиков на Руби
относительно конкретных аспектов стиля оформления (например, оформление строк
в кавычках, пробелы при оформлении хешей, месторасположение точки при
многострочном последовательном вызове методов и т.д.). В таких ситуациях мы
рассматривали все распространенные стили, вам же решать, какой из этих стилей
вы будете применять последовательно в вашем коде.
Это руководство все еще находится в процессе создания: у многих правил нет
примеров, у других нет примеров, достаточно ясно объясняющих эти правила. В свое
время каждое правило найдет свое объяснение, а пока просто примите их к сведению.
Вы можете создать копию этого руководства в форматах PDF или HTML при помощи
Transmuter.
RuboCop — это анализатор кода, основывающийся на правилах этого
руководства по оформлению.
Переводы данного руководства доступны на следующих языках:
Оглавление
Организация исходного кода
Используйте
UTF-8
в качестве кодировки для исходногокода.[ссылка]
Используйте два пробела на уровень
отступа (т.е. мягкую табуляцию). Никаких знаков табуляции.
[ссылка]
Используйте стиль Unix для строк (пользователи
*BSD/Solaris/Linux/OS X используют их по умолчанию, пользователям Windows
нужно обратить особое внимание).[ссылка]
Если вы используете Git, вы можете добавить следующие настройки
в вашу конфигурацию, чтобы предотвратить ненамеренное проникновение в ваш
код строк, оканчивающихся в стиле Windows:
$ git config --global core.autocrlf true
Не используйте
;
для разделения директив ивыражений. Отсюда непосредственно следует, что каждая директива должна занимать
свою отдельную строку.[ссылка]
Используйте преимущественно однострочный
формат для определений классов с пустым телом.
[ссылка]
Избегайте однострочных методов. И хотя
они достаточно популярны в среде программистов, существует множество
неприятных мелочей, связанных с синтаксисом их определения, которые делают
применение таких методов нежелательным. В любом случае однострочные методы не
должны содержать больше одного выражения.
[ссылка]
Одним исключением в этом правиле являются методы с пустым телом.
Вставляйте пробелы вокруг операторов, после
запятых, двоеточий и точек с запятыми, вокруг
{
и перед}
.Пробелы (по большей части) игнорируются интерпретатором Руби, но
их правильное использование является ключом к написанию легко читаемого кода.
[ссылка]
Единственным исключением для операторов является оператор степени:
{
и}
заслуживают некоторого пояснения, так как они используютсядля блоков и для литералов хешей, а также для интерполяции строк.
Для литералов хешей два стиля являются общепринятыми:
Первый вариант несколько проще для чтения и, по всей вероятности,
более распространен среди членов сообщества программистов на Руби.
Второй вариант имеет преимущество в том, что создается видимое различие
между блоками и литералами хешей. Какой бы стиль вы ни выбрали, применяйте
его единообразно.
Не используйте пробел после
(
,[
или перед]
,)
.[ссылка]Не используйте пробел после
!
.[ссылка]
Записывайте литералы диапазонов
без пробелов.[link]
Делайте отступ для
when
таким же, как идля
case
. Я знаю, что многие не согласятся с этим, но этот стильпредписывается как "Языком программирования Ruby", так и "Programming Ruby".
[ссылка]
Присваивая результат условного
выражения переменной, сохраняйте соответствие уровней отступа.
[ссылка]
Используйте пустые строки для
разделения определений методов и выделения логических частей определений
внутри них.[ссылка]
Избегайте запятых после последнего
параметра в вызове метода, особенно когда параметры расположены в отдельных
строках.[ссылка]
Вставляйте пробелы вокруг оператора
присваивания
=
, когда назначаете параметрам метода значения по умолчанию:[ссылка]
Хотя в некоторых книгах по Ruby рекомендуют первый стиль, второй
гораздо более нагляден.
Не используйте символ продления строк
\
везде, где можно обойтись без него. Практически не используйте его нигде,
кроме как при конкатенации строк.[ссылка]
Используйте единый стиль
многострочных последовательных цепочек вызовов методов. В сообществе Руби
популярны два взаимоисключающих стиля их оформления: с точкой в начале
(вариант A) и с точкой в конце (вариант B).
[ссылка]
A Когда продолжаете цепочку вызовов методов на
следующую строку, начинайте её с точки.
B Соответственно, наоборот, когда продолжаете цепочку
вызовов на следующей строке, завершайте строку точкой
.
, даваяпонять, что продолжение выражения следует
C аргументами за и против обоих стилей можно ознакомиться в дискуссии
здесь.
Выравнивайте параметры вызова метода, если
вызов занимает более одной строки. Если выравнивание невозможно из-за
ограничений на длину строки, то используйте одинарный отступ.
[ссылка]
Выравнивайте элементы литералов массива,
если они занимают несколько строк.[ссылка]
Добавляйте символ подчеркивания
в большие числовые константы для улучшения их восприятия.
[ссылка]
Используйте устоявшиеся правила RDoc
для описания интерфейсов. Не отделяйте блок комментария от начала определения
метода
def
пустой строкой.[ссылка]Ограничивайте длину строк 80-ю
символами.[ссылка]
Не оставляйте пробелы в конце строки.
[ссылка]
Завершайте каждый файл переводом строки.
[ссылка]
Не пользуйтесь блочными комментариями. Их
нельзя разместить на необходимом уровне отступа. К тому же их сложнее
воспринимать, чем обычные комментарии.[ссылка]
Синтаксис
Используйте
::
только для обращения к константам (в том числе к классам имодулям) и конструкторам класса (например,
Array()
илиNokogiri::HTML()
).Никогда не используйте
::
для обычного вызова методов.[ссылка]
Используйте
def
со скобками, когда у метода есть параметры. Опускайтескобки, когда метод не принимает параметров.
[ссылка]
Используйте оператор
for
только в случаях, когдавы точно знаете, зачем вы это делаете. В подавляющем большинстве остальных случаев
стоит применять итераторы. Оператор
for
реализуется при помощиeach
(такимобразом вы добавляете еще один уровень абстракции), но с некоторыми отличиями:
не создается отдельная область видимости (в отличии от
each
) и переменные,объявленные в теле
for
, будут видны за пределами блока.[ссылка]
Не используйте
then
для условийif/unless
,объявленных на нескольких строках.[ссылка]
Всегда записывайте условие для
if/unless
на той же строке, что содержит
if/then
в многострочном условии.[ссылка]
Предпочитайте тернарный оператор (
?:
)конструкциям с
if/then/else/end
. Он используется чаще и по определениюболее краток.[ссылка]
Используйте только одно выражение в каждой
ветви тернарного оператора. Отсюда следует, что лучше избегать вложенных
тернарных операторов. При возникновении такой необходимости применяйте
конструкции с
if/else
.[ссылка]Не используйте
if x: ...
, в Руби 1.9 эту синтаксическую конструкцию удалили,используйте вместо нее тернарные операторы.
[ссылка]
Не используйте точку с запятой в
if x; ...
. Применяйте тернарные операторы.[ссылка]
Извлекайте пользу из такого факта, что
if
иcase
являются выражениями,возвращающими результирующие значения.
[ссылка]
Применяйте
when x then ...
для однострочныхвыражений. Вариант записи
when x: ...
был удален, начиная с Руби 1.9.[ссылка]
Не используйте
when x; ...
по аналогиис предыдущим правилом.[ссылка]
Используйте
!
вместоnot
.[ссылка]
Не используйте
!!
.[ссылка]
Ключевые слова
and
иor
следует забыть. Онине несут дополнительной пользы. Всегда используйте
&&
и||
вместо них.[ссылка]
Избегайте многострочных тернарных
операторов
? :
. Используйте вместо нихif/unless
.[ссылка]
Для однострочных выражений по возможности
модификатор
if/unless
. Другим хорошим вариантом являются операторыуправления потоком исполнения
&&/||
.[ссылка]
Избегайте
if/unless
в конценетривиального многострочного блока.
[ссылка]
Используйте
unless
вместоif
для отрицательных условий (или
||
для управления потоком исполнения).[ссылка]
Не используйте
unless
вместе сelse
.Перепишите такие выражение с положительной проверкой.
[ссылка]
Не используйте скобки для ограничения условных
выражений в
if/unless/while/until
.[ссылка]Однако в этом правиле есть некоторые исключения, например,
надежные присвоения в условных выражениях.
Не используйте
while/until УСЛОВИЕ do
для многострочных циклов с
while/until
.[ссылка]
Используйте
while/until
для однострочныйвыражений.[ссылка]
Используйте
until
вместоwhile
для условий на отрицания.[ссылка]
Используйте
Kernel#loop
вместоwhile/until
для бесконечного цикла.[ссылка]
Используйте
Kernel#loop
сbreak
вместоbegin/end/until
илиbegin/end/while
для циклов с постусловием.[ссылка]
Не используйте скобки при вызове методов,
являющихся частью таких DSL, как Rake, Rails, RSpec, методов, имеющих
статус ключевого слова, например,
attr_reader
,puts
и при вызовеаксессоров. Используйте скобки при вызове прочих методов.
[ссылка]
Не используйте фигурные скобки для
ограничения хешей, передаваемых методу.
[ссылка]
Не используйте фигурные скобки для
ограничения хешей, передаваемых методу, и скобки вокруг параметров для
методов, являющихся частью DSL.
[ссылка]
Опускайте скобки при вызове метода без
параметров.
[ссылка]
Используйте краткую форму для вызова
proc
, если вызываемый метод являетсяединственным в блоке.
[link]
Используйте преимущественно
{...}
в случаеоднострочных блоков, а
do...end
в случае многострочных блоков (многострочныепоследовательности вызовов методов всегда выглядят ужасно). Старайтесь
применять
do...end
для логических операций и определений методов (например,для Rakefile и некоторых DSL). Не используйте
do...end
в цепочках вызовов.[ссылка]
Некоторые из нас поспорят, что многострочные последовательные вызовы с блоками
при использовании {...} выглядят неплохо, но тогда стоит себя спросить, а
читается ли такой код и не стоит ли выделить эти блоки в отдельные специальные
методы.
Попробуйте использовать блоки напрямую в виде
аргумента в случае, когда блок просто передает свои аргументы в другой блок.
В этом случае обратите внимание на падение производительности, так как
аргументы будут преобразованы в объект класс
Proc
.[ссылка]
Избегайте ключевого слова
return
везде,где это не нужно для управления ветвлением.
[ссылка]
Избегайте ключевого слова
self
везде,где оно не требуется. Оно необходимо только при вызове методов доступа
(
attr_reader
,attr_writer
,attr_accessor
).[ссылка]
В качестве бездоказательного утверждения:
избегайте маскирования методов локальными переменными, если они не
эквивалентны.
[ссылка]
Используйте возвращаемое
оператором присваивания (
=
) значение только в случаях, когда всевыражение стоит в скобках. Эта идиома достаточно распространена среди
программистов на Руби и часто называется надежное присваивание в логических
выражениях.
[ссылка]
По возможности используйте сокращенные операторы присваивания.
[ссылка]
Используйте оператор
||=
для инициализации переменных, только еслипеременная еще не инициализирована.
[ссылка]
Не используйте оператор
||=
для инициализации логических переменных.Это вызовет проблемы, если текущим значением переменной будет
false
.[ссылка]
Используйте оператор
&&=
для предварительной работы с переменными, которыеуже или еще не инициализированы. Использование оператора
&&=
изменитзначение переменной, только если она инициализирована. При этом отпадает
необходимость в проверке с
if
.[ссылка]
Избегайте явного использования оператора равенства в case
===
. Какподсказывает его имя, этот оператор предназначен для имплицитного
применения в выражениях
case
, в отрыве от них он приводит только кразночтениям в коде.
[ссылка]
Не используйте
eql?
, если будет достаточно==
. Более строгая семантикасравнения, реализованная в
eql?
, достаточно редко нужна на практике.[link]
Избегайте специальных переменных, заимствованных из языка Перл, например,
$:
,$;
и т.д. Они сложно воспринимаются, и их использование приветствуетсятолько в однострочных скриптах. В остальных случаях применяйте легкие для
восприятия варианты этих переменных из библиотеки
English
.[ссылка]
Не оставляйте пробел между именем метода и открывающей скобкой.
[ссылка]
Если первый аргумент при вызове метода начинается скобкой, то всегда
используйте скобки при вызове метода. Например, пишем так:
f((3 + 2) + 1)
.[ссылка]
Всегда вызывайте интерпретатор Руби с ключом
-w
, чтобы получать напоминания оправилах, описанных выше, даже если вы о них забываете.
[ссылка]
Используйте новый синтаксис лямбда-выражений для однострочных блоков. Используйте
метод
lambda
для многострочных блоков.[ссылка]
Используйте
proc
вместоProc.new
.[ссылка]
Используйте
proc.call()
вместоproc[]
илиproc.()
длялямбда-выражений и блоков.
[ссылка]
Начинайте неиспользуемые параметры блока с подчеркивания
_
. Также допустимоиспользовать только подчеркивание
_
, хотя это и менее информативно. Этадоговоренность распознается интерпретатором Руби и Рубокопом и уберет
предупреждения о неиспользуемых переменных.
[ссылка]
Используйте переменные
$stdout/$stderr/$stdin
вместо константSTDOUT/STDERR/STDIN
.STDOUT/STDERR/STDIN
являются константами, поэтому приих переопределении (вы это можете сделать, например, для перенаправления
ввода-вывода) интерпретатор будет выдавать предупреждения.
[ссылка]
Используйте
warn
вместо$stderr.puts
. Это не только короче, но и позволитвам скрыть все предупреждения, если вам это понадобится (для этого задайте
уровень предупреждений равный
0
при помощи опции-W0
).[ссылка]
Используйте
sprintf
и его алиасformat
вместо довольно запутанного методаString#%
.[ссылка]
Используйте
Array#join
вместо достаточно неочевидногоArray#*
со строковымаргументом.
[ссылка]
Используйте
[*var]
илиArray()
вместо явной проверки с помощьюArray
,когда вам приходится работать с переменной, которая по вашим ожиданиям должна
быть массивом, но вы в этом не полностью уверены.
[ссылка]
Используйте интервалы или метод
Comparable#between?
вместо сложной логикидля сравнения, когда это возможно.
[ссылка]
Используйте предикативные методы вместо явного сравнения с использованием
==
. Сравнение чисел можно проводить явно.[ссылка]
Проводите явную проверку на значение
nil
, только если вы работаетес логическими значениями.
[ссылка]
Старайтесь не использовать блоки
BEGIN
.[ссылка]
Никогда не используйте блоки
END
. Используйте методKernel#at_exit
.[ссылка]
Избегайте переменных-перевертышей (flip-flops).
[ссылка]
Избегайте вложенных условий для управления ветвлением. Используйте проверочные
выражения (guard clauses). Проверочные выражения - это условные выражения
в самом начале функции, которые срабатывают при первой же возможности.
[ссылка]
Используйте в циклах
next
в место блоков с условием.Наименование
Используйте английский язык, называя
идентификаторы.[ссылка]
Используйте
snake_case
дляимен символов, методов и переменных.
[ссылка]
Используйте
CamelCase
для имен классов имодулей. Сокращения вроде
HTTP
,RFC
,XML
набирайте заглавными буквами.[ссылка]
Используйте
snake_case
, называя файлы,например,
hello_world.rb
.[ссылка]Используйте
snake_case
, называя каталоги,например,
lib/hello_world/hello_world.rb
.[ссылка]
Старайтесь создавать только один класс или
модуль в каждом файле исходного кода. Называйте эти файлы по имени класса или
модуля, изменив запись в форме
CamelCase
наsnake_case
.[ссылка]
Используйте
SCREAMING_SNAKE_CASE
длявсех других констант кроме имен классов и модулей.
[ссылка]
Идентификаторы предикативных методов, т.е.
методов, возвращающих логическое значение, должны оканчиваться вопросительным
знаком. Например,
Array#empty?
. Методы, не возвращающие логическое значение,не должны оканчиваться вопросительным знаком.
[ссылка]
Идентификаторы потенциально опасных
методов, т.е. таких методов, которые могут изменить
self
или его аргументы,должны оканчиваться восклицательным знаком, если есть соответствующий
безопасный вариант такого метода. Например,
exit!
, который не вызываетзавершающий скрипт в отличии от
exit
, выполняющего финализацию.[ссылка]
Определяйте безопасный метод (вариант
без восклицательного знака) при помощи вызова опасного метода (с
восклицательным знаком), если это возможно.
[ссылка]
При использовании
#reduce
с коротким блоком,называйте аргументы
|a, e|
(accumulator, element).[ссылка]
При определении бинарных операторов называйте параметр
other
. Исключениесоставляют методы
#<<
и#[]
, так как их семантика сильно отличается.[ссылка]
Используйте
#map
вместо#collect
,#find
вместо#detect
,#select
вместо#find_all
,#reduce
вместо#inject
и#size
вместо#length
. Это требованиене сложно реализовать. Если использование альтернатив улучшит восприятие кода,
то можно использовать и их. Все описанные варианты были взяты из языка
Smalltalk и не распространены в других языках программирования. Причиной,
почему не следует использовать
#find_all
вместо#select
, является хорошаясочетаемость с методом
#reject
, и эти наименования очевидны.[ссылка]
Не используйте
#count
в качестве заметы для#size
. Для объектов классов с включеннымEnumerable
(кроме классаArray
)это приведет к затратному полному обходу всех элементов для определения
размера.[ссылка]
Используйте
#flat_map
вместо#map
+#flatten
.Это правило не относится к массивам с глубиной больше 2, например, если
users.first.songs == ['a', ['b', 'c']]
, то используйте#map
+#flatten
,а не
#flat_map
. Метод#flat_map
уменьшает глубину на один уровень. Метод#flatten
сглаживает вложенность любого уровня.[ссылка]
Используйте метод
#reverse_each
вместо#reverse.each
, так как некоторыеклассы, включающие в себя модуль
Enumerable
, дадут вам очень эффективнуюреализацию. Даже в худшем случае, когда класс не реализует этот метод
отдельно, наследуемая реализация из модуля
Enumerable
будет по меньшей меретакой же эффективной, как и для
#reverse.each
.[ссылка]
Комментарии
Пишите говорящий за себя код и смело пропускайте все остальное в этом разделе.
Серьезно!
[ссылка]
Пишите комментарии по-английски.
[ссылка]
Используйте один пробел между символом
#
в начале и текстом самогокомментария.
[ссылка]
Комментарии длиной больше одного слова должны
оформляться в виде законченных предложений (с большой буквы и со знаками
препинания).
Разделяйте предложения одним пробелом.
[ссылка]
Избегайте избыточного комментирования.
[ссылка]
Актуализируйте существующие комментарии.
Устаревший комментарий гораздо хуже отсутствующего комментария.
[ссылка]
плохого кода. Перепишите код, чтобы он говорил сам за себя.
[ссылка]
Пометки в комментариях
Обычно пометки следует записывать
на предшествующей описываемому коду строке.[ссылка]
Пометка отделяется двоеточием и пробелом, потом
следует примечание, описывающее проблему.[ссылка]
Если для описания проблемы потребуются несколько строк, то на каждой
последующей строке следует сделать отступ в три пробела после символа
#
.[ссылка]
В тех случаях, когда проблема настолько
очевидна, что любые описания покажутся избыточными, пометки можно поставить
в конце вызывающей проблему строки. Однако такое применение должно быть
исключением, а не правилом.[ссылка]
Используйте
TODO
, чтобы пометить отсутствующие возможности или функционал,которые должны быть добавлены позже.
[ссылка]
Используйте
FIXME
, чтобы пометить код с ошибками, который должен бытьисправлен.
[ссылка]
Используйте
OPTIMIZE
, чтобы пометить медленный или неэффективный код,который может вызвать проблемы с производительностью.
[ссылка]
Используйте
HACK
, чтобы пометить код "с душком", который должен бытьпереработан и использует сомнительные практики разработки.
[ссылка]
Используйте
REVIEW
, чтобы пометить все, что должно быть проверено наработоспособность. Например,
REVIEW: Are we sure this is how the client does X currently?
.[ссылка]
Используйте персональные пометки, если это подходит по месту, но обязательно
опишите их смысл в файле
README
(или похожем) для вашего проекта.[ссылка]
Классы и модули
Придерживайтесь единообразной структуры
классов.[ссылка]
Если определение класса занимает несколько строк, постарайтесь вынести такой
класс в отдельный файл. Файл с определением стоит поместить в директорию,
названную по имени родительского класса, внутри которого определяется
вложенный класс.
[ссылка]
Если класс определяет только методы класса,
то трансформируйте такой класс в модуль. Использовать классы логично в тех
ситуациях, когда нужно создавать экземпляры класса.
[ссылка]
Используйте
module_function
вместоextend self
, когда вам нужно преобразовать включаемые методы модуля вметоды модуля.
[ссылка]
Создавая иерархии классов, проверяйте их на
соответствие принципу подстановки Барбары Лисков.
[ссылка]
Проверяйте дизайн ваших классов на
соответствие принципу SOLID,
если такая возможность есть.
[ссылка]
Для описывающих предметные области объектов всегда
определяйте метод
#to_s
.[ссылка]
Применяйте макросы из семества
attr_
длятривиальных методов доступа к объекту.
[ссылка]
Не используйте обобщенную форму
attr
. Используйтеattr_reader
иattr_accessor
вместо нее.[ссылка]
Подумайте об использовании
Struct.new
, этаконструкция даст вам сразу простейшие методы доступа к состоянию,
метод инициализации и методы сравнения.
[ссылка]
Не дополняйте
Struct.new
при помощи#extend
. В этом случае уже создаетсяновый класс. При дополнении вы создадите избыточный уровень абстракции, это
может привезти к странным ошибкам при многократной загрузке кода из файла.
[ссылка]
Продумывайте варианты добавления фабричных методов как дополнительной
возможности создавать экземпляры конкретного класса.
[ссылка]
Используйте технику утиной типизации (duck typing) вместо
наследования.
[ссылка]
Избегайте переменных класса (
@@
) из-за их"непристойного" поведения при наследовании.
[ссылка]
Как вы видите, все классы в иерархии фактически делят одну и ту же
переменную класса. Как правило, вам следует использовать переменные
экземпляра класса вместо переменной класса.
Ограничивайте область видимости методов (
private
,protected
) в зависимостиот их планируемого применения. Не оставляйте все в области
public
(этостандартное значение). В конце концов мы пишем на Руби, а не на Питоне.
[ссылка]
Делайте отступы для указателей
public
,protected
иprivate
такими же,как и у самих определений методов, к которым они относятся. Оставляйте пустую
строку выше, а также после указателя, чтобы подчеркнуть, что он относится ко
всем определяемым ниже методам.
[ссылка]
Для определения синглетных методов используйте
def self.method
. Это упроститрефакторинг, так как имя класса будет использоваться только один раз.
[ссылка]
Используйте
alias
при определении алиасов методов в лексической областивидимости класса.
self
в данном случае также имеет лексическую областьвидимости, и это подчеркивает тот факт, что алиас будет указывать на метод
того класса, в котором определен. Вызов не будет перенаправлен неявно.
[link]
Так как
alias
, как иdef
, является ключевым словом, используйте простыеимена методов, а не символы или строки в качестве аргументов. Другими словами,
пишите
alias foo bar
, а неalias :foo :bar
.Также обратите внимание, как Ruby обрабатывает алиасы при наследовании: алиас
будет привязан к тому методу, который находится в области видимости в момент
объявления. Динамическое перенаправление вызова не производится.
В этом примере
Fugitive#given_name
будет вызывать метод базового классаWesterner#first_name
, а неFugitive#first_name
. Чтобы переопределитьповедение
Fugitive#given_name
, нужно объявить алиас в классе-наследнике.Всегда применяйте
alias_method
для определения алиасов методов модулей,классов или синглетных классов во время выполнения, так как
alias
использует лексическую область видимости, что приводит к неопределенному
поведению в данном случае.
[link]
Исключения
Вызывайте исключения при помощи ключевого слова
fail
.Используйте
raise
только при перехвате исключения и вызове его же заново.В этом случае вы не вызываете исключение, а лишь намеренно передаете его дальше
по стеку.[ссылка]
Нет нужды задавать
RuntimeError
явнов качестве аргумента при вызове
fail/raise
с двумя аргументами.[ссылка]
Передавайте класс исключения и сообщение
в форме двух аргументов для
fail/raise
вместо экземпляра класса исключения.[ссылка]
Не возвращайте значений в блоке
ensure
.Если вы явным образом возвращаете значение из блока
ensure
, то возвращениебудет обрабатываться сначала и метод вернет значение, как если бы исключения
не было вовсе. По итогу исключение будет просто тихо проигнорировано.
[ссылка]
Используйте имплицитную форму блока
begin
по возможности.[ссылка]
Смягчайте неудобства, связанные с
использование блоков
begin
при помощи contingency methods (термин введенАвди Гриммом).[ссылка]
Не подавляйте исключения без обработки.
[ссылка]
Откажитесь от использования
rescue
в видепостмодификатора.[ссылка]
Управляйте ветвлением в программе
без помощи исключений.[ссылка]
Не перехватывайте напрямую класс исключений
Exception
. Это будет перехватывать сигналы и вызовыexit
, чтопотребует в крайнем случае завершения процесса при помощи
kill -9
.[ссылка]
Размещайте более специфичные исключения
в иерархии проверки, иначе они никогда не будут отфильтрованы.
[ссылка]
Освобождайте используемые вашей программой ресурсы в блоке
ensure
.[ссылка]
Применяйте варианты доступа к ресурсам, которые гарантируют автоматический
возврат выделенных ресурсов, если есть такая возможность.
[link]
Преимущественно используйте исключения, определенные в стандартной библиотеке,
не создавайте без нужды новые классы исключений.
[ссылка]
Коллекции
При создании массивов и хешей применяйте
нотацию с литералами. Используйте конструкторы класса, только если вам нужно
передать дополнительные параметры при создании коллекций.
[ссылка]
Используйте нотацию
%w
для литералов массивов,когда вам необходимо создать массив слов (непустых строк без пробелов и
метасимволов). Это правило касается лишь массивов с двумя и более
элементами.[ссылка]
Используйте нотацию
%i
для литералов массивов,когда вам необходимо создать массив символов. Помните, что эта нотация
несовместима с синтаксисом Ruby 1.9 и старше. Это правило касается лишь
массивов с двумя и более элементами.[ссылка]
Не ставьте запятую после последнего
элемента в литералах массивов и хешей, особенно если элементы находятся не на
разных строках.[ссылка]
Не создавайте массивы с большими незанятыми
промежутками адресов.[ссылка]
При доступе к первому и последнему элементам
массива используйте методы
#first
или#last
, а не индексы[0]
и[-1]
.[ссылка]
Используйте класс
Set
вместоArray
, если выработаете с уникальными элементами. Класс
Set
реализует несортированнуюколлекцию элементов без повторений и является гибридом интуитивных операций
класса
Array
и легкого и быстрого доступа классаHash
.[ссылка]
Используйте символы вместо строк в качестве
ключей хешей.[ссылка]
Не используйте мутируемые объекты в качестве
ключей для хешей.[ссылка]
Применяйте введенный в Ruby 1.9 синтаксис для
литералов хешей, когда ключами являются символы.
[ссылка]
Не используйте разные способы записи
хешей одновременно (нотации до и после Ruby 1.9). Если вы используете не только
символы в качестве ключей, то применяйте только старую нотацию со стрелками.
[ссылка]
Применяйте
Hash#key?
вместоHash#has_key?
иHash#value?
вместоHash#has_value?
. Матц описываетздесь
свои планы исключить эти методы в будущем.
[ссылка]
Для надежной работы с заданными ключами, о
существовании которых доподлинно известно, используйте
Hash#fetch
.[ссылка]
Задавайте стандартные значения для хешей
при помощи
Hash#fetch
, не реализуйте эту логику самостоятельно.[ссылка]
Используйте блоки вместо значений
Hash#fetch
по умолчанию, если вызываемыйкод имеет сторонние эффекты или сложен для выполнения.
[ссылка]
Используйте
Hash#values_at
, когда вам нужно получить несколько значений хешаза один раз.
[ссылка]
Вы можете положиться на то, что хеши в Ruby 1.9
и младше отсортированы.[ссылка]
Никогда не модифицируйте коллекцию в
процессе ее обхода.[ссылка]
Получая доступ к элементам коллекций, старайтесь избегать доступа при помощи
[n]
, а используйте альтернативные методы доступа, если таковые определены.Это обезопасит вас от вызова
[]
наnil
.[link]
При определении методов доступа к коллекции, добавьте альтернативную форму,
чтобы оградить пользователей от необходимости проверки на
nil
перед доступомк элементу коллекции.
[link]
Строки
Используйте интерполяцию строк и форматные
шаблоны, а не конкатенацию строк.
[ссылка]
Избегайте пробелов внутри скобок вокруг интерполируемых выражений в строках.
[ссылка]
Постарайтесь внедрить единообразных
стиль кавычек для строчных литералов. В среде программистов на Руби есть два
популярных стиля, оба из них считаются приемлемыми. Стиль А подразумевает
одинарные кавычки по умолчанию, а стиль B двойные кавычки.
[ссылка]
Стиль A: Используйте одинарные кавычки, если вам не нужна интерполяция строк
или специальные символы вроде
\t
,\n
,'
и т.д.Стиль B: Используйте двойные кавычки в ваших строчных литералах, если они не
содержат
"
или экранируйте символы, которые не должны интерполироваться.Второй стиль, по некоторым мнениям, более распространен среди разработчиков на
Руби. Однако в этом руководстве оформление строк следует первому правилу.
Не используйте запись для литералов
алфавитных символов
?x
. Начиная с версии Руби 1.9, этот вариант записиизбыточен:
?x
будет интерпретироваться в виде'x'
(строкас единственным символом в ней).[ссылка]
Всегда применяйте фигурные скобки
{}
вокруг глобальных переменных и переменных экземпляров класса при интерполяции
строк.[ссылка]
Не используйте метод
Object#to_s
для интерполируемыхобъектов, он вызывается автоматически при интерполяции.
[ссылка]
Не применяйте метод
String#+
, когда вам нужнособрать вместе большие отрезки строк. Вместо этого используйте
String#<<
.Конкатенация изменяет экземпляр строки и всегда работает быстрее, чем
String#+
,который создает целую кучу новых строковых объектов.
[ссылка]
Избегайте метода
String#gsub
в случаях, когда можно использовать болеебыстрый и специализированный альтернативный метод.
[link]
При использовании многострочных HEREDOC не забывайте, что пробелы в начале
строк тоже являются частью создаваемой строки. Примером хорошего стиля
является применение техник, основывающихся на ограничителях, для удаления
ненужных пробелов.
[ссылка]
Регулярные выражения
Не используйте регулярные выражения, когда вам нужно просто найти в строке
подстроку:
string['text']
.[ссылка]
В простейших случаях вы просто можете использовать индексирование строк.
[ссылка]
Используйте группировку без сохранения,
если вы не планируете использовать содержание выделенной скобками группы.
[ссылка]
Откажитесь от использования наследия
Перла вроде мистических переменных, обозначающих группы совпадений (
$1
,$2
и т.д.). Вместо этого используйте
Regexp.last_match(n)
.[ссылка]
Применение пронумерованных групп
совпадений может быть сложной задачей. Вместо этого используйте поименованные
группы с говорящими именами.[ссылка]
Классы символов используют лишь небольшой
набор метасимволов, которые вам придется обрабатывать:
^
,-
,\
,]
,поэтому нет нужды экранировать
.
или скобки внутри[]
.[ссылка]
Будьте осторожны с символами
^
и$
,так как они обозначают начало/конец строки в тексте, а не строчного литерала.
Если вам надо обозначить начало и конец литерала, то используйте
\A
и\z
.Не путайте
\Z
и\z
:\Z
является эквивалентом/\n?\z/
.[ссылка]
Используйте модификатор
x
для сложных регулярныхвыражений. Он поможет вам сделать выражения удобочитаемыми и позволит добавлять
комментарии. Не забывайте при этом, что пробелы в данном случае игнорируются.
[ссылка]
В случае сложных замен либо подстановок
sub
/gsub
можно использовать с блоком или хешем параметров.
[ссылка]
Процентные литералы
Используйте
%()
(это сокращение от%Q
)для строк без переносов, в которых реализуется интерполяция и присутствуют
двойные кавычки. Для строк с переносами лучше используйте формат HERE Doc.
[ссылка]
Избегайте
%q
, если это не случай строки с символами кавычек'
и"
одновременно Обычные строки читаются проще, и их следует использовать, если
нет излишне большого количества символов, которые нужно будет экранировать.
[ссылка]
Используйте
%r
для регулярных выражений, которые обрабатывают хотя бы одинсимвол
/
, в остальных случаях используйте стандартный синтаксис.[ссылка]
Откажитесь от использования
%x
кроме случаев, когда вы хотите вызватьвнешнюю команду с обратными кавычками в теле (что само по себе маловероятно).
[ссылка]
Старайтесь избегать
%s
. По общепринятому мнению, предпочтительным способомопределения символа с пробелами в имени является
:"some string"
.[ссылка]
Используйте
()
в качестве ограничителейдля всех литералов со знаком
%
кроме%r
. Так как круглые скобки оченьчасто используются в самих регулярных выражениях, во многих случаях менее
частый символ
{
может быть лучшим выбором для ограничителя (разумеется,с учетом смысла регулярного выражения).
[ссылка]
Метапрограммирование
Откажитесь от метапрограммирования
ради метапрограммирования как такового.
[ссылка]
Не разводите беспорядок в базовых классах
при написании библиотек (не используйте "monkey patching").
[ссылка]
Используйте
#class_eval
с блоком вместоинтерполяции значений в строке. Если вы используете интерполяцию, то всегда
указывайте дополнительно
__FILE__
и__LINE__
, чтобы информация о стекевызова была осмысленной:[ссылка]
#define_method
предпочтительнее, чем#class_eval { def ... }
При использовании
#class_eval
(или других#eval
) с интерполяцией строк обязательно добавляйте комментарий, которыйбудет наглядно показывать, как интерполированные значения будут выглядеть
(примеры, используемые в исходном коде Rails):[ссылка]
Избегайте
#method_missing
для целейметапрограммирования, так как стек вызова становится нечитаемым, метод не виден
в
#methods
, опечатки в вызовах методов пройдут незамеченными, например,nukes.launch_state = false
. Используйте делегирование, проксирование или же#define_method
. Если вы используете#method_missing
:[ссылка]
обязательно задайте
#respond_to_missing?
;перехватывайте вызовы только с четко определенными префиксами, например,
#find_by_*
-- задайте в своем коде наиболее узкие рамки длянеопределенностей;
вызывайте
#super
в конце ваших выражений;делегируйте вызовы понятным, "немагическим" методам:
Разное
Пишите код, не дающий предупреждений при вызове
ruby -w
.[ссылка]Не используйте хеши в качестве
необязательных параметров. Возможно, ваш метод просто делает слишком много.
Это не касается, однако, методов инициализации объектов.
[ссылка]
Старайтесь не писать методы длиннее 10 строк. В
идеальном случае большинство методов должны быть короче 5 строк. Пустые строки
не подсчитываются.[ссылка]
Не создавайте методы с более чем тремя-четырьмя
параметрами.[ссылка]
Если вам действительно нужны глобальные
функции, включайте их в модуль Kernel и сделайте их приватными.
[ссылка]
Используйте переменные модулей вместо глобальных
переменных.[ссылка]
Используйте
OptionParser
для анализа сложныхаргументов командной строки и
ruby -s
для элементарных случаев.[ссылка]
Используйте вариант
Time.now
, а неTime.new
,когда хотите получить текущее значение системного времени.
[ссылка]
Пишите код в функциональном стиле без изменения
значений, когда это подходит по смыслу.[ссылка]
Не изменяйте значения параметров, если только это не есть цель метода.
[ссылка]
Старайтесь не создавать
вложенные структуры с уровнем вложения больше третьего.
[ссылка]
Будьте последовательны. В идеальном мире
последовательно придерживайтесь данного руководства.
[ссылка]
Руководствуйтесь здравым смыслом.
[ссылка]
Инструментарий
В этом разделе собраны инструменты, которые могут помочь вам автоматически
сверить ваш код на Руби с предписаниями этого руководства.
РубоКоп
RuboCop — это утилита проверки стиля
программного кода на Руби, который основывается на этом руководстве.
РубоКоп уже реализует большую часть этого руководства, поддерживает MRI 1.9
и MRI 2.0 и хорошо интегрируется с редактором Емакс.
RubyMine
Модуль проверки кода RubyMine
частично основывается
на этом руководстве.
Сотрудничество
Ничто, описанное в этом руководстве, не высечено в камне. И я очень хотел бы
сотрудничать со всеми, кто интересуется стилистикой оформления кода на Руби,
чтобы мы смогли вместе создать ресурс, который был бы полезен для всего
сообщества программистов на Руби.
Не стесняйтесь создавать отчеты об ошибках и присылать мне запросы на интеграцию
вашего кода. И заранее большое спасибо за вашу помощь!
Вы можете поддержать проект (и РубоКоп) денежным взносом при помощи
gittip.
Как сотрудничать в проекте?
Это просто! Следуйте руководству по
сотрудничеству.
Лицензирование
Данная работа опубликована на условиях лицензии Creative Commons Attribution
3.0 Unported License
Расскажи другому
Создаваемое сообществом руководство по стилю оформления будет малопригодным для
сообщества, которое об этом руководстве ничего не знает. Делитесь ссылками на
это руководство с вашими друзьями и коллегами доступными вам средствами. Каждый
получаемый нами комментарий, предложение или мнение сделает это руководство еще
чуточку лучше. А ведь мы хотим самое лучшее руководство из возможных, не так ли?
Всего,
Божидар