Почему код должен
быть стильным?
Владимир Дементьев, 19.03.2015
План
— Что такое Style Guide?
— Зачем и почему?
— Как?
2
Style Guide
Стилистический справочник или руководство по стилю —
справочное издание с набором стандартов и обязательных для
соблюдения требований при написании и оформлении статей в
конкретном издании или при составлении документов в той или
иной организации.
3
Rails Style Guide
http://github.com/bbatsov/rails-style-guide
4
RSpec
http://betterspecs.org/
5
Зачем все это?
6
1. Разработчикам легче понимать друг друга,
когда они говорят на одном языке.
7
1. Разработчикам легче понимать друг друга,
когда они говорят на одном языке.
def some_kinda_fun a, even = false
x = if even then a+1 else a end
{:x => a, :y => x}
end
def some_kinda_fun(a, even: false)
x = flag ? a+1 : a
{x: a, y: x}
end
8
1. Разработчикам легче понимать друг друга,
когда они говорят на одном языке.
unless user.active? || address.confirmed?
...
end
If !user.blank?
…
end
9
1. Разработчикам легче понимать друг друга,
когда они говорят на одном языке.
2. История изменений содержит только
изменения в логике, а не в форматировании.
10
1. Разработчикам легче понимать друг друга,
когда они говорят на одном языке.
2. История изменений содержит только
изменения в логике, а не в форматировании.
3. Новым членам команды проще влиться в
процесс разработки.
11
1. Разработчикам легче понимать друг друга,
когда они говорят на одном языке.
2. История изменений содержит только
изменения в логике, а не в форматировании.
3. Новым членам команды проще влиться в
процесс разработки.
4. Предупреждаем появление глупых ошибок.
12
4. Предупреждаем появление глупых ошибок.
user = User.new
user.name = "John"
user.save
redirect_to user
13
4. Предупреждаем появление глупых ошибок.
user = User.new
user.name = "John”
user.save!
puts user.id
redirect_to user
14
4. Предупреждаем появление глупых ошибок.
# плохо
Client.where(“orders_count = #{params[:count]}”)
# хорошо
Client.where(“orders_count = ?”, params[:count])
15
4. Предупреждаем появление глупых ошибок.
# плохо
Client.where(“status != ?”, params[:status])
# хорошо
Client.where.not(status: params[:status])
16
4. Предупреждаем появление глупых ошибок.
# плохо
Time.now
# хорошо
Time.zone.now
17
1. Разработчикам легче понимать друг друга,
когда они говорят на одном языке.
2. История изменений содержит только
изменения в логике, а не в форматировании.
3. Новым членам команды проще влиться в
процесс разработки.
4. Предупреждаем появление глупых ошибок.
5. Пишем более быстрый код.
18
5. Пишем более быстрый код.
# плохо
If User.where(status: 1).length > 0
# хорошо
User. where(status: 1).exists?
19
5. Пишем более быстрый код.
# плохо
my_arr.reverse.each { ... }
my_arr.select { … }.first
# хорошо
my_arr.reverse_each { … }
my_arr.detect { … }
20
Кто нас спасёт?
21
Кто нас спасёт?
22
Rubocop: Cops
— Style – стиль кода (форматирование)
Style/UnlessElse – не используй unless с else
Style/TrailingWhitespace – избегай пробелов в
конце строки
Style/StringLiterals – использование ковычек
(двойные или одинарные?)
23
Rubocop: Cops
— Lint – синтаксис и плохие практики
Lint/DuplicateMethods – проверяет на наличие
повторяющихся методов
Lint/RequireParentheses – не забывай про
скобки в сложных условиях
(if day.is? 'monday' && month == :jan)
Lint/Debugger – не забудь удалить binding.pry
24
Rubocop: Cops
— Metrics – различные метрики кода
Metrics/LineLength – следит за длиной строки
Metrics/BlockNesting – следит за глубиной
ветвления
Metrics/MethodLength – следит за числом строк
в методе
25
Rubocop: Cops
— Rails – специфические проверки для RoR
Rails/HasAndBelongsToMany – предостерегает
от использования HABTM в пользу has_many:
:through
Rails/Validation – ругается на использование
old school валидаций (validate_presence_of, etc)
Rails/TimeZone – ругается на использование
временных функций без временной зоны
26
Rubocop: Cops
— Performance – как сделать код быстрее
Performance/Detect – используй detect вместо
select.first
Performance/ReverseEach – используй
reverse_each вместо reverse.each
Продолжение следует…
27
Rubocop: Custom Cops
— RSpec (https://github.com/nevir/rubocop-rspec)
RSpec/MultipleDescribes – должен быть только
один describe верхнего уровня в файле
RSpec/InstanceVariable – используй let(:user) {…}
вместо before { @user = … }
28
Rubocop: Начало работы
gem install rubocop # установили
rubocop # запустили
rubocop –l # только Lint копы
rubocop –a # автоматическое исправление
29
Rubocop: Конфигурация
~/.rubocop.yml
или
project_dir/rubocop.yml
или
rubocop –c my_config.yml
30
Rubocop: Pre-commit hook
http://gist.github.com/palkan/d3ea6692569a218a8743
ln –s rubocop_pre_commit.rb .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
31
Кто нас спасёт?
Hound – делает для вас стилистический Code Review
32
Hound CI
– Ruby (Rubocop)
33
Hound CI
– Ruby (Rubocop)
– JavaScript (JSHint)
34
Hound CI
– Ruby (Rubocop)
– JavaScript (JSHint)
– CoffeeScript (CoffeeLint)
35
Hound CI
– Ruby (Rubocop)
– JavaScript (JSHint)
– CoffeeScript (CoffeeLint)
– SCSS (SCSS-Lint)
36
Кто нас спасёт?
37
Вопросы

Why does code style matter?

  • 1.
    Почему код должен бытьстильным? Владимир Дементьев, 19.03.2015
  • 2.
    План — Что такоеStyle Guide? — Зачем и почему? — Как? 2
  • 3.
    Style Guide Стилистический справочникили руководство по стилю — справочное издание с набором стандартов и обязательных для соблюдения требований при написании и оформлении статей в конкретном издании или при составлении документов в той или иной организации. 3
  • 4.
  • 5.
  • 6.
  • 7.
    1. Разработчикам легчепонимать друг друга, когда они говорят на одном языке. 7
  • 8.
    1. Разработчикам легчепонимать друг друга, когда они говорят на одном языке. def some_kinda_fun a, even = false x = if even then a+1 else a end {:x => a, :y => x} end def some_kinda_fun(a, even: false) x = flag ? a+1 : a {x: a, y: x} end 8
  • 9.
    1. Разработчикам легчепонимать друг друга, когда они говорят на одном языке. unless user.active? || address.confirmed? ... end If !user.blank? … end 9
  • 10.
    1. Разработчикам легчепонимать друг друга, когда они говорят на одном языке. 2. История изменений содержит только изменения в логике, а не в форматировании. 10
  • 11.
    1. Разработчикам легчепонимать друг друга, когда они говорят на одном языке. 2. История изменений содержит только изменения в логике, а не в форматировании. 3. Новым членам команды проще влиться в процесс разработки. 11
  • 12.
    1. Разработчикам легчепонимать друг друга, когда они говорят на одном языке. 2. История изменений содержит только изменения в логике, а не в форматировании. 3. Новым членам команды проще влиться в процесс разработки. 4. Предупреждаем появление глупых ошибок. 12
  • 13.
    4. Предупреждаем появлениеглупых ошибок. user = User.new user.name = "John" user.save redirect_to user 13
  • 14.
    4. Предупреждаем появлениеглупых ошибок. user = User.new user.name = "John” user.save! puts user.id redirect_to user 14
  • 15.
    4. Предупреждаем появлениеглупых ошибок. # плохо Client.where(“orders_count = #{params[:count]}”) # хорошо Client.where(“orders_count = ?”, params[:count]) 15
  • 16.
    4. Предупреждаем появлениеглупых ошибок. # плохо Client.where(“status != ?”, params[:status]) # хорошо Client.where.not(status: params[:status]) 16
  • 17.
    4. Предупреждаем появлениеглупых ошибок. # плохо Time.now # хорошо Time.zone.now 17
  • 18.
    1. Разработчикам легчепонимать друг друга, когда они говорят на одном языке. 2. История изменений содержит только изменения в логике, а не в форматировании. 3. Новым членам команды проще влиться в процесс разработки. 4. Предупреждаем появление глупых ошибок. 5. Пишем более быстрый код. 18
  • 19.
    5. Пишем болеебыстрый код. # плохо If User.where(status: 1).length > 0 # хорошо User. where(status: 1).exists? 19
  • 20.
    5. Пишем болеебыстрый код. # плохо my_arr.reverse.each { ... } my_arr.select { … }.first # хорошо my_arr.reverse_each { … } my_arr.detect { … } 20
  • 21.
  • 22.
  • 23.
    Rubocop: Cops — Style– стиль кода (форматирование) Style/UnlessElse – не используй unless с else Style/TrailingWhitespace – избегай пробелов в конце строки Style/StringLiterals – использование ковычек (двойные или одинарные?) 23
  • 24.
    Rubocop: Cops — Lint– синтаксис и плохие практики Lint/DuplicateMethods – проверяет на наличие повторяющихся методов Lint/RequireParentheses – не забывай про скобки в сложных условиях (if day.is? 'monday' && month == :jan) Lint/Debugger – не забудь удалить binding.pry 24
  • 25.
    Rubocop: Cops — Metrics– различные метрики кода Metrics/LineLength – следит за длиной строки Metrics/BlockNesting – следит за глубиной ветвления Metrics/MethodLength – следит за числом строк в методе 25
  • 26.
    Rubocop: Cops — Rails– специфические проверки для RoR Rails/HasAndBelongsToMany – предостерегает от использования HABTM в пользу has_many: :through Rails/Validation – ругается на использование old school валидаций (validate_presence_of, etc) Rails/TimeZone – ругается на использование временных функций без временной зоны 26
  • 27.
    Rubocop: Cops — Performance– как сделать код быстрее Performance/Detect – используй detect вместо select.first Performance/ReverseEach – используй reverse_each вместо reverse.each Продолжение следует… 27
  • 28.
    Rubocop: Custom Cops —RSpec (https://github.com/nevir/rubocop-rspec) RSpec/MultipleDescribes – должен быть только один describe верхнего уровня в файле RSpec/InstanceVariable – используй let(:user) {…} вместо before { @user = … } 28
  • 29.
    Rubocop: Начало работы geminstall rubocop # установили rubocop # запустили rubocop –l # только Lint копы rubocop –a # автоматическое исправление 29
  • 30.
  • 31.
    Rubocop: Pre-commit hook http://gist.github.com/palkan/d3ea6692569a218a8743 ln–s rubocop_pre_commit.rb .git/hooks/pre-commit chmod +x .git/hooks/pre-commit 31
  • 32.
    Кто нас спасёт? Hound– делает для вас стилистический Code Review 32
  • 33.
    Hound CI – Ruby(Rubocop) 33
  • 34.
    Hound CI – Ruby(Rubocop) – JavaScript (JSHint) 34
  • 35.
    Hound CI – Ruby(Rubocop) – JavaScript (JSHint) – CoffeeScript (CoffeeLint) 35
  • 36.
    Hound CI – Ruby(Rubocop) – JavaScript (JSHint) – CoffeeScript (CoffeeLint) – SCSS (SCSS-Lint) 36
  • 37.
  • 38.