Rubocop 적용기 & 백엔드 개발 주관적 꿀팁
2018-09-19 / 발표자 : 채민균
EmptyLinesAroundClassBody:
Enabled: false
EmptyLinesAroundMethodBody:
Enabled: false
Metrics/LineLength:
Enabled: false
SpaceInsideBlockBraces:
Enabled: false
TrailingBlankLines:
Enabled: false
SpaceInsideHashLiteralBraces:
Enabled: false
EmptyLinesAroundBlockBody:
Enabled: false
ClassAndModuleChildren:
Enabled: false
NumericLiterals:
Enabled: false
BlockLength:
Enabled: false
MethodLength:
Enabled: false
Documentation:
Enabled: false
AbcSize:
Enabled: false
SymbolArray:
Enabled: false
EmptyLineAfterMagicComment:
Enabled: false
IndentHash:
Enabled: false
ClassLength:
Enabled: false
PerceivedComplexity:
Enabled: false
CyclomaticComplexity:
Enabled: false
IndentationWidth:
Enabled: false
AsciiComments:
Enabled: false
Metrics/ParameterLists:
Enabled: false
ExpandPathArguments:
Enabled: false
MultilineOperationIndentation:
Enabled: false
MultilineMethodCallIndentation:
Enabled: false
EmptyMethod:
Enabled: false
Security/Open:
Enabled: false
Style/InverseMethods:
Enabled: false
Layout/CommentIndentation:
Enabled: false
AllCops:
Excludes:
- db/schema.rb
Adison Performance Rubocop Setting
Style:
Enabled: false
Layout:
Enabled: false
Metrics/LineLength:
Enabled: false
Metrics/BlockLength:
Enabled: false
Metrics/MethodLength:
Enabled: false
Metrics/AbcSize:
Enabled: false
Metrics/ClassLength:
Enabled: false
Metrics/ModuleLength:
Enabled: false
AllCops:
Excludes:
- db/schema.rb
Recommend Rubocop Setting
Notice that you have to change file name to pre-commit
1. $ cd .git/hooks
2. $ mv pre-commit.sample pre-commit
3. add this text to pre-commit file and save
#!/bin/sh
#
# Check for ruby style errors
red='\033[0;31m'
green='\033[0;32m'
yellow='\033[0;33m'
NC='\033[0m'
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object
# Change it to match your initial commit sha
against=123acdac4c698f24f2352cf34c3b12e246b48af1
fi
# Check if rubocop is installed for the current project
bin/bundle exec rubocop -v >/dev/null 2>&1 || { echo >&2 "${red}[Ruby Style][Fatal]: Add rubocop to your Gemfile"; exit 1; }
# Get only the staged files
FILES="$(git diff --cached --name-only --diff-filter=AMC | grep "\.rb$" | tr '\n' ' ')"
echo "${green}[Ruby Style][Info]: Checking Ruby Style${NC}"
if [ -n "$FILES" ]
then
echo "${green}[Ruby Style][Info]: ${FILES}${NC}"
if [ ! -f '.rubocop.yml' ]; then
echo "${yellow}[Ruby Style][Warning]: No .rubocop.yml config file.${NC}"
fi
# Run rubocop on the staged files
bin/bundle exec rubocop ${FILES}
if [ $? -ne 0 ]; then
echo "${red}[Ruby Style][Error]: Fix the issues and commit again${NC}"
exit 1
fi
else
echo "${green}[Ruby Style][Info]: No files to check${NC}"
fi
exit 0How to Set Rubocop Git Pre-Commit Hook
#1 before
if event_type.include?(INSTALL)
type = INSTALL
elsif event_type.include?(OPEN)
type = OPEN
elsif event_type.include?(PREREGISTRATION)
type = PREREGISTRATION
else
type = EVENT
endApplied Rubocop Examples
#1 after
type = if event_type.include?(INSTALL)
INSTALL
elsif event_type.include?(OPEN)
OPEN
elsif event_type.include?(PREREGISTRATION)
PREREGISTRATION
else
EVENT
endApplied Rubocop Examples
#2 before
def delete_whitespace(foo)
foo.gsub(' ', '')
end
Applied Rubocop Examples
#2 after
def delete_whitespace(foo)
foo.delete(' ')
endApplied Rubocop Examples
#2 performance test
def go
s = Time.now.to_f
10000.times do
qwe = '405 402 401 350 392 4178 3841 473 1274y1 17405 120412 421830'
qwe.gsub!(' ', '')
end
f = Time.now.to_f
f - s
end
def to
s = Time.now.to_f
10000.times do
qwe = '405 402 401 350 392 4178 3841 473 1274y1 17405 120412 421830'
qwe.delete!(' ')
end
f = Time.now.to_f
f - s
end
a = 0
b = 0
100.times do
a += go
b += to
end
# a = 2.8520665168762207
# b = 0.8430917263031006
# It's almost 3.4 times fast!!!Applied Rubocop Examples
#3 before
if string_value == 'a' ||
string_value == 'b' ||
string_value == 'c' ||
string_value == 'd'
# do something
endApplied Rubocop Examples
#4 after
if %w[a b c d].include?(string_value)
# do something
endApplied Rubocop Examples
#4 performance test
def go
s = Time.now.to_f
array = %w[a w e f k o d a x d f q w e r t y u u z x d 1 3 5 6 d c b d s a s 2 4 6 2 3 4 6 7 7 1 z v d q]
count = 0
array.each {|element| count += 1 if element == 'a' || element == 'x' || element == 'd'}
f = Time.now.to_f
f - s
end
def to
s = Time.now.to_f
array = %w[a w e f k o d a x d f q w e r t y u u z x d 1 3 5 6 d c b d s a s 2 4 6 2 3 4 6 7 7 1 z v d q]
count = 0
candidates = %w[a x d]
array.each {|element| count += 1 if candidates.include?(element)}
f = Time.now.to_f
f - s
end
a = 0
b = 0
100000.times do
a += go
b += to
end
#a = 1.6121020317077637
#b = 1.032500982284546
#It's almost 1.6 times fast!!!Applied Rubocop Examples
#5 Do not use these function prefix with this case
1.get_ with no parameter
def get_element
end
def element
end
2.set_ with one parameter
def set_element(foo)
end
def element=(foo)
end
3.is_ has_
def is_unique
end
def unique?
end
Applied Rubocop Examples
#5 Do not use case
link : http://midwire.github.io/blog/2011/08/26/ruby-performance-case-vs-if-elsif/Applied Rubocop Examples
고찰에서 나온 주관적 꿀팁
- 왜 legacy 가 생기는 걸까?
- 왜 예상치 못한 bug 가 발생하는 걸까?
How to Reduce Legacy
1. 안쓰는 기능이 생기면 관련코드는 적어도 주석처리하거나 삭제할 것.
2. 초반 설계를 잘할 것.(어렵...ㅠ)
How to Reduce Bug
1. 컨트롤러는 최대한 가벼울 것. (요약문 짜듯이!)
컨트롤러가 무거우면 반드시 스파게티 코드가 생기기마련
rubocop 설정만 해주면 Metrics cop 이 알아서 잡아줄 것이다.
2. Active Record에는 해당 테이블에'만' 종속적인 함수'만' 짠다!
A.rb 에서 다른 모델을 불러오는 코드가 있다면 다른 모델이나 다른 계층으로 불리할 것.
여러 모델에서 같이 사용하는 함수가 있다면 이 또한 다른 모델이나 다른 계층으로 불리할 것.
3. 함수는 그 자체로 온전할 것.
모든 파라미터 값들에 대해 예외처리를 해줘야 나중에 해당 함수를 사용하는 다른 사람들로 부터 버그를 피할 수 있다. 특히 nil case.
4. 특정 케이스가 아니라면 여러 서버의 코드에 싱크를 맞춰놓을 것.
apply rubocop
By mingyun chae
apply rubocop
루비온레일즈에서 rubocop 을 적용했던 내용을 공유합니다.
- 506