├── .gitattributes ├── CONTRIBUTING.md ├── README-koKR.md └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | *.md whitespace=trailing-space,tab-in-indent 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | * [Fork](https://help.github.com/articles/fork-a-repo) the project on GitHub. 2 | * Make your feature addition or bug fix in a feature branch. (Include a description of your changes) 3 | * Push your feature branch to GitHub. 4 | * Send a [Pull Request](https://help.github.com/articles/using-pull-requests). -------------------------------------------------------------------------------- /README-koKR.md: -------------------------------------------------------------------------------- 1 | # 서론 2 | 3 | > 롤 모델이 중요하다.
4 | > -- Officer Alex J. Murphy / RoboCop 5 | 6 | 나는 루비 개발자로서 항상 한 가지 문제로 괴로웠다. — 파이썬 개발자들은 7 | 훌륭한 프로그래밍 스타일 가이드([PEP-8][])를 가지고 있는데, 우리에겐 코딩 8 | 스타일과 모범 사례를 가진 공식적인 가이드가 전혀 없다는 것이다. 그리고 나는 9 | 그것이야말로 문제라고 확신한다. 또한 루비의 훌륭한 해커 커뮤니티는 모두가 탐낼 10 | 만한 문서를 만들어낼 능력이 있다고 확신한다. 11 | 12 | 이 가이드는 사내 루비 코딩 가이드 라인으로 시작됐다. 13 | 그러나 몇몇 포인트에서 내가 작성한 가이드가 일반 루비 커뮤니티에도 도움이 되게끔 14 | 써서 이와 같은 중복 작업이 더는 없기를 바라며 작업하기로 했다. 그러나 루비 15 | 커뮤니티에 의해 자체적으로 수립된 예제, 숙어, 스타일에 관한 프로그래밍 방식 16 | 역시 많은 관련자에게 도움이 될 것이다. 17 | 18 | 가이드를 작성하기 시작한 때부터 본인은 여러 유수의 루비 커뮤니티로부터 소중한 19 | 피드백을 받았다. 여러 분들의 그러한 협력과 노고에 다시 한 번 감사의 말씀을 20 | 올린다. 많은 분들의 도움이 있었기에 가이드를 작성할 수 있었고, 그러한 상호작용을 21 | 통해 여타의 모든 루비 개발 관계자들에게 도움될 수 있으리라 본다. 22 | 23 | 한 가지 더, 레일즈에 관심 있는 사람이라면, 추가적으로 필요한 부분은 [루비 온 24 | 레일스 스타일 가이드][rails-style-guide]를 참고하면 된다. 25 | 26 | # 루비 스타일 가이드 27 | 28 | 이 루비 스타일 가이드는 다른 루비 개발자와 유지가능한 코드를 작성하는 모범사례를 29 | 적용하는 것을 추천한다. 현실을 반영한 스타일 가이드는 사람들이 사용하지만, 30 | 사람들이 거부하는 이상을 추구하는 스타일 가이드는 아무도 사용하지 않게 될 수 31 | 있다. — 그게 아무리 좋다고 해도 말이다. 32 | 33 | 이 가이드는 관련된 규칙에 따라 여러 부분으로 나뉘어 있다.(자명하다고 판단된 34 | 것을 제외하고는)규칙을 적으며 근거를 덧붙이려 노력했다. 35 | 36 | 이 모든 규칙들이 갑자기 제시되지는 않았다. 이것들 대부분이 내 전문분야인 37 | 소프트웨어 엔지니어로서의 수많은 경험, 루비 커뮤니티원의 제안, 또한 높은 평가를 38 | 받고 있는 프로그래밍 리소스인 ["Programming Ruby"][pickaxe]와 39 | ["The Ruby Programming Language"][trpl]를 기반으로 하였다. 40 | 41 | 특정 스타일에 대해서 루비 커뮤니티의 명백한 합의를 얻지 못한 부분도 있다.(문자열 42 | 구문 따옴표, 해시문 내에서의 공백, 여러 줄에 걸친 메소드 체인에서의 점(.)위치 43 | 등) 이러한 시나리오에서는 모든 유명한 스타일들이 허용되므로, 어떤 것을 44 | 사용할지는 당신이 선택하고 적용하기 나름이다. 45 | 46 | 이 가이드 라인은 시간에 따라 발전한다. 새로운 규칙이 확인되고, 오래된 규칙은 47 | 루비가 변함에 따라 쓸모없어진다. 48 | 49 | 많은 프로젝트가 (대개 여기서 유래된) 그들만의 코딩 스타일 가이드 라인을 가진다. 50 | 상충하는 부분이 있을 경우, 그 프로젝트에선 프로젝트의 가이드 라인을 우선하라. 51 | 52 | 이 가이드는 [Pandoc][]를 통해 PDF나 HTML로 복사해갈 수 있다. 53 | 54 | [RuboCop][]은 이 스타일 가이드에 기반한 코드 분석기다. 55 | 56 | 이 가이드의 번역은 다음의 언어들로 되어있다. 57 | 58 | * [Chinese Simplified](https://github.com/JuanitoFatas/ruby-style-guide/blob/master/README-zhCN.md) 59 | * [Chinese Traditional](https://github.com/JuanitoFatas/ruby-style-guide/blob/master/README-zhTW.md) 60 | * [French](https://github.com/gauthier-delacroix/ruby-style-guide/blob/master/README-frFR.md) 61 | * [German](https://github.com/arbox/de-ruby-style-guide/blob/master/README-deDE.md) 62 | * [Japanese](https://github.com/fortissimo1997/ruby-style-guide/blob/japanese/README.ja.md) 63 | * [한국어](https://github.com/dalzony/ruby-style-guide/blob/master/README-koKR.md) 64 | * [Portuguese (pt-BR)](https://github.com/rubensmabueno/ruby-style-guide/blob/master/README-PT-BR.md) 65 | * [Russian](https://github.com/arbox/ruby-style-guide/blob/master/README-ruRU.md) 66 | * [Spanish](https://github.com/alemohamad/ruby-style-guide/blob/master/README-esLA.md) 67 | * [Vietnamese](https://github.com/CQBinh/ruby-style-guide/blob/master/README-viVN.md) 68 | 69 | ## Table of Contents 70 | 71 | * [소스 코드 레이아웃](#소스-코드-레이아웃) 72 | * [구문](#구문) 73 | * [네이밍](#네이밍) 74 | * [주석](#주석) 75 | * [주석 어노테이션](#주석-어노테이션) 76 | * [클래스와 모듈](#클래스와-모듈) 77 | * [예외](#예외) 78 | * [컬렉션](#컬렉션) 79 | * [숫자](#숫자) 80 | * [문자열](#문자열) 81 | * [날짜 및 시간](#날짜-및-시간) 82 | * [정규식](#정규식) 83 | * [퍼센트 리터럴](#퍼센트-리터럴) 84 | * [메타프로그래밍](#메타프로그래밍) 85 | * [그 밖에](#그 밖에) 86 | * [도구들](#도구들) 87 | 88 | ## 소스 코드 레이아웃 89 | 90 | > 거의 모든 사람들이 자신의 것을 제외한 모든 코딩 스타일이 번잡하고 가독성이 91 | > 떨어진다고 확신한다. 앞 문장에서 "자신의 것을 제외한"을 없앤다면 아마도 맞는 92 | > 말일지도...
93 | > -- Jerry Coffin (on indentation) 94 | 95 | * 96 | 소스 파일의 인코딩은 `UTF-8`을 사용하라. 97 | [[link](#utf-8)] 98 | 99 | * 100 | 탭은 들여쓰기 단위별로 **공백 2칸**을 사용하라.(소프트 탭 사용) 하드 탭 101 | 사용 안 함 102 | [[link](#spaces-indentation)] 103 | 104 | ```Ruby 105 | # 나쁜 예 - 공백 4칸 106 | def some_method 107 | do_something 108 | end 109 | 110 | # 좋은 예 111 | def some_method 112 | do_something 113 | end 114 | ``` 115 | 116 | * 117 | Unix 스타일로 줄바꿈 하라.(\*BSD/Solaris/Linux/OS X 사용자들은 기본으로 118 | 설정되어 있다. Windows 사용자에겐 특히 주의가 필요하다.) 119 | [[link](#crlf)] 120 | 121 | * 만약 Git을 사용하고 있으면, 다음 설정을 추가함으로써 프로젝트가 Windows 122 | 줄바꿈 형식으로 강제 설정되는 것을 막을 수 있을 것이다. 123 | 124 | ```bash 125 | $ git config --global core.autocrlf true 126 | ``` 127 | * 128 | 두 개 이상의 명령문과 표현식을 세미콜론(;)으로 나눠쓰지 말아라. 한 줄에 한 129 | 개씩 쓰는 것을 권장한다. 130 | [[link](#no-semicolon)] 131 | 132 | ```Ruby 133 | # 나쁜 예 134 | puts 'foobar'; # 불필요한 세미콜론 135 | 136 | puts 'foo'; puts 'bar' # 같은 줄에 표현식이 2개 137 | 138 | # 좋은 예 139 | puts 'foobar' 140 | 141 | puts 'foo' 142 | puts 'bar' 143 | 144 | puts 'foo', 'bar' # 이 경우는 puts가 두 변수 다 적용됨. 145 | ``` 146 | 147 | * 148 | 본문이 없는 클래스는 한 줄 형식이 권장된다. 149 | [[link](#single-line-classes)] 150 | 151 | ```Ruby 152 | # 나쁜 예 153 | class FooError < StandardError 154 | end 155 | 156 | # 나쁘지 않은 예 157 | class FooError < StandardError; end 158 | 159 | # 좋은 예 160 | FooError = Class.new(StandardError) 161 | ``` 162 | 163 | * 164 | 한 줄짜리 메소드를 작성하지 마라. 그런 방식이 비록 현장에서 많이 쓰이긴 하지만, 165 | 그러한 syntax 사용법이 익숙지 않아 좋아하지 않는 경우도 있기 때문이다. 어쨌든 166 | 한 줄에는 하나 이상의 메소드가 표현되어선 안 된다. 167 | [[link](#no-single-line-methods)] 168 | 169 | ```Ruby 170 | # 나쁜 예 171 | def too_much; something; something_else; end 172 | 173 | # 나쁘지 않은 예 - 처음의 ;(세미콜론)은 필요 174 | def no_braces_method; body end 175 | 176 | # 나쁘지 않은 예 - 두 번째의 ;는 선택사항 177 | def no_braces_method; body; end 178 | 179 | # 나쁘지 않은 예 - 문법은 맞지만, ;이 없으면 가독성이 떨어짐 180 | def some_method() body end 181 | 182 | # 좋은 예 183 | def some_method 184 | body 185 | end 186 | ``` 187 | 188 | 본문이 비어있는 메소드는 이 규칙에서 예외다. 189 | 190 | ```Ruby 191 | # 좋은 예 192 | def no_op; end 193 | ``` 194 | 195 | * 196 | 연산자 전후, 콤마 뒤, 콜론과 세미콜론 뒤에 공백(space)을 써라. 197 | 공백은 루비 인터프리터에는 (대부분의 경우) 중요하지 않지만 적절하게 사용하면 198 | 읽기 쉬운 코드를 작성할 수 있다. 199 | [[link](#spaces-operators)] 200 | 201 | ```Ruby 202 | sum = 1 + 2 203 | a, b = 1, 2 204 | class FooError < StandardError; end 205 | ``` 206 | 207 | 유일한 예외는 지수 연산자다. 208 | 209 | ```Ruby 210 | # 나쁜 예 211 | e = M * c ** 2 212 | 213 | # 좋은 예 214 | e = M * c**2 215 | ``` 216 | 217 | * 218 | `(`, `[`의 뒤, `]`, `)`의 앞에 공백을 쓰지 마라. 219 | `{`의 주변과 `}`의 앞에 공백을 써라. 220 | [[link](#spaces-braces)] 221 | 222 | ```Ruby 223 | # 나쁜 예 224 | some( arg ).other 225 | [ 1, 2, 3 ].each{|e| puts e} 226 | 227 | # 좋은 예 228 | some(arg).other 229 | [1, 2, 3].each { |e| puts e } 230 | ``` 231 | 232 | `{`, `}` 전후의 공백은 구문을 명확하게 하기 위해 쓸 만한데, 그 이유는 233 | 문자열 보간법(string interpolation)을 사용할 때뿐만 아니라 블록이나 234 | 해시문에 사용될 수 있기 때문이다. 235 | 236 | 해시문에서는 다음 두 가지 스타일이 허용된다. 237 | 첫 번째 방법이 조금 더 읽기 좋다.(그리고 루비 커뮤니티에서 확실히 더 인기가 238 | 있다.) 두 번째 방법은 블록과 해시를 시각적으로 구별화 수 있는 장점이 있다. 239 | 무엇이든 하나를 선택하면, 일관적으로 적용하자. 240 | 241 | ```Ruby 242 | # 좋은 예 - {뒤와 }앞에 공백 243 | { one: 1, two: 2 } 244 | 245 | # 좋은 예 - {뒤 와 }앞에 공백 없이 246 | {one: 1, two: 2} 247 | ``` 248 | 249 | 보간 표현식에서는 괄호 안에 패딩 공백이 없어야 한다. 250 | 251 | ```Ruby 252 | # 나쁜 예 253 | "From: #{ user.first_name }, #{ user.last_name }" 254 | 255 | # 좋은 예 256 | "From: #{user.first_name}, #{user.last_name}" 257 | ``` 258 | 259 | * 260 | `!` 뒤에 공백을 넣지 않는다. 261 | [[link](#no-space-bang)] 262 | 263 | ```Ruby 264 | # 나쁜 예 265 | ! something 266 | 267 | # 좋은 예 268 | !something 269 | ``` 270 | 271 | * 272 | 레인지문에는 공백을 넣지 않는다. 273 | [[link](#no-space-inside-range-literals)] 274 | 275 | ```Ruby 276 | # 나쁜 예 277 | 1 .. 3 278 | 'a' ... 'z' 279 | 280 | # 좋은 예 281 | 1..3 282 | 'a'...'z' 283 | ``` 284 | 285 | * 286 | `when`은 `case`와 같은 깊이로 들여 쓰자. 287 | "The RubyProgramming Language"와 "Programming Ruby"에서 사용하는 288 | 스타일이다. 289 | [[link](#indent-when-to-case)] 290 | 291 | ```Ruby 292 | # 나쁜 예 293 | case 294 | when song.name == 'Misty' 295 | puts 'Not again!' 296 | when song.duration > 120 297 | puts 'Too long!' 298 | when Time.now.hour > 21 299 | puts "It's too late" 300 | else 301 | song.play 302 | end 303 | 304 | # 좋은 예 305 | case 306 | when song.name == 'Misty' 307 | puts 'Not again!' 308 | when song.duration > 120 309 | puts 'Too long!' 310 | when Time.now.hour > 21 311 | puts "It's too late" 312 | else 313 | song.play 314 | end 315 | ``` 316 | 317 | * 318 | 조건식의 결과를 변수에 대입하는 경우, 그 가지(case)의 일반적인 정렬을 유지하라. 319 | [[link](#indent-conditional-assignment)] 320 | 321 | ```Ruby 322 | # 나쁜 예 - 상당히 복잡함 323 | kind = case year 324 | when 1850..1889 then 'Blues' 325 | when 1890..1909 then 'Ragtime' 326 | when 1910..1929 then 'New Orleans Jazz' 327 | when 1930..1939 then 'Swing' 328 | when 1940..1950 then 'Bebop' 329 | else 'Jazz' 330 | end 331 | 332 | result = if some_cond 333 | calc_something 334 | else 335 | calc_something_else 336 | end 337 | 338 | # 좋은 예 - 어떻게 돌아가는지 분명함 339 | kind = case year 340 | when 1850..1889 then 'Blues' 341 | when 1890..1909 then 'Ragtime' 342 | when 1910..1929 then 'New Orleans Jazz' 343 | when 1930..1939 then 'Swing' 344 | when 1940..1950 then 'Bebop' 345 | else 'Jazz' 346 | end 347 | 348 | result = if some_cond 349 | calc_something 350 | else 351 | calc_something_else 352 | end 353 | 354 | # 좋은 예(가로 폭의 효율이 약간 더 좋음) 355 | kind = 356 | case year 357 | when 1850..1889 then 'Blues' 358 | when 1890..1909 then 'Ragtime' 359 | when 1910..1929 then 'New Orleans Jazz' 360 | when 1930..1939 then 'Swing' 361 | when 1940..1950 then 'Bebop' 362 | else 'Jazz' 363 | end 364 | 365 | result = 366 | if some_cond 367 | calc_something 368 | else 369 | calc_something_else 370 | end 371 | ``` 372 | 373 | * 374 | 메소드 정의와, 단락이 논리적으로 구분될 때마다 사이에 빈줄을 넣어 분할하자. 375 | [[link](#empty-lines-between-methods)] 376 | 377 | ```Ruby 378 | def some_method 379 | data = initialize(options) 380 | 381 | data.manipulate! 382 | 383 | data.result 384 | end 385 | 386 | def some_method 387 | result 388 | end 389 | ``` 390 | 391 | * 392 | 메소드 호출의 마지막 인수 뒤에 쉼표를 피한다. 인수가 여러 줄로 나누어져 있지 393 | 않을 때는 특히 피한다. 394 | [[link](#no-trailing-params-comma)] 395 | 396 | ```Ruby 397 | # 나쁜 예 - 쉽게 인수를 이동/추가/삭제할 수 있지만 여전히 권장하진 않는다. 398 | some_method( 399 | size, 400 | count, 401 | color, 402 | ) 403 | 404 | # 나쁜 예 405 | some_method(size, count, color, ) 406 | 407 | # 좋은 예 408 | some_method(size, count, color) 409 | ``` 410 | 411 | * 412 | 메소드의 인수에 기본 값을 대입할 때에는, `=` 연산자 주변에 공백을 넣어라. 413 | [[link](#spaces-around-equals)] 414 | 415 | ```Ruby 416 | # 나쁜 예 417 | def some_method(arg1=:default, arg2=nil, arg3=[]) 418 | # do something... 419 | end 420 | 421 | # 좋은 예 422 | def some_method(arg1 = :default, arg2 = nil, arg3 = []) 423 | # do something... 424 | end 425 | ``` 426 | 427 | 여러 루비 책들이 첫 번째 스타일을 권장하지만, 실제로는 두 번째 스타일이 좀 더 428 | 눈에 잘 띈다.(그리고 분명히 읽기 더 쉽다.) 429 | 430 | * 431 | 불필요하게 `\`로 줄을 바꾸는 것을 피하라. 실제로 프로그래밍할 때 긴 문자열을 432 | 자르는 경우 말고는 줄을 임의로 바꾸지 마라. 433 | [[link](#no-trailing-backslash)] 434 | 435 | ```Ruby 436 | # 나쁜 예 437 | result = 1 - \ 438 | 2 439 | 440 | # 좋은 예(하지만 여전히 못생겼다.) 441 | result = 1 \ 442 | - 2 443 | 444 | long_string = 'First part of the long string' \ 445 | ' and second part of the long string' 446 | ``` 447 | 448 | * 449 | 메소드 연쇄가 여러 줄에 걸쳐서 이루어질 때, 일관된 스타일을 적용하라. 450 | 루비에서 여러 줄에 걸친 메소드 연쇄 표현 스타일은 크게 두 가지가 있는데, 451 | 둘 모두 괜찮은 방식이다. `.`의 위치에 따라 선두법(leading, A방식)과 452 | 후방법(trailing, B방식)이 있다. 453 | [[link](#consistent-multi-line-chains)] 454 | 455 | * **(A방식)** 연쇄적인 메소드 호출이 서로 다른 줄에 걸쳐 연결되어 있을 때, 456 | 두 번째 라인에 `.`을 두라. 457 | 458 | ```Ruby 459 | # 나쁜 예 - 두 번째 줄을 이해하기 위해서 첫 번째 라인을 찾아야 함 460 | one.two.three. 461 | four 462 | 463 | # 좋은 예 - 두 번째 줄에서 어떤일이 일어나는지 즉시 알 수 있음 464 | one.two.three 465 | .four 466 | ``` 467 | 468 | * **(B방식)** 연쇄적인 메소드 호출이 서로 다른 줄에 걸쳐 연결되어 있을 때, 469 | 이를 명확히 하기 위해 첫 번째 줄에 `.`을 포함시켜라. 470 | 471 | ```Ruby 472 | # 나쁜 예 - 메소드 연쇄가 이어지는지 알기 위해서 다음 줄을 읽을 필요가 있음 473 | one.two.three 474 | .four 475 | 476 | # 좋은 예 - 메소드 연쇄가 다음줄에서 이어지는지 한눈에 알 수 있음 477 | one.two.three. 478 | four 479 | ``` 480 | 481 | 양 쪽 스타일의 장점에 대한 논의는 482 | [여기](https://github.com/bbatsov/ruby-style-guide/pull/176)에서 볼 수 있다. 483 | 484 | * 485 | 메소드 호출이 여러 줄에 걸쳐 일어날 경우 인수들을 적절히 정렬하라. 486 | 라인 길이 제한으로 인수들을 정렬하기 어려울 때에는 두 번째 인수부터 한 칸 487 | 들여쓰기를(single indent) 하되, 이 때 첫 번째 인수가 들여쓰기 이전에 줄바꿈이 488 | 없었는지 확인해야 된다.(아래 세 번째 예에서 to:'bob@example.com' (첫 번째 489 | 인수)의 줄이 넘어가면 네 번째 예처럼 작성하면 된다.) 490 | [[link](#no-double-indent)] 491 | 492 | ```Ruby 493 | # 처음 상태(줄이 너무 길다) 494 | def send_mail(source) 495 | Mailer.deliver(to: 'bob@example.com', from: 'us@example.com', subject: 'Important message', body: source.text) 496 | end 497 | 498 | # 나쁜 예(들여쓰기 두번) 499 | def send_mail(source) 500 | Mailer.deliver( 501 | to: 'bob@example.com', 502 | from: 'us@example.com', 503 | subject: 'Important message', 504 | body: source.text) 505 | end 506 | 507 | # 좋은 예 508 | def send_mail(source) 509 | Mailer.deliver(to: 'bob@example.com', 510 | from: 'us@example.com', 511 | subject: 'Important message', 512 | body: source.text) 513 | end 514 | 515 | # 좋은 예(보통의 들여쓰기) 516 | def send_mail(source) 517 | Mailer.deliver( 518 | to: 'bob@example.com', 519 | from: 'us@example.com', 520 | subject: 'Important message', 521 | body: source.text 522 | ) 523 | end 524 | ``` 525 | 526 | * 527 | 여러 줄에 걸친 배열 요소들을 정리하라. 528 | [[link](#align-multiline-arrays)] 529 | 530 | ```Ruby 531 | # 나쁜 예 - 단일 들여쓰기 532 | menu_item = ['Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 533 | 'Baked beans', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam'] 534 | 535 | # 좋은 예 536 | menu_item = [ 537 | 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 538 | 'Baked beans', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam' 539 | ] 540 | 541 | # 좋은 예 542 | menu_item = 543 | ['Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 544 | 'Baked beans', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam'] 545 | ``` 546 | 547 | * 548 | 너무 큰 숫자는 밑줄을 이용하면 가독성이 좋아진다. 549 | [[link](#underscores-in-numerics)] 550 | 551 | ```Ruby 552 | # 나쁜 예 - 0이 몇 개나 됩니까? 553 | num = 1000000 554 | 555 | # 좋은 예 - 사람이 해석하기에도 훨씬 쉽다. 556 | num = 1_000_000 557 | ``` 558 | 559 | * 560 | 숫자 접두사는 소문자를 사용한다. 8진법에는 `0o`를, 16진법에는 `0x`를, 561 | 2진법에는 `0b`를 사용한다. 10진법 숫자에 `0d` 접두사를 사용하지 않는다. 562 | [[link](#numeric-literal-prefixes)] 563 | 564 | ```Ruby 565 | # 나쁜 예 566 | num = 01234 567 | num = 0O1234 568 | num = 0X12AB 569 | num = 0B10101 570 | num = 0D1234 571 | num = 0d1234 572 | 573 | # 좋은 예 - 숫자와 접두사를 구분하기 쉽다. 574 | num = 0o1234 575 | num = 0x12AB 576 | num = 0b10101 577 | num = 1234 578 | ``` 579 | 580 | * 581 | [Rdoc][rdoc]과 API 문서의 컨벤션을 이용하라. 582 | `def`와 명령 블록 사이에 빈 줄을 넣지 마라. 583 | [[link](#rdoc-conventions)] 584 | 585 | * 586 | 한 행에는 80자까지만 쓴다. 587 | [[link](#80-character-limits)] 588 | 589 | * 590 | 줄 끝의 공백은 피한다. 591 | [[link](#no-trailing-whitespace)] 592 | 593 | * 594 | 모든 파일 끝에 줄바꿈을 넣는다. 595 | [[link](#newline-eof)] 596 | 597 | * 598 | 블록 형태의 주석을 사용하지 마라. 앞에 공백이 들어가면 작동하지 않고, 일반 599 | 주석과 달리 쉽게 발견하기 어렵다. 600 | [[link](#no-block-comments)] 601 | 602 | ```Ruby 603 | # 나쁜 예 604 | =begin 605 | comment line 606 | another comment line 607 | =end 608 | 609 | # 좋은 예 610 | # comment line 611 | # another comment line 612 | ``` 613 | 614 | ## 구문 615 | 616 | * 617 | `::`는 상수(클래스나 모듈 포함)와 생성자(`Array()` 또는 `Nokogiri::HTML()` 618 | 같은)를 참조할 때만 사용하라. 일반 메소드 호출에서는 `::`를 쓰지 마라. 619 | [[link](#double-colons)] 620 | 621 | ```Ruby 622 | # 나쁜 예 623 | SomeClass::some_method 624 | some_object::some_method 625 | 626 | # 좋은 예 627 | SomeClass.some_method 628 | some_object.some_method 629 | SomeModule::SomeClass::SOME_CONST 630 | SomeModule::SomeClass() 631 | ``` 632 | 633 | * 634 | 매개변수가 있을 때 `def`와 괄호를 함께 사용하라. 받을 매개변수가 없을 때에는 635 | 괄호를 제거하라. 636 | [[link](#method-parens)] 637 | 638 | ```Ruby 639 | # 나쁜 예 640 | def some_method() 641 | # 내용 생략 642 | end 643 | 644 | # 좋은 예 645 | def some_method 646 | # 내용 생략 647 | end 648 | 649 | # 나쁜 예 650 | def some_method_with_parameters param1, param2 651 | # 내용 생략 652 | end 653 | 654 | # 좋은 예 655 | def some_method_with_parameters(param1, param2) 656 | # 내용 생략 657 | end 658 | ``` 659 | 660 | * 661 | 메소드를 호출할 때 인자를 괄호로 감싼다. 특히 `f((3 + 2) + 1)`과 같이 첫 번째 662 | 인자가 여는 괄호(`(`)로 시작할 때 주의한다. 663 | [[link](#method-invocation-parens)] 664 | 665 | ```Ruby 666 | # 나쁜 예 667 | x = Math.sin y 668 | # 좋은 예 669 | x = Math.sin(y) 670 | 671 | # 나쁜 예 672 | array.delete e 673 | # 좋은 예 674 | array.delete(e) 675 | 676 | # 나쁜 예 677 | temperance = Person.new 'Temperance', 30 678 | # 좋은 예 679 | temperance = Person.new('Temperance', 30) 680 | ``` 681 | 682 | 다음 경우에만 괄호를 생략한다. 683 | 684 | * 인자가 없는 메소드 호출: 685 | 686 | ```Ruby 687 | # 나쁜 예 688 | Kernel.exit!() 689 | 2.even?() 690 | fork() 691 | 'test'.upcase() 692 | 693 | # 좋은 예 694 | Kernel.exit! 695 | 2.even? 696 | fork 697 | 'test'.upcase 698 | ``` 699 | 700 | * 내부 DSL을 구성하는 메소드(예: Rake, 레일스, RSpec): 701 | 702 | ```Ruby 703 | # 나쁜 예 704 | validates(:name, presence: true) 705 | # 좋은 예 706 | validates :name, presence: true 707 | ``` 708 | 709 | * 루비에서 "키워드"로 취급되는 메소드: 710 | 711 | ```Ruby 712 | class Person 713 | # 나쁜 예 714 | attr_reader(:name, :age) 715 | # 좋은 예 716 | attr_reader :name, :age 717 | 718 | # 내용 생략 719 | end 720 | 721 | # 나쁜 예 722 | puts(temperance.age) 723 | # 좋은 예 724 | puts temperance.age 725 | ``` 726 | 727 | * 728 | 선택적인 인자는 인자 목록의 마지막에 선언한다. 729 | 루비에서 선택적인 인자를 목록 앞쪽에 사용하면 의도치 않은 결과를 반환할 수 730 | 있다. 731 | [[link](#optional-arguments)] 732 | 733 | ```Ruby 734 | # 나쁜 예 735 | def some_method(a = 1, b = 2, c, d) 736 | puts "#{a}, #{b}, #{c}, #{d}" 737 | end 738 | 739 | some_method('w', 'x') # => '1, 2, w, x' 740 | some_method('w', 'x', 'y') # => 'w, 2, x, y' 741 | some_method('w', 'x', 'y', 'z') # => 'w, x, y, z' 742 | 743 | # 좋은 예 744 | def some_method(c, d, a = 1, b = 2) 745 | puts "#{a}, #{b}, #{c}, #{d}" 746 | end 747 | 748 | some_method('w', 'x') # => '1, 2, w, x' 749 | some_method('w', 'x', 'y') # => 'y, 2, w, x' 750 | some_method('w', 'x', 'y', 'z') # => 'y, z, w, x' 751 | ``` 752 | 753 | * 754 | 변수를 선언할 때 병렬 대입(parallel assignment)을 피한다. 병렬 대입은 메소드 755 | 호출의 결과일 때, 스플랫 연산자와 사용할 때, 변수를 교환 대입할 때 사용한다. 756 | 병렬 대입은 일반 대입에 비해 가독성이 떨어진다. 757 | [[link](#parallel-assignment)] 758 | 759 | ```Ruby 760 | # 나쁜 예 761 | a, b, c, d = 'foo', 'bar', 'baz', 'foobar' 762 | 763 | # 좋은 예 764 | a = 'foo' 765 | b = 'bar' 766 | c = 'baz' 767 | d = 'foobar' 768 | 769 | # 좋은 예 - 변수 교환 대입 770 | # 변수 교환 대입은 특별한 경우다. 771 | # 각 변수에 대입된 값을 교환할 수 있기 때문이다. 772 | a = 'foo' 773 | b = 'bar' 774 | 775 | a, b = b, a 776 | puts a # => 'bar' 777 | puts b # => 'foo' 778 | 779 | # 좋은 예 - 메소드 반환 780 | def multi_return 781 | [1, 2] 782 | end 783 | 784 | first, second = multi_return 785 | 786 | # 좋은 예 - 스플랫과 함께 사용 787 | first, *list = [1, 2, 3, 4] # first => 1, list => [2, 3, 4] 788 | 789 | hello_array = *'Hello' # => ["Hello"] 790 | 791 | a = *(1..3) # => [1, 2, 3] 792 | ``` 793 | 794 | * 795 | 병렬 대입할 때 불필요한 뒤의 밑줄 변수를 피하라. 이름 있는 밑줄 변수는 796 | 문맥을 읽는데 도움이 되기 떄문에 밑줄 변수보다 권장된다. 뒤의 밑줄 변수는 797 | 대입의 왼쪽에 스프렛 변수가 정의 되고 스프렛 변수가 밑줄이 아닐 때만 필요하다. 798 | [[link]](#trailing-underscore-variables) 799 | 800 | ```Ruby 801 | # 나쁜 예 802 | foo = 'one,two,three,four,five' 803 | # 유용한 정보가 아닌 불필요한 대입 804 | first, second, _ = foo.split(',') 805 | first, _, _ = foo.split(',') 806 | first, *_ = foo.split(',') 807 | 808 | # 좋은 예 809 | foo = 'one,two,three,four,five' 810 | # 밑줄 변수는 마지막 밑줄 요소를 제외한 전 요소를 가져오고 싶다는걸 보여주기 811 | # 위해 필요하다. 812 | *beginning, _ = foo.split(',') 813 | *beginning, something, _ = foo.split(',') 814 | 815 | a, = foo.split(',') 816 | a, b, = foo.split(',') 817 | # 사용하지 않는 변수에 불필요한 대입이지만, 유용한 정보를 제공한다. 818 | first, _second = foo.split(',') 819 | first, _second, = foo.split(',') 820 | first, *_ending = foo.split(',') 821 | ``` 822 | 823 | * 824 | `for`을 쓸 때에는 정확히 그 용법을 알고 있을 때에만 사용해야 한다. 대부분 825 | 반복자(iterator)가 `for` 대신 사용된다. `for` 구문은 `each`의 관점에서 826 | 실행되기 때문에 일종의 우회적인 방식을 사용하지만, `each` 용법과는 다른 점이 827 | 있다. 즉, `for`는 `each`와는 다르게 새로운 영역을 생성하는 것이 아니기 때문에, 828 | `for` 구문 내부에서 정의된 변수들은 `for` 외부에서도 접근 가능하다. 829 | [[link](#no-for-loops)] 830 | 831 | ```Ruby 832 | arr = [1, 2, 3] 833 | 834 | # 나쁜 예 835 | for elem in arr do 836 | puts elem 837 | end 838 | 839 | # elem은 for문 밖에서도 접근 가능한 것에 주의 840 | elem # => 3 841 | 842 | # 좋은 예 843 | arr.each { |elem| puts elem } 844 | 845 | # elem을 each블록 밖에서는 접근할 수 없음 846 | elem # => NameError: undefined local variable or method `elem' 847 | ``` 848 | 849 | * 850 | `if`/`unless`문의 내용이 여러 줄일 때에는 `then`을 쓰지 마라. 851 | [[link](#no-then)] 852 | 853 | ```Ruby 854 | # 나쁜 예 855 | if some_condition then 856 | # 내용 생략 857 | end 858 | 859 | # 좋은 예 860 | if some_condition 861 | # 내용 생략 862 | end 863 | ``` 864 | 865 | * 866 | 조건문의 내용이 여러 줄일 때, 조건식은 항상 `if/unless`와 같은 줄에 붙여 써라. 867 | [[link](#same-line-condition)] 868 | 869 | ```Ruby 870 | # 나쁜 예 871 | if 872 | some_condition 873 | do_something 874 | do_something_else 875 | end 876 | 877 | # 좋은 예 878 | if some_condition 879 | do_something 880 | do_something_else 881 | end 882 | ``` 883 | 884 | * 885 | `if/then/else/end` 구문 보다, 삼항 연산자(`?:`)를 더욱 선호한다. 그게 좀 더 886 | 명쾌하고 간결하다. 887 | [[link](#ternary-operator)] 888 | 889 | ```Ruby 890 | # 나쁜 예 891 | result = if some_condition then something else something_else end 892 | 893 | # 좋은 예 894 | result = some_condition ? something : something_else 895 | ``` 896 | 897 | * 898 | 삼항 연산자는 하나의 식마다 한 개의 표현식을 쓴다. 즉, 삼항 연산자는 중첩해서 899 | 써서는 안 된다. 그러한 경우는 `if/else` 구문을 사용하는 것이 좋다. 900 | [[link](#no-nested-ternary)] 901 | 902 | ```Ruby 903 | # 나쁜 예 904 | some_condition ? (nested_condition ? nested_something : nested_something_else) : something_else 905 | 906 | # 좋은 예 907 | if some_condition 908 | nested_condition ? nested_something : nested_something_else 909 | else 910 | something_else 911 | end 912 | ``` 913 | * 914 | `if x; ...`는 사용하지마라. 대신 삼항 연산자를 사용하라. 915 | [[link](#no-semicolon-ifs)] 916 | 917 | ```Ruby 918 | # 나쁜 예 919 | result = if some_condition; something else something_else end 920 | 921 | # 좋은 예 922 | result = some_condition ? something : something_else 923 | ``` 924 | 925 | * 926 | `if`와 `case`은 결과를 반환하는 표현식이라는 사실을 이용하라. 927 | [[link](#use-if-case-returns)] 928 | 929 | ```Ruby 930 | # 나쁜 예 931 | if condition 932 | result = x 933 | else 934 | result = y 935 | end 936 | 937 | # 좋은 예 938 | result = 939 | if condition 940 | x 941 | else 942 | y 943 | end 944 | ``` 945 | 946 | * 947 | 하나의 행의 경우에는 `when x then ...`을 이용하라. 대안인 `when x:...`는 루비 948 | 1.9에서 없어졌다. 949 | [[link](#one-line-cases)] 950 | 951 | * 952 | `when x; ...`문을 사용하지마라. 앞서 말한 규칙을 보라. 953 | [[link](#no-when-semicolons)] 954 | 955 | * 956 | `not`보다는 `!`를 사용하라. 957 | [[link](#bang-not-not)] 958 | 959 | ```Ruby 960 | # 나쁜 예 - 연산자 우선순위에 의해 소괄호가 요구됨 961 | x = (not something) 962 | 963 | # 좋은 예 964 | x = !something 965 | ``` 966 | 967 | * 968 | `!!`의 사용은 피하라 969 | [[link](#no-bang-bang)] 970 | 971 | `!!`는 값을 boolean으로 만들지만, 제어 구문의 조건문에서 명시적으로 변환할 972 | 필요는 없으며 의도를 불명확하게 만들 뿐이다. `nil` 검사를 하고 싶다면 `nil?`을 973 | 사용하라. 974 | 975 | ```Ruby 976 | # 나쁜 예 977 | x = 'test' 978 | # 불분명한 nil 검사 979 | if !!x 980 | # 내용 생략 981 | end 982 | 983 | # 좋은 예 984 | x = 'test' 985 | if x 986 | # 내용 생략 987 | end 988 | ``` 989 | 990 | * 991 | `and`와 `or`은 금지어다. 약간의 가독성 개선은 이로 발생하는 발견하기 어려운 992 | 미묘한 버그의 발생 가능성이 커지는 점에 비하면 그만한 가치가 없다. 993 | 대신에 boolean을 비교하고 싶다면 항상 `&&`와 `||`를 써라. 분기를 위해서라면 994 | `if`나 `unless`를 사용하라. `&&`나 `||`를 사용할 수도 있지만 상대적으로 가독성이 995 | 좋지 않다. 996 | [[link](#no-and-or-or)] 997 | 998 | ```Ruby 999 | # 나쁜 예 1000 | # boolean 식 1001 | ok = got_needed_arguments and arguments_are_valid 1002 | 1003 | # 제어문 1004 | document.save or fail(RuntimError, "Failed to save document!") 1005 | 1006 | # 좋은 예 1007 | # boolean 식 1008 | if some_condition && some_other_condition 1009 | do_something 1010 | end 1011 | 1012 | # 제어문 1013 | fail(RuntimeError, "Failed to save document!") unless document.save 1014 | 1015 | # ok 1016 | # 제어문 1017 | document.save || fail(RuntimeError, "Failed to save document!") 1018 | ``` 1019 | 1020 | * 1021 | 여러 줄의 조건문에는 `?:`(삼항 연산자)를 피하라. 대신 `if`/`unless`를 1022 | 사용하라. 1023 | [[link](#no-multiline-ternary)] 1024 | 1025 | * 1026 | 구문이 한 줄일 때에는, 같은 줄 끝에 `if`/`unless`를 사용하는 것이 좋다. 1027 | 또 다른 좋은 표현방법은 `&&`/`||`과 같은 제어문을 쓰는 것이다. 1028 | [[link](#if-as-a-modifier)] 1029 | 1030 | ```Ruby 1031 | # 나쁜 예 1032 | if some_condition 1033 | do_something 1034 | end 1035 | 1036 | # 좋은 예 1037 | do_something if some_condition 1038 | 1039 | # 또 다른 좋은 예 1040 | some_condition && do_something 1041 | ``` 1042 | 1043 | * 1044 | 간단하지 않고 여러 줄에 걸친 구문 블록에는 한 줄 `if`/`unless`를 피하라. 1045 | [[link](#no-multiline-if-modifiers)] 1046 | 1047 | ```Ruby 1048 | # 나쁜 예 1049 | 10.times do 1050 | # 내용 여러 줄 생략 1051 | end if some_condition 1052 | 1053 | # 좋은 예 1054 | if some_condition 1055 | 10.times do 1056 | # 내용 여러 줄 생략 1057 | end 1058 | end 1059 | ``` 1060 | 1061 | * 1062 | 중첩된 `if`/`unless`/`while`/`until` 조건의 사용을 피하라. 적절하게 1063 | `&&`/`||`를 사용하라. 1064 | [[link](#no-nested-modifiers)] 1065 | 1066 | ```Ruby 1067 | # 나쁜 예 1068 | do_something if other_condition if some_condition 1069 | 1070 | # 좋은 예 1071 | do_something if some_condition && other_condition 1072 | ``` 1073 | 1074 | * 1075 | `if` 뒤의 부정적인 조건보다는 `unless`(나 `||`)가 더 좋다. 1076 | [[link](#unless-for-negatives)] 1077 | 1078 | ```Ruby 1079 | # 나쁜 예 1080 | do_something if !some_condition 1081 | 1082 | # 나쁜 예 1083 | do_something if not some_condition 1084 | 1085 | # 좋은 예 1086 | do_something unless some_condition 1087 | 1088 | # 또 다른 좋은 방법 1089 | some_condition || do_something 1090 | ``` 1091 | 1092 | * 1093 | `unless`에는 `else`를 쓰지 마라. 긍정적인 경우가 앞에 오도록 다시 작성하라. 1094 | [[link](#no-else-with-unless)] 1095 | 1096 | ```Ruby 1097 | # 나쁜 예 1098 | unless success? 1099 | puts 'failure' 1100 | else 1101 | puts 'success' 1102 | end 1103 | 1104 | # 좋은 예 1105 | if success? 1106 | puts 'success' 1107 | else 1108 | puts 'failure' 1109 | end 1110 | ``` 1111 | 1112 | * 1113 | 제어식의 조건 앞뒤에는 괄호를 사용하지 마라. 1114 | [[link](#no-parens-around-condition)] 1115 | 1116 | ```Ruby 1117 | # 나쁜 예 1118 | if (x > 10) 1119 | # 내용 생략 1120 | end 1121 | 1122 | # 좋은 예 1123 | if x > 10 1124 | # 내용 생략 1125 | end 1126 | ``` 1127 | 1128 | * 1129 | `while/until` 문의 내용이 여러 줄일 때에는, `while/until condition do`를 쓰지 1130 | 마라. 1131 | [[link](#no-multiline-while-do)] 1132 | 1133 | ```Ruby 1134 | # 나쁜 예 1135 | while x > 5 do 1136 | # 내용 생략 1137 | end 1138 | 1139 | until x > 5 do 1140 | # 내용 생략 1141 | end 1142 | 1143 | # 좋은 예 1144 | while x > 5 1145 | # 내용 생략 1146 | end 1147 | 1148 | until x > 5 1149 | # 내용 생략 1150 | end 1151 | ``` 1152 | 1153 | * 1154 | 구문이 한 줄일 때에는, 같은 줄 끝에 `while/until`를 쓰는 것이 좋다. 1155 | [[link](#while-as-a-modifier)] 1156 | 1157 | ```Ruby 1158 | # 나쁜 예 1159 | while some_condition 1160 | do_something 1161 | end 1162 | 1163 | # 좋은 예 1164 | do_something while some_condition 1165 | ``` 1166 | 1167 | * 1168 | `while`에 부정적인 조건을 쓰기보단 `until`을 쓰는 것이 좋다. 1169 | [[link](#until-for-negatives)] 1170 | 1171 | ```Ruby 1172 | # 나쁜 예 1173 | do_something while !some_condition 1174 | 1175 | # 좋은 예 1176 | do_something until some_condition 1177 | ``` 1178 | 1179 | * 1180 | 무한 반복문이 필요할 때에는, `while/until`보다 `Kernel#loop`를 쓰는 것이 더 좋다. 1181 | [[link](#infinite-loop)] 1182 | 1183 | ```ruby 1184 | # 나쁜 예 1185 | while true 1186 | do_something 1187 | end 1188 | 1189 | until false 1190 | do_something 1191 | end 1192 | 1193 | # 좋은 예 1194 | loop do 1195 | do_something 1196 | end 1197 | ``` 1198 | 1199 | * 1200 | 종결조건을 나중에 판정하는 반복문을 쓸 때, `begin/end/until` 또는 1201 | `begin/end/while`보다는 `Kernel#loop`와 `break`를 사용하라. 1202 | [[link](#loop-with-break)] 1203 | 1204 | ```Ruby 1205 | # 나쁜 예 1206 | begin 1207 | puts val 1208 | val += 1 1209 | end while val < 0 1210 | 1211 | # 좋은 예 1212 | loop do 1213 | puts val 1214 | val += 1 1215 | break unless val < 0 1216 | end 1217 | ``` 1218 | 1219 | * 1220 | 옵션들이 해시라면 가장 바깥 중괄호를 생략한다. 1221 | [[link](#no-braces-opts-hash)] 1222 | 1223 | ```Ruby 1224 | # 나쁜 예 1225 | user.set({ name: 'John', age: 45, permissions: { read: true } }) 1226 | 1227 | # 좋은 예 1228 | user.set(name: 'John', age: 45, permissions: { read: true }) 1229 | ``` 1230 | 1231 | * 1232 | 내장된 DSL의 일부인 메소드들에 대해 바깥의 중괄호와 괄호를 생략한다. 1233 | [[link](#no-dsl-decorating)] 1234 | 1235 | ```Ruby 1236 | class Person < ActiveRecord::Base 1237 | # 나쁜 예 1238 | validates(:name, { presence: true, length: { within: 1..10 } }) 1239 | 1240 | # 좋은 예 1241 | validates :name, presence: true, length: { within: 1..10 } 1242 | end 1243 | ``` 1244 | 1245 | * 1246 | 블록의 연산이 메소드 호출뿐이라면 프록 발동 단축(proc invocation shorthand)을 1247 | 사용한다. 1248 | [[link](#single-action-blocks)] 1249 | 1250 | ```Ruby 1251 | # 나쁜 예 1252 | names.map { |name| name.upcase } 1253 | 1254 | # 좋은 예 1255 | names.map(&:upcase) 1256 | ``` 1257 | 1258 | * 1259 | 한 줄짜리 블록에서는 `do...end`보다 `{...}`가 권장된다. 여러 줄짜리 블록에 1260 | 대해 `{...}`를 사용하는 것은 피하라.(줄이 많으면 항상 보기에 안 좋다.) 1261 | "제어 흐름"과 "메소드 정의"에는 항상 `do...end`를 사용하라.(예. Rakefile이나 1262 | 특정 DSL 내에서) 연속적(chaining)일 때는 `do...end`를 피하라. 1263 | [[link](#single-line-blocks)] 1264 | 1265 | ```Ruby 1266 | names = %w[Bozhidar Steve Sarah] 1267 | 1268 | # 나쁜 예 1269 | names.each do |name| 1270 | puts name 1271 | end 1272 | 1273 | # 좋은 예 1274 | names.each { |name| puts name } 1275 | 1276 | # 나쁜 예 1277 | names.select do |name| 1278 | name.start_with?('S') 1279 | end.map { |name| name.upcase } 1280 | 1281 | # 좋은 예 1282 | names.select { |name| name.start_with?('S') }.map(&:upcase) 1283 | ``` 1284 | 1285 | 어떤 사람은 {...}를 사용하는 여러 줄에 걸친 연쇄(chaining)다 보기에 괜찮다고 1286 | 주장할 수도 있겠지만 정말 그러한지는 다음 사항들에 대해 자문해봐야 한다. 1287 | 그렇게 작성된 코드가 가독성이 좋은가? 또 블록 내부의 내용이 깔끔하게 메소드로 1288 | 추출 가능한가? 등에 대해서 말이다. 1289 | 1290 | * 1291 | 다른 블록에 인수만 넘기는 블록문 쓰는 것을 피하기 위해, 명시적으로 블록 1292 | 인수를 사용하는 것을 고려해보라. 블록이 `proc`으로 변하면서, 성능에 영향을 1293 | 주는 것을 조심해야 한다. 1294 | [[link](#block-argument)] 1295 | 1296 | ```Ruby 1297 | require 'tempfile' 1298 | 1299 | # 나쁜 예 1300 | def with_tmp_dir 1301 | Dir.mktmpdir do |tmp_dir| 1302 | Dir.chdir(tmp_dir) { |dir| yield dir } # block just passes arguments 1303 | end 1304 | end 1305 | 1306 | # 좋은 예 1307 | def with_tmp_dir(&block) 1308 | Dir.mktmpdir do |tmp_dir| 1309 | Dir.chdir(tmp_dir, &block) 1310 | end 1311 | end 1312 | 1313 | with_tmp_dir do |dir| 1314 | puts "dir is accessible as a parameter and pwd is set: #{dir}" 1315 | end 1316 | ``` 1317 | 1318 | * 1319 | 제어문에 불필요한 `return`을 피하라. 1320 | [[link](#no-explicit-return)] 1321 | 1322 | ```Ruby 1323 | # 나쁜 예 1324 | def some_method(some_arr) 1325 | return some_arr.size 1326 | end 1327 | 1328 | # 좋은 예 1329 | def some_method(some_arr) 1330 | some_arr.size 1331 | end 1332 | ``` 1333 | 1334 | * 1335 | 불필요한 `self`를 피하라.(이건, self write accessor를 호출할 때나, 1336 | 예약어 뒤에 오는 메소드, 또는 오버로드 가능한 연산자만 필요하다.) 1337 | [[link](#no-self-unless-required)] 1338 | 1339 | ```Ruby 1340 | # 나쁜 예 1341 | def ready? 1342 | if self.last_reviewed_at > self.last_updated_at 1343 | self.worker.update(self.content, self.options) 1344 | self.status = :in_progress 1345 | end 1346 | self.status == :verified 1347 | end 1348 | 1349 | # 좋은 예 1350 | def ready? 1351 | if last_reviewed_at > last_updated_at 1352 | worker.update(content, options) 1353 | self.status = :in_progress 1354 | end 1355 | status == :verified 1356 | end 1357 | ``` 1358 | 1359 | * 1360 | 당연하지만 지역 변수와 메소드가 같은 것을 의미하지 않을 때, 지역변수로 메소드를 1361 | 가리는 것을 피하라. 1362 | [[link](#no-shadowing)] 1363 | 1364 | ```Ruby 1365 | class Foo 1366 | attr_accessor :options 1367 | 1368 | # 괜찮은 예 1369 | def initialize(options) 1370 | self.options = options 1371 | # option과 self.option은 여기서 같다. 1372 | end 1373 | 1374 | # 나쁜 예 1375 | def do_something(options = {}) 1376 | unless options[:when] == :later 1377 | output(self.options[:message]) 1378 | end 1379 | end 1380 | 1381 | # 좋은 예 1382 | def do_something(params = {}) 1383 | unless params[:when] == :later 1384 | output(options[:message]) 1385 | end 1386 | end 1387 | end 1388 | ``` 1389 | 1390 | * 1391 | 배정문이 괄호 안에 싸인 경우를 제외하고는, 조건식에서 `=`(배정 연산자)를 써서 1392 | 값을 반환하지 마라. 이것은 *조건문에서 안전하게 대입하기*라 불리는 루비 사용자 1393 | 사이에서는 상당히 유명한 관용 표현이다. 1394 | [[link](#safe-assignment-in-condition)] 1395 | 1396 | ```Ruby 1397 | # 나쁜 예(+ 주의) 1398 | if v = array.grep(/foo/) 1399 | do_something(v) 1400 | # 생략 1401 | end 1402 | 1403 | # 좋은 예(MRI would still complain, but RuboCop won't) 1404 | if (v = array.grep(/foo/)) 1405 | do_something(v) 1406 | # 생략 1407 | end 1408 | 1409 | # 좋은 예 1410 | v = array.grep(/foo/) 1411 | if v 1412 | do_something(v) 1413 | # 생략 1414 | end 1415 | ``` 1416 | 1417 | * 1418 | 가능하면 생략된 스타일의 자체 대입 연산자를 사용하라. 1419 | [[link](#self-assignment)] 1420 | 1421 | ```Ruby 1422 | # 나쁜 예 1423 | x = x + y 1424 | x = x * y 1425 | x = x**y 1426 | x = x / y 1427 | x = x || y 1428 | x = x && y 1429 | 1430 | # 좋은 예 1431 | x += y 1432 | x *= y 1433 | x **= y 1434 | x /= y 1435 | x ||= y 1436 | x &&= y 1437 | ``` 1438 | 1439 | * 1440 | 초기화가 안된 변수를 초기화 할 때에는 `||=`를 사용하라. 1441 | [[link](#double-pipe-for-uninit)] 1442 | 1443 | ```Ruby 1444 | # 나쁜 예 1445 | name = name ? name : 'Bozhidar' 1446 | 1447 | # 나쁜 예 1448 | name = 'Bozhidar' unless name 1449 | 1450 | # 좋은 예 - name이 nil이나 false가 아니면 'Bozhidar'로 초기화한다. 1451 | name ||= 'Bozhidar' 1452 | ``` 1453 | 1454 | * 1455 | boolean 변수에 대해서는 `||=`로 초기화하지 마라.(현재 변수가 `false`일 때, 1456 | 무슨 일이 일어날지 생각하라.) 1457 | [[link](#no-double-pipes-for-bools)] 1458 | 1459 | ```Ruby 1460 | # 나쁜 예 - enabled가 false 일 때도 true로 대입 1461 | enabled ||= true 1462 | 1463 | # 좋은 예 1464 | enabled = true if enabled.nil? 1465 | ``` 1466 | 1467 | * 1468 | 존재여부를 모르는 전처리 변수에는 `&&=`를 쓴다. `&&=`를 사용하면 값이 존재할 1469 | 때만 값을 바꾸기 때문에 값 존재 여부를 확인하는 `if`는 없어도 된다. 1470 | [[link](#double-amper-preprocess)] 1471 | 1472 | ```Ruby 1473 | # 나쁜 예 1474 | if something 1475 | something = something.downcase 1476 | end 1477 | 1478 | # 나쁜 예 1479 | something = something ? something.downcase : nil 1480 | 1481 | # 괜찮은 예 1482 | something = something.downcase if something 1483 | 1484 | # 좋은 예 1485 | something = something && something.downcase 1486 | 1487 | # 더 좋은 예 1488 | something &&= something.downcase 1489 | ``` 1490 | 1491 | * 1492 | case 동등(equality) 연산자 `===`를 사용하는 것을 피하라. 왜냐하면 그 이름에서 1493 | 말해주듯, 이 연산자는 암묵적으로 `case`의(동등 여부뿐만 아니라) 상태를 1494 | 판별하는 데에 사용되도록 고안되었기 때문에, 외부에서 본다면 약간 혼란스러운 1495 | 코드가 된다. 1496 | [[link](#no-case-equality)] 1497 | 1498 | ```Ruby 1499 | # 나쁜 예 1500 | Array === something 1501 | (1..100) === 7 1502 | /something/ === some_string 1503 | 1504 | # 좋은 예 1505 | something.is_a?(Array) 1506 | (1..100).include?(7) 1507 | some_string =~ /something/ 1508 | ``` 1509 | 1510 | * 1511 | `==`로 할수 있을 때에는 `eql?`을 사용하지 마라. `eql?`이 제공하는 엄격한 1512 | 비교는 대부분 필요 없다. 1513 | [[link](#eql)] 1514 | 1515 | ```Ruby 1516 | # 나쁜 예 - eql?은 문자열에서는 ==와 같음 1517 | 'ruby'.eql? some_str 1518 | 1519 | # 좋은 예 1520 | 'ruby' == some_str 1521 | 1.0.eql? x # Integer와 Float 1의 식별하기 위해 eql?을 사용하는 것은 괜찮다. 1522 | ``` 1523 | 1524 | * 1525 | 펄 스타일의 특수 변수(`$:`, `$;` 등) 사용을 피하라. 그들은 상당히 1526 | 기괴해 보이고, one-liner 스크립트 외에서 사용된 경우에는 읽기 힘들다. `English` 1527 | 라이브러리에서 제공하는 인간 친화적인 alias를 사용하라. 1528 | [[link](#no-cryptic-perlisms)] 1529 | 1530 | ```Ruby 1531 | # 나쁜 예 1532 | $:.unshift File.dirname(__FILE__) 1533 | 1534 | # 좋은 예 1535 | require 'English' 1536 | $LOAD_PATH.unshift File.dirname(__FILE__) 1537 | ``` 1538 | 1539 | * 1540 | 메소드 이름과 괄호 사이에 공백을 넣지 마라. 1541 | [[link](#parens-no-spaces)] 1542 | 1543 | ```Ruby 1544 | # 나쁜 예 1545 | f (3 + 2) + 1 1546 | 1547 | # 좋은 예 1548 | f(3 + 2) + 1 1549 | ``` 1550 | 1551 | * 1552 | 항상 `-w` 옵션과 함께 루비 인터프리터를 실행하라. 그러면 위의 규칙들을 1553 | 잊어버렸을 때 경고할 것이다. 1554 | [[link](#always-warn-at-runtime)] 1555 | 1556 | * 1557 | 중첩 메소드 선언을 사용하는 대신, 람다를 사용한다. 1558 | 중첩 메소드 선언은 사실 밖의 메소드와 같은 범위(예를 들어 클래스)에서 메소드를 1559 | 생성한다. 더욱이, "중첩된 메소드"는 선언이 들어있는 메소드가 호출될 떄마다 1560 | 재정의된다. 1561 | [[link](#no-nested-methods)] 1562 | 1563 | ```Ruby 1564 | # 나쁜 예 1565 | def foo(x) 1566 | def bar(y) 1567 | # 몸통 생략 1568 | end 1569 | 1570 | bar(x) 1571 | end 1572 | 1573 | # 좋은 예 - 위와 같지만, foo가 호출될 때마다 bar가 매번 재정의되지 않는다 1574 | def bar(y) 1575 | # 몸통 생략 1576 | end 1577 | 1578 | def foo(x) 1579 | bar(x) 1580 | end 1581 | 1582 | # 좋은 예 1583 | def foo(x) 1584 | bar = ->(y) { ... } 1585 | bar.call(x) 1586 | end 1587 | ``` 1588 | 1589 | * 1590 | 한 줄짜리 본문 블록에 새로운 lambda 구문을 사용하라. `lambda` 메소드는 1591 | 여러 줄이 있는 블록에 써라. 1592 | [[link](#lambda-multi-line)] 1593 | 1594 | ```Ruby 1595 | # 나쁜 예 1596 | l = lambda { |a, b| a + b } 1597 | l.call(1, 2) 1598 | 1599 | # 맞지만, 보기에 매우 어색한 예 1600 | l = ->(a, b) do 1601 | tmp = a * 7 1602 | tmp * b / 50 1603 | end 1604 | 1605 | # 좋은 예 1606 | l = ->(a, b) { a + b } 1607 | l.call(1, 2) 1608 | 1609 | l = lambda do |a, b| 1610 | tmp = a * 7 1611 | tmp * b / 50 1612 | end 1613 | ``` 1614 | 1615 | * 1616 | 매개변수와 함께 새로운 람다(stabby lambda)를 사용할 때에는 매개변수 괄호를 1617 | 생략하지 않는다. 1618 | [[link](#stabby-lambda-with-args)] 1619 | 1620 | ```Ruby 1621 | # 나쁜 예 1622 | l = ->x, y { something(x, y) } 1623 | 1624 | # 좋은 예 1625 | l = ->(x, y) { something(x, y) } 1626 | ``` 1627 | 1628 | * 1629 | 매개변수 없이 새로운 람다(stabby lambda)를 사용할 때에는 매개변수 괄호를 1630 | 생략한다. 1631 | [[link](#stabby-lambda-no-args)] 1632 | 1633 | ```Ruby 1634 | # 나쁜 예 1635 | l = ->() { something } 1636 | 1637 | # 좋은 예 1638 | l = -> { something } 1639 | ``` 1640 | 1641 | * 1642 | `Proc.new`보다는 `proc`을 권장한다. 1643 | [[link](#proc)] 1644 | 1645 | ```Ruby 1646 | # 나쁜 예 1647 | p = Proc.new { |n| puts n } 1648 | 1649 | # 좋은 예 1650 | p = proc { |n| puts n } 1651 | ``` 1652 | 1653 | * 1654 | lambda나 proc에서 `proc[]`이나 `proc.()`보다 `proc.call()`을 권장한다. 1655 | [[link](#proc-call)] 1656 | 1657 | ```Ruby 1658 | # 나쁜 예 - Enumeration 접근과 비슷해 보임 1659 | l = ->(v) { puts v } 1660 | l[1] 1661 | 1662 | # 역시 나쁜 예 - 잘 쓰지 않는 구문 1663 | l = ->(v) { puts v } 1664 | l.(1) 1665 | 1666 | # 좋은 예 1667 | l = ->(v) { puts v } 1668 | l.call(1) 1669 | ``` 1670 | 1671 | * 1672 | 사용하지 않는 블록 인수나, 지역변수에는 `_`를 앞에 붙여라.(설명이 좀 없더라도) 1673 | `_`만 쓰는 것도 가능하다. 이 컨벤션은 루비 인터프리터와 Robocop과 같은 툴에 1674 | 의해 인지되고, 사용하지 않는 변수에 대한 경고를 숨긴다. 1675 | [[link](#underscore-unused-vars)] 1676 | 1677 | ```Ruby 1678 | # 나쁜 예 1679 | result = hash.map { |k, v| v + 1 } 1680 | 1681 | def something(x) 1682 | unused_var, used_var = something_else(x) 1683 | # 생략 1684 | end 1685 | 1686 | # 좋은 예 1687 | result = hash.map { |_k, v| v + 1 } 1688 | 1689 | def something(x) 1690 | _unused_var, used_var = something_else(x) 1691 | # 생략 1692 | end 1693 | 1694 | # 좋은 예 1695 | result = hash.map { |_, v| v + 1 } 1696 | 1697 | def something(x) 1698 | _, used_var = something_else(x) 1699 | # 생략 1700 | end 1701 | ``` 1702 | 1703 | * 1704 | `STDOUT/STDERR/STDIN`보다는 `$stdout/$stderr/$stdin`을 사용하라. 1705 | `STDOUT/STDERR/STDIN`은 상수이며, 루비에서의 상수는 실제로 재대입 할 수 1706 | 있다.(다른 스트림으로 리디렉션도 가능) 물론 재대입하면 인터프리터의 경고가 1707 | 나올 것이다. 1708 | [[link](#global-stdout)] 1709 | 1710 | * 1711 | `$stderr.puts`보다는 `warn`을 사용하라. 좀 더 간결하고 명확할 뿐만 아니라 1712 | `warn`을 사용하면 필요에 따라 경고를 숨길 수도 있다.(`-W0`를 통해 경고 수준을 1713 | 0으로 함으로써) 1714 | [[link](#warn)] 1715 | 1716 | * 1717 | 기괴한 `String#%`메소드보다는 `sprintf`와 alias인 `format`사용이 더 좋다. 1718 | [[link](#sprintf)] 1719 | 1720 | ```Ruby 1721 | # 나쁜 예 1722 | '%d %d' % [20, 10] 1723 | # => '20 10' 1724 | 1725 | # 좋은 예 1726 | sprintf('%d %d', 20, 10) 1727 | # => '20 10' 1728 | 1729 | # 좋은 예 1730 | sprintf('%{first} %{second}', first: 20, second: 10) 1731 | # => '20 10' 1732 | 1733 | format('%d %d', 20, 10) 1734 | # => '20 10' 1735 | 1736 | # 좋은 예 1737 | format('%{first} %{second}', first: 20, second: 10) 1738 | # => '20 10' 1739 | ``` 1740 | 1741 | * 1742 | 문자 인수와 함께 쓰는 기괴한 `Array#*` 보다 `Array#join`의 사용을 선호한다. 1743 | [[link](#array-join)] 1744 | 1745 | ```Ruby 1746 | # 나쁜 예 1747 | %w[one two three] * ', ' 1748 | # => 'one, two, three' 1749 | 1750 | # 좋은 예 1751 | %w[one two three].join(', ') 1752 | # => 'one, two, three' 1753 | ``` 1754 | 1755 | * 1756 | 변수가 배열인지 모르겠지만 그것을 Array로 취급하고 싶을 때에는 명시적인 `Array` 1757 | 체크나 `[*var]` 대신에 `Array()`를 사용하라. 1758 | [[link](#array-coercion)] 1759 | 1760 | ```Ruby 1761 | # 나쁜 예 1762 | paths = [paths] unless paths.is_a? Array 1763 | paths.each { |path| do_something(path) } 1764 | 1765 | # 나쁜 예(항상 새로운 배열 인스턴스를 만듦) 1766 | [*paths].each { |path| do_something(path) } 1767 | 1768 | # 좋은 예(좀 더 가독성이 높은) 1769 | Array(paths).each { |path| do_something(path) } 1770 | ``` 1771 | 1772 | * 1773 | 복잡한 비교논리를 사용하는 것 대신에 가능하면 범위나 `Comparable#between?`을 1774 | 사용하라. 1775 | [[link](#ranges-or-between)] 1776 | 1777 | ```Ruby 1778 | # 나쁜 예 1779 | do_something if x >= 1000 && x <= 2000 1780 | 1781 | # 좋은 예 1782 | do_something if (1000..2000).include?(x) 1783 | 1784 | # 좋은 예 1785 | do_something if x.between?(1000, 2000) 1786 | ``` 1787 | 1788 | * 1789 | `==`로 비교하기 보다 서술형 메소드(predicate methods)를 사용하는 것이 더 좋다. 1790 | 숫자 비교는 괜찮다. 1791 | [[link](#predicate-methods)] 1792 | 1793 | ```Ruby 1794 | # 나쁜 예 1795 | if x % 2 == 0 1796 | end 1797 | 1798 | if x % 2 == 1 1799 | end 1800 | 1801 | if x == nil 1802 | end 1803 | 1804 | if x == 0 1805 | end 1806 | 1807 | # 좋은 예 1808 | if x.even? 1809 | end 1810 | 1811 | if x.odd? 1812 | end 1813 | 1814 | if x.nil? 1815 | end 1816 | 1817 | if x.zero? 1818 | end 1819 | ``` 1820 | 1821 | * 1822 | boolean 값을 다룰 때가 아니면, 명시적으로 '`nil`이 아닌 것'을 체크하는 것을 1823 | 피하라. 1824 | [[link](#no-non-nil-checks)] 1825 | 1826 | ```ruby 1827 | # 나쁜 예 1828 | do_something if !something.nil? 1829 | do_something if something != nil 1830 | 1831 | # 좋은 예 1832 | do_something if something 1833 | 1834 | # 좋은 예 - boolean을 다룸 1835 | def value_set? 1836 | !@some_boolean.nil? 1837 | end 1838 | ``` 1839 | 1840 | * 1841 | `BEGIN` 블록 사용을 피하라. 1842 | [[link](#no-BEGIN-blocks)] 1843 | 1844 | * 1845 | `END` 블록 사용을 피하라. 차라리 `Kernel#at_exit`를 써라. 1846 | [[link](#no-END-blocks)] 1847 | 1848 | ```ruby 1849 | # 나쁜 예 1850 | END { puts 'Goodbye!' } 1851 | 1852 | # 좋은 예 1853 | at_exit { puts 'Goodbye!' } 1854 | ``` 1855 | 1856 | * 1857 | flip-flop 사용을 피하라. 1858 | [[link](#no-flip-flops)] 1859 | 1860 | * 1861 | 제어문에서 중첩된 조건문은 피하라. 1862 | [[link](#no-nested-conditionals)] 1863 | 1864 | 유효하지 않은 데이터가 들어갈 수도 있는 경우, 보호 구문을 권장한다. 보호 1865 | 구문은 함수에서 가능한 한 빨리 탈출할 수 있게 하는 함수 제일 처음에 있는 1866 | 조건문을 말한다. 1867 | 1868 | ```Ruby 1869 | # 나쁜 예 1870 | def compute_thing(thing) 1871 | if thing[:foo] 1872 | update_with_bar(thing[:foo]) 1873 | if thing[:foo][:bar] 1874 | partial_compute(thing) 1875 | else 1876 | re_compute(thing) 1877 | end 1878 | end 1879 | end 1880 | 1881 | # 좋은 예 1882 | def compute_thing(thing) 1883 | return unless thing[:foo] 1884 | update_with_bar(thing[:foo]) 1885 | return re_compute(thing) unless thing[:foo][:bar] 1886 | partial_compute(thing) 1887 | end 1888 | ``` 1889 | 1890 | 반복문 내에서는 조건문 블록 대신에 `next`를 선호한다. 1891 | 1892 | ```Ruby 1893 | # 나쁜 예 1894 | [0, 1, 2, 3].each do |item| 1895 | if item > 1 1896 | puts item 1897 | end 1898 | end 1899 | 1900 | # 좋은 예 1901 | [0, 1, 2, 3].each do |item| 1902 | next unless item > 1 1903 | puts item 1904 | end 1905 | ``` 1906 | 1907 | * 1908 | `collect`보다는 `map`을, `detect`보다는 `find`를, `find_all`보다는 `select`를, 1909 | `inject`보다는 `reduce`를, `length`보다는 `size`를 권장한다. 이것이 무리한 1910 | 요구는 아니다. 다른 alias를 써서 가독성이 좋아진다면, 그것도 괜찮다. 메소드의 1911 | 시적인 표현은 Smalltalk 언어로 부터 물려받은 것으로, 일반적인 다른 프로그래밍 1912 | 언어와는 다르다. `select`를 사용하는 이유는 `reject`와 함께 쓰일 때 1913 | `find_all`보다 좀 더 잘 어울리고 이름 자체가 충분한 설명이 되기 때문이다. 1914 | [[link](#map-find-select-reduce-size)] 1915 | 1916 | * 1917 | `size`를 대신해서 `count`를 쓰지 마라. `Array`외의 `Enumerable`객체들은 1918 | 크기를 결정하기 위해 모든 콜렉션을 반복한다. 1919 | [[link](#count-vs-size)] 1920 | 1921 | ```Ruby 1922 | # 나쁜 예 1923 | some_hash.count 1924 | 1925 | # 좋은 예 1926 | some_hash.size 1927 | ``` 1928 | 1929 | * 1930 | `map` + `flatten`의 조합을 사용하는 것 대신 `flat_map`을 사용하라. 이것은 1931 | 2차원 이상의 배열에는 적용되지는 않는다. 다시 말해서, 1932 | `users.first.songs == ['a', ['b','c']]`의 경우는 `flat_map`보다는 1933 | `map + flatten`를 사용하라. `flat_map`은 1차원의 배열만 1차원으로 만드는 반면 1934 | `flatten`은 모든 것을 1차원 배열로 만든다. 1935 | [[link](#flat-map)] 1936 | 1937 | ```Ruby 1938 | # 나쁜 예 1939 | all_songs = users.map(&:songs).flatten.uniq 1940 | 1941 | # 좋은 예 1942 | all_songs = users.flat_map(&:songs).uniq 1943 | ``` 1944 | 1945 | * 1946 | `reverse.each`보다는 `reverse_each`를 써라. `include Enumerable`을 사용하는 1947 | 몇몇 클래스에서 좀 더 효율적인 구현을 사용하기 떄문이다. 최악 경우 1948 | 클래스에서 특별한 구현을 사용하지 않는다고 해도, `Enumerable`에서 상속된 1949 | 일반적인 구현은 `reverse.each` 정도의 효율을 낸다. 1950 | [[link](#reverse-each)] 1951 | 1952 | ```Ruby 1953 | # 나쁜 예 1954 | array.reverse.each { ... } 1955 | 1956 | # 좋은 예 1957 | array.reverse_each { ... } 1958 | ``` 1959 | 1960 | ## 네이밍 1961 | 1962 | > 프로그래밍에서 정말 어려운 것은 캐시무효화와 이름 짓기뿐이다.
1963 | > -- Phil Karlton 1964 | 1965 | * 1966 | 식별자는 영어로 쓴다. 1967 | [[link](#english-identifiers)] 1968 | 1969 | ```Ruby 1970 | # 나쁜 예 - ascii 문자가 아닌 식별자 1971 | заплата = 1_000 1972 | 1973 | # 나쁜 예 - 식별자가 (키릴문자 대신에)라틴어 문자로 적힌 불가리어 단어다. 1974 | zaplata = 1_000 1975 | 1976 | # 좋은 예 1977 | salary = 1_000 1978 | ``` 1979 | 1980 | * 1981 | 심볼,메소드,변수에 대해 `snake_case`를 써라. 1982 | [[link](#snake-case-symbols-methods-vars)] 1983 | 1984 | ```Ruby 1985 | # 나쁜 예 1986 | :'some symbol' 1987 | :SomeSymbol 1988 | :someSymbol 1989 | 1990 | someVar = 5 1991 | var_10 = 10 1992 | 1993 | def someMethod 1994 | # 생략 1995 | end 1996 | 1997 | def SomeMethod 1998 | # 생략 1999 | end 2000 | 2001 | # 좋은 예 2002 | :some_symbol 2003 | 2004 | some_var = 5 2005 | var10 = 10 2006 | 2007 | def some_method 2008 | # 생략 2009 | end 2010 | ``` 2011 | 2012 | * 2013 | 심볼이나 메소드, 변수명에서 숫자를 띄우지 마라. 2014 | [[link](#snake-case-symbols-methods-vars-with-numbers)] 2015 | 2016 | ```Ruby 2017 | # 나쁜 예 2018 | :some_sym_1 2019 | 2020 | some_var_1 = 1 2021 | 2022 | def some_method_1 2023 | # some code 2024 | end 2025 | 2026 | # 좋은 예 2027 | :some_sym1 2028 | 2029 | some_var1 = 1 2030 | 2031 | def some_method1 2032 | # some code 2033 | end 2034 | ``` 2035 | 2036 | 2037 | * 2038 | 클래스와 모듈에 대해서는 `CamelCase`(카멜표기)를 사용하라. 2039 | (HTTP,RFC,XML와 같은 약어는 대문자로 유지하라) 2040 | [[link](#camelcase-classes)] 2041 | 2042 | ```Ruby 2043 | # 나쁜 예 2044 | class Someclass 2045 | # 생략 2046 | end 2047 | 2048 | class Some_Class 2049 | # 생략 2050 | end 2051 | 2052 | class SomeXml 2053 | # 생략 2054 | end 2055 | 2056 | class XmlSomething 2057 | # 생략 2058 | end 2059 | 2060 | # 좋은 예 2061 | class SomeClass 2062 | # 생략 2063 | end 2064 | 2065 | class SomeXML 2066 | # 생략 2067 | end 2068 | 2069 | class XMLSomething 2070 | # 생략 2071 | end 2072 | ``` 2073 | 2074 | * 2075 | 파일 이름은 `snake_case`로 써라. 2076 | 예. `hello_world.rb` 2077 | [[link](#snake-case-files)] 2078 | 2079 | * 2080 | 디렉토리 이름은 `snake_case`로 써라. 2081 | 예. `lib/hello_world/hello_world.rb` 2082 | [[link](#snake-case-dirs)] 2083 | 2084 | * 2085 | 되도록이면 하나의 소스파일은 하나의 클래스/모듈을 갖도록 하라. 파일명은 2086 | `CamelCase`로 적힌 클래스/모듈이름을 `snake_case`로 바꾼 것으로 하라. 2087 | [[link](#one-class-per-file)] 2088 | 2089 | * 2090 | 다른 상수들은 `SCREAMING_SNAKE_CASE`을 사용하라. 2091 | [[link](#screaming-snake-case)] 2092 | 2093 | ```Ruby 2094 | # 나쁜 예 2095 | SomeConst = 5 2096 | 2097 | # 좋은 예 2098 | SOME_CONST = 5 2099 | ``` 2100 | 2101 | * 2102 | 서술형 메소드(boolean 값을 반환하는 메소드)의 이름은 꼭 물음표로 끝나야 한다. 2103 | (예를 들어 `Array#empty?`) 메소드가 boolean 값을 반환하는게 아니라면, 물음표로 2104 | 끝나선 안 된다. 2105 | [[link](#bool-methods-qmark)] 2106 | 2107 | * 2108 | 단정 메소드에 `is`, `does`, `can` 같은 보조 전치사를 붙이는 것을 피하라. 2109 | 이런 단어는 장황할 뿐만 아니라 `empty?`, `include?` 같은 루비 핵심 라이브러리의 2110 | 이진 메소드의 스타일과 다르기도 하다. 2111 | [[link](#bool-methods-prefix)] 2112 | 2113 | ```Ruby 2114 | # 나쁜 예 2115 | class Person 2116 | def is_tall? 2117 | true 2118 | end 2119 | 2120 | def can_play_basketball? 2121 | false 2122 | end 2123 | 2124 | def does_like_candy? 2125 | true 2126 | end 2127 | end 2128 | 2129 | # 좋은 예 2130 | class Person 2131 | def tall? 2132 | true 2133 | end 2134 | 2135 | def basketball_player? 2136 | false 2137 | end 2138 | 2139 | def likes_candy? 2140 | true 2141 | end 2142 | end 2143 | ``` 2144 | 2145 | * 2146 | 잠재적으로 *위험한* 메소드의(예를 들어, `self`나 인수를 수정하는 메소드와 2147 | `exit!`(finalizer를 실행하지 않음) 등) 이름은 *위험한* 메소드의 안전한 버전이 2148 | 존재할 때는 느낌표로 끝낸다. 2149 | [[link](#dangerous-method-bang)] 2150 | 2151 | ```Ruby 2152 | # 나쁜 예 - 'safe'한 메소드가 없다. 2153 | class Person 2154 | def update! 2155 | end 2156 | end 2157 | 2158 | # 좋은 예 2159 | class Person 2160 | def update 2161 | end 2162 | end 2163 | 2164 | # 좋은 예 2165 | class Person 2166 | def update! 2167 | end 2168 | 2169 | def update 2170 | end 2171 | end 2172 | ``` 2173 | 2174 | * 2175 | 가능하면 bang(위험한) 관점에서 non-bang(안전한)메소드를 정의하라. 2176 | [[link](#safe-because-unsafe)] 2177 | 2178 | ```Ruby 2179 | class Array 2180 | def flatten_once! 2181 | res = [] 2182 | 2183 | each do |e| 2184 | [*e].each { |f| res << f } 2185 | end 2186 | 2187 | replace(res) 2188 | end 2189 | 2190 | def flatten_once 2191 | dup.flatten_once! 2192 | end 2193 | end 2194 | ``` 2195 | 2196 | * 2197 | 이항 연산자를 정의할 때에는, 매개변수 이름을 `other`로 하라. 2198 | (`<<`와 `[]`는 의미가 달라지므로 이 규칙에서 제외된다.) 2199 | [[link](#other-param)] 2200 | 2201 | ```Ruby 2202 | def +(other) 2203 | # 내용 생략 2204 | end 2205 | ``` 2206 | 2207 | ## 주석 2208 | 2209 | > 좋은 코드는 가장 좋은 문서이다. 주석을 추가하려고 할 때 스스로에게 물어보라. 2210 | > "이 주석이 필요 없으려면 코드를 어떻게 만들면 될까?" 코드를 더 잘 작성하여 2211 | > 문서를 명확하게 하자.
2212 | > -- Steve McConnell 2213 | 2214 | * 2215 | 스스로 문서화가 되는 코드를 작성하고 이 단락은 무시하도록 하자. 진짜로! 2216 | [[link](#no-comments)] 2217 | 2218 | * 2219 | 주석은 영어로 작성한다. 2220 | [[link](#english-comments)] 2221 | 2222 | * 2223 | `#`뒤에 한 칸 띄고 주석 내용을 작성한다. 2224 | [[link](#hash-space)] 2225 | 2226 | * 2227 | 한 단어 이상의 주석은 대문자 표기법과 구두점 규칙을 사용한다. 마침표 뒤에는 2228 | [공백](https://en.wikipedia.org/wiki/Sentence_spacing)을 사용한다. 2229 | [[link](#english-syntax)] 2230 | 2231 | * 2232 | 불필요한 주석은 피한다. 2233 | [[link](#no-superfluous-comments)] 2234 | 2235 | ```Ruby 2236 | # 나쁜 예 2237 | counter += 1 # Increments counter by one. 2238 | ``` 2239 | 2240 | * 2241 | 주석은 최신 상태로 유지한다. 코드내용과 맞지 않는 주석은 없는 것이 낫다. 2242 | [[link](#comment-upkeep)] 2243 | 2244 | > 좋은 주석은 좋은 유머와 같다. 설명이 필요없다.
2245 | > — 오래된 프로그래머 격언, [Russ Olsen](http://eloquentruby.com/blog/2011/03/07/good-code-and-good-jokes/) 2246 | 2247 | * 2248 | 나쁜 코드에 대해서 주석을 달지 마라. 코드가 스스로 설명할 수 있도록 리펙토링 2249 | 하라.("한다, 안 한다가 있을 뿐이야. 해보는 건 없어." Yoda) 2250 | [[link](#refactor-dont-comment)] 2251 | 2252 | ### 주석 어노테이션 2253 | 2254 | * 2255 | 어노테이션은 관련된 코드 바로 위에 작성한다. 2256 | [[link](#annotate-above)] 2257 | 2258 | * 2259 | 어노테이션 키워드는 콜론과 공백 다음에 설명을 작성한다. 2260 | [[link](#annotate-keywords)] 2261 | 2262 | * 2263 | 만약 설명이 여러 줄인 경우 다음 줄은 `#`을 쓰고 세 칸 들여쓰기 한다.(한 칸은 2264 | 일반적으로 하고, 두 칸은 들여쓰기 목적) 2265 | [[link](#indent-annotations)] 2266 | 2267 | ```Ruby 2268 | def bar 2269 | # FIXME: This has crashed occasionally since v3.2.1. It may 2270 | # be related to the BarBazUtil upgrade. 2271 | baz(:quux) 2272 | end 2273 | ``` 2274 | 2275 | * 2276 | 설명이 명확하지 않고 중복되는 경우 예외적으로 라인 뒤쪽에 어노테이션을 2277 | 작성한다.(규칙은 아님) 2278 | [[link](#rare-eol-annotations)] 2279 | 2280 | ```Ruby 2281 | def bar 2282 | sleep 100 # OPTIMIZE 2283 | end 2284 | ``` 2285 | 2286 | * 2287 | `TODO`는 빠진 기능을 나중에 추가해야 할 때 사용한다. 2288 | [[link](#todo)] 2289 | 2290 | * 2291 | `FIXME`는 코드가 깨져 고쳐야 할 때 사용한다. 2292 | [[link](#fixme)] 2293 | 2294 | * 2295 | `OPTIMIZE`는 코드가 느리거나 비효율적이라서 성능상 문제가 생기는 경우에 2296 | 사용한다. 2297 | [[link](#optimize)] 2298 | 2299 | * 2300 | `HACK`은 코드에 냄새가 있는 것 같아 이야기해 보고 리팩토링이 필요한 경우 2301 | 사용한다. 2302 | [[link](#hack)] 2303 | 2304 | * 2305 | `REVIEW`는 의도한 대로 동작하는지 확인해야 하는 경우에 사용한다. 예를 들어: 2306 | `REVIEW: Are we sure this is how the client does X currently?` 2307 | [[link](#review)] 2308 | 2309 | * 2310 | 다른 어노테이션 키워드들은 필요에 따라 작성하고 `README` 같은 곳에 정리해둔다. 2311 | [[link](#document-annotations)] 2312 | 2313 | ### 매직 코멘트 2314 | 2315 | * 2316 | 매직 코멘트는 모든 코드와 문서 위에 두어라. 매직 코멘트는 소스 파일에 2317 | 쉬뱅(#!)을 사용하는 경우에만 그 밑에 두어라. 2318 | [[link](#magic-comments-first)] 2319 | 2320 | ```Ruby 2321 | # 좋은 예 2322 | # frozen_string_literal: true 2323 | # Some documentation about Person 2324 | class Person 2325 | end 2326 | 2327 | # 나쁜 예 2328 | # Some documentation about Person 2329 | # frozen_string_literal: true 2330 | class Person 2331 | end 2332 | ``` 2333 | 2334 | ```Ruby 2335 | # 좋은 예 2336 | #!/usr/bin/env ruby 2337 | # frozen_string_literal: true 2338 | App.parse(ARGV) 2339 | 2340 | # 나쁜 예 2341 | # frozen_string_literal: true 2342 | #!/usr/bin/env ruby 2343 | App.parse(ARGV) 2344 | ``` 2345 | 2346 | * 2347 | 여러 개의 매직 코멘트를 사용하는 경우에는 한 줄에 하나의 매직 코멘트만 사용하라. 2348 | [[link](#one-magic-comment-per-line)] 2349 | 2350 | ```Ruby 2351 | # 좋은 예 2352 | # frozen_string_literal: true 2353 | # encoding: ascii-8bit 2354 | 2355 | # 나쁜 예 2356 | # -*- frozen_string_literal: true; encoding: ascii-8bit -*- 2357 | ``` 2358 | 2359 | * 2360 | 매직 코멘트와 코드, 문서 사이에 빈 줄을 사이에 두어라. 2361 | [[link](#separate-magic-comments-from-code)] 2362 | 2363 | ```Ruby 2364 | # 좋은 예 2365 | # frozen_string_literal: true 2366 | 2367 | # Some documentation about Person 2368 | class Person 2369 | # 생략 2370 | end 2371 | 2372 | # 나쁜 예 2373 | # frozen_string_literal: true 2374 | # Some documentation about Person 2375 | class Person 2376 | # 생략 2377 | end 2378 | ``` 2379 | 2380 | ## 클래스와 모듈 2381 | 2382 | * 2383 | 클래스 정의는 일관된 구조를 사용한다. 2384 | [[link](#consistent-classes)] 2385 | 2386 | ```Ruby 2387 | class Person 2388 | # extend와 include가 먼저 나온다. 2389 | extend SomeModule 2390 | include AnotherModule 2391 | 2392 | # inner classes 2393 | CustomError = Class.new(StandardError) 2394 | 2395 | # 상수는 다음에 나온다. 2396 | SOME_CONSTANT = 20 2397 | 2398 | # 그 뒤로 attribute 매크로가 온다. 2399 | attr_reader :name 2400 | 2401 | # 다른 매크로들이 있다면 그 다음에 나온다. 2402 | validates :name 2403 | 2404 | # public 클래스 메소드가 다음 줄에 온다. 2405 | def self.some_method 2406 | end 2407 | 2408 | # 초기화는 클래스 메소드와 다른 인스턴스 메소드 사이에 온다. 2409 | def initialize 2410 | end 2411 | 2412 | # 다른 public 인스턴스 메소드가 뒤에 온다. 2413 | def some_method 2414 | end 2415 | 2416 | # protected와 private 메소드는 마지막 근처에 모아둔다. 2417 | protected 2418 | 2419 | def some_protected_method 2420 | end 2421 | 2422 | private 2423 | 2424 | def some_private_method 2425 | end 2426 | end 2427 | ``` 2428 | 2429 | * 2430 | 한 줄 이상의 클래스는 클래스 안에 선언하지 않는다. 이런 경우에는 클래스 이름의 2431 | 폴더를 만들고 각각의 inner 클래스를 별도의 파일로 분리해 보는 것도 좋다. 2432 | [[link](#file-classes)] 2433 | 2434 | ```Ruby 2435 | # 나쁜 예 2436 | 2437 | # foo.rb 2438 | class Foo 2439 | class Bar 2440 | # 안에 30개의 메소드 2441 | end 2442 | 2443 | class Car 2444 | # 안에 20개의 메소드 2445 | end 2446 | 2447 | # 안에 30개의 메소드 2448 | end 2449 | 2450 | # 좋은 예 2451 | 2452 | # foo.rb 2453 | class Foo 2454 | # 안에 30개의 메소드 2455 | end 2456 | 2457 | # foo/bar.rb 2458 | class Foo 2459 | class Bar 2460 | # 안에 30개의 메소드 2461 | end 2462 | end 2463 | 2464 | # foo/car.rb 2465 | class Foo 2466 | class Car 2467 | # 안에 20개의 메소드 2468 | end 2469 | end 2470 | ``` 2471 | 2472 | * 2473 | 클래스 메소드만 가지는 클래스는 모듈로 선언하는 것이 더 좋다. 클래스는 2474 | 인스턴스를 생성해서 사용할 때만 사용한다. 2475 | [[link](#modules-vs-classes)] 2476 | 2477 | ```Ruby 2478 | # 나쁜 예 2479 | class SomeClass 2480 | def self.some_method 2481 | # 내용 생략 2482 | end 2483 | 2484 | def self.some_other_method 2485 | # 내용 생략 2486 | end 2487 | end 2488 | 2489 | # 좋은 예 2490 | module SomeModule 2491 | module_function 2492 | 2493 | def some_method 2494 | # 내용 생략 2495 | end 2496 | 2497 | def some_other_method 2498 | # 내용 생략 2499 | end 2500 | end 2501 | ``` 2502 | 2503 | * 2504 | 모듈의 인스턴스 메소드를 클래스 메소드로 바꿀 때는 `extend self`보다는 2505 | `module_function`을 더 선호한다. 2506 | [[link](#module-function)] 2507 | 2508 | ```Ruby 2509 | # 나쁜 예 2510 | module Utilities 2511 | extend self 2512 | 2513 | def parse_something(string) 2514 | # 여기에 뭔가 2515 | end 2516 | 2517 | def other_utility_method(number, string) 2518 | # 여기에 좀 더 뭔가 2519 | end 2520 | end 2521 | 2522 | # 좋은 예 2523 | module Utilities 2524 | module_function 2525 | 2526 | def parse_something(string) 2527 | # 여기에 뭔가 2528 | end 2529 | 2530 | def other_utility_method(number, string) 2531 | # 여기에 좀 더 뭔가 2532 | end 2533 | end 2534 | ``` 2535 | 2536 | * 2537 | 클래스 계층을 디자인 할 때는 [리스코프 치환 2538 | 원칙](https://ko.wikipedia.org/wiki/리스코프_치환_원칙)에 따른다. 2539 | [[link](#liskov)] 2540 | 2541 | * 2542 | 클래스는 가능한 한 [SOLID](https://ko.wikipedia.org/wiki/SOLID) 원칙을 따른다. 2543 | [[link](#solid-design)] 2544 | 2545 | * 2546 | 도메인 객체 클래스는 항상 적합한 `to_s` 메소드를 제공한다. 2547 | [[link](#define-to-s)] 2548 | 2549 | ```Ruby 2550 | class Person 2551 | attr_reader :first_name, :last_name 2552 | 2553 | def initialize(first_name, last_name) 2554 | @first_name = first_name 2555 | @last_name = last_name 2556 | end 2557 | 2558 | def to_s 2559 | "#{@first_name} #{@last_name}" 2560 | end 2561 | end 2562 | ``` 2563 | 2564 | * 2565 | 특별한 일을 하지 않는 accessor나 mutator는 `attr`류의 함수를 사용한다. 2566 | [[link](#attr_family)] 2567 | 2568 | ```Ruby 2569 | # 나쁜 예 2570 | class Person 2571 | def initialize(first_name, last_name) 2572 | @first_name = first_name 2573 | @last_name = last_name 2574 | end 2575 | 2576 | def first_name 2577 | @first_name 2578 | end 2579 | 2580 | def last_name 2581 | @last_name 2582 | end 2583 | end 2584 | 2585 | # 좋은 예 2586 | class Person 2587 | attr_reader :first_name, :last_name 2588 | 2589 | def initialize(first_name, last_name) 2590 | @first_name = first_name 2591 | @last_name = last_name 2592 | end 2593 | end 2594 | ``` 2595 | 2596 | * 2597 | accessor와 mutator 메소드 이름에 `get_` 및 `set_` 접두사를 사용하지 않는다. 2598 | 루비 컨벤션에 따르면 accessor(reader) 메소드에 속성 이름을 사용하고 2599 | mutator(writer) 메소드에 `attr_name=`을 사용한다. 2600 | [[link](#accessor_mutator_method_names)] 2601 | 2602 | ```Ruby 2603 | # 나쁜 예 2604 | class Person 2605 | def get_name 2606 | "#{@first_name} #{@last_name}" 2607 | end 2608 | 2609 | def set_name(name) 2610 | @first_name, @last_name = name.split(' ') 2611 | end 2612 | end 2613 | 2614 | # 좋은 예 2615 | class Person 2616 | def name 2617 | "#{@first_name} #{@last_name}" 2618 | end 2619 | 2620 | def name=(name) 2621 | @first_name, @last_name = name.split(' ') 2622 | end 2623 | end 2624 | ``` 2625 | 2626 | * 2627 | 그냥 `attr`을 사용하지 말고 `attr_reader`나 `attr_accessor`을 사용한다. 2628 | [[link](#attr)] 2629 | 2630 | ```Ruby 2631 | # 나쁜 예 - accessor를 하나 생성(루비 1.9에서 비추천됨) 2632 | attr :something, true 2633 | attr :one, :two, :three # attr_reader 처럼 동작한다. 2634 | 2635 | # 좋은 예 2636 | attr_accessor :something 2637 | attr_reader :one, :two, :three 2638 | ``` 2639 | 2640 | * 2641 | 특별하지 않은 accessor와 생성자, 비교 연산자를 가지는 클래스는 `Struct.new`를 2642 | 사용해 보는 것도 좋다. 2643 | [[link](#struct-new)] 2644 | 2645 | ```Ruby 2646 | # 좋은 예 2647 | class Person 2648 | attr_accessor :first_name, :last_name 2649 | 2650 | def initialize(first_name, last_name) 2651 | @first_name = first_name 2652 | @last_name = last_name 2653 | end 2654 | end 2655 | 2656 | # 더 좋은 예 2657 | Person = Struct.new(:first_name, :last_name) do 2658 | end 2659 | ``` 2660 | 2661 | * 2662 | `Struct.new`에 의해 초기화된 인스턴스를 확장하지 않는다. `Struct.new`를 2663 | 확장하는 것은 쓸데없는 클래스 계층을 하나 더 만드는 것이고 만약 그 파일이 2664 | 여러 번 require 된다면 이상한 에러가 날지도 모른다. 2665 | [[link](#no-extend-struct-new)] 2666 | 2667 | ```Ruby 2668 | # 나쁜 예 2669 | class Person < Struct.new(:first_name, :last_name) 2670 | end 2671 | 2672 | # 좋은 예 2673 | Person = Struct.new(:first_name, :last_name) 2674 | ``` 2675 | 2676 | * 2677 | 어떤 클래스의 인스턴스를 생성할 때 좀 더 명확한 방법을 제공하는 팩토리 2678 | 메소드를 추가하는 것을 고려해보자. 2679 | [[link](#factory-methods)] 2680 | 2681 | ```Ruby 2682 | class Person 2683 | def self.create(options_hash) 2684 | # 내용 생략 2685 | end 2686 | end 2687 | ``` 2688 | 2689 | * 2690 | 상속보다는 [duck-typing](https://ko.wikipedia.org/wiki/덕_타이핑)을 쓰는 것이 더 좋다. 2691 | [[link](#duck-typing)] 2692 | 2693 | ```Ruby 2694 | # 나쁜 예 2695 | class Animal 2696 | # abstract 메소드 2697 | def speak 2698 | end 2699 | end 2700 | 2701 | # superclass를 상속 2702 | class Duck < Animal 2703 | def speak 2704 | puts 'Quack! Quack' 2705 | end 2706 | end 2707 | 2708 | # superclass를 상속 2709 | class Dog < Animal 2710 | def speak 2711 | puts 'Bau! Bau!' 2712 | end 2713 | end 2714 | 2715 | # good 2716 | class Duck 2717 | def speak 2718 | puts 'Quack! Quack' 2719 | end 2720 | end 2721 | 2722 | class Dog 2723 | def speak 2724 | puts 'Bau! Bau!' 2725 | end 2726 | end 2727 | ``` 2728 | 2729 | * 2730 | 클래스 변수(`@@`)는 상속을 할 때 좋지 않기 때문에 사용을 피한다. 2731 | [[link](#no-class-vars)] 2732 | 2733 | ```Ruby 2734 | class Parent 2735 | @@class_var = 'parent' 2736 | 2737 | def self.print_class_var 2738 | puts @@class_var 2739 | end 2740 | end 2741 | 2742 | class Child < Parent 2743 | @@class_var = 'child' 2744 | end 2745 | 2746 | Parent.print_class_var # => 'child'가 출력된다. 2747 | ``` 2748 | 2749 | 상속 계층에 있는 모든 클래스는 하나의 클래스 변수를 공유한다. 클래스 2750 | 변수보다는 클래스 인스턴스 변수를 사용하는 것이 더 좋다. 2751 | 2752 | * 2753 | 메소드에는 사용되는 목적에 맞는 접근 권한(`private`, `protected`)을 부여한다. 2754 | 전부 다 기본 접근 권한인 `public` 상태로 두지 마라. 우리는 지금 *파이썬*이 2755 | 아닌 *루비* 코딩을 하고 있다.(역자주 파이썬은 명시적인 private 메소드가 없다.) 2756 | [[link](#visibility)] 2757 | 2758 | * 2759 | `public`, `protected`, `private`은 메소드 정의와 같은 레벨로 들여쓰기 한다. 2760 | 접근 제한자 아래로 모든 메소드들이 적용된다는 것을 명확하게 하기 위해 접근 2761 | 제한자 위, 아래로 빈 줄을 넣어 준다. 2762 | [[link](#indent-public-private-protected)] 2763 | 2764 | ```Ruby 2765 | class SomeClass 2766 | def public_method 2767 | # 생략 2768 | end 2769 | 2770 | private 2771 | 2772 | def private_method 2773 | # 생략 2774 | end 2775 | 2776 | def another_private_method 2777 | # 생략 2778 | end 2779 | end 2780 | ``` 2781 | 2782 | * 2783 | 클래스 메소드를 정의할 때는 `def self.method`를 사용한다. 이렇게 하면 2784 | 클래스명이 반복되지 않기 때문에 클래스명 변경으로 리펙토링할 때 좀 더 쉬워진다. 2785 | [[link](#def-self-class-methods)] 2786 | 2787 | ```Ruby 2788 | class TestClass 2789 | # 나쁜 예 2790 | def TestClass.some_method 2791 | # 내용 생략 2792 | end 2793 | 2794 | # 좋은 예 2795 | def self.some_other_method 2796 | # 내용 생략 2797 | end 2798 | 2799 | # 클래스 메소드가 많은 경우 아래와 같이 2800 | # 사용하면 편리하다. 2801 | class << self 2802 | def first_method 2803 | # 내용 생략 2804 | end 2805 | 2806 | def second_method_etc 2807 | # 내용 생략 2808 | end 2809 | end 2810 | end 2811 | ``` 2812 | 2813 | * 2814 | 엘리아스 메소드가 문법적 클래스의 범위에 있고 이 문맥에서 `self`의 범위도 2815 | 문법적이고 alias의 접근이 명시적이지 않을 때의 실행시나 서브 클래스에서 2816 | 변경되지 않는 것을 유저가 명확히 이해할 때는`alias`를 사용한다. 2817 | [[link](#alias-method-lexically)] 2818 | 2819 | ```Ruby 2820 | class Westerner 2821 | def first_name 2822 | @names.first 2823 | end 2824 | 2825 | alias given_name first_name 2826 | end 2827 | ``` 2828 | 2829 | `alias`가 `def` 같은 키워드이기 때문에, 심볼이나 문자열 대신, 생 인자를 2830 | 사용한다. 다시 말하면, `alias :foo :bar`대신 `alias foo bar`를 사용한다. 2831 | 2832 | 또 루비가 어떻게 alias와 상속을 처리하는지 알아야한다: alias는 2833 | alias가 선언되었을 때의 메소드를 참조한다. alias는 동적으로 전달되지 2834 | 않는다. 2835 | 2836 | ```Ruby 2837 | class Fugitive < Westerner 2838 | def first_name 2839 | 'Nobody' 2840 | end 2841 | end 2842 | ``` 2843 | 2844 | 이 예제에서, `Fugitive#given_name`는 `Fugitive#first_name`가 아니라 2845 | 여전히 원래의 `Westerner#first_name` 메소드를 호출한다. 2846 | `Fugitive#given_name`의 행동으로 오버라이드 하려면 파생된 클래스에서도 2847 | 재정의 해주어야 한다. 2848 | 2849 | ```Ruby 2850 | class Fugitive < Westerner 2851 | def first_name 2852 | 'Nobody' 2853 | end 2854 | 2855 | alias given_name first_name 2856 | end 2857 | ``` 2858 | 2859 | * 2860 | 모듈, 클래스, 싱글턴 클래스를 실행중에 alias 할 때는 항상 `alias_method` 2861 | 를 사용한다. 이런 경우에 `alias`의 문법적 범위로는 결과를 예측 하기 힘들다. 2862 | [[link](#alias-method)] 2863 | 2864 | ```Ruby 2865 | module Mononymous 2866 | def self.included(other) 2867 | other.class_eval { alias_method :full_name, :given_name } 2868 | end 2869 | end 2870 | 2871 | class Sting < Westerner 2872 | include Mononymous 2873 | end 2874 | ``` 2875 | 2876 | * 2877 | 클래스나 모듈 메소드가 서로를 호출하는 경우에 `self`나 `.`을 포함한 자신의 2878 | 이름을 생략해라. 이는 클래스를 함수인 것처럼 사용하는 '서비스 클래스'나 다른 2879 | 비슷한 컨셉에서 많이 볼 수 있다. 이는 그러한 클래스를 만들 때의 반복 작업을 2880 | 줄이기 위한 의도를 가지고 있다. 2881 | [[link](#class-and-self)] 2882 | 2883 | ```Ruby 2884 | class TestClass 2885 | # 나쁜 예 -- 클래스의 이름이 바뀌거나 메소드의 위치가 바뀔 때 해야 할 작업이 더 많다 2886 | def self.call(param1, param2) 2887 | TestClass.new(param1).call(param2) 2888 | end 2889 | 2890 | # 나쁜 예 -- 필요 이상으로 장황하다 2891 | def self.call(param1, param2) 2892 | self.new(param1).call(param2) 2893 | end 2894 | 2895 | # 좋은 예 2896 | def self.call(param1, param2) 2897 | new(param1).call(param2) 2898 | end 2899 | 2900 | # ...다른 메소드들... 2901 | end 2902 | ``` 2903 | 2904 | ## 예외 2905 | 2906 | * 2907 | 예외를 발생 시킬때 `fail`대신 `raise`를 사용한다. 2908 | [[link](#prefer-raise-over-fail)] 2909 | 2910 | ```Ruby 2911 | # 나쁜 예 2912 | fail SomeException, 'message' 2913 | 2914 | # 좋은 예 2915 | raise SomeException, 'message' 2916 | ``` 2917 | 2918 | * 2919 | `raise`를 사용할 때 `RuntimeError`를 첫 번째 인수로 하는 메소드는 사용하지 2920 | 않는다. 2921 | [[link](#no-explicit-runtimeerror)] 2922 | 2923 | ```Ruby 2924 | # 나쁜 예 2925 | raise RuntimeError, 'message' 2926 | 2927 | # 좋은 예 - 기본적으로 RuntimeError가 발생한다. 2928 | raise 'message' 2929 | ``` 2930 | 2931 | * 2932 | 예외 인스턴스를 생성해서 `raise`를 하는 것보다 `raise`의 첫 번째 2933 | 인수에 예외 클래스를 넘기는 메소드를 사용하는 것이 더 좋다. 2934 | [[link](#exception-class-messages)] 2935 | 2936 | ```Ruby 2937 | # 나쁜 예 2938 | raise SomeException.new('message') 2939 | # `raise SomeException.new('message'), backtrace` 이렇게 쓸 수 는 없다. 2940 | 2941 | # 좋은 예 2942 | raise SomeException, 'message' 2943 | # `raise SomeException, 'message', backtrace`와 일관성이 있다. 2944 | ``` 2945 | 2946 | * 2947 | `ensure` 블록에서 리턴하지 마라. `ensure` 안에서 명시적으로 리턴을 하면 예외가 2948 | 발생하기 전에 리턴이 되고 예외가 발생하지 않은 것처럼 동작할 것이다. 2949 | [[link](#no-return-ensure)] 2950 | 2951 | ```Ruby 2952 | # 나쁜 예 2953 | def foo 2954 | raise 2955 | ensure 2956 | return '매우 안좋은 생각' 2957 | end 2958 | ``` 2959 | 2960 | * 2961 | 가능하면 *함축적인 begin 블록*을 사용한다. 2962 | [[link](#begin-implicit)] 2963 | 2964 | ```Ruby 2965 | # 나쁜 예 2966 | def foo 2967 | begin 2968 | # 메인 로직은 여기에 2969 | rescue 2970 | # 실패처리는 여기에 2971 | end 2972 | end 2973 | 2974 | # 좋은 예 2975 | def foo 2976 | # 메인 로직은 여기에 2977 | rescue 2978 | # 실패처리는 여기에 2979 | end 2980 | ``` 2981 | 2982 | * 2983 | `begin` 블록이 많아지는 것을 줄이기 위해서 *contingency 메소드*를 사용한다. 2984 | (용어는 Avdi Grimm가 만들었다). 2985 | [[link](#contingency-methods)] 2986 | 2987 | ```Ruby 2988 | # 나쁜 예 2989 | begin 2990 | something_that_might_fail 2991 | rescue IOError 2992 | # IOError 처리 2993 | end 2994 | 2995 | begin 2996 | something_else_that_might_fail 2997 | rescue IOError 2998 | # IOError 처리 2999 | end 3000 | 3001 | # 좋은 예 3002 | def with_io_error_handling 3003 | yield 3004 | rescue IOError 3005 | # IOError 처리 3006 | end 3007 | 3008 | with_io_error_handling { something_that_might_fail } 3009 | 3010 | with_io_error_handling { something_else_that_might_fail } 3011 | ``` 3012 | 3013 | * 3014 | 예외를 먹지 마라. 3015 | [[link](#dont-hide-exceptions)] 3016 | 3017 | ```Ruby 3018 | # 나쁜 예 3019 | begin 3020 | # 여기에서 예외가 발생한다. 3021 | rescue SomeError 3022 | # rescue 절에서 아무것도 하지 않는다. 3023 | end 3024 | 3025 | # 나쁜 예 3026 | do_something rescue nil 3027 | ``` 3028 | 3029 | * 3030 | `rescue`를 사용할 때 구문 변경자 사용을 피한다. 3031 | [[link](#no-rescue-modifiers)] 3032 | 3033 | ```Ruby 3034 | # 나쁜 예 - 여기서 StandardError 예외와 StandardError를 상속한 예외들을 잡는다. 3035 | read_file rescue handle_error($!) 3036 | 3037 | # 좋은 예 - 여기서 Error::ENOENT 예외와 Error:ENOENT를 상속한 예외들만 잡는다. 3038 | def foo 3039 | read_file 3040 | rescue Errno::ENOENT => ex 3041 | handle_error(ex) 3042 | end 3043 | ``` 3044 | 3045 | * 3046 | 예외를 흐름 제어에 사용하지 마라. 3047 | [[link](#no-exceptional-flows)] 3048 | 3049 | ```Ruby 3050 | # 나쁜 예 3051 | begin 3052 | n / d 3053 | rescue ZeroDivisionError 3054 | puts 'Cannot divide by 0!' 3055 | end 3056 | 3057 | # 좋은 예 3058 | if d.zero? 3059 | puts 'Cannot divide by 0!' 3060 | else 3061 | n / d 3062 | end 3063 | ``` 3064 | 3065 | * 3066 | `Exception`을 rescue 하는 것을 피한다. 그렇게 하면 `exit`를 잡기 위해서 3067 | 프로세스에 `kill -9`가 필요하다.(역자주 Exception은 루비의 최상위 예외 3068 | 클래스인데 Interrupt나 SyntaxError 등도 포함된다. Interrupt를 rescue 하면 3069 | Ctrl+C로 프로그램을 종료할 수 없다. `kill -9`로는 종료가 가능하다. 또 3070 | eval 등으로 동적으로 코드를 로드할 때 발생할지도 모르는 SyntaxError도 예상치 3071 | 못하게 잡게 되어 적절한 처리를 못할지도 모른다. 3072 | http://stackoverflow.com/questions/10048173/why-is-it-bad-style-to-rescue-exception-e-in-ruby) 3073 | [[link](#no-blind-rescues)] 3074 | 3075 | ```Ruby 3076 | # 나쁜 예 3077 | begin 3078 | # exit를 호출하면 kill 시그널이 잡힌다.(kill -9는 제외) 3079 | exit 3080 | rescue Exception 3081 | puts "you didn't really want to exit, right?" 3082 | # 예외 처리 3083 | end 3084 | 3085 | # 좋은 예 3086 | begin 3087 | # 많은 개발자들의 예상하는 Exception 대신 StandardError를 잡게된다. 3088 | rescue => e 3089 | # 예외 처리 3090 | end 3091 | 3092 | # 이것도 좋은 예 3093 | begin 3094 | # 여기서 예외 발생 3095 | rescue StandardError => e 3096 | # 예외 처리 3097 | end 3098 | ``` 3099 | 3100 | * 3101 | rescue를 이어서 사용할 때는 더 구체적인 예외부터 순서대로 작성한다. 그렇지 3102 | 않으면 rescue에 안 걸릴 수 있다. 3103 | [[link](#exception-ordering)] 3104 | 3105 | ```Ruby 3106 | # 나쁜 예 3107 | begin 3108 | # 코드 3109 | rescue StandardError => e 3110 | # 예외 처리 3111 | rescue IOError => e 3112 | # 여기는 실행되지 않는다. 3113 | end 3114 | 3115 | # 좋은 예 3116 | begin 3117 | # 코드 3118 | rescue IOError => e 3119 | # 예외 처리 3120 | rescue StandardError => e 3121 | # 에외 처리 3122 | end 3123 | ``` 3124 | 3125 | * 3126 | `ensure` 블록에서 사용했던 자원을 모두 반환한다. 3127 | [[link](#release-resources)] 3128 | 3129 | ```Ruby 3130 | f = File.open('testfile') 3131 | begin 3132 | # .. process 3133 | rescue 3134 | # .. handle error 3135 | ensure 3136 | f.close unless f.nil? 3137 | end 3138 | ``` 3139 | 3140 | * 3141 | 가능한 한 자동으로 리소스를 정리해주는 버전의 메소드를 사용한다. 3142 | [[link](#auto-release-resources)] 3143 | 3144 | ```Ruby 3145 | # 나쁜 예 - 파일 서술자를 명시적으로 닫아야 함 3146 | f = File.open('testfile') 3147 | # 파일 처리 작업 3148 | f.close 3149 | 3150 | # 좋은 예 - 파일 서술자가 자동으로 닫힘 3151 | File.open('testfile') do |f| 3152 | # 파일 처리 작업 3153 | end 3154 | ``` 3155 | 3156 | * 3157 | 표준 라이브러리에 있는 예외보다는 새로운 예외 클래스를 만들어 사용하는 것이 3158 | 더 좋다. 3159 | [[link](#standard-exceptions)] 3160 | 3161 | ## 컬렉션 3162 | 3163 | * 3164 | 배열과 해시 생성 노테이션을 사용한다.(생성자에 매개변수를 전달하지 않는다면) 3165 | [[link](#literal-array-hash)] 3166 | 3167 | ```Ruby 3168 | # 나쁜 예 3169 | arr = Array.new 3170 | hash = Hash.new 3171 | 3172 | # 좋은 예 3173 | arr = [] 3174 | hash = {} 3175 | ``` 3176 | 3177 | * 3178 | 단어에 대한 배열이 필요할 때는 `%w` 리터럴을 사용한다.(공백이나 특수문자가 3179 | 없는 비어 있지 않은 문자열) 두 개 이상의 항목을 가질 때만 이 규칙을 적용한다. 3180 | [[link](#percent-w)] 3181 | 3182 | ```Ruby 3183 | # 나쁜 예 3184 | STATES = ['draft', 'open', 'closed'] 3185 | 3186 | # 좋은 예 3187 | STATES = %w[draft open closed] 3188 | ``` 3189 | 3190 | * 3191 | 심볼에 대한 배열이 필요할 때는 `%i` 리터럴을 사용한다.(루비 1.9와 호환성이 3192 | 필요 없는 경우) 두 개 이상의 항목을 가질 때만 이 규칙을 적용한다. 3193 | [[link](#percent-i)] 3194 | 3195 | ```Ruby 3196 | # 나쁜 예 3197 | STATES = [:draft, :open, :closed] 3198 | 3199 | # 좋은 예 3200 | STATES = %i[draft open closed] 3201 | ``` 3202 | 3203 | * 3204 | 배열이나 해시의 마지막 항목에 콤마를 사용하지 마라. 특히 항목이 여러 줄로 3205 | 나뉘어 있는 경우가 아니라면 더 사용하지 마라. 3206 | [[link](#no-trailing-array-commas)] 3207 | 3208 | ```Ruby 3209 | # 나쁜 예 - 항목을 이동/추가/삭제 하는 것이 쉽지만 사용하지 마라. 3210 | VALUES = [ 3211 | 1001, 3212 | 2020, 3213 | 3333, 3214 | ] 3215 | 3216 | # 나쁜 예 3217 | VALUES = [1001, 2020, 3333, ] 3218 | 3219 | # 좋은 예 3220 | VALUES = [1001, 2020, 3333] 3221 | ``` 3222 | 3223 | * 3224 | 큰 빈 공간을 가진 배열을 생성하지 마라. 3225 | [[link](#no-gappy-arrays)] 3226 | 3227 | ```Ruby 3228 | arr = [] 3229 | arr[100] = 1 # 많은 nil 값을 가지는 배열이 생성되었다. 3230 | ``` 3231 | 3232 | * 3233 | 배열의 첫 번째나 마지막 항목에 접근할 때 `[0]` 또는 `[-1]` 대신 `first`나 3234 | `last`를 사용하라. 3235 | [[link](#first-and-last)] 3236 | 3237 | * 3238 | 유일한 항목을 다룰 때는 `Array` 대신 `Set`을 사용하라. `Set`은 중복이 없고 3239 | 정렬되지 않은 항목을 다룰 수 있는 컬렉션 구현체이다. `Set`은 배열의 직관적인 3240 | 동작들과 `Hash`의 빠른 조회 특성을 모두 가지고 있다. 3241 | [[link](#set-vs-array)] 3242 | 3243 | * 3244 | 해시 키는 문자열 보다 심볼을 사용하는 것이 좋다. 3245 | [[link](#symbols-as-keys)] 3246 | 3247 | ```Ruby 3248 | # 나쁜 예 3249 | hash = { 'one' => 1, 'two' => 2, 'three' => 3 } 3250 | 3251 | # 좋은 예 3252 | hash = { one: 1, two: 2, three: 3 } 3253 | ``` 3254 | 3255 | * 3256 | 변경 가능한 객체를 해시 키로 사용하지 마라. 3257 | [[link](#no-mutable-keys)] 3258 | 3259 | * 3260 | 해시 키가 심볼인 경우 루비 1.9 해시 리터럴을 사용하라. 3261 | [[link](#hash-literals)] 3262 | 3263 | ```Ruby 3264 | # 나쁜 예 3265 | hash = { :one => 1, :two => 2, :three => 3 } 3266 | 3267 | # 좋은 예 3268 | hash = { one: 1, two: 2, three: 3 } 3269 | ``` 3270 | 3271 | * 3272 | 하나의 해시에 루비 1.9 해시 문법과 기존 해시 문법을 섞어 쓰지 마라. 심볼이 3273 | 아닌 키가 포함되어 있다면 이전의 해시 문법을 사용하라. 3274 | [[link](#no-mixed-hash-syntaces)] 3275 | 3276 | ```Ruby 3277 | # 나쁜 예 3278 | { a: 1, 'b' => 2 } 3279 | 3280 | # 좋은 예 3281 | { :a => 1, 'b' => 2 } 3282 | ``` 3283 | 3284 | * 3285 | `Hash#has_key?` 대신 `Hash#key?`, `Hash#has_value?` 대신 `Hash#value?`를 3286 | 사용하라. 3287 | [[link](#hash-key)] 3288 | 3289 | ```Ruby 3290 | # 나쁜 예 3291 | hash.has_key?(:test) 3292 | hash.has_value?(value) 3293 | 3294 | # 좋은 예 3295 | hash.key?(:test) 3296 | hash.value?(value) 3297 | ``` 3298 | 3299 | * 3300 | `Hash#keys.each` 대신 `Hash#each_key`를, `Hash#values.each` 대신 3301 | `Hash#each_value`를 사용하라. 3302 | [[link](#hash-each)] 3303 | 3304 | ```Ruby 3305 | # 나쁜 예 3306 | hash.keys.each { |k| p k } 3307 | hash.values.each { |v| p v } 3308 | hash.each { |k, _v| p k } 3309 | hash.each { |_k, v| p v } 3310 | 3311 | # 좋은 예 3312 | hash.each_key { |k| p k } 3313 | hash.each_value { |v| p v } 3314 | ``` 3315 | 3316 | * 3317 | 해시 키로 명확히 있어야 하는 값을 다룰 때에는 `Hash#fetch`를 사용하라. 3318 | [[link](#hash-fetch)] 3319 | 3320 | ```Ruby 3321 | heroes = { batman: 'Bruce Wayne', superman: 'Clark Kent' } 3322 | # 나쁜 예 - 만약 실수가 있다고 한다면 알아채지 못할 수 있다. 3323 | heroes[:batman] # => 'Bruce Wayne' 3324 | heroes[:supermann] # => nil 3325 | 3326 | # 좋은 예 - 문제를 명확하게 하기 위해서 KeyError 예외가 발생한다. 3327 | heroes.fetch(:supermann) 3328 | ``` 3329 | 3330 | * 3331 | 해시 값에 기본 값을 사용하는 경우 커스텀 로직보다는 `Hash#fetch`를 사용하라. 3332 | [[link](#hash-fetch-defaults)] 3333 | 3334 | ```Ruby 3335 | batman = { name: 'Bruce Wayne', is_evil: false } 3336 | 3337 | # 나쁜 예 - 그냥 || 연산자를 사용한다면 예상하지 못한 결과를 얻을 수도 있다. 3338 | batman[:is_evil] || true # => true 3339 | 3340 | # 좋은 예 - 제대로 된 false 값을 얻을 수 있다. 3341 | batman.fetch(:is_evil, true) # => false 3342 | ``` 3343 | 3344 | * 3345 | `Hash#fetch` 기본 값 대신 블록을 사용하는 것이 좋다. 3346 | 실행해야 할 코드는 부작용이 있을 수도 있고, 실행 비용이 비쌀 수도 있다. 3347 | [[link](#use-hash-blocks)] 3348 | 3349 | ```Ruby 3350 | batman = { name: 'Bruce Wayne' } 3351 | 3352 | # 나쁜 예 - 만약 기본 값을 사용하는 경우, 함수가 먼저 실행이 되므로 3353 | # 여러 번 실행되는 경우 프로그램이 느려질 수 있다. 3354 | batman.fetch(:powers, obtain_batman_powers) # obtain_batman_powers는 오래 걸리는 함수이다. 3355 | 3356 | # good - 블록은 나중에 실행된다. 그래서 KeyError 예외가 발생하는 경우만 실행된다. 3357 | batman.fetch(:powers) { obtain_batman_powers } 3358 | ``` 3359 | 3360 | * 3361 | 해시에서 여러 개의 값을 가져오고 싶다면 `Hash#values_at`을 사용하라. 3362 | [[link](#hash-values-at)] 3363 | 3364 | ```Ruby 3365 | # 나쁜 예 3366 | email = data['email'] 3367 | username = data['nickname'] 3368 | 3369 | # 좋은 예 3370 | email, username = data.values_at('email', 'nickname') 3371 | ``` 3372 | 3373 | * 3374 | Ruby 1.9의 해시는 순서가 보장된다는 것을 기억하자. 3375 | [[link](#ordered-hashes)] 3376 | 3377 | * 3378 | 컬렉션을 순회하는 동안 컬렉션을 수정하지 마라. 3379 | [[link](#no-modifying-collections)] 3380 | 3381 | * 3382 | 컬렉션의 요소에 접근할 때는, 가능한 한 리더 메소드의 다른 형식을 사용해 `[n]`을 3383 | 통한 직접 접근을 피한다. 이는 `nil`에 `[]`를 호출하는 것을 방지한다. 3384 | [[link](#accessing-elements-directly)] 3385 | 3386 | ```Ruby 3387 | # 나쁜 예 3388 | Regexp.last_match[1] 3389 | 3390 | # 좋은 예 3391 | Regexp.last_match(1) 3392 | ``` 3393 | 3394 | * 3395 | 컬렉션의 접근자를 만들 때에는, 다른 형식을 제공해 사용자가 컬렉션의 요소에 3396 | 접근하기 전에 `nil`을 체크하지 않도록 한다. 3397 | [[link](#provide-alternate-accessor-to-collections)] 3398 | 3399 | ```Ruby 3400 | # 나쁜 예 3401 | def awesome_things 3402 | @awesome_things 3403 | end 3404 | 3405 | # 좋은 예 3406 | def awesome_things(index = nil) 3407 | if index && @awesome_things 3408 | @awesome_things[index] 3409 | else 3410 | @awesome_things 3411 | end 3412 | end 3413 | ``` 3414 | 3415 | ## 숫자 3416 | 3417 | * 3418 | 정수의 타입 확인에 `Integer`를 사용하라. `Fixnum`은 플랫폼 의존적이기 때문에 3419 | 이걸로 확인하면 32 비트와 64 비트 기기에서 다른 결과를 반환한다. 3420 | [[link](#integer-type-checking)] 3421 | 3422 | ```Ruby 3423 | timestamp = Time.now.to_i 3424 | 3425 | # 나쁜 예 3426 | timestamp.is_a? Fixnum 3427 | timestamp.is_a? Bignum 3428 | 3429 | # 좋은 예 3430 | timestamp.is_a? Integer 3431 | ``` 3432 | 3433 | * 3434 | 난수를 생성할 때 정수와 오프셋 대신 범위를 사용하라. 3435 | 의도를 더 명확히 표현할 수 있다. 주사위를 굴리는 상황을 생각해 보자. 3436 | [[link](#random-numbers)] 3437 | 3438 | ```Ruby 3439 | # 나쁜 예 3440 | rand(6) + 1 3441 | 3442 | # 좋은 예 3443 | rand(1..6) 3444 | ``` 3445 | 3446 | ## 문자열 3447 | 3448 | * 3449 | 문자열을 합치는 것보다 포맷팅이나 문자열 삽입을 사용하는 것이 더 좋다. 3450 | [[link](#pad-string-interpolation)] 3451 | 3452 | ```Ruby 3453 | # 나쁜 예 3454 | email_with_name = user.name + ' <' + user.email + '>' 3455 | 3456 | # 좋은 예 3457 | email_with_name = "#{user.name} <#{user.email}>" 3458 | 3459 | # 좋은 예 3460 | email_with_name = format('%s <%s>', user.name, user.email) 3461 | ``` 3462 | 3463 | * 3464 | 일관된 문자열 따옴표 스타일을 선택한다. 루비 커뮤니티에는 많이 사용하는 두 가지 3465 | 스타일이 있는데 둘 다 괜찮다. 하나는 작은따옴표를 사용하는 방식(A 방식)이고 3466 | 다른 하나는 큰따옴표를 사용하는 방식이다(B 방식). 3467 | [[link](#consistent-string-literals)] 3468 | 3469 | * **(A 방식)**`\t`, `\n`, `'` 등의 특수문자나 문자열 삽입이 필요 없는 경우는 3470 | 작은따옴표를 사용하는 것이 좋다. 3471 | 3472 | ```Ruby 3473 | # 나쁜 예 3474 | name = "Bozhidar" 3475 | 3476 | # 좋은 예 3477 | name = 'Bozhidar' 3478 | ``` 3479 | 3480 | * **(B 방식)** `"`를 포함하지 않거나 이스케이프된 특수문자를 제한할 필요가 3481 | 없는 경우에는 큰따옴표를 사용한다. 3482 | 3483 | ```Ruby 3484 | # 나쁜 예 3485 | name = 'Bozhidar' 3486 | 3487 | # 좋은 예 3488 | name = "Bozhidar" 3489 | ``` 3490 | 3491 | 이 가이드에서 문자열 리터럴은 첫 번째 스타일로 통일한다. 3492 | 3493 | * 3494 | 문자 리터럴인 `?x`는 사용하지 않는다. 루비 1.9에서는 기본적으로 필요 없다. 3495 | `?x`는 `'x'`로 해석된다.(문자 하나가 포함된 문자열) 3496 | [[link](#no-character-literals)] 3497 | 3498 | ```Ruby 3499 | # 나쁜 예 3500 | char = ?c 3501 | 3502 | # 좋은 예 3503 | char = 'c' 3504 | ``` 3505 | 3506 | * 3507 | 인스턴스 변수나 글로벌 변수를 가지고 문자열 삽입하는 경우 `{}`를 없애지 마라. 3508 | [[link](#curlies-interpolate)] 3509 | 3510 | ```Ruby 3511 | class Person 3512 | attr_reader :first_name, :last_name 3513 | 3514 | def initialize(first_name, last_name) 3515 | @first_name = first_name 3516 | @last_name = last_name 3517 | end 3518 | 3519 | # 나쁜 예 - 동작하지만 어색함 3520 | def to_s 3521 | "#@first_name #@last_name" 3522 | end 3523 | 3524 | # 좋은 예 3525 | def to_s 3526 | "#{@first_name} #{@last_name}" 3527 | end 3528 | end 3529 | 3530 | $global = 0 3531 | # 나쁜 예 3532 | puts "$global = #$global" 3533 | 3534 | # 좋은 예 3535 | puts "$global = #{$global}" 3536 | ``` 3537 | 3538 | * 3539 | 문자열 삽입에 `Object#to_s`를 사용하지 마라. 이건 자동으로 호출된다. 3540 | [[link](#no-to-s)] 3541 | 3542 | ```Ruby 3543 | # 나쁜 예 3544 | message = "This is the #{result.to_s}." 3545 | 3546 | # 좋은 예 3547 | message = "This is the #{result}." 3548 | ``` 3549 | 3550 | * 3551 | 큰 문자열 데이터가 필요할 때 `String#+`를 사용하지 마라. 대신 `String#<<`를 3552 | 사용하라. 문자열 자체를 변경하는 것이 새로운 문자열 객체를 생성하는 3553 | `String#+`보다 항상 빠르다. 3554 | [[link](#concat-strings)] 3555 | 3556 | ```Ruby 3557 | # 나쁜 예 3558 | html = '' 3559 | html += '

Page title

' 3560 | 3561 | paragraphs.each do |paragraph| 3562 | html += "

#{paragraph}

" 3563 | end 3564 | 3565 | # 좋고 더 빠르다 3566 | html = '' 3567 | html << '

Page title

' 3568 | 3569 | paragraphs.each do |paragraph| 3570 | html << "

#{paragraph}

" 3571 | end 3572 | ``` 3573 | 3574 | * 3575 | 다른 더 빠른 대안이 있을 때 `String#gsub`를 사용하지 마라. 3576 | [[link](#dont-abuse-gsub)] 3577 | 3578 | ```Ruby 3579 | url = 'http://example.com' 3580 | str = 'lisp-case-rules' 3581 | 3582 | # 나쁜 예 3583 | url.gsub('http://', 'https://') 3584 | str.gsub('-', '_') 3585 | 3586 | # 좋은 예 3587 | url.sub('http://', 'https://') 3588 | str.tr('-', '_') 3589 | ``` 3590 | 3591 | * 3592 | 여러 줄로 heredoc을 사용할 때 공백 문자들이 유지된다는 사실을 잊지 말자. 특정 3593 | 기준을 정하고 나머지 불필요한 공백을 모두 없애는 것이 좋은 방법이다. 3594 | [[link](#heredocs)] 3595 | 3596 | ```Ruby 3597 | code = <<-END.gsub(/^\s+\|/, '') 3598 | |def test 3599 | | some_method 3600 | | other_method 3601 | |end 3602 | END 3603 | # => "def test\n some_method\n other_method\nend\n" 3604 | ``` 3605 | 3606 | * 3607 | 루비 2.3의 물결표 히어독은 여러 줄의 문자열의 들여쓰기에 좋다. 3608 | [[link](#squiggly-heredocs)] 3609 | 3610 | ```Ruby 3611 | # 나쁜 예 - Powerpack String#strip_margin 사용 3612 | code = <<-END.strip_margin('|') 3613 | |def test 3614 | | some_method 3615 | | other_method 3616 | |end 3617 | END 3618 | 3619 | # 나쁜 예 3620 | code = <<-END 3621 | def test 3622 | some_method 3623 | other_method 3624 | end 3625 | END 3626 | 3627 | # 좋은 예 3628 | code = <<~END 3629 | def test 3630 | some_method 3631 | other_method 3632 | end 3633 | END 3634 | ``` 3635 | 3636 | ## 날짜 및 시간 3637 | 3638 | * 3639 | 시스템의 현재 시각을 가져올 때 `Time.new` 대신 `Time.now`를 사용한다. 3640 | [[link](#time-now)] 3641 | 3642 | * 3643 | 구시대의 달력이 필요한 것이 아니라면 `DateTime`을 사용하지 않는다. 필요할 3644 | 때에는 `start` 인자를 명시적으로 지정해서 의도를 확실히 나타낸다. 3645 | [[link](#no-datetime)] 3646 | 3647 | ```Ruby 3648 | # 나쁜 예 - 현재 시각을 위해 DateTime을 사용함 3649 | DateTime.now 3650 | 3651 | # 좋은 예 - 현재 시각을 위해 Time을 사용함 3652 | Time.now 3653 | 3654 | # 나쁜 예 - 그레고리력 날짜를 위해 DateTime을 사용함 3655 | DateTime.iso8601('2016-06-29') 3656 | 3657 | # 좋은 예 - 그레고리력 날짜를 위해 Date를 사용함 3658 | Date.iso8601('2016-06-29') 3659 | 3660 | # 좋은 예 - 율리우스력 날짜를 위해 DateTime을 start 인자와 함께 사용함 3661 | DateTime.iso8601('1751-04-23', Date::ENGLAND) 3662 | ``` 3663 | 3664 | ## 정규식 3665 | 3666 | > 어떤 사람들은 문제에 직면했을 때 다음과 같이 생각한다.
3667 | > "음 알았어, 난 정규식을 사용 할 거야." 이제 그들에게는 두 개의 문제가 생겼다.
3668 | > -- Jamie Zawinski 3669 | 3670 | * 3671 | 문자열 안에 단순한 텍스트를 찾는 것이라면 정규식을 사용하지 마라. `string['text']` 3672 | [[link](#no-regexp-for-plaintext)] 3673 | 3674 | * 3675 | 간단한 생성을 위해서 문자열 인덱스에 정규식을 바로 사용할 수 있다. 3676 | [[link](#regexp-string-index)] 3677 | 3678 | ```Ruby 3679 | match = string[/regexp/] # regexp과 매칭 되는 문자열을 가져온다. 3680 | first_group = string[/text(grp)/, 1] # 정규식 그룹에 있는 값을 뽑아 낸다. 3681 | string[/text (grp)/, 1] = 'replace' # 정규식 그룹에 있는 값을 새로운 값으로 바꾼다. 3682 | ``` 3683 | 3684 | * 3685 | 정규식 그룹에서 값을 뽑아서 사용하지 않는다면 non-capturing 그룹을 사용하라. 3686 | [[link](#non-capturing-regexp)] 3687 | 3688 | ```Ruby 3689 | # 나쁜 예 3690 | /(first|second)/ 3691 | 3692 | # 좋은 예 3693 | /(?:first|second)/ 3694 | ``` 3695 | 3696 | * 3697 | 정규식 그룹에서 값을 사용할 때(`$1`, `$2` 등)처럼 암호문 같은 펄 변수 3698 | 기호를 사용하지 마라. 대신 `Regexp.last_match(n)`를 사용하라. 3699 | [[link](#no-perl-regexp-last-matchers)] 3700 | 3701 | ```Ruby 3702 | /(regexp)/ =~ string 3703 | # 생략 3704 | 3705 | # 나쁜 예 3706 | process $1 3707 | 3708 | # 좋은 예 3709 | process Regexp.last_match(1) 3710 | ``` 3711 | 3712 | * 3713 | 정규식 그룹에서 값을 사용할 때 숫자 형식은 안에 뭐가 있는지 알아보기 힘들기 3714 | 때문에 사용을 피한다. 대신 이름 기반의 정규식 그룹을 사용한다. 3715 | [[link](#no-numbered-regexes)] 3716 | 3717 | ```Ruby 3718 | # 나쁜 예 3719 | /(regexp)/ =~ string 3720 | # 생략 3721 | process Regexp.last_match(1) 3722 | 3723 | # 좋은 예 3724 | /(?regexp)/ =~ string 3725 | # 생략 3726 | process meaningful_var 3727 | ``` 3728 | 3729 | * 3730 | 문자들 중에 몇 개의 문자(`^`, `-`, `\`, `]`)만 특수문자로 다뤄지기 때문에 3731 | `[]` 안에서 `.`을 이스케이프 하면 안 된다. 3732 | [[link](#limit-escapes)] 3733 | 3734 | * 3735 | 줄의 시작과 끝을 다루는 `^`와 `$`는 문자열의 시작과 끝이 아니기 때문에 3736 | 주의해서 사용해야 한다. 만약 문자열 전체를 매칭하는 경우에는 `\A`와 `\z`를 3737 | 사용한다.(`/\n?\z/`와 같은 `\Z`와 혼동하지 않는다.) 3738 | [[link](#caret-and-dollar-regexp)] 3739 | 3740 | ```Ruby 3741 | string = "some injection\nusername" 3742 | string[/^username$/] # 찾음 3743 | string[/\Ausername\z/] # 못 찾음 3744 | ``` 3745 | 3746 | * 3747 | 복잡한 정규식에 `x`를 사용한다. `x`를 사용하면 좀 더 읽기 좋아지고 유용한 3748 | 주석도 추가할 수 있다. 공백이 무시되는 것에 주의 한다. 3749 | [[link](#comment-regexes)] 3750 | 3751 | ```Ruby 3752 | regexp = / 3753 | start # some text 3754 | \s # white space char 3755 | (group) # first group 3756 | (?:alt1|alt2) # some alternation 3757 | end 3758 | /x 3759 | ``` 3760 | 3761 | * 3762 | `sub`/`gsub`를 사용해서 복잡한 치환을 하는 경우 블록이나 해시를 사용할 수 있다. 3763 | [[link](#gsub-blocks)] 3764 | 3765 | ```Ruby 3766 | words = 'foo bar' 3767 | words.sub(/f/, 'f' => 'F') # => 'Foo bar' 3768 | words.gsub(/\w+/) { |word| word.capitalize } # => 'Foo Bar' 3769 | ``` 3770 | 3771 | ## 퍼센트 리터럴 3772 | 3773 | * 3774 | 큰따옴표와 문자열 삽입이 필요한 한 줄 문자열에만 `%()`(`%Q`의 짧은 표현)를 3775 | 사용한다. 여러 줄의 문자열은 heredoc을 사용한다. 3776 | [[link](#percent-q-shorthand)] 3777 | 3778 | ```Ruby 3779 | # 나쁜 예(문자열 삽입이 없다) 3780 | %(
Some text
) 3781 | # should be '
Some text
' 3782 | 3783 | # 나쁜 예(큰따옴표가 없다) 3784 | %(This is #{quality} style) 3785 | # should be "This is #{quality} style" 3786 | 3787 | # 나쁜 예(여러 줄이다) 3788 | %(
\n#{exclamation}\n
) 3789 | # should be a heredoc. 3790 | 3791 | # 좋은 예(한 줄에 큰따옴표와 문자열 삽입이 필요하다) 3792 | %(#{name}) 3793 | ``` 3794 | 3795 | * 3796 | `'`와 `"`가 둘 다 들어있는 문자열이 아닌 경우에 %()나 %q()와 같은 것들의 3797 | 사용을 피한다. 일반 문자열 리터럴이 더 읽기 좋고 이스케이프 할 문자가 많지 3798 | 않은 경우에는 더 좋다. 3799 | [[link](#percent-q)] 3800 | 3801 | ```Ruby 3802 | # 나쁜 예 3803 | name = %q(Bruce Wayne) 3804 | time = %q(8 o'clock) 3805 | question = %q("What did you say?") 3806 | 3807 | # 좋은 예 3808 | name = 'Bruce Wayne' 3809 | time = "8 o'clock" 3810 | question = '"What did you say?"' 3811 | quote = %q(

"What did you say?"

) 3812 | ``` 3813 | 3814 | * 3815 | *적어도* 하나의 '/' 문자가 있는 경우에만 `%r`을 사용한다. 3816 | [[link](#percent-r)] 3817 | 3818 | ```Ruby 3819 | # 나쁜 예 3820 | %r{\s+} 3821 | 3822 | # 좋은 예 3823 | %r{^/(.*)$} 3824 | %r{^/blog/2011/(.*)$} 3825 | ``` 3826 | 3827 | * 3828 | 실행하려는 명령어 안에 역따옴표가 있는 경우에만(흔하지는 않지만) `%x`를 사용한다. 3829 | [[link](#percent-x)] 3830 | 3831 | ```Ruby 3832 | # 나쁜 예 3833 | date = %x(date) 3834 | 3835 | # 좋은 예 3836 | date = `date` 3837 | echo = %x(echo `date`) 3838 | ``` 3839 | 3840 | * 3841 | `%s`의 사용은 피한다. 루비 커뮤니티에서는 공백이 포함된 심볼을 만들 때는 3842 | `:"문자열"`을 사용하기로 결정한 것으로 보인다. 3843 | [[link](#percent-s)] 3844 | 3845 | * 3846 | 대부분의 경우 퍼센트 리터럴에서는 괄호를 사용하라. 3847 | [[link](#percent-literal-braces)] 3848 | - 문자열 리터럴(`%q`, `%Q`)은 `()`를 사용한다. 3849 | - 배열 리터럴(`%w`, `%i`, `%W`, `%I`)은 표준 배열 리터럴과 동일한 `[]`를 사용한다. 3850 | - 정규표현식 리터럴(`%r`)은 정규표현식 내부에서 괄호를 빈번하게 사용하기 때문에 3851 | `{}`를 사용한다. 그런 이유로 덜 흔하게 사용되는 `{`이 `%r` 리터럴에 가장 좋다. 3852 | - 그 이외의 모든 리터럴(예: `%s`, `%x`)은 `()`를 사용한다. 3853 | 3854 | ```Ruby 3855 | # 나쁜 예 3856 | %q{"Test's king!", John said.} 3857 | 3858 | # 좋은 예 3859 | %q("Test's king!", John said.) 3860 | 3861 | # 나쁜 예 3862 | %w(one two three) 3863 | %i(one two three) 3864 | 3865 | # 좋은 예 3866 | %w[one two three] 3867 | %i[one two three] 3868 | 3869 | # 나쁜 예 3870 | %r((\w+)-(\d+)) 3871 | %r{\w{1,2}\d{2,5}} 3872 | 3873 | # 좋은 예 3874 | %r{(\w+)-(\d+)} 3875 | %r|\w{1,2}\d{2,5}| 3876 | ``` 3877 | 3878 | ## 메타프로그래밍 3879 | 3880 | * 3881 | 쓸데없는 메타프로그래밍은 하지 마라. 3882 | [[link](#no-needless-metaprogramming)] 3883 | 3884 | * 3885 | 라이브러리를 작성할 때 코어 클래스를 망쳐놓지 마라.(거기에 Monkey-patch를 3886 | 하지 마라.) 3887 | [[link](#no-monkey-patching)] 3888 | 3889 | * 3890 | `class_eval` 폼 블록은 문자열 삽입 폼보다 더 좋다. 3891 | [[link](#block-class-eval)] 3892 | 3893 | - 문자열 삽입 폼을 사용할 때는 백트레이스를 위해서 항상 `__FILE__`과 3894 | `__LINE__`을 써야 한다. 3895 | 3896 | ```ruby 3897 | class_eval 'def use_relative_model_naming?; true; end', __FILE__, __LINE__ 3898 | ``` 3899 | 3900 | - `define_method`가 `class_eval{ def ... }`보다 좋다. 3901 | 3902 | * 3903 | 문자열 삽입과 함께 `class_eval`(또는 다른 `eval`)을 사용할 때는 실행되어 3904 | 보여지게 될 코드를 주석으로 추가한다.(레일스 코드를 참고) 3905 | [[link](#eval-comment-docs)] 3906 | 3907 | ```ruby 3908 | # from activesupport/lib/active_support/core_ext/string/output_safety.rb 3909 | UNSAFE_STRING_METHODS.each do |unsafe_method| 3910 | if 'String'.respond_to?(unsafe_method) 3911 | class_eval <<-EOT, __FILE__, __LINE__ + 1 3912 | def #{unsafe_method}(*params, &block) # def capitalize(*params, &block) 3913 | to_str.#{unsafe_method}(*params, &block) # to_str.capitalize(*params, &block) 3914 | end # end 3915 | 3916 | def #{unsafe_method}!(*params) # def capitalize!(*params) 3917 | @dirty = true # @dirty = true 3918 | super # super 3919 | end # end 3920 | EOT 3921 | end 3922 | end 3923 | ``` 3924 | 3925 | * 3926 | 백트레이스 할 때 `#methods` 리스트에 출력되지 않고 메소드 호출에 오타가 있는 3927 | 경우에(예를 들어 `nukes.launch_state = false`) 발견되지 않기 때문에 메타 3928 | 프로그래밍에서 `method_missing`을 사용하지 않는다. 대신 델리게이션이나 프록시 3929 | `define_method`를 사용한다. 만약 `method_missing`을 사용해야 한다면: 3930 | [[link](#no-method-missing)] 3931 | 3932 | - [`respond_to_missing?`](http://blog.marc-andre.ca/2010/11/methodmissing-politely.html)도 3933 | 정의해야 한다. 3934 | - `find_by_*` 같은 잘 알려진 prefix를 가진 메소드만 잡는다 -- 가능한 한 코드를 3935 | 단정적으로 만든다. 3936 | - 구문 끝에서 `super`를 호출한다. 3937 | - 일반 메소드에 단정적으로 위임한다. 3938 | 3939 | ```ruby 3940 | # 나쁜 예 3941 | def method_missing(meth, *params, &block) 3942 | if /^find_by_(?.*)/ =~ meth 3943 | # ... find_by 하는 코드가 많이 3944 | else 3945 | super 3946 | end 3947 | end 3948 | 3949 | # 좋은 예 3950 | def method_missing(meth, *params, &block) 3951 | if /^find_by_(?.*)/ =~ meth 3952 | find_by(prop, *params, &block) 3953 | else 3954 | super 3955 | end 3956 | end 3957 | 3958 | # 가장 좋은 것은 찾을 수 있는 모든 속성에 define_method를 선언하는 것이다. 3959 | ``` 3960 | 3961 | * 3962 | `private`/`protected` 범위를 회피하지 않도록, `send`대신 `public_send`를 3963 | 사용한다. 3964 | [[link](#prefer-public-send)] 3965 | 3966 | ```ruby 3967 | # Activatable concern을 인클루드하는 ActiveModel Organization이 있다 3968 | module Activatable 3969 | extend ActiveSupport::Concern 3970 | 3971 | included do 3972 | before_create :create_token 3973 | end 3974 | 3975 | private 3976 | 3977 | def reset_token 3978 | # 생략 3979 | end 3980 | 3981 | def create_token 3982 | # 생략 3983 | end 3984 | 3985 | def activate! 3986 | # 생략 3987 | end 3988 | end 3989 | 3990 | class Organization < ActiveRecord::Base 3991 | include Activatable 3992 | end 3993 | 3994 | linux_organization = Organization.find(...) 3995 | # 나쁜 예 - 프라이버시 위반 3996 | linux_organization.send(:reset_token) 3997 | # 좋은 예 - 예외를 발생 시킴 3998 | linux_organization.public_send(:reset_token) 3999 | ``` 4000 | 4001 | * 4002 | `send`대신 `__send__`를 사용한다. `send`는 있는 메소드와 겹칠 수 있다. 4003 | [[link](#prefer-__send__)] 4004 | 4005 | ```ruby 4006 | require 'socket' 4007 | 4008 | u1 = UDPSocket.new 4009 | u1.bind('127.0.0.1', 4913) 4010 | u2 = UDPSocket.new 4011 | u2.connect('127.0.0.1', 4913) 4012 | # 받을 객체에 메시지를 보내지 않음. 4013 | # 대신 UDP 소켓에 메시지를 보냄. 4014 | u2.send :sleep, 0 4015 | # 받을 객체에 메시지를 보냄. 4016 | u2.__send__ ... 4017 | ``` 4018 | 4019 | ## 그 밖에 4020 | 4021 | * 4022 | `ruby -w`로 안전한 코드를 작성한다. 4023 | [[link](#always-warn)] 4024 | 4025 | * 4026 | Optional 매개변수로 해시를 사용하지 않는다.(객체 생성자는 이 규칙에서 예외다.) 4027 | [[link](#no-optional-hash-params)] 4028 | 4029 | * 4030 | 메소드는 10줄을 넘지 않게 하라. 이상적으로 대부분의 메소드는 5줄 이하여야 한다. 4031 | 빈 줄은 제외한다. 4032 | [[link](#short-methods)] 4033 | 4034 | * 4035 | 3개 또는 4개 이상의 매개변수 리스트는 사용하지 않는다. 4036 | [[link](#too-many-params)] 4037 | 4038 | * 4039 | 전역 메소드가 정말로 필요하다면 private으로 만들고 Kernel에 추가하라. 4040 | [[link](#private-global-methods)] 4041 | 4042 | * 4043 | 전역 변수 대신에 모듈 변수를 사용하라. 4044 | [[link](#instance-vars)] 4045 | 4046 | ```Ruby 4047 | # 나쁜 예 4048 | $foo_bar = 1 4049 | 4050 | # 좋은 예 4051 | module Foo 4052 | class << self 4053 | attr_accessor :bar 4054 | end 4055 | end 4056 | 4057 | Foo.bar = 1 4058 | ``` 4059 | 4060 | * 4061 | 복잡한 명령어 라인에서 인수를 가져올 때 `OptionParser`를 사용하고 간단한 옵션은 4062 | `ruby -s`를 사용한다. 4063 | [[link](#optionparser)] 4064 | 4065 | * 4066 | 코드에서 되도록 변경을 피하고 함수형 방식을 사용하라. 4067 | [[link](#functional-code)] 4068 | 4069 | * 4070 | 메소드의 목적이 매개변수의 수정이 아닌 경우 매개변수를 수정하면 안 된다. 4071 | [[link](#no-param-mutations)] 4072 | 4073 | * 4074 | 블록 안에 3단 이상의 블록을 포함하지 마라. 4075 | [[link](#three-is-the-number-thou-shalt-count)] 4076 | 4077 | * 4078 | 일관성을 지켜라. 이 가이드 라인을 가지고 일관성을 유지하는 것이 이상적이다. 4079 | [[link](#be-consistent)] 4080 | 4081 | * 4082 | 상식에 맞게 하라. 4083 | [[link](#common-sense)] 4084 | 4085 | ## 도구들 4086 | 4087 | 이 가이드를 대신해서 자동으로 루비 코드를 체크해주는 도구들이 몇 가지 있다. 4088 | 4089 | ### RuboCop 4090 | 4091 | [RuboCop][]은 이 가이드를 기반으로 해서 루비 코드 스타일을 체크해준다. 이 4092 | 가이드의 상당 부분을 커버하는 RuboCop은 MRI 1.9와 MRI 2.0을 지원하고 Emacs와 4093 | 통합에 좋다. 4094 | 4095 | ### RubyMine 4096 | 4097 | [RubyMine](http://www.jetbrains.com/ruby/)의 코드 인스펙션은 4098 | [부분적으로](http://confluence.jetbrains.com/display/RUBYDEV/RubyMine+Inspections) 4099 | 이 가이드에 기반한다. 4100 | 4101 | # 참여하기 4102 | 4103 | 이 가이드는 아직 완성되지 않았다. — 몇 가지 규칙은 예제가 없고, 몇 가지 4104 | 규칙은 충분하고 명확한 설명이 없다. 그런 규칙을 보완해 루비 커뮤니티를 훌륭히(또 4105 | 간단히) 도울 수 있다. 4106 | 4107 | (바라건대)이러한 문제들은 곧 해결될 것이다. — 일단 그렇다는 걸 기억하고 4108 | 있으면 된다. 4109 | 4110 | 이 가이드는 확정된 가이드가 아니다. 나는 루비 코딩 스타일에 흥미를 가지고 있는 4111 | 사람들과 함께 만들어가고 싶다. 그래서 모든 루비 커뮤니티에서 유용하게 사용될 4112 | 자료로 사용되면 좋겠다. 4113 | 4114 | 개선을 위해서 티켓을 열거나 풀 리퀘스트를 마음껏 보내라. 당신의 도움에 미리 4115 | 감사한다! 4116 | 4117 | 또 이 프로젝트(와 RuboCop)에 금전적인 기부는 [Gratipay](https://gratipay.com/~bbatsov/)를 4118 | 통해서 할 수 있다. 4119 | 4120 | [![Support via Gratipay](https://cdn.rawgit.com/gratipay/gratipay-badge/2.3.0/dist/gratipay.png)](https://gratipay.com/~bbatsov/) 4121 | 4122 | ## 어떻게 참여하나요? 4123 | 4124 | [contribution guidelines](https://github.com/bbatsov/ruby-style-guide/blob/master/CONTRIBUTING.md)을 4125 | 따라서 하면 쉽다! 4126 | 4127 | # 라이센스 4128 | 4129 | ![Creative Commons License](http://i.creativecommons.org/l/by/3.0/88x31.png) 4130 | [Creative Commons Attribution 3.0 Unported License](http://creativecommons.org/licenses/by/3.0/deed.en_US)에 4131 | 따라 이용가능하다. 4132 | 4133 | # 공유합시다! 4134 | 4135 | 커뮤니티 기반 스타일 가이드는 이걸 모르는 곳에서는 거의 쓸모가 없다. 이 가이드를 4136 | 친구나 동료에게 트윗하거나 공유하라. 우리가 받는 모든 댓글이나 의견, 제안은 이 4137 | 가이드를 좀 더 좋게 만들 수 있다. 더 좋은 가이드를 가지고 싶지 않은가? 4138 | 4139 | 화이팅,
4140 | [Bozhidar](https://twitter.com/bbatsov) 4141 | 4142 | [PEP-8]: https://www.python.org/dev/peps/pep-0008/ 4143 | [rails-style-guide]: https://github.com/bbatsov/rails-style-guide 4144 | [pickaxe]: https://pragprog.com/book/ruby4/programming-ruby-1-9-2-0 4145 | [trpl]: http://www.amazon.com/Ruby-Programming-Language-David-Flanagan/dp/0596516177 4146 | [Pandoc]: http://pandoc.org/ 4147 | [RuboCop]: https://github.com/bbatsov/rubocop 4148 | [rdoc]: http://rdoc.sourceforge.net/doc/ 4149 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Prelude 2 | 3 | > Role models are important.
4 | > -- Officer Alex J. Murphy / RoboCop 5 | 6 | One thing has always bothered me as a Ruby developer—Python developers 7 | have a great programming style reference ([PEP-8][]) and we never got an 8 | official guide, documenting Ruby coding style and best practices. And I do 9 | believe that style matters. I also believe that a great hacker community, such 10 | as Ruby has, should be quite capable of producing this coveted document. 11 | 12 | This guide started its life as our internal company Ruby coding guidelines 13 | (written by yours truly). At some point I decided that the work I was doing 14 | might be interesting to members of the Ruby community in general and that the 15 | world had little need for another internal company guideline. But the world 16 | could certainly benefit from a community-driven and community-sanctioned set of 17 | practices, idioms and style prescriptions for Ruby programming. 18 | 19 | Since the inception of the guide I've received a lot of feedback from members of 20 | the exceptional Ruby community around the world. Thanks for all the suggestions 21 | and the support! Together we can make a resource beneficial to each and every 22 | Ruby developer out there. 23 | 24 | By the way, if you're into Rails you might want to check out the complementary 25 | [Ruby on Rails Style Guide][rails-style-guide]. 26 | 27 | # The Ruby Style Guide 28 | 29 | This Ruby style guide recommends best practices so that real-world Ruby 30 | programmers can write code that can be maintained by other real-world Ruby 31 | programmers. A style guide that reflects real-world usage gets used, while a 32 | style guide that holds to an ideal that has been rejected by the people it is 33 | supposed to help risks not getting used at all—no matter how good it is. 34 | 35 | The guide is separated into several sections of related rules. I've tried to add 36 | the rationale behind the rules (if it's omitted I've assumed it's pretty 37 | obvious). 38 | 39 | I didn't come up with all the rules out of nowhere—they are mostly 40 | based on my extensive career as a professional software engineer, 41 | feedback and suggestions from members of the Ruby community and 42 | various highly regarded Ruby programming resources, such as 43 | ["Programming Ruby"][pickaxe] and 44 | ["The Ruby Programming Language"][trpl]. 45 | 46 | There are some areas in which there is no clear consensus in the Ruby community 47 | regarding a particular style (like string literal quoting, spacing inside hash 48 | literals, dot position in multi-line method chaining, etc.). In such scenarios 49 | all popular styles are acknowledged and it's up to you to pick one and apply it 50 | consistently. 51 | 52 | This style guide evolves over time as additional conventions are 53 | identified and past conventions are rendered obsolete by changes in 54 | Ruby itself. 55 | 56 | Many projects have their own coding style guidelines (often derived 57 | from this guide). In the event of any conflicts, such 58 | project-specific guides take precedence for that project. 59 | 60 | You can generate a PDF or an HTML copy of this guide using 61 | [Pandoc][]. 62 | 63 | [RuboCop][] is a code analyzer, based on this 64 | style guide. 65 | 66 | Translations of the guide are available in the following languages: 67 | 68 | * [Chinese Simplified](https://github.com/JuanitoFatas/ruby-style-guide/blob/master/README-zhCN.md) 69 | * [Chinese Traditional](https://github.com/JuanitoFatas/ruby-style-guide/blob/master/README-zhTW.md) 70 | * [French](https://github.com/gauthier-delacroix/ruby-style-guide/blob/master/README-frFR.md) 71 | * [German](https://github.com/arbox/de-ruby-style-guide/blob/master/README-deDE.md) 72 | * [Japanese](https://github.com/fortissimo1997/ruby-style-guide/blob/japanese/README.ja.md) 73 | * [Korean](https://github.com/dalzony/ruby-style-guide/blob/master/README-koKR.md) 74 | * [Portuguese (pt-BR)](https://github.com/rubensmabueno/ruby-style-guide/blob/master/README-PT-BR.md) 75 | * [Russian](https://github.com/arbox/ruby-style-guide/blob/master/README-ruRU.md) 76 | * [Spanish](https://github.com/alemohamad/ruby-style-guide/blob/master/README-esLA.md) 77 | * [Vietnamese](https://github.com/CQBinh/ruby-style-guide/blob/master/README-viVN.md) 78 | 79 | ## Table of Contents 80 | 81 | * [Source Code Layout](#source-code-layout) 82 | * [Syntax](#syntax) 83 | * [Naming](#naming) 84 | * [Comments](#comments) 85 | * [Comment Annotations](#comment-annotations) 86 | * [Classes & Modules](#classes--modules) 87 | * [Exceptions](#exceptions) 88 | * [Collections](#collections) 89 | * [Numbers](#numbers) 90 | * [Strings](#strings) 91 | * [Date & Time](#date--time) 92 | * [Regular Expressions](#regular-expressions) 93 | * [Percent Literals](#percent-literals) 94 | * [Metaprogramming](#metaprogramming) 95 | * [Misc](#misc) 96 | * [Tools](#tools) 97 | 98 | ## Source Code Layout 99 | 100 | > Nearly everybody is convinced that every style but their own is 101 | > ugly and unreadable. Leave out the "but their own" and they're 102 | > probably right...
103 | > -- Jerry Coffin (on indentation) 104 | 105 | * 106 | Use `UTF-8` as the source file encoding. 107 | [[link](#utf-8)] 108 | 109 | * 110 | Use two **spaces** per indentation level (aka soft tabs). No hard tabs. 111 | [[link](#spaces-indentation)] 112 | 113 | ```Ruby 114 | # bad - four spaces 115 | def some_method 116 | do_something 117 | end 118 | 119 | # good 120 | def some_method 121 | do_something 122 | end 123 | ``` 124 | 125 | * 126 | Use Unix-style line endings. (\*BSD/Solaris/Linux/OS X users are covered by 127 | default, Windows users have to be extra careful.) 128 | [[link](#crlf)] 129 | 130 | * If you're using Git you might want to add the following 131 | configuration setting to protect your project from Windows line 132 | endings creeping in: 133 | 134 | ```bash 135 | $ git config --global core.autocrlf true 136 | ``` 137 | 138 | * 139 | Don't use `;` to separate statements and expressions. As a corollary—use 140 | one expression per line. 141 | [[link](#no-semicolon)] 142 | 143 | ```Ruby 144 | # bad 145 | puts 'foobar'; # superfluous semicolon 146 | 147 | puts 'foo'; puts 'bar' # two expressions on the same line 148 | 149 | # good 150 | puts 'foobar' 151 | 152 | puts 'foo' 153 | puts 'bar' 154 | 155 | puts 'foo', 'bar' # this applies to puts in particular 156 | ``` 157 | 158 | * 159 | Prefer a single-line format for class definitions with no body. 160 | [[link](#single-line-classes)] 161 | 162 | ```Ruby 163 | # bad 164 | class FooError < StandardError 165 | end 166 | 167 | # okish 168 | class FooError < StandardError; end 169 | 170 | # good 171 | FooError = Class.new(StandardError) 172 | ``` 173 | 174 | * 175 | Avoid single-line methods. Although they are somewhat popular in the wild, 176 | there are a few peculiarities about their definition syntax that make their 177 | use undesirable. At any rate—there should be no more than one expression 178 | in a single-line method. 179 | [[link](#no-single-line-methods)] 180 | 181 | ```Ruby 182 | # bad 183 | def too_much; something; something_else; end 184 | 185 | # okish - notice that the first ; is required 186 | def no_braces_method; body end 187 | 188 | # okish - notice that the second ; is optional 189 | def no_braces_method; body; end 190 | 191 | # okish - valid syntax, but no ; makes it kind of hard to read 192 | def some_method() body end 193 | 194 | # good 195 | def some_method 196 | body 197 | end 198 | ``` 199 | 200 | One exception to the rule are empty-body methods. 201 | 202 | ```Ruby 203 | # good 204 | def no_op; end 205 | ``` 206 | 207 | * 208 | Use spaces around operators, after commas, colons and semicolons. 209 | Whitespace might be (mostly) irrelevant to the Ruby interpreter, 210 | but its proper use is the key to writing easily readable code. 211 | [[link](#spaces-operators)] 212 | 213 | ```Ruby 214 | sum = 1 + 2 215 | a, b = 1, 2 216 | class FooError < StandardError; end 217 | ``` 218 | 219 | The only exception, regarding operators, is the exponent operator: 220 | 221 | ```Ruby 222 | # bad 223 | e = M * c ** 2 224 | 225 | # good 226 | e = M * c**2 227 | ``` 228 | 229 | * 230 | No spaces after `(`, `[` or before `]`, `)`. 231 | Use spaces around `{` and before `}`. 232 | [[link](#spaces-braces)] 233 | 234 | ```Ruby 235 | # bad 236 | some( arg ).other 237 | [ 1, 2, 3 ].each{|e| puts e} 238 | 239 | # good 240 | some(arg).other 241 | [1, 2, 3].each { |e| puts e } 242 | ``` 243 | 244 | `{` and `}` deserve a bit of clarification, since they are used 245 | for block and hash literals, as well as string interpolation. 246 | 247 | For hash literals two styles are considered acceptable. 248 | The first variant is slightly more readable (and arguably more 249 | popular in the Ruby community in general). The second variant has 250 | the advantage of adding visual difference between block and hash 251 | literals. Whichever one you pick—apply it consistently. 252 | 253 | ```Ruby 254 | # good - space after { and before } 255 | { one: 1, two: 2 } 256 | 257 | # good - no space after { and before } 258 | {one: 1, two: 2} 259 | ``` 260 | 261 | With interpolated expressions, there should be no padded-spacing inside the braces. 262 | 263 | ```Ruby 264 | # bad 265 | "From: #{ user.first_name }, #{ user.last_name }" 266 | 267 | # good 268 | "From: #{user.first_name}, #{user.last_name}" 269 | ``` 270 | 271 | * 272 | No space after `!`. 273 | [[link](#no-space-bang)] 274 | 275 | ```Ruby 276 | # bad 277 | ! something 278 | 279 | # good 280 | !something 281 | ``` 282 | 283 | * 284 | No space inside range literals. 285 | [[link](#no-space-inside-range-literals)] 286 | 287 | ```Ruby 288 | # bad 289 | 1 .. 3 290 | 'a' ... 'z' 291 | 292 | # good 293 | 1..3 294 | 'a'...'z' 295 | ``` 296 | 297 | * 298 | Indent `when` as deep as `case`. This is the style established in both 299 | "The Ruby Programming Language" and "Programming Ruby". 300 | [[link](#indent-when-to-case)] 301 | 302 | ```Ruby 303 | # bad 304 | case 305 | when song.name == 'Misty' 306 | puts 'Not again!' 307 | when song.duration > 120 308 | puts 'Too long!' 309 | when Time.now.hour > 21 310 | puts "It's too late" 311 | else 312 | song.play 313 | end 314 | 315 | # good 316 | case 317 | when song.name == 'Misty' 318 | puts 'Not again!' 319 | when song.duration > 120 320 | puts 'Too long!' 321 | when Time.now.hour > 21 322 | puts "It's too late" 323 | else 324 | song.play 325 | end 326 | ``` 327 | 328 | * 329 | When assigning the result of a conditional expression to a variable, 330 | preserve the usual alignment of its branches. 331 | [[link](#indent-conditional-assignment)] 332 | 333 | ```Ruby 334 | # bad - pretty convoluted 335 | kind = case year 336 | when 1850..1889 then 'Blues' 337 | when 1890..1909 then 'Ragtime' 338 | when 1910..1929 then 'New Orleans Jazz' 339 | when 1930..1939 then 'Swing' 340 | when 1940..1950 then 'Bebop' 341 | else 'Jazz' 342 | end 343 | 344 | result = if some_cond 345 | calc_something 346 | else 347 | calc_something_else 348 | end 349 | 350 | # good - it's apparent what's going on 351 | kind = case year 352 | when 1850..1889 then 'Blues' 353 | when 1890..1909 then 'Ragtime' 354 | when 1910..1929 then 'New Orleans Jazz' 355 | when 1930..1939 then 'Swing' 356 | when 1940..1950 then 'Bebop' 357 | else 'Jazz' 358 | end 359 | 360 | result = if some_cond 361 | calc_something 362 | else 363 | calc_something_else 364 | end 365 | 366 | # good (and a bit more width efficient) 367 | kind = 368 | case year 369 | when 1850..1889 then 'Blues' 370 | when 1890..1909 then 'Ragtime' 371 | when 1910..1929 then 'New Orleans Jazz' 372 | when 1930..1939 then 'Swing' 373 | when 1940..1950 then 'Bebop' 374 | else 'Jazz' 375 | end 376 | 377 | result = 378 | if some_cond 379 | calc_something 380 | else 381 | calc_something_else 382 | end 383 | ``` 384 | 385 | * 386 | Use empty lines between method definitions and also to break up methods 387 | into logical paragraphs internally. 388 | [[link](#empty-lines-between-methods)] 389 | 390 | ```Ruby 391 | def some_method 392 | data = initialize(options) 393 | 394 | data.manipulate! 395 | 396 | data.result 397 | end 398 | 399 | def some_method 400 | result 401 | end 402 | ``` 403 | 404 | * 405 | Avoid comma after the last parameter in a method call, especially when the 406 | parameters are not on separate lines. 407 | [[link](#no-trailing-params-comma)] 408 | 409 | ```Ruby 410 | # bad - easier to move/add/remove parameters, but still not preferred 411 | some_method( 412 | size, 413 | count, 414 | color, 415 | ) 416 | 417 | # bad 418 | some_method(size, count, color, ) 419 | 420 | # good 421 | some_method(size, count, color) 422 | ``` 423 | 424 | * 425 | Use spaces around the `=` operator when assigning default values to method 426 | parameters: 427 | [[link](#spaces-around-equals)] 428 | 429 | ```Ruby 430 | # bad 431 | def some_method(arg1=:default, arg2=nil, arg3=[]) 432 | # do something... 433 | end 434 | 435 | # good 436 | def some_method(arg1 = :default, arg2 = nil, arg3 = []) 437 | # do something... 438 | end 439 | ``` 440 | 441 | While several Ruby books suggest the first style, the second is much more 442 | prominent in practice (and arguably a bit more readable). 443 | 444 | * 445 | Avoid line continuation `\` where not required. In practice, avoid using 446 | line continuations for anything but string concatenation. 447 | [[link](#no-trailing-backslash)] 448 | 449 | ```Ruby 450 | # bad 451 | result = 1 - \ 452 | 2 453 | 454 | # good (but still ugly as hell) 455 | result = 1 \ 456 | - 2 457 | 458 | long_string = 'First part of the long string' \ 459 | ' and second part of the long string' 460 | ``` 461 | 462 | * 463 | Adopt a consistent multi-line method chaining style. There are two popular 464 | styles in the Ruby community, both of which are considered 465 | good—leading `.` (Option A) and trailing `.` (Option B). 466 | [[link](#consistent-multi-line-chains)] 467 | 468 | * **(Option A)** When continuing a chained method invocation on 469 | another line keep the `.` on the second line. 470 | 471 | ```Ruby 472 | # bad - need to consult first line to understand second line 473 | one.two.three. 474 | four 475 | 476 | # good - it's immediately clear what's going on the second line 477 | one.two.three 478 | .four 479 | ``` 480 | 481 | * **(Option B)** When continuing a chained method invocation on another line, 482 | include the `.` on the first line to indicate that the 483 | expression continues. 484 | 485 | ```Ruby 486 | # bad - need to read ahead to the second line to know that the chain continues 487 | one.two.three 488 | .four 489 | 490 | # good - it's immediately clear that the expression continues beyond the first line 491 | one.two.three. 492 | four 493 | ``` 494 | 495 | A discussion on the merits of both alternative styles can be found 496 | [here](https://github.com/bbatsov/ruby-style-guide/pull/176). 497 | 498 | * 499 | Align the parameters of a method call if they span more than one 500 | line. When aligning parameters is not appropriate due to line-length 501 | constraints, single indent for the lines after the first is also 502 | acceptable. 503 | [[link](#no-double-indent)] 504 | 505 | ```Ruby 506 | # starting point (line is too long) 507 | def send_mail(source) 508 | Mailer.deliver(to: 'bob@example.com', from: 'us@example.com', subject: 'Important message', body: source.text) 509 | end 510 | 511 | # bad (double indent) 512 | def send_mail(source) 513 | Mailer.deliver( 514 | to: 'bob@example.com', 515 | from: 'us@example.com', 516 | subject: 'Important message', 517 | body: source.text) 518 | end 519 | 520 | # good 521 | def send_mail(source) 522 | Mailer.deliver(to: 'bob@example.com', 523 | from: 'us@example.com', 524 | subject: 'Important message', 525 | body: source.text) 526 | end 527 | 528 | # good (normal indent) 529 | def send_mail(source) 530 | Mailer.deliver( 531 | to: 'bob@example.com', 532 | from: 'us@example.com', 533 | subject: 'Important message', 534 | body: source.text 535 | ) 536 | end 537 | ``` 538 | 539 | * 540 | Align the elements of array literals spanning multiple lines. 541 | [[link](#align-multiline-arrays)] 542 | 543 | ```Ruby 544 | # bad - single indent 545 | menu_item = ['Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 546 | 'Baked beans', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam'] 547 | 548 | # good 549 | menu_item = [ 550 | 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 551 | 'Baked beans', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam' 552 | ] 553 | 554 | # good 555 | menu_item = 556 | ['Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 557 | 'Baked beans', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam'] 558 | ``` 559 | 560 | * 561 | Add underscores to large numeric literals to improve their readability. 562 | [[link](#underscores-in-numerics)] 563 | 564 | ```Ruby 565 | # bad - how many 0s are there? 566 | num = 1000000 567 | 568 | # good - much easier to parse for the human brain 569 | num = 1_000_000 570 | ``` 571 | 572 | * 573 | Prefer smallcase letters for numeric literal prefixes. 574 | `0o` for octal, `0x` for hexadecimal and `0b` for binary. 575 | Do not use `0d` prefix for decimal literals. 576 | [[link](#numeric-literal-prefixes)] 577 | 578 | ```Ruby 579 | # bad 580 | num = 01234 581 | num = 0O1234 582 | num = 0X12AB 583 | num = 0B10101 584 | num = 0D1234 585 | num = 0d1234 586 | 587 | # good - easier to separate digits from the prefix 588 | num = 0o1234 589 | num = 0x12AB 590 | num = 0b10101 591 | num = 1234 592 | ``` 593 | 594 | * 595 | Use [Rdoc][rdoc] and its conventions for API documentation. Don't put an 596 | empty line between the comment block and the `def`. 597 | [[link](#rdoc-conventions)] 598 | 599 | * 600 | Limit lines to 80 characters. 601 | [[link](#80-character-limits)] 602 | 603 | * 604 | Avoid trailing whitespace. 605 | [[link](#no-trailing-whitespace)] 606 | 607 | * 608 | End each file with a newline. 609 | [[link](#newline-eof)] 610 | 611 | * 612 | Don't use block comments. They cannot be preceded by whitespace and are not 613 | as easy to spot as regular comments. 614 | [[link](#no-block-comments)] 615 | 616 | ```Ruby 617 | # bad 618 | =begin 619 | comment line 620 | another comment line 621 | =end 622 | 623 | # good 624 | # comment line 625 | # another comment line 626 | ``` 627 | 628 | ## Syntax 629 | 630 | * 631 | Use `::` only to reference constants(this includes classes and 632 | modules) and constructors (like `Array()` or `Nokogiri::HTML()`). 633 | Do not use `::` for regular method invocation. 634 | [[link](#double-colons)] 635 | 636 | ```Ruby 637 | # bad 638 | SomeClass::some_method 639 | some_object::some_method 640 | 641 | # good 642 | SomeClass.some_method 643 | some_object.some_method 644 | SomeModule::SomeClass::SOME_CONST 645 | SomeModule::SomeClass() 646 | ``` 647 | 648 | * 649 | Use `def` with parentheses when there are parameters. Omit the 650 | parentheses when the method doesn't accept any parameters. 651 | [[link](#method-parens)] 652 | 653 | ```Ruby 654 | # bad 655 | def some_method() 656 | # body omitted 657 | end 658 | 659 | # good 660 | def some_method 661 | # body omitted 662 | end 663 | 664 | # bad 665 | def some_method_with_parameters param1, param2 666 | # body omitted 667 | end 668 | 669 | # good 670 | def some_method_with_parameters(param1, param2) 671 | # body omitted 672 | end 673 | ``` 674 | 675 | * 676 | Use parentheses around the arguments of method invocations, 677 | especially if the first argument begins with an open parenthesis `(`, 678 | as in `f((3 + 2) + 1)`. 679 | [[link](#method-invocation-parens)] 680 | 681 | ```Ruby 682 | # bad 683 | x = Math.sin y 684 | # good 685 | x = Math.sin(y) 686 | 687 | # bad 688 | array.delete e 689 | # good 690 | array.delete(e) 691 | 692 | # bad 693 | temperance = Person.new 'Temperance', 30 694 | # good 695 | temperance = Person.new('Temperance', 30) 696 | ``` 697 | 698 | Only omit parentheses for 699 | 700 | * Method calls with no arguments: 701 | 702 | ```Ruby 703 | # bad 704 | Kernel.exit!() 705 | 2.even?() 706 | fork() 707 | 'test'.upcase() 708 | 709 | # good 710 | Kernel.exit! 711 | 2.even? 712 | fork 713 | 'test'.upcase 714 | ``` 715 | 716 | * Methods that are part of an internal DSL (e.g., Rake, Rails, RSpec): 717 | 718 | ```Ruby 719 | # bad 720 | validates(:name, presence: true) 721 | # good 722 | validates :name, presence: true 723 | ``` 724 | 725 | * Methods that have "keyword" status in Ruby: 726 | 727 | ```Ruby 728 | class Person 729 | # bad 730 | attr_reader(:name, :age) 731 | # good 732 | attr_reader :name, :age 733 | 734 | # body omitted 735 | end 736 | 737 | # bad 738 | puts(temperance.age) 739 | # good 740 | puts temperance.age 741 | ``` 742 | 743 | * 744 | Define optional arguments at the end of the list of arguments. 745 | Ruby has some unexpected results when calling methods that have 746 | optional arguments at the front of the list. 747 | [[link](#optional-arguments)] 748 | 749 | ```Ruby 750 | # bad 751 | def some_method(a = 1, b = 2, c, d) 752 | puts "#{a}, #{b}, #{c}, #{d}" 753 | end 754 | 755 | some_method('w', 'x') # => '1, 2, w, x' 756 | some_method('w', 'x', 'y') # => 'w, 2, x, y' 757 | some_method('w', 'x', 'y', 'z') # => 'w, x, y, z' 758 | 759 | # good 760 | def some_method(c, d, a = 1, b = 2) 761 | puts "#{a}, #{b}, #{c}, #{d}" 762 | end 763 | 764 | some_method('w', 'x') # => '1, 2, w, x' 765 | some_method('w', 'x', 'y') # => 'y, 2, w, x' 766 | some_method('w', 'x', 'y', 'z') # => 'y, z, w, x' 767 | ``` 768 | 769 | * 770 | Avoid the use of parallel assignment for defining variables. Parallel 771 | assignment is allowed when it is the return of a method call, used with 772 | the splat operator, or when used to swap variable assignment. Parallel 773 | assignment is less readable than separate assignment. 774 | [[link](#parallel-assignment)] 775 | 776 | ```Ruby 777 | # bad 778 | a, b, c, d = 'foo', 'bar', 'baz', 'foobar' 779 | 780 | # good 781 | a = 'foo' 782 | b = 'bar' 783 | c = 'baz' 784 | d = 'foobar' 785 | 786 | # good - swapping variable assignment 787 | # Swapping variable assignment is a special case because it will allow you to 788 | # swap the values that are assigned to each variable. 789 | a = 'foo' 790 | b = 'bar' 791 | 792 | a, b = b, a 793 | puts a # => 'bar' 794 | puts b # => 'foo' 795 | 796 | # good - method return 797 | def multi_return 798 | [1, 2] 799 | end 800 | 801 | first, second = multi_return 802 | 803 | # good - use with splat 804 | first, *list = [1, 2, 3, 4] # first => 1, list => [2, 3, 4] 805 | 806 | hello_array = *'Hello' # => ["Hello"] 807 | 808 | a = *(1..3) # => [1, 2, 3] 809 | ``` 810 | 811 | * 812 | Avoid the use of unnecessary trailing underscore variables during 813 | parallel assignment. Named underscore variables are to be preferred over 814 | underscore variables because of the context that they provide. 815 | Trailing underscore variables are necessary when there is a splat variable 816 | defined on the left side of the assignment, and the splat variable is 817 | not an underscore. 818 | [[link]](#trailing-underscore-variables) 819 | 820 | ```Ruby 821 | # bad 822 | foo = 'one,two,three,four,five' 823 | # Unnecessary assignment that does not provide useful information 824 | first, second, _ = foo.split(',') 825 | first, _, _ = foo.split(',') 826 | first, *_ = foo.split(',') 827 | 828 | 829 | # good 830 | foo = 'one,two,three,four,five' 831 | # The underscores are needed to show that you want all elements 832 | # except for the last number of underscore elements 833 | *beginning, _ = foo.split(',') 834 | *beginning, something, _ = foo.split(',') 835 | 836 | a, = foo.split(',') 837 | a, b, = foo.split(',') 838 | # Unnecessary assignment to an unused variable, but the assignment 839 | # provides us with useful information. 840 | first, _second = foo.split(',') 841 | first, _second, = foo.split(',') 842 | first, *_ending = foo.split(',') 843 | ``` 844 | 845 | * 846 | Do not use `for`, unless you know exactly why. Most of the time iterators 847 | should be used instead. `for` is implemented in terms of `each` (so you're 848 | adding a level of indirection), but with a twist—`for` doesn't 849 | introduce a new scope (unlike `each`) and variables defined in its block 850 | will be visible outside it. 851 | [[link](#no-for-loops)] 852 | 853 | ```Ruby 854 | arr = [1, 2, 3] 855 | 856 | # bad 857 | for elem in arr do 858 | puts elem 859 | end 860 | 861 | # note that elem is accessible outside of the for loop 862 | elem # => 3 863 | 864 | # good 865 | arr.each { |elem| puts elem } 866 | 867 | # elem is not accessible outside each's block 868 | elem # => NameError: undefined local variable or method `elem' 869 | ``` 870 | 871 | * 872 | Do not use `then` for multi-line `if`/`unless`. 873 | [[link](#no-then)] 874 | 875 | ```Ruby 876 | # bad 877 | if some_condition then 878 | # body omitted 879 | end 880 | 881 | # good 882 | if some_condition 883 | # body omitted 884 | end 885 | ``` 886 | 887 | * 888 | Always put the condition on the same line as the `if`/`unless` in a 889 | multi-line conditional. 890 | [[link](#same-line-condition)] 891 | 892 | ```Ruby 893 | # bad 894 | if 895 | some_condition 896 | do_something 897 | do_something_else 898 | end 899 | 900 | # good 901 | if some_condition 902 | do_something 903 | do_something_else 904 | end 905 | ``` 906 | 907 | * 908 | Favor the ternary operator(`?:`) over `if/then/else/end` constructs. 909 | It's more common and obviously more concise. 910 | [[link](#ternary-operator)] 911 | 912 | ```Ruby 913 | # bad 914 | result = if some_condition then something else something_else end 915 | 916 | # good 917 | result = some_condition ? something : something_else 918 | ``` 919 | 920 | * 921 | Use one expression per branch in a ternary operator. This 922 | also means that ternary operators must not be nested. Prefer 923 | `if/else` constructs in these cases. 924 | [[link](#no-nested-ternary)] 925 | 926 | ```Ruby 927 | # bad 928 | some_condition ? (nested_condition ? nested_something : nested_something_else) : something_else 929 | 930 | # good 931 | if some_condition 932 | nested_condition ? nested_something : nested_something_else 933 | else 934 | something_else 935 | end 936 | ``` 937 | 938 | * 939 | Do not use `if x; ...`. Use the ternary 940 | operator instead. 941 | [[link](#no-semicolon-ifs)] 942 | 943 | ```Ruby 944 | # bad 945 | result = if some_condition; something else something_else end 946 | 947 | # good 948 | result = some_condition ? something : something_else 949 | ``` 950 | 951 | * 952 | Leverage the fact that `if` and `case` are expressions which return a 953 | result. 954 | [[link](#use-if-case-returns)] 955 | 956 | ```Ruby 957 | # bad 958 | if condition 959 | result = x 960 | else 961 | result = y 962 | end 963 | 964 | # good 965 | result = 966 | if condition 967 | x 968 | else 969 | y 970 | end 971 | ``` 972 | 973 | * 974 | Use `when x then ...` for one-line cases. The alternative syntax `when x: 975 | ...` has been removed as of Ruby 1.9. 976 | [[link](#one-line-cases)] 977 | 978 | * 979 | Do not use `when x; ...`. See the previous rule. 980 | [[link](#no-when-semicolons)] 981 | 982 | * 983 | Use `!` instead of `not`. 984 | [[link](#bang-not-not)] 985 | 986 | ```Ruby 987 | # bad - parentheses are required because of op precedence 988 | x = (not something) 989 | 990 | # good 991 | x = !something 992 | ``` 993 | 994 | * 995 | Avoid the use of `!!`. 996 | [[link](#no-bang-bang)] 997 | 998 | `!!` converts a value to boolean, but you don't need this explicit 999 | conversion in the condition of a control expression; using it only 1000 | obscures your intention. If you want to do a `nil` check, use `nil?` 1001 | instead. 1002 | 1003 | ```Ruby 1004 | # bad 1005 | x = 'test' 1006 | # obscure nil check 1007 | if !!x 1008 | # body omitted 1009 | end 1010 | 1011 | # good 1012 | x = 'test' 1013 | if x 1014 | # body omitted 1015 | end 1016 | ``` 1017 | 1018 | * 1019 | The `and` and `or` keywords are banned. The minimal added readability is just 1020 | not worth the high probability of introducing subtle bugs. For boolean 1021 | expressions, always use `&&` and `||` instead. For flow control, use 1022 | `if` and `unless`; `&&` and `||` are also acceptable but less clear. 1023 | [[link](#no-and-or-or)] 1024 | 1025 | ```Ruby 1026 | # bad 1027 | # boolean expression 1028 | ok = got_needed_arguments and arguments_are_valid 1029 | 1030 | # control flow 1031 | document.save or fail(RuntimError, "Failed to save document!") 1032 | 1033 | # good 1034 | # boolean expression 1035 | ok = got_needed_arguments && arguments_are_valid 1036 | 1037 | # control flow 1038 | fail(RuntimeError, "Failed to save document!") unless document.save 1039 | 1040 | # ok 1041 | # control flow 1042 | document.save || fail(RuntimeError, "Failed to save document!") 1043 | ``` 1044 | 1045 | * 1046 | Avoid multi-line `?:` (the ternary operator); use `if`/`unless` instead. 1047 | [[link](#no-multiline-ternary)] 1048 | 1049 | * 1050 | Favor modifier `if`/`unless` usage when you have a single-line body. Another 1051 | good alternative is the usage of control flow `&&`/`||`. 1052 | [[link](#if-as-a-modifier)] 1053 | 1054 | ```Ruby 1055 | # bad 1056 | if some_condition 1057 | do_something 1058 | end 1059 | 1060 | # good 1061 | do_something if some_condition 1062 | 1063 | # another good option 1064 | some_condition && do_something 1065 | ``` 1066 | 1067 | * 1068 | Avoid modifier `if`/`unless` usage at the end of a non-trivial multi-line 1069 | block. 1070 | [[link](#no-multiline-if-modifiers)] 1071 | 1072 | ```Ruby 1073 | # bad 1074 | 10.times do 1075 | # multi-line body omitted 1076 | end if some_condition 1077 | 1078 | # good 1079 | if some_condition 1080 | 10.times do 1081 | # multi-line body omitted 1082 | end 1083 | end 1084 | ``` 1085 | 1086 | * 1087 | Avoid nested modifier `if`/`unless`/`while`/`until` usage. Favor `&&`/`||` if 1088 | appropriate. 1089 | [[link](#no-nested-modifiers)] 1090 | 1091 | ```Ruby 1092 | # bad 1093 | do_something if other_condition if some_condition 1094 | 1095 | # good 1096 | do_something if some_condition && other_condition 1097 | ``` 1098 | 1099 | * 1100 | Favor `unless` over `if` for negative conditions (or control flow `||`). 1101 | [[link](#unless-for-negatives)] 1102 | 1103 | ```Ruby 1104 | # bad 1105 | do_something if !some_condition 1106 | 1107 | # bad 1108 | do_something if not some_condition 1109 | 1110 | # good 1111 | do_something unless some_condition 1112 | 1113 | # another good option 1114 | some_condition || do_something 1115 | ``` 1116 | 1117 | * 1118 | Do not use `unless` with `else`. Rewrite these with the positive case first. 1119 | [[link](#no-else-with-unless)] 1120 | 1121 | ```Ruby 1122 | # bad 1123 | unless success? 1124 | puts 'failure' 1125 | else 1126 | puts 'success' 1127 | end 1128 | 1129 | # good 1130 | if success? 1131 | puts 'success' 1132 | else 1133 | puts 'failure' 1134 | end 1135 | ``` 1136 | 1137 | * 1138 | Don't use parentheses around the condition of a control expression. 1139 | [[link](#no-parens-around-condition)] 1140 | 1141 | ```Ruby 1142 | # bad 1143 | if (x > 10) 1144 | # body omitted 1145 | end 1146 | 1147 | # good 1148 | if x > 10 1149 | # body omitted 1150 | end 1151 | ``` 1152 | 1153 | Note that there is an exception to this rule, namely [safe assignment in 1154 | condition](#safe-assignment-in-condition). 1155 | 1156 | * 1157 | Do not use `while/until condition do` for multi-line `while/until`. 1158 | [[link](#no-multiline-while-do)] 1159 | 1160 | ```Ruby 1161 | # bad 1162 | while x > 5 do 1163 | # body omitted 1164 | end 1165 | 1166 | until x > 5 do 1167 | # body omitted 1168 | end 1169 | 1170 | # good 1171 | while x > 5 1172 | # body omitted 1173 | end 1174 | 1175 | until x > 5 1176 | # body omitted 1177 | end 1178 | ``` 1179 | 1180 | * 1181 | Favor modifier `while/until` usage when you have a single-line body. 1182 | [[link](#while-as-a-modifier)] 1183 | 1184 | ```Ruby 1185 | # bad 1186 | while some_condition 1187 | do_something 1188 | end 1189 | 1190 | # good 1191 | do_something while some_condition 1192 | ``` 1193 | 1194 | * 1195 | Favor `until` over `while` for negative conditions. 1196 | [[link](#until-for-negatives)] 1197 | 1198 | ```Ruby 1199 | # bad 1200 | do_something while !some_condition 1201 | 1202 | # good 1203 | do_something until some_condition 1204 | ``` 1205 | 1206 | * 1207 | Use `Kernel#loop` instead of `while/until` when you need an infinite loop. 1208 | [[link](#infinite-loop)] 1209 | 1210 | ```ruby 1211 | # bad 1212 | while true 1213 | do_something 1214 | end 1215 | 1216 | until false 1217 | do_something 1218 | end 1219 | 1220 | # good 1221 | loop do 1222 | do_something 1223 | end 1224 | ``` 1225 | 1226 | * 1227 | Use `Kernel#loop` with `break` rather than `begin/end/until` or 1228 | `begin/end/while` for post-loop tests. 1229 | [[link](#loop-with-break)] 1230 | 1231 | ```Ruby 1232 | # bad 1233 | begin 1234 | puts val 1235 | val += 1 1236 | end while val < 0 1237 | 1238 | # good 1239 | loop do 1240 | puts val 1241 | val += 1 1242 | break unless val < 0 1243 | end 1244 | ``` 1245 | 1246 | * 1247 | Omit the outer braces around an implicit options hash. 1248 | [[link](#no-braces-opts-hash)] 1249 | 1250 | ```Ruby 1251 | # bad 1252 | user.set({ name: 'John', age: 45, permissions: { read: true } }) 1253 | 1254 | # good 1255 | user.set(name: 'John', age: 45, permissions: { read: true }) 1256 | ``` 1257 | 1258 | * 1259 | Omit both the outer braces and parentheses for methods that are part of an 1260 | internal DSL. 1261 | [[link](#no-dsl-decorating)] 1262 | 1263 | ```Ruby 1264 | class Person < ActiveRecord::Base 1265 | # bad 1266 | validates(:name, { presence: true, length: { within: 1..10 } }) 1267 | 1268 | # good 1269 | validates :name, presence: true, length: { within: 1..10 } 1270 | end 1271 | ``` 1272 | 1273 | * 1274 | Use the proc invocation shorthand when the invoked method is the only operation of a block. 1275 | [[link](#single-action-blocks)] 1276 | 1277 | ```Ruby 1278 | # bad 1279 | names.map { |name| name.upcase } 1280 | 1281 | # good 1282 | names.map(&:upcase) 1283 | ``` 1284 | 1285 | * 1286 | Prefer `{...}` over `do...end` for single-line blocks. Avoid using `{...}` 1287 | for multi-line blocks (multi-line chaining is always ugly). Always use 1288 | `do...end` for "control flow" and "method definitions" (e.g. in Rakefiles and 1289 | certain DSLs). Avoid `do...end` when chaining. 1290 | [[link](#single-line-blocks)] 1291 | 1292 | ```Ruby 1293 | names = %w[Bozhidar Steve Sarah] 1294 | 1295 | # bad 1296 | names.each do |name| 1297 | puts name 1298 | end 1299 | 1300 | # good 1301 | names.each { |name| puts name } 1302 | 1303 | # bad 1304 | names.select do |name| 1305 | name.start_with?('S') 1306 | end.map { |name| name.upcase } 1307 | 1308 | # good 1309 | names.select { |name| name.start_with?('S') }.map(&:upcase) 1310 | ``` 1311 | 1312 | Some will argue that multi-line chaining would look OK with the use of {...}, 1313 | but they should ask themselves—is this code really readable and can the 1314 | blocks' contents be extracted into nifty methods? 1315 | 1316 | * 1317 | Consider using explicit block argument to avoid writing block literal that 1318 | just passes its arguments to another block. Beware of the performance impact, 1319 | though, as the block gets converted to a Proc. 1320 | [[link](#block-argument)] 1321 | 1322 | ```Ruby 1323 | require 'tempfile' 1324 | 1325 | # bad 1326 | def with_tmp_dir 1327 | Dir.mktmpdir do |tmp_dir| 1328 | Dir.chdir(tmp_dir) { |dir| yield dir } # block just passes arguments 1329 | end 1330 | end 1331 | 1332 | # good 1333 | def with_tmp_dir(&block) 1334 | Dir.mktmpdir do |tmp_dir| 1335 | Dir.chdir(tmp_dir, &block) 1336 | end 1337 | end 1338 | 1339 | with_tmp_dir do |dir| 1340 | puts "dir is accessible as a parameter and pwd is set: #{dir}" 1341 | end 1342 | ``` 1343 | 1344 | * 1345 | Avoid `return` where not required for flow of control. 1346 | [[link](#no-explicit-return)] 1347 | 1348 | ```Ruby 1349 | # bad 1350 | def some_method(some_arr) 1351 | return some_arr.size 1352 | end 1353 | 1354 | # good 1355 | def some_method(some_arr) 1356 | some_arr.size 1357 | end 1358 | ``` 1359 | 1360 | * 1361 | Avoid `self` where not required. (It is only required when calling a self 1362 | write accessor, methods named after reserved words, or overloadable operators.) 1363 | [[link](#no-self-unless-required)] 1364 | 1365 | ```Ruby 1366 | # bad 1367 | def ready? 1368 | if self.last_reviewed_at > self.last_updated_at 1369 | self.worker.update(self.content, self.options) 1370 | self.status = :in_progress 1371 | end 1372 | self.status == :verified 1373 | end 1374 | 1375 | # good 1376 | def ready? 1377 | if last_reviewed_at > last_updated_at 1378 | worker.update(content, options) 1379 | self.status = :in_progress 1380 | end 1381 | status == :verified 1382 | end 1383 | ``` 1384 | 1385 | * 1386 | As a corollary, avoid shadowing methods with local variables unless they are 1387 | both equivalent. 1388 | [[link](#no-shadowing)] 1389 | 1390 | ```Ruby 1391 | class Foo 1392 | attr_accessor :options 1393 | 1394 | # ok 1395 | def initialize(options) 1396 | self.options = options 1397 | # both options and self.options are equivalent here 1398 | end 1399 | 1400 | # bad 1401 | def do_something(options = {}) 1402 | unless options[:when] == :later 1403 | output(self.options[:message]) 1404 | end 1405 | end 1406 | 1407 | # good 1408 | def do_something(params = {}) 1409 | unless params[:when] == :later 1410 | output(options[:message]) 1411 | end 1412 | end 1413 | end 1414 | ``` 1415 | 1416 | * 1417 | Don't use the return value of `=` (an assignment) in conditional expressions 1418 | unless the assignment is wrapped in parentheses. This is a fairly popular 1419 | idiom among Rubyists that's sometimes referred to as *safe assignment in 1420 | condition*. 1421 | [[link](#safe-assignment-in-condition)] 1422 | 1423 | ```Ruby 1424 | # bad (+ a warning) 1425 | if v = array.grep(/foo/) 1426 | do_something(v) 1427 | # some code 1428 | end 1429 | 1430 | # good (MRI would still complain, but RuboCop won't) 1431 | if (v = array.grep(/foo/)) 1432 | do_something(v) 1433 | # some code 1434 | end 1435 | 1436 | # good 1437 | v = array.grep(/foo/) 1438 | if v 1439 | do_something(v) 1440 | # some code 1441 | end 1442 | ``` 1443 | 1444 | * 1445 | Use shorthand self assignment operators whenever applicable. 1446 | [[link](#self-assignment)] 1447 | 1448 | ```Ruby 1449 | # bad 1450 | x = x + y 1451 | x = x * y 1452 | x = x**y 1453 | x = x / y 1454 | x = x || y 1455 | x = x && y 1456 | 1457 | # good 1458 | x += y 1459 | x *= y 1460 | x **= y 1461 | x /= y 1462 | x ||= y 1463 | x &&= y 1464 | ``` 1465 | 1466 | * 1467 | Use `||=` to initialize variables only if they're not already initialized. 1468 | [[link](#double-pipe-for-uninit)] 1469 | 1470 | ```Ruby 1471 | # bad 1472 | name = name ? name : 'Bozhidar' 1473 | 1474 | # bad 1475 | name = 'Bozhidar' unless name 1476 | 1477 | # good - set name to 'Bozhidar', only if it's nil or false 1478 | name ||= 'Bozhidar' 1479 | ``` 1480 | 1481 | * 1482 | Don't use `||=` to initialize boolean variables. (Consider what would happen 1483 | if the current value happened to be `false`.) 1484 | [[link](#no-double-pipes-for-bools)] 1485 | 1486 | ```Ruby 1487 | # bad - would set enabled to true even if it was false 1488 | enabled ||= true 1489 | 1490 | # good 1491 | enabled = true if enabled.nil? 1492 | ``` 1493 | 1494 | * 1495 | Use `&&=` to preprocess variables that may or may not exist. Using `&&=` 1496 | will change the value only if it exists, removing the need to check its 1497 | existence with `if`. 1498 | [[link](#double-amper-preprocess)] 1499 | 1500 | ```Ruby 1501 | # bad 1502 | if something 1503 | something = something.downcase 1504 | end 1505 | 1506 | # bad 1507 | something = something ? something.downcase : nil 1508 | 1509 | # ok 1510 | something = something.downcase if something 1511 | 1512 | # good 1513 | something = something && something.downcase 1514 | 1515 | # better 1516 | something &&= something.downcase 1517 | ``` 1518 | 1519 | * 1520 | Avoid explicit use of the case equality operator `===`. As its name implies 1521 | it is meant to be used implicitly by `case` expressions and outside of them it 1522 | yields some pretty confusing code. 1523 | [[link](#no-case-equality)] 1524 | 1525 | ```Ruby 1526 | # bad 1527 | Array === something 1528 | (1..100) === 7 1529 | /something/ === some_string 1530 | 1531 | # good 1532 | something.is_a?(Array) 1533 | (1..100).include?(7) 1534 | some_string =~ /something/ 1535 | ``` 1536 | 1537 | * 1538 | Do not use `eql?` when using `==` will do. The stricter comparison semantics 1539 | provided by `eql?` are rarely needed in practice. 1540 | [[link](#eql)] 1541 | 1542 | ```Ruby 1543 | # bad - eql? is the same as == for strings 1544 | 'ruby'.eql? some_str 1545 | 1546 | # good 1547 | 'ruby' == some_str 1548 | 1.0.eql? x # eql? makes sense here if want to differentiate between Integer and Float 1 1549 | ``` 1550 | 1551 | * 1552 | Avoid using Perl-style special variables (like `$:`, `$;`, etc. ). They are 1553 | quite cryptic and their use in anything but one-liner scripts is discouraged. 1554 | Use the human-friendly aliases provided by the `English` library. 1555 | [[link](#no-cryptic-perlisms)] 1556 | 1557 | ```Ruby 1558 | # bad 1559 | $:.unshift File.dirname(__FILE__) 1560 | 1561 | # good 1562 | require 'English' 1563 | $LOAD_PATH.unshift File.dirname(__FILE__) 1564 | ``` 1565 | 1566 | * 1567 | Do not put a space between a method name and the opening parenthesis. 1568 | [[link](#parens-no-spaces)] 1569 | 1570 | ```Ruby 1571 | # bad 1572 | f (3 + 2) + 1 1573 | 1574 | # good 1575 | f(3 + 2) + 1 1576 | ``` 1577 | 1578 | * 1579 | Always run the Ruby interpreter with the `-w` option so it will warn you if 1580 | you forget either of the rules above! 1581 | [[link](#always-warn-at-runtime)] 1582 | 1583 | * 1584 | Do not use nested method definitions, use lambda instead. 1585 | Nested method definitions actually produce methods in the same scope 1586 | (e.g. class) as the outer method. Furthermore, the "nested method" will be 1587 | redefined every time the method containing its definition is invoked. 1588 | [[link](#no-nested-methods)] 1589 | 1590 | ```Ruby 1591 | # bad 1592 | def foo(x) 1593 | def bar(y) 1594 | # body omitted 1595 | end 1596 | 1597 | bar(x) 1598 | end 1599 | 1600 | # good - the same as the previous, but no bar redefinition on every foo call 1601 | def bar(y) 1602 | # body omitted 1603 | end 1604 | 1605 | def foo(x) 1606 | bar(x) 1607 | end 1608 | 1609 | # also good 1610 | def foo(x) 1611 | bar = ->(y) { ... } 1612 | bar.call(x) 1613 | end 1614 | ``` 1615 | 1616 | * 1617 | Use the new lambda literal syntax for single line body blocks. Use the 1618 | `lambda` method for multi-line blocks. 1619 | [[link](#lambda-multi-line)] 1620 | 1621 | ```Ruby 1622 | # bad 1623 | l = lambda { |a, b| a + b } 1624 | l.call(1, 2) 1625 | 1626 | # correct, but looks extremely awkward 1627 | l = ->(a, b) do 1628 | tmp = a * 7 1629 | tmp * b / 50 1630 | end 1631 | 1632 | # good 1633 | l = ->(a, b) { a + b } 1634 | l.call(1, 2) 1635 | 1636 | l = lambda do |a, b| 1637 | tmp = a * 7 1638 | tmp * b / 50 1639 | end 1640 | ``` 1641 | 1642 | * 1643 | Don't omit the parameter parentheses when defining a stabby lambda with 1644 | parameters. 1645 | [[link](#stabby-lambda-with-args)] 1646 | 1647 | ```Ruby 1648 | # bad 1649 | l = ->x, y { something(x, y) } 1650 | 1651 | # good 1652 | l = ->(x, y) { something(x, y) } 1653 | ``` 1654 | 1655 | * 1656 | Omit the parameter parentheses when defining a stabby lambda with 1657 | no parameters. 1658 | [[link](#stabby-lambda-no-args)] 1659 | 1660 | ```Ruby 1661 | # bad 1662 | l = ->() { something } 1663 | 1664 | # good 1665 | l = -> { something } 1666 | ``` 1667 | 1668 | * 1669 | Prefer `proc` over `Proc.new`. 1670 | [[link](#proc)] 1671 | 1672 | ```Ruby 1673 | # bad 1674 | p = Proc.new { |n| puts n } 1675 | 1676 | # good 1677 | p = proc { |n| puts n } 1678 | ``` 1679 | 1680 | * 1681 | Prefer `proc.call()` over `proc[]` or `proc.()` for both lambdas and procs. 1682 | [[link](#proc-call)] 1683 | 1684 | ```Ruby 1685 | # bad - looks similar to Enumeration access 1686 | l = ->(v) { puts v } 1687 | l[1] 1688 | 1689 | # also bad - uncommon syntax 1690 | l = ->(v) { puts v } 1691 | l.(1) 1692 | 1693 | # good 1694 | l = ->(v) { puts v } 1695 | l.call(1) 1696 | ``` 1697 | 1698 | * 1699 | Prefix with `_` unused block parameters and local variables. It's also 1700 | acceptable to use just `_` (although it's a bit less descriptive). This 1701 | convention is recognized by the Ruby interpreter and tools like RuboCop and 1702 | will suppress their unused variable warnings. 1703 | [[link](#underscore-unused-vars)] 1704 | 1705 | ```Ruby 1706 | # bad 1707 | result = hash.map { |k, v| v + 1 } 1708 | 1709 | def something(x) 1710 | unused_var, used_var = something_else(x) 1711 | # some code 1712 | end 1713 | 1714 | # good 1715 | result = hash.map { |_k, v| v + 1 } 1716 | 1717 | def something(x) 1718 | _unused_var, used_var = something_else(x) 1719 | # some code 1720 | end 1721 | 1722 | # good 1723 | result = hash.map { |_, v| v + 1 } 1724 | 1725 | def something(x) 1726 | _, used_var = something_else(x) 1727 | # some code 1728 | end 1729 | ``` 1730 | 1731 | * 1732 | Use `$stdout/$stderr/$stdin` instead of `STDOUT/STDERR/STDIN`. 1733 | `STDOUT/STDERR/STDIN` are constants, and while you can actually reassign 1734 | (possibly to redirect some stream) constants in Ruby, you'll get an 1735 | interpreter warning if you do so. 1736 | [[link](#global-stdout)] 1737 | 1738 | * 1739 | Use `warn` instead of `$stderr.puts`. Apart from being more concise and 1740 | clear, `warn` allows you to suppress warnings if you need to (by setting the 1741 | warn level to 0 via `-W0`). 1742 | [[link](#warn)] 1743 | 1744 | * 1745 | Favor the use of `sprintf` and its alias `format` over the fairly cryptic 1746 | `String#%` method. 1747 | [[link](#sprintf)] 1748 | 1749 | ```Ruby 1750 | # bad 1751 | '%d %d' % [20, 10] 1752 | # => '20 10' 1753 | 1754 | # good 1755 | sprintf('%d %d', 20, 10) 1756 | # => '20 10' 1757 | 1758 | # good 1759 | sprintf('%{first} %{second}', first: 20, second: 10) 1760 | # => '20 10' 1761 | 1762 | format('%d %d', 20, 10) 1763 | # => '20 10' 1764 | 1765 | # good 1766 | format('%{first} %{second}', first: 20, second: 10) 1767 | # => '20 10' 1768 | ``` 1769 | 1770 | * 1771 | Favor the use of `Array#join` over the fairly cryptic `Array#*` with 1772 | a string argument. 1773 | [[link](#array-join)] 1774 | 1775 | ```Ruby 1776 | # bad 1777 | %w[one two three] * ', ' 1778 | # => 'one, two, three' 1779 | 1780 | # good 1781 | %w[one two three].join(', ') 1782 | # => 'one, two, three' 1783 | ``` 1784 | 1785 | * 1786 | Use `Array()` instead of explicit `Array` check or `[*var]`, when dealing 1787 | with a variable you want to treat as an Array, but you're not certain it's an 1788 | array. 1789 | [[link](#array-coercion)] 1790 | 1791 | ```Ruby 1792 | # bad 1793 | paths = [paths] unless paths.is_a? Array 1794 | paths.each { |path| do_something(path) } 1795 | 1796 | # bad (always creates a new Array instance) 1797 | [*paths].each { |path| do_something(path) } 1798 | 1799 | # good (and a bit more readable) 1800 | Array(paths).each { |path| do_something(path) } 1801 | ``` 1802 | 1803 | * 1804 | Use ranges or `Comparable#between?` instead of complex comparison logic when 1805 | possible. 1806 | [[link](#ranges-or-between)] 1807 | 1808 | ```Ruby 1809 | # bad 1810 | do_something if x >= 1000 && x <= 2000 1811 | 1812 | # good 1813 | do_something if (1000..2000).include?(x) 1814 | 1815 | # good 1816 | do_something if x.between?(1000, 2000) 1817 | ``` 1818 | 1819 | * 1820 | Favor the use of predicate methods to explicit comparisons with `==`. 1821 | Numeric comparisons are OK. 1822 | [[link](#predicate-methods)] 1823 | 1824 | ```Ruby 1825 | # bad 1826 | if x % 2 == 0 1827 | end 1828 | 1829 | if x % 2 == 1 1830 | end 1831 | 1832 | if x == nil 1833 | end 1834 | 1835 | # good 1836 | if x.even? 1837 | end 1838 | 1839 | if x.odd? 1840 | end 1841 | 1842 | if x.nil? 1843 | end 1844 | 1845 | if x.zero? 1846 | end 1847 | 1848 | if x == 0 1849 | end 1850 | ``` 1851 | 1852 | * 1853 | Don't do explicit non-`nil` checks unless you're dealing with boolean 1854 | values. 1855 | [[link](#no-non-nil-checks)] 1856 | 1857 | ```ruby 1858 | # bad 1859 | do_something if !something.nil? 1860 | do_something if something != nil 1861 | 1862 | # good 1863 | do_something if something 1864 | 1865 | # good - dealing with a boolean 1866 | def value_set? 1867 | !@some_boolean.nil? 1868 | end 1869 | ``` 1870 | 1871 | * 1872 | Avoid the use of `BEGIN` blocks. 1873 | [[link](#no-BEGIN-blocks)] 1874 | 1875 | * 1876 | Do not use `END` blocks. Use `Kernel#at_exit` instead. 1877 | [[link](#no-END-blocks)] 1878 | 1879 | ```ruby 1880 | # bad 1881 | END { puts 'Goodbye!' } 1882 | 1883 | # good 1884 | at_exit { puts 'Goodbye!' } 1885 | ``` 1886 | 1887 | * 1888 | Avoid the use of flip-flops. 1889 | [[link](#no-flip-flops)] 1890 | 1891 | * 1892 | Avoid use of nested conditionals for flow of control. 1893 | [[link](#no-nested-conditionals)] 1894 | 1895 | Prefer a guard clause when you can assert invalid data. A guard clause 1896 | is a conditional statement at the top of a function that bails out as 1897 | soon as it can. 1898 | 1899 | ```Ruby 1900 | # bad 1901 | def compute_thing(thing) 1902 | if thing[:foo] 1903 | update_with_bar(thing[:foo]) 1904 | if thing[:foo][:bar] 1905 | partial_compute(thing) 1906 | else 1907 | re_compute(thing) 1908 | end 1909 | end 1910 | end 1911 | 1912 | # good 1913 | def compute_thing(thing) 1914 | return unless thing[:foo] 1915 | update_with_bar(thing[:foo]) 1916 | return re_compute(thing) unless thing[:foo][:bar] 1917 | partial_compute(thing) 1918 | end 1919 | ``` 1920 | 1921 | Prefer `next` in loops instead of conditional blocks. 1922 | 1923 | ```Ruby 1924 | # bad 1925 | [0, 1, 2, 3].each do |item| 1926 | if item > 1 1927 | puts item 1928 | end 1929 | end 1930 | 1931 | # good 1932 | [0, 1, 2, 3].each do |item| 1933 | next unless item > 1 1934 | puts item 1935 | end 1936 | ``` 1937 | 1938 | * 1939 | Prefer `map` over `collect`, `find` over `detect`, `select` over `find_all`, 1940 | `reduce` over `inject` and `size` over `length`. This is not a hard 1941 | requirement; if the use of the alias enhances readability, it's ok to use it. 1942 | The rhyming methods are inherited from Smalltalk and are not common in other 1943 | programming languages. The reason the use of `select` is encouraged over 1944 | `find_all` is that it goes together nicely with `reject` and its name is 1945 | pretty self-explanatory. 1946 | [[link](#map-find-select-reduce-size)] 1947 | 1948 | * 1949 | Don't use `count` as a substitute for `size`. For `Enumerable` objects other 1950 | than `Array` it will iterate the entire collection in order to determine its 1951 | size. 1952 | [[link](#count-vs-size)] 1953 | 1954 | ```Ruby 1955 | # bad 1956 | some_hash.count 1957 | 1958 | # good 1959 | some_hash.size 1960 | ``` 1961 | 1962 | * 1963 | Use `flat_map` instead of `map` + `flatten`. This does not apply for arrays 1964 | with a depth greater than 2, i.e. if `users.first.songs == ['a', ['b','c']]`, 1965 | then use `map + flatten` rather than `flat_map`. `flat_map` flattens the 1966 | array by 1, whereas `flatten` flattens it all the way. 1967 | [[link](#flat-map)] 1968 | 1969 | ```Ruby 1970 | # bad 1971 | all_songs = users.map(&:songs).flatten.uniq 1972 | 1973 | # good 1974 | all_songs = users.flat_map(&:songs).uniq 1975 | ``` 1976 | 1977 | * 1978 | Prefer `reverse_each` to `reverse.each` because some classes that `include 1979 | Enumerable` will provide an efficient implementation. Even in the worst case 1980 | where a class does not provide a specialized implementation, the general 1981 | implementation inherited from `Enumerable` will be at least as efficient as 1982 | using `reverse.each`. 1983 | [[link](#reverse-each)] 1984 | 1985 | ```Ruby 1986 | # bad 1987 | array.reverse.each { ... } 1988 | 1989 | # good 1990 | array.reverse_each { ... } 1991 | ``` 1992 | 1993 | ## Naming 1994 | 1995 | > The only real difficulties in programming are cache invalidation and 1996 | > naming things.
1997 | > -- Phil Karlton 1998 | 1999 | * 2000 | Name identifiers in English. 2001 | [[link](#english-identifiers)] 2002 | 2003 | ```Ruby 2004 | # bad - identifier using non-ascii characters 2005 | заплата = 1_000 2006 | 2007 | # bad - identifier is a Bulgarian word, written with Latin letters (instead of Cyrillic) 2008 | zaplata = 1_000 2009 | 2010 | # good 2011 | salary = 1_000 2012 | ``` 2013 | 2014 | * 2015 | Use `snake_case` for symbols, methods and variables. 2016 | [[link](#snake-case-symbols-methods-vars)] 2017 | 2018 | ```Ruby 2019 | # bad 2020 | :'some symbol' 2021 | :SomeSymbol 2022 | :someSymbol 2023 | 2024 | someVar = 5 2025 | var_10 = 10 2026 | 2027 | def someMethod 2028 | # some code 2029 | end 2030 | 2031 | def SomeMethod 2032 | # some code 2033 | end 2034 | 2035 | # good 2036 | :some_symbol 2037 | 2038 | some_var = 5 2039 | var10 = 10 2040 | 2041 | def some_method 2042 | # some code 2043 | end 2044 | ``` 2045 | 2046 | * 2047 | Do not separate numbers from letters on symbols, methods and variables. 2048 | [[link](#snake-case-symbols-methods-vars-with-numbers)] 2049 | 2050 | ```Ruby 2051 | # bad 2052 | :some_sym_1 2053 | 2054 | some_var_1 = 1 2055 | 2056 | def some_method_1 2057 | # some code 2058 | end 2059 | 2060 | # good 2061 | :some_sym1 2062 | 2063 | some_var1 = 1 2064 | 2065 | def some_method1 2066 | # some code 2067 | end 2068 | ``` 2069 | 2070 | 2071 | * 2072 | Use `CamelCase` for classes and modules. (Keep acronyms like HTTP, RFC, XML 2073 | uppercase.) 2074 | [[link](#camelcase-classes)] 2075 | 2076 | ```Ruby 2077 | # bad 2078 | class Someclass 2079 | # some code 2080 | end 2081 | 2082 | class Some_Class 2083 | # some code 2084 | end 2085 | 2086 | class SomeXml 2087 | # some code 2088 | end 2089 | 2090 | class XmlSomething 2091 | # some code 2092 | end 2093 | 2094 | # good 2095 | class SomeClass 2096 | # some code 2097 | end 2098 | 2099 | class SomeXML 2100 | # some code 2101 | end 2102 | 2103 | class XMLSomething 2104 | # some code 2105 | end 2106 | ``` 2107 | 2108 | * 2109 | Use `snake_case` for naming files, e.g. `hello_world.rb`. 2110 | [[link](#snake-case-files)] 2111 | 2112 | * 2113 | Use `snake_case` for naming directories, e.g. 2114 | `lib/hello_world/hello_world.rb`. 2115 | [[link](#snake-case-dirs)] 2116 | 2117 | * 2118 | Aim to have just a single class/module per source file. Name the file name 2119 | as the class/module, but replacing CamelCase with snake_case. 2120 | [[link](#one-class-per-file)] 2121 | 2122 | * 2123 | Use `SCREAMING_SNAKE_CASE` for other constants. 2124 | [[link](#screaming-snake-case)] 2125 | 2126 | ```Ruby 2127 | # bad 2128 | SomeConst = 5 2129 | 2130 | # good 2131 | SOME_CONST = 5 2132 | ``` 2133 | 2134 | * 2135 | The names of predicate methods (methods that return a boolean value) should 2136 | end in a question mark. (i.e. `Array#empty?`). Methods that don't return a 2137 | boolean, shouldn't end in a question mark. 2138 | [[link](#bool-methods-qmark)] 2139 | 2140 | * 2141 | Avoid prefixing predicate methods with the auxiliary verbs such as `is`, 2142 | `does`, or `can`. These words are redundant and inconsistent with the style of 2143 | boolean methods in the Ruby core library, such as `empty?` and `include?`. 2144 | [[link](#bool-methods-prefix)] 2145 | 2146 | ```Ruby 2147 | # bad 2148 | class Person 2149 | def is_tall? 2150 | true 2151 | end 2152 | 2153 | def can_play_basketball? 2154 | false 2155 | end 2156 | 2157 | def does_like_candy? 2158 | true 2159 | end 2160 | end 2161 | 2162 | # good 2163 | class Person 2164 | def tall? 2165 | true 2166 | end 2167 | 2168 | def basketball_player? 2169 | false 2170 | end 2171 | 2172 | def likes_candy? 2173 | true 2174 | end 2175 | end 2176 | ``` 2177 | 2178 | * 2179 | The names of potentially *dangerous* methods (i.e. methods that modify 2180 | `self` or the arguments, `exit!` (doesn't run the finalizers like `exit` 2181 | does), etc.) should end with an exclamation mark if there exists a safe 2182 | version of that *dangerous* method. 2183 | [[link](#dangerous-method-bang)] 2184 | 2185 | ```Ruby 2186 | # bad - there is no matching 'safe' method 2187 | class Person 2188 | def update! 2189 | end 2190 | end 2191 | 2192 | # good 2193 | class Person 2194 | def update 2195 | end 2196 | end 2197 | 2198 | # good 2199 | class Person 2200 | def update! 2201 | end 2202 | 2203 | def update 2204 | end 2205 | end 2206 | ``` 2207 | 2208 | * 2209 | Define the non-bang (safe) method in terms of the bang (dangerous) one if 2210 | possible. 2211 | [[link](#safe-because-unsafe)] 2212 | 2213 | ```Ruby 2214 | class Array 2215 | def flatten_once! 2216 | res = [] 2217 | 2218 | each do |e| 2219 | [*e].each { |f| res << f } 2220 | end 2221 | 2222 | replace(res) 2223 | end 2224 | 2225 | def flatten_once 2226 | dup.flatten_once! 2227 | end 2228 | end 2229 | ``` 2230 | 2231 | * 2232 | When defining binary operators, name the parameter `other`(`<<` and `[]` are 2233 | exceptions to the rule, since their semantics are different). 2234 | [[link](#other-arg)] 2235 | 2236 | ```Ruby 2237 | def +(other) 2238 | # body omitted 2239 | end 2240 | ``` 2241 | 2242 | ## Comments 2243 | 2244 | > Good code is its own best documentation. As you're about to add a 2245 | > comment, ask yourself, "How can I improve the code so that this 2246 | > comment isn't needed?" Improve the code and then document it to make 2247 | > it even clearer.
2248 | > -- Steve McConnell 2249 | 2250 | * 2251 | Write self-documenting code and ignore the rest of this section. Seriously! 2252 | [[link](#no-comments)] 2253 | 2254 | * 2255 | Write comments in English. 2256 | [[link](#english-comments)] 2257 | 2258 | * 2259 | Use one space between the leading `#` character of the comment and the text 2260 | of the comment. 2261 | [[link](#hash-space)] 2262 | 2263 | * 2264 | Comments longer than a word are capitalized and use punctuation. Use [one 2265 | space](https://en.wikipedia.org/wiki/Sentence_spacing) after periods. 2266 | [[link](#english-syntax)] 2267 | 2268 | * 2269 | Avoid superfluous comments. 2270 | [[link](#no-superfluous-comments)] 2271 | 2272 | ```Ruby 2273 | # bad 2274 | counter += 1 # Increments counter by one. 2275 | ``` 2276 | 2277 | * 2278 | Keep existing comments up-to-date. An outdated comment is worse than no 2279 | comment at all. 2280 | [[link](#comment-upkeep)] 2281 | 2282 | > Good code is like a good joke: it needs no explanation.
2283 | > — old programmers maxim, through [Russ Olsen](http://eloquentruby.com/blog/2011/03/07/good-code-and-good-jokes/) 2284 | 2285 | * 2286 | Avoid writing comments to explain bad code. Refactor the code to make it 2287 | self-explanatory. ("Do or do not—there is no try." Yoda) 2288 | [[link](#refactor-dont-comment)] 2289 | 2290 | ### Comment Annotations 2291 | 2292 | * 2293 | Annotations should usually be written on the line immediately above the 2294 | relevant code. 2295 | [[link](#annotate-above)] 2296 | 2297 | * 2298 | The annotation keyword is followed by a colon and a space, then a note 2299 | describing the problem. 2300 | [[link](#annotate-keywords)] 2301 | 2302 | * 2303 | If multiple lines are required to describe the problem, subsequent lines 2304 | should be indented three spaces after the `#` (one general plus two for 2305 | indentation purpose). 2306 | [[link](#indent-annotations)] 2307 | 2308 | ```Ruby 2309 | def bar 2310 | # FIXME: This has crashed occasionally since v3.2.1. It may 2311 | # be related to the BarBazUtil upgrade. 2312 | baz(:quux) 2313 | end 2314 | ``` 2315 | 2316 | * 2317 | In cases where the problem is so obvious that any documentation would be 2318 | redundant, annotations may be left at the end of the offending line with no 2319 | note. This usage should be the exception and not the rule. 2320 | [[link](#rare-eol-annotations)] 2321 | 2322 | ```Ruby 2323 | def bar 2324 | sleep 100 # OPTIMIZE 2325 | end 2326 | ``` 2327 | 2328 | * 2329 | Use `TODO` to note missing features or functionality that should be added at 2330 | a later date. 2331 | [[link](#todo)] 2332 | 2333 | * 2334 | Use `FIXME` to note broken code that needs to be fixed. 2335 | [[link](#fixme)] 2336 | 2337 | * 2338 | Use `OPTIMIZE` to note slow or inefficient code that may cause performance 2339 | problems. 2340 | [[link](#optimize)] 2341 | 2342 | * 2343 | Use `HACK` to note code smells where questionable coding practices were used 2344 | and should be refactored away. 2345 | [[link](#hack)] 2346 | 2347 | * 2348 | Use `REVIEW` to note anything that should be looked at to confirm it is 2349 | working as intended. For example: `REVIEW: Are we sure this is how the client 2350 | does X currently?` 2351 | [[link](#review)] 2352 | 2353 | * 2354 | Use other custom annotation keywords if it feels appropriate, but be sure to 2355 | document them in your project's `README` or similar. 2356 | [[link](#document-annotations)] 2357 | 2358 | ### Magic Comments 2359 | 2360 | * 2361 | Place magic comments above all code and documentation. Magic comments should only go below shebangs if they are needed in your source file. 2362 | [[link](#magic-comments-first)] 2363 | 2364 | ```Ruby 2365 | # good 2366 | # frozen_string_literal: true 2367 | # Some documentation about Person 2368 | class Person 2369 | end 2370 | 2371 | # bad 2372 | # Some documentation about Person 2373 | # frozen_string_literal: true 2374 | class Person 2375 | end 2376 | ``` 2377 | 2378 | ```Ruby 2379 | # good 2380 | #!/usr/bin/env ruby 2381 | # frozen_string_literal: true 2382 | App.parse(ARGV) 2383 | 2384 | # bad 2385 | # frozen_string_literal: true 2386 | #!/usr/bin/env ruby 2387 | App.parse(ARGV) 2388 | ``` 2389 | 2390 | * 2391 | Use one magic comment per line if you need multiple. 2392 | [[link](#one-magic-comment-per-line)] 2393 | 2394 | ```Ruby 2395 | # good 2396 | # frozen_string_literal: true 2397 | # encoding: ascii-8bit 2398 | 2399 | # bad 2400 | # -*- frozen_string_literal: true; encoding: ascii-8bit -*- 2401 | ``` 2402 | 2403 | * 2404 | Separate magic comments from code and documentation with a blank line. 2405 | [[link](#separate-magic-comments-from-code)] 2406 | 2407 | ```Ruby 2408 | # good 2409 | # frozen_string_literal: true 2410 | 2411 | # Some documentation for Person 2412 | class Person 2413 | # Some code 2414 | end 2415 | 2416 | # bad 2417 | # frozen_string_literal: true 2418 | # Some documentation for Person 2419 | class Person 2420 | # Some code 2421 | end 2422 | ``` 2423 | 2424 | ## Classes & Modules 2425 | 2426 | * 2427 | Use a consistent structure in your class definitions. 2428 | [[link](#consistent-classes)] 2429 | 2430 | ```Ruby 2431 | class Person 2432 | # extend and include go first 2433 | extend SomeModule 2434 | include AnotherModule 2435 | 2436 | # inner classes 2437 | CustomError = Class.new(StandardError) 2438 | 2439 | # constants are next 2440 | SOME_CONSTANT = 20 2441 | 2442 | # afterwards we have attribute macros 2443 | attr_reader :name 2444 | 2445 | # followed by other macros (if any) 2446 | validates :name 2447 | 2448 | # public class methods are next in line 2449 | def self.some_method 2450 | end 2451 | 2452 | # initialization goes between class methods and other instance methods 2453 | def initialize 2454 | end 2455 | 2456 | # followed by other public instance methods 2457 | def some_method 2458 | end 2459 | 2460 | # protected and private methods are grouped near the end 2461 | protected 2462 | 2463 | def some_protected_method 2464 | end 2465 | 2466 | private 2467 | 2468 | def some_private_method 2469 | end 2470 | end 2471 | ``` 2472 | 2473 | * 2474 | Don't nest multi-line classes within classes. Try to have such nested 2475 | classes each in their own file in a folder named like the containing class. 2476 | [[link](#file-classes)] 2477 | 2478 | ```Ruby 2479 | # bad 2480 | 2481 | # foo.rb 2482 | class Foo 2483 | class Bar 2484 | # 30 methods inside 2485 | end 2486 | 2487 | class Car 2488 | # 20 methods inside 2489 | end 2490 | 2491 | # 30 methods inside 2492 | end 2493 | 2494 | # good 2495 | 2496 | # foo.rb 2497 | class Foo 2498 | # 30 methods inside 2499 | end 2500 | 2501 | # foo/bar.rb 2502 | class Foo 2503 | class Bar 2504 | # 30 methods inside 2505 | end 2506 | end 2507 | 2508 | # foo/car.rb 2509 | class Foo 2510 | class Car 2511 | # 20 methods inside 2512 | end 2513 | end 2514 | ``` 2515 | 2516 | * 2517 | Prefer modules to classes with only class methods. Classes should be used 2518 | only when it makes sense to create instances out of them. 2519 | [[link](#modules-vs-classes)] 2520 | 2521 | ```Ruby 2522 | # bad 2523 | class SomeClass 2524 | def self.some_method 2525 | # body omitted 2526 | end 2527 | 2528 | def self.some_other_method 2529 | # body omitted 2530 | end 2531 | end 2532 | 2533 | # good 2534 | module SomeModule 2535 | module_function 2536 | 2537 | def some_method 2538 | # body omitted 2539 | end 2540 | 2541 | def some_other_method 2542 | # body omitted 2543 | end 2544 | end 2545 | ``` 2546 | 2547 | * 2548 | Favor the use of `module_function` over `extend self` when you want to turn 2549 | a module's instance methods into class methods. 2550 | [[link](#module-function)] 2551 | 2552 | ```Ruby 2553 | # bad 2554 | module Utilities 2555 | extend self 2556 | 2557 | def parse_something(string) 2558 | # do stuff here 2559 | end 2560 | 2561 | def other_utility_method(number, string) 2562 | # do some more stuff 2563 | end 2564 | end 2565 | 2566 | # good 2567 | module Utilities 2568 | module_function 2569 | 2570 | def parse_something(string) 2571 | # do stuff here 2572 | end 2573 | 2574 | def other_utility_method(number, string) 2575 | # do some more stuff 2576 | end 2577 | end 2578 | ``` 2579 | 2580 | * 2581 | When designing class hierarchies make sure that they conform to the [Liskov 2582 | Substitution 2583 | Principle](https://en.wikipedia.org/wiki/Liskov_substitution_principle). 2584 | [[link](#liskov)] 2585 | 2586 | * 2587 | Try to make your classes as 2588 | [SOLID](https://en.wikipedia.org/wiki/SOLID_\(object-oriented_design\)) as 2589 | possible. 2590 | [[link](#solid-design)] 2591 | 2592 | * 2593 | Always supply a proper `to_s` method for classes that represent domain 2594 | objects. 2595 | [[link](#define-to-s)] 2596 | 2597 | ```Ruby 2598 | class Person 2599 | attr_reader :first_name, :last_name 2600 | 2601 | def initialize(first_name, last_name) 2602 | @first_name = first_name 2603 | @last_name = last_name 2604 | end 2605 | 2606 | def to_s 2607 | "#{@first_name} #{@last_name}" 2608 | end 2609 | end 2610 | ``` 2611 | 2612 | * 2613 | Use the `attr` family of functions to define trivial accessors or mutators. 2614 | [[link](#attr_family)] 2615 | 2616 | ```Ruby 2617 | # bad 2618 | class Person 2619 | def initialize(first_name, last_name) 2620 | @first_name = first_name 2621 | @last_name = last_name 2622 | end 2623 | 2624 | def first_name 2625 | @first_name 2626 | end 2627 | 2628 | def last_name 2629 | @last_name 2630 | end 2631 | end 2632 | 2633 | # good 2634 | class Person 2635 | attr_reader :first_name, :last_name 2636 | 2637 | def initialize(first_name, last_name) 2638 | @first_name = first_name 2639 | @last_name = last_name 2640 | end 2641 | end 2642 | ``` 2643 | 2644 | * 2645 | For accessors and mutators, avoid prefixing method names with 2646 | `get_` and `set_`. 2647 | It is a Ruby convention to use attribute names for accessors (readers) and 2648 | `attr_name=` for mutators (writers). 2649 | [[link](#accessor_mutator_method_names)] 2650 | 2651 | ```Ruby 2652 | # bad 2653 | class Person 2654 | def get_name 2655 | "#{@first_name} #{@last_name}" 2656 | end 2657 | 2658 | def set_name(name) 2659 | @first_name, @last_name = name.split(' ') 2660 | end 2661 | end 2662 | 2663 | # good 2664 | class Person 2665 | def name 2666 | "#{@first_name} #{@last_name}" 2667 | end 2668 | 2669 | def name=(name) 2670 | @first_name, @last_name = name.split(' ') 2671 | end 2672 | end 2673 | ``` 2674 | 2675 | * 2676 | Avoid the use of `attr`. Use `attr_reader` and `attr_accessor` instead. 2677 | [[link](#attr)] 2678 | 2679 | ```Ruby 2680 | # bad - creates a single attribute accessor (deprecated in Ruby 1.9) 2681 | attr :something, true 2682 | attr :one, :two, :three # behaves as attr_reader 2683 | 2684 | # good 2685 | attr_accessor :something 2686 | attr_reader :one, :two, :three 2687 | ``` 2688 | 2689 | * 2690 | Consider using `Struct.new`, which defines the trivial accessors, 2691 | constructor and comparison operators for you. 2692 | [[link](#struct-new)] 2693 | 2694 | ```Ruby 2695 | # good 2696 | class Person 2697 | attr_accessor :first_name, :last_name 2698 | 2699 | def initialize(first_name, last_name) 2700 | @first_name = first_name 2701 | @last_name = last_name 2702 | end 2703 | end 2704 | 2705 | # better 2706 | Person = Struct.new(:first_name, :last_name) do 2707 | end 2708 | ``` 2709 | 2710 | * 2711 | Don't extend an instance initialized by `Struct.new`. Extending it introduces 2712 | a superfluous class level and may also introduce weird errors if the file is 2713 | required multiple times. 2714 | [[link](#no-extend-struct-new)] 2715 | 2716 | ```Ruby 2717 | # bad 2718 | class Person < Struct.new(:first_name, :last_name) 2719 | end 2720 | 2721 | # good 2722 | Person = Struct.new(:first_name, :last_name) 2723 | ``` 2724 | 2725 | * 2726 | Consider adding factory methods to provide additional sensible ways to 2727 | create instances of a particular class. 2728 | [[link](#factory-methods)] 2729 | 2730 | ```Ruby 2731 | class Person 2732 | def self.create(options_hash) 2733 | # body omitted 2734 | end 2735 | end 2736 | ``` 2737 | 2738 | * 2739 | Prefer [duck-typing](https://en.wikipedia.org/wiki/Duck_typing) over 2740 | inheritance. 2741 | [[link](#duck-typing)] 2742 | 2743 | ```Ruby 2744 | # bad 2745 | class Animal 2746 | # abstract method 2747 | def speak 2748 | end 2749 | end 2750 | 2751 | # extend superclass 2752 | class Duck < Animal 2753 | def speak 2754 | puts 'Quack! Quack' 2755 | end 2756 | end 2757 | 2758 | # extend superclass 2759 | class Dog < Animal 2760 | def speak 2761 | puts 'Bau! Bau!' 2762 | end 2763 | end 2764 | 2765 | # good 2766 | class Duck 2767 | def speak 2768 | puts 'Quack! Quack' 2769 | end 2770 | end 2771 | 2772 | class Dog 2773 | def speak 2774 | puts 'Bau! Bau!' 2775 | end 2776 | end 2777 | ``` 2778 | 2779 | * 2780 | Avoid the usage of class (`@@`) variables due to their "nasty" behavior in 2781 | inheritance. 2782 | [[link](#no-class-vars)] 2783 | 2784 | ```Ruby 2785 | class Parent 2786 | @@class_var = 'parent' 2787 | 2788 | def self.print_class_var 2789 | puts @@class_var 2790 | end 2791 | end 2792 | 2793 | class Child < Parent 2794 | @@class_var = 'child' 2795 | end 2796 | 2797 | Parent.print_class_var # => will print 'child' 2798 | ``` 2799 | 2800 | As you can see all the classes in a class hierarchy actually share one 2801 | class variable. Class instance variables should usually be preferred 2802 | over class variables. 2803 | 2804 | * 2805 | Assign proper visibility levels to methods (`private`, `protected`) in 2806 | accordance with their intended usage. Don't go off leaving everything `public` 2807 | (which is the default). After all we're coding in *Ruby* now, not in *Python*. 2808 | [[link](#visibility)] 2809 | 2810 | * 2811 | Indent the `public`, `protected`, and `private` methods as much as the method 2812 | definitions they apply to. Leave one blank line above the visibility modifier 2813 | and one blank line below in order to emphasize that it applies to all methods 2814 | below it. 2815 | [[link](#indent-public-private-protected)] 2816 | 2817 | ```Ruby 2818 | class SomeClass 2819 | def public_method 2820 | # some code 2821 | end 2822 | 2823 | private 2824 | 2825 | def private_method 2826 | # some code 2827 | end 2828 | 2829 | def another_private_method 2830 | # some code 2831 | end 2832 | end 2833 | ``` 2834 | 2835 | * 2836 | Use `def self.method` to define class methods. This makes the code 2837 | easier to refactor since the class name is not repeated. 2838 | [[link](#def-self-class-methods)] 2839 | 2840 | ```Ruby 2841 | class TestClass 2842 | # bad 2843 | def TestClass.some_method 2844 | # body omitted 2845 | end 2846 | 2847 | # good 2848 | def self.some_other_method 2849 | # body omitted 2850 | end 2851 | 2852 | # Also possible and convenient when you 2853 | # have to define many class methods. 2854 | class << self 2855 | def first_method 2856 | # body omitted 2857 | end 2858 | 2859 | def second_method_etc 2860 | # body omitted 2861 | end 2862 | end 2863 | end 2864 | ``` 2865 | 2866 | * 2867 | Prefer `alias` when aliasing methods in lexical class scope as the 2868 | resolution of `self` in this context is also lexical, and it communicates 2869 | clearly to the user that the indirection of your alias will not be altered 2870 | at runtime or by any subclass unless made explicit. 2871 | [[link](#alias-method-lexically)] 2872 | 2873 | ```Ruby 2874 | class Westerner 2875 | def first_name 2876 | @names.first 2877 | end 2878 | 2879 | alias given_name first_name 2880 | end 2881 | ``` 2882 | 2883 | Since `alias`, like `def`, is a keyword, prefer bareword arguments over 2884 | symbols or strings. In other words, do `alias foo bar`, not 2885 | `alias :foo :bar`. 2886 | 2887 | Also be aware of how Ruby handles aliases and inheritance: an alias 2888 | references the method that was resolved at the time the alias was defined; 2889 | it is not dispatched dynamically. 2890 | 2891 | ```Ruby 2892 | class Fugitive < Westerner 2893 | def first_name 2894 | 'Nobody' 2895 | end 2896 | end 2897 | ``` 2898 | 2899 | In this example, `Fugitive#given_name` would still call the original 2900 | `Westerner#first_name` method, not `Fugitive#first_name`. To override the 2901 | behavior of `Fugitive#given_name` as well, you'd have to redefine it in the 2902 | derived class. 2903 | 2904 | ```Ruby 2905 | class Fugitive < Westerner 2906 | def first_name 2907 | 'Nobody' 2908 | end 2909 | 2910 | alias given_name first_name 2911 | end 2912 | ``` 2913 | 2914 | * 2915 | Always use `alias_method` when aliasing methods of modules, classes, or 2916 | singleton classes at runtime, as the lexical scope of `alias` leads to 2917 | unpredictability in these cases. 2918 | [[link](#alias-method)] 2919 | 2920 | ```Ruby 2921 | module Mononymous 2922 | def self.included(other) 2923 | other.class_eval { alias_method :full_name, :given_name } 2924 | end 2925 | end 2926 | 2927 | class Sting < Westerner 2928 | include Mononymous 2929 | end 2930 | ``` 2931 | 2932 | * 2933 | When class (or module) methods call other such methods, omit the use of a 2934 | leading `self` or own name followed by a `.` when calling other such methods. 2935 | This is often seen in "service classes" or other similar concepts where a 2936 | class is treated as though it were a function. This convention tends to reduce 2937 | repetitive boilerpate in such classes. 2938 | [[link](#class-and-self)] 2939 | 2940 | ```Ruby 2941 | class TestClass 2942 | # bad -- more work when class renamed/method moved 2943 | def self.call(param1, param2) 2944 | TestClass.new(param1).call(param2) 2945 | end 2946 | 2947 | # bad -- more verbose than necessary 2948 | def self.call(param1, param2) 2949 | self.new(param1).call(param2) 2950 | end 2951 | 2952 | # good 2953 | def self.call(param1, param2) 2954 | new(param1).call(param2) 2955 | end 2956 | 2957 | # ...other methods... 2958 | end 2959 | ``` 2960 | 2961 | ## Exceptions 2962 | 2963 | * 2964 | Prefer `raise` over `fail` for exceptions. 2965 | [[link](#prefer-raise-over-fail)] 2966 | 2967 | ```Ruby 2968 | # bad 2969 | fail SomeException, 'message' 2970 | 2971 | # good 2972 | raise SomeException, 'message' 2973 | ``` 2974 | 2975 | * 2976 | Don't specify `RuntimeError` explicitly in the two argument version of 2977 | `raise`. 2978 | [[link](#no-explicit-runtimeerror)] 2979 | 2980 | ```Ruby 2981 | # bad 2982 | raise RuntimeError, 'message' 2983 | 2984 | # good - signals a RuntimeError by default 2985 | raise 'message' 2986 | ``` 2987 | 2988 | * 2989 | Prefer supplying an exception class and a message as two separate arguments 2990 | to `raise`, instead of an exception instance. 2991 | [[link](#exception-class-messages)] 2992 | 2993 | ```Ruby 2994 | # bad 2995 | raise SomeException.new('message') 2996 | # Note that there is no way to do `raise SomeException.new('message'), backtrace`. 2997 | 2998 | # good 2999 | raise SomeException, 'message' 3000 | # Consistent with `raise SomeException, 'message', backtrace`. 3001 | ``` 3002 | 3003 | * 3004 | Do not return from an `ensure` block. If you explicitly return from a method 3005 | inside an `ensure` block, the return will take precedence over any exception 3006 | being raised, and the method will return as if no exception had been raised at 3007 | all. In effect, the exception will be silently thrown away. 3008 | [[link](#no-return-ensure)] 3009 | 3010 | ```Ruby 3011 | # bad 3012 | def foo 3013 | raise 3014 | ensure 3015 | return 'very bad idea' 3016 | end 3017 | ``` 3018 | 3019 | * 3020 | Use *implicit begin blocks* where possible. 3021 | [[link](#begin-implicit)] 3022 | 3023 | ```Ruby 3024 | # bad 3025 | def foo 3026 | begin 3027 | # main logic goes here 3028 | rescue 3029 | # failure handling goes here 3030 | end 3031 | end 3032 | 3033 | # good 3034 | def foo 3035 | # main logic goes here 3036 | rescue 3037 | # failure handling goes here 3038 | end 3039 | ``` 3040 | 3041 | * 3042 | Mitigate the proliferation of `begin` blocks by using *contingency methods* 3043 | (a term coined by Avdi Grimm). 3044 | [[link](#contingency-methods)] 3045 | 3046 | ```Ruby 3047 | # bad 3048 | begin 3049 | something_that_might_fail 3050 | rescue IOError 3051 | # handle IOError 3052 | end 3053 | 3054 | begin 3055 | something_else_that_might_fail 3056 | rescue IOError 3057 | # handle IOError 3058 | end 3059 | 3060 | # good 3061 | def with_io_error_handling 3062 | yield 3063 | rescue IOError 3064 | # handle IOError 3065 | end 3066 | 3067 | with_io_error_handling { something_that_might_fail } 3068 | 3069 | with_io_error_handling { something_else_that_might_fail } 3070 | ``` 3071 | 3072 | * 3073 | Don't suppress exceptions. 3074 | [[link](#dont-hide-exceptions)] 3075 | 3076 | ```Ruby 3077 | # bad 3078 | begin 3079 | # an exception occurs here 3080 | rescue SomeError 3081 | # the rescue clause does absolutely nothing 3082 | end 3083 | 3084 | # bad 3085 | do_something rescue nil 3086 | ``` 3087 | 3088 | * 3089 | Avoid using `rescue` in its modifier form. 3090 | [[link](#no-rescue-modifiers)] 3091 | 3092 | ```Ruby 3093 | # bad - this catches exceptions of StandardError class and its descendant classes 3094 | read_file rescue handle_error($!) 3095 | 3096 | # good - this catches only the exceptions of Errno::ENOENT class and its descendant classes 3097 | def foo 3098 | read_file 3099 | rescue Errno::ENOENT => ex 3100 | handle_error(ex) 3101 | end 3102 | ``` 3103 | 3104 | * 3105 | Don't use exceptions for flow of control. 3106 | [[link](#no-exceptional-flows)] 3107 | 3108 | ```Ruby 3109 | # bad 3110 | begin 3111 | n / d 3112 | rescue ZeroDivisionError 3113 | puts 'Cannot divide by 0!' 3114 | end 3115 | 3116 | # good 3117 | if d.zero? 3118 | puts 'Cannot divide by 0!' 3119 | else 3120 | n / d 3121 | end 3122 | ``` 3123 | 3124 | * 3125 | Avoid rescuing the `Exception` class. This will trap signals and calls to 3126 | `exit`, requiring you to `kill -9` the process. 3127 | [[link](#no-blind-rescues)] 3128 | 3129 | ```Ruby 3130 | # bad 3131 | begin 3132 | # calls to exit and kill signals will be caught (except kill -9) 3133 | exit 3134 | rescue Exception 3135 | puts "you didn't really want to exit, right?" 3136 | # exception handling 3137 | end 3138 | 3139 | # good 3140 | begin 3141 | # a blind rescue rescues from StandardError, not Exception as many 3142 | # programmers assume. 3143 | rescue => e 3144 | # exception handling 3145 | end 3146 | 3147 | # also good 3148 | begin 3149 | # an exception occurs here 3150 | rescue StandardError => e 3151 | # exception handling 3152 | end 3153 | ``` 3154 | 3155 | * 3156 | Put more specific exceptions higher up the rescue chain, otherwise they'll 3157 | never be rescued from. 3158 | [[link](#exception-ordering)] 3159 | 3160 | ```Ruby 3161 | # bad 3162 | begin 3163 | # some code 3164 | rescue StandardError => e 3165 | # some handling 3166 | rescue IOError => e 3167 | # some handling that will never be executed 3168 | end 3169 | 3170 | # good 3171 | begin 3172 | # some code 3173 | rescue IOError => e 3174 | # some handling 3175 | rescue StandardError => e 3176 | # some handling 3177 | end 3178 | ``` 3179 | 3180 | * 3181 | Release external resources obtained by your program in an `ensure` block. 3182 | [[link](#release-resources)] 3183 | 3184 | ```Ruby 3185 | f = File.open('testfile') 3186 | begin 3187 | # .. process 3188 | rescue 3189 | # .. handle error 3190 | ensure 3191 | f.close if f 3192 | end 3193 | ``` 3194 | 3195 | * 3196 | Use versions of resource obtaining methods that do automatic 3197 | resource cleanup when possible. 3198 | [[link](#auto-release-resources)] 3199 | 3200 | ```Ruby 3201 | # bad - you need to close the file descriptor explicitly 3202 | f = File.open('testfile') 3203 | # some action on the file 3204 | f.close 3205 | 3206 | # good - the file descriptor is closed automatically 3207 | File.open('testfile') do |f| 3208 | # some action on the file 3209 | end 3210 | ``` 3211 | 3212 | * 3213 | Favor the use of exceptions from the standard library over introducing new 3214 | exception classes. 3215 | [[link](#standard-exceptions)] 3216 | 3217 | ## Collections 3218 | 3219 | * 3220 | Prefer literal array and hash creation notation (unless you need to pass 3221 | parameters to their constructors, that is). 3222 | [[link](#literal-array-hash)] 3223 | 3224 | ```Ruby 3225 | # bad 3226 | arr = Array.new 3227 | hash = Hash.new 3228 | 3229 | # good 3230 | arr = [] 3231 | hash = {} 3232 | ``` 3233 | 3234 | * 3235 | Prefer `%w` to the literal array syntax when you need an array of words 3236 | (non-empty strings without spaces and special characters in them). Apply this 3237 | rule only to arrays with two or more elements. 3238 | [[link](#percent-w)] 3239 | 3240 | ```Ruby 3241 | # bad 3242 | STATES = ['draft', 'open', 'closed'] 3243 | 3244 | # good 3245 | STATES = %w[draft open closed] 3246 | ``` 3247 | 3248 | * 3249 | Prefer `%i` to the literal array syntax when you need an array of symbols 3250 | (and you don't need to maintain Ruby 1.9 compatibility). Apply this rule only 3251 | to arrays with two or more elements. 3252 | [[link](#percent-i)] 3253 | 3254 | ```Ruby 3255 | # bad 3256 | STATES = [:draft, :open, :closed] 3257 | 3258 | # good 3259 | STATES = %i[draft open closed] 3260 | ``` 3261 | 3262 | * 3263 | Avoid comma after the last item of an `Array` or `Hash` literal, especially 3264 | when the items are not on separate lines. 3265 | [[link](#no-trailing-array-commas)] 3266 | 3267 | ```Ruby 3268 | # bad - easier to move/add/remove items, but still not preferred 3269 | VALUES = [ 3270 | 1001, 3271 | 2020, 3272 | 3333, 3273 | ] 3274 | 3275 | # bad 3276 | VALUES = [1001, 2020, 3333, ] 3277 | 3278 | # good 3279 | VALUES = [1001, 2020, 3333] 3280 | ``` 3281 | 3282 | * 3283 | Avoid the creation of huge gaps in arrays. 3284 | [[link](#no-gappy-arrays)] 3285 | 3286 | ```Ruby 3287 | arr = [] 3288 | arr[100] = 1 # now you have an array with lots of nils 3289 | ``` 3290 | 3291 | * 3292 | When accessing the first or last element from an array, prefer `first` or 3293 | `last` over `[0]` or `[-1]`. 3294 | [[link](#first-and-last)] 3295 | 3296 | * 3297 | Use `Set` instead of `Array` when dealing with unique elements. `Set` 3298 | implements a collection of unordered values with no duplicates. This is a 3299 | hybrid of `Array`'s intuitive inter-operation facilities and `Hash`'s fast 3300 | lookup. 3301 | [[link](#set-vs-array)] 3302 | 3303 | * 3304 | Prefer symbols instead of strings as hash keys. 3305 | [[link](#symbols-as-keys)] 3306 | 3307 | ```Ruby 3308 | # bad 3309 | hash = { 'one' => 1, 'two' => 2, 'three' => 3 } 3310 | 3311 | # good 3312 | hash = { one: 1, two: 2, three: 3 } 3313 | ``` 3314 | 3315 | * 3316 | Avoid the use of mutable objects as hash keys. 3317 | [[link](#no-mutable-keys)] 3318 | 3319 | * 3320 | Use the Ruby 1.9 hash literal syntax when your hash keys are symbols. 3321 | [[link](#hash-literals)] 3322 | 3323 | ```Ruby 3324 | # bad 3325 | hash = { :one => 1, :two => 2, :three => 3 } 3326 | 3327 | # good 3328 | hash = { one: 1, two: 2, three: 3 } 3329 | ``` 3330 | 3331 | * 3332 | Don't mix the Ruby 1.9 hash syntax with hash rockets in the same hash 3333 | literal. When you've got keys that are not symbols stick to the hash rockets 3334 | syntax. 3335 | [[link](#no-mixed-hash-syntaces)] 3336 | 3337 | ```Ruby 3338 | # bad 3339 | { a: 1, 'b' => 2 } 3340 | 3341 | # good 3342 | { :a => 1, 'b' => 2 } 3343 | ``` 3344 | 3345 | * 3346 | Use `Hash#key?` instead of `Hash#has_key?` and `Hash#value?` instead of 3347 | `Hash#has_value?`. 3348 | [[link](#hash-key)] 3349 | 3350 | ```Ruby 3351 | # bad 3352 | hash.has_key?(:test) 3353 | hash.has_value?(value) 3354 | 3355 | # good 3356 | hash.key?(:test) 3357 | hash.value?(value) 3358 | ``` 3359 | 3360 | * 3361 | Use `Hash#each_key` instead of `Hash#keys.each` and `Hash#each_value` 3362 | instead of `Hash#values.each`. 3363 | [[link](#hash-each)] 3364 | 3365 | ```Ruby 3366 | # bad 3367 | hash.keys.each { |k| p k } 3368 | hash.values.each { |v| p v } 3369 | hash.each { |k, _v| p k } 3370 | hash.each { |_k, v| p v } 3371 | 3372 | # good 3373 | hash.each_key { |k| p k } 3374 | hash.each_value { |v| p v } 3375 | ``` 3376 | 3377 | * 3378 | Use `Hash#fetch` when dealing with hash keys that should be present. 3379 | [[link](#hash-fetch)] 3380 | 3381 | ```Ruby 3382 | heroes = { batman: 'Bruce Wayne', superman: 'Clark Kent' } 3383 | # bad - if we make a mistake we might not spot it right away 3384 | heroes[:batman] # => 'Bruce Wayne' 3385 | heroes[:supermann] # => nil 3386 | 3387 | # good - fetch raises a KeyError making the problem obvious 3388 | heroes.fetch(:supermann) 3389 | ``` 3390 | 3391 | * 3392 | Introduce default values for hash keys via `Hash#fetch` as opposed to using 3393 | custom logic. 3394 | [[link](#hash-fetch-defaults)] 3395 | 3396 | ```Ruby 3397 | batman = { name: 'Bruce Wayne', is_evil: false } 3398 | 3399 | # bad - if we just use || operator with falsy value we won't get the expected result 3400 | batman[:is_evil] || true # => true 3401 | 3402 | # good - fetch work correctly with falsy values 3403 | batman.fetch(:is_evil, true) # => false 3404 | ``` 3405 | 3406 | * 3407 | Prefer the use of the block instead of the default value in `Hash#fetch` 3408 | if the code that has to be evaluated may have side effects or be expensive. 3409 | [[link](#use-hash-blocks)] 3410 | 3411 | ```Ruby 3412 | batman = { name: 'Bruce Wayne' } 3413 | 3414 | # bad - if we use the default value, we eager evaluate it 3415 | # so it can slow the program down if done multiple times 3416 | batman.fetch(:powers, obtain_batman_powers) # obtain_batman_powers is an expensive call 3417 | 3418 | # good - blocks are lazy evaluated, so only triggered in case of KeyError exception 3419 | batman.fetch(:powers) { obtain_batman_powers } 3420 | ``` 3421 | 3422 | * 3423 | Use `Hash#values_at` when you need to retrieve several values consecutively 3424 | from a hash. 3425 | [[link](#hash-values-at)] 3426 | 3427 | ```Ruby 3428 | # bad 3429 | email = data['email'] 3430 | username = data['nickname'] 3431 | 3432 | # good 3433 | email, username = data.values_at('email', 'nickname') 3434 | ``` 3435 | 3436 | * 3437 | Rely on the fact that as of Ruby 1.9 hashes are ordered. 3438 | [[link](#ordered-hashes)] 3439 | 3440 | * 3441 | Do not modify a collection while traversing it. 3442 | [[link](#no-modifying-collections)] 3443 | 3444 | * 3445 | When accessing elements of a collection, avoid direct access 3446 | via `[n]` by using an alternate form of the reader method if it is 3447 | supplied. This guards you from calling `[]` on `nil`. 3448 | [[link](#accessing-elements-directly)] 3449 | 3450 | ```Ruby 3451 | # bad 3452 | Regexp.last_match[1] 3453 | 3454 | # good 3455 | Regexp.last_match(1) 3456 | ``` 3457 | 3458 | * 3459 | When providing an accessor for a collection, provide an alternate form 3460 | to save users from checking for `nil` before accessing an element in 3461 | the collection. 3462 | [[link](#provide-alternate-accessor-to-collections)] 3463 | 3464 | ```Ruby 3465 | # bad 3466 | def awesome_things 3467 | @awesome_things 3468 | end 3469 | 3470 | # good 3471 | def awesome_things(index = nil) 3472 | if index && @awesome_things 3473 | @awesome_things[index] 3474 | else 3475 | @awesome_things 3476 | end 3477 | end 3478 | ``` 3479 | ## Numbers 3480 | 3481 | * 3482 | Use `Integer` check type of an integer number. Since `Fixnum` is 3483 | platform-dependent, checking against it will return different results on 3484 | 32-bit and 64-bit machines. 3485 | [[link](#integer-type-checking)] 3486 | 3487 | ```Ruby 3488 | timestamp = Time.now.to_i 3489 | 3490 | # bad 3491 | timestamp.is_a? Fixnum 3492 | timestamp.is_a? Bignum 3493 | 3494 | # good 3495 | timestamp.is_a? Integer 3496 | ``` 3497 | 3498 | * 3499 | Prefer to use ranges when generating random numbers instead of integers with offsets, 3500 | since it clearly states your intentions. Imagine simulating a role of a dice: 3501 | [[link](#random-numbers)] 3502 | 3503 | ```Ruby 3504 | # bad 3505 | rand(6) + 1 3506 | 3507 | # good 3508 | rand(1..6) 3509 | ``` 3510 | 3511 | ## Strings 3512 | 3513 | * 3514 | Prefer string interpolation and string formatting instead of string 3515 | concatenation: 3516 | [[link](#string-interpolation)] 3517 | 3518 | ```Ruby 3519 | # bad 3520 | email_with_name = user.name + ' <' + user.email + '>' 3521 | 3522 | # good 3523 | email_with_name = "#{user.name} <#{user.email}>" 3524 | 3525 | # good 3526 | email_with_name = format('%s <%s>', user.name, user.email) 3527 | ``` 3528 | 3529 | * 3530 | Adopt a consistent string literal quoting style. There are two popular 3531 | styles in the Ruby community, both of which are considered good—single 3532 | quotes by default (Option A) and double quotes by default (Option B). 3533 | [[link](#consistent-string-literals)] 3534 | 3535 | * **(Option A)** Prefer single-quoted strings when you don't need 3536 | string interpolation or special symbols such as `\t`, `\n`, `'`, 3537 | etc. 3538 | 3539 | ```Ruby 3540 | # bad 3541 | name = "Bozhidar" 3542 | 3543 | # good 3544 | name = 'Bozhidar' 3545 | ``` 3546 | 3547 | * **(Option B)** Prefer double-quotes unless your string literal 3548 | contains `"` or escape characters you want to suppress. 3549 | 3550 | ```Ruby 3551 | # bad 3552 | name = 'Bozhidar' 3553 | 3554 | # good 3555 | name = "Bozhidar" 3556 | ``` 3557 | 3558 | The string literals in this guide are aligned with the first style. 3559 | 3560 | * 3561 | Don't use the character literal syntax `?x`. Since Ruby 1.9 it's basically 3562 | redundant—`?x` would interpreted as `'x'` (a string with a single 3563 | character in it). 3564 | [[link](#no-character-literals)] 3565 | 3566 | ```Ruby 3567 | # bad 3568 | char = ?c 3569 | 3570 | # good 3571 | char = 'c' 3572 | ``` 3573 | 3574 | * 3575 | Don't leave out `{}` around instance and global variables being interpolated 3576 | into a string. 3577 | [[link](#curlies-interpolate)] 3578 | 3579 | ```Ruby 3580 | class Person 3581 | attr_reader :first_name, :last_name 3582 | 3583 | def initialize(first_name, last_name) 3584 | @first_name = first_name 3585 | @last_name = last_name 3586 | end 3587 | 3588 | # bad - valid, but awkward 3589 | def to_s 3590 | "#@first_name #@last_name" 3591 | end 3592 | 3593 | # good 3594 | def to_s 3595 | "#{@first_name} #{@last_name}" 3596 | end 3597 | end 3598 | 3599 | $global = 0 3600 | # bad 3601 | puts "$global = #$global" 3602 | 3603 | # good 3604 | puts "$global = #{$global}" 3605 | ``` 3606 | 3607 | * 3608 | Don't use `Object#to_s` on interpolated objects. It's invoked on them 3609 | automatically. 3610 | [[link](#no-to-s)] 3611 | 3612 | ```Ruby 3613 | # bad 3614 | message = "This is the #{result.to_s}." 3615 | 3616 | # good 3617 | message = "This is the #{result}." 3618 | ``` 3619 | 3620 | * 3621 | Avoid using `String#+` when you need to construct large data chunks. 3622 | Instead, use `String#<<`. Concatenation mutates the string instance in-place 3623 | and is always faster than `String#+`, which creates a bunch of new string 3624 | objects. 3625 | [[link](#concat-strings)] 3626 | 3627 | ```Ruby 3628 | # bad 3629 | html = '' 3630 | html += '

Page title

' 3631 | 3632 | paragraphs.each do |paragraph| 3633 | html += "

#{paragraph}

" 3634 | end 3635 | 3636 | # good and also fast 3637 | html = '' 3638 | html << '

Page title

' 3639 | 3640 | paragraphs.each do |paragraph| 3641 | html << "

#{paragraph}

" 3642 | end 3643 | ``` 3644 | 3645 | * 3646 | Don't use `String#gsub` in scenarios in which you can use a faster more specialized alternative. 3647 | [[link](#dont-abuse-gsub)] 3648 | 3649 | ```Ruby 3650 | url = 'http://example.com' 3651 | str = 'lisp-case-rules' 3652 | 3653 | # bad 3654 | url.gsub('http://', 'https://') 3655 | str.gsub('-', '_') 3656 | 3657 | # good 3658 | url.sub('http://', 'https://') 3659 | str.tr('-', '_') 3660 | ``` 3661 | 3662 | * 3663 | When using heredocs for multi-line strings keep in mind the fact that they 3664 | preserve leading whitespace. It's a good practice to employ some margin based 3665 | on which to trim the excessive whitespace. 3666 | [[link](#heredocs)] 3667 | 3668 | ```Ruby 3669 | code = <<-END.gsub(/^\s+\|/, '') 3670 | |def test 3671 | | some_method 3672 | | other_method 3673 | |end 3674 | END 3675 | # => "def test\n some_method\n other_method\nend\n" 3676 | ``` 3677 | 3678 | * 3679 | Use Ruby 2.3's squiggly heredocs for nicely indented multi-line strings. 3680 | [[link](#squiggly-heredocs)] 3681 | 3682 | ```Ruby 3683 | # bad - using Powerpack String#strip_margin 3684 | code = <<-END.strip_margin('|') 3685 | |def test 3686 | | some_method 3687 | | other_method 3688 | |end 3689 | END 3690 | 3691 | # also bad 3692 | code = <<-END 3693 | def test 3694 | some_method 3695 | other_method 3696 | end 3697 | END 3698 | 3699 | # good 3700 | code = <<~END 3701 | def test 3702 | some_method 3703 | other_method 3704 | end 3705 | END 3706 | ``` 3707 | 3708 | ## Date & Time 3709 | 3710 | * 3711 | Prefer `Time.now` over `Time.new` when retrieving the current system time. 3712 | [[link](#time-now)] 3713 | 3714 | * 3715 | Don't use `DateTime` unless you need to account for historical calendar 3716 | reform -- and if you do, explicitly specify the `start` argument to 3717 | clearly state your intentions. 3718 | [[link](#no-datetime)] 3719 | 3720 | ```Ruby 3721 | # bad - uses DateTime for current time 3722 | DateTime.now 3723 | 3724 | # good - uses Time for current time 3725 | Time.now 3726 | 3727 | # bad - uses DateTime for modern date 3728 | DateTime.iso8601('2016-06-29') 3729 | 3730 | # good - uses Date for modern date 3731 | Date.iso8601('2016-06-29') 3732 | 3733 | # good - uses DateTime with start argument for historical date 3734 | DateTime.iso8601('1751-04-23', Date::ENGLAND) 3735 | ``` 3736 | 3737 | ## Regular Expressions 3738 | 3739 | > Some people, when confronted with a problem, think 3740 | > "I know, I'll use regular expressions." Now they have two problems.
3741 | > -- Jamie Zawinski 3742 | 3743 | * 3744 | Don't use regular expressions if you just need plain text search in string: 3745 | `string['text']` 3746 | [[link](#no-regexp-for-plaintext)] 3747 | 3748 | * 3749 | For simple constructions you can use regexp directly through string index. 3750 | [[link](#regexp-string-index)] 3751 | 3752 | ```Ruby 3753 | match = string[/regexp/] # get content of matched regexp 3754 | first_group = string[/text(grp)/, 1] # get content of captured group 3755 | string[/text (grp)/, 1] = 'replace' # string => 'text replace' 3756 | ``` 3757 | 3758 | * 3759 | Use non-capturing groups when you don't use the captured result. 3760 | [[link](#non-capturing-regexp)] 3761 | 3762 | ```Ruby 3763 | # bad 3764 | /(first|second)/ 3765 | 3766 | # good 3767 | /(?:first|second)/ 3768 | ``` 3769 | 3770 | * 3771 | Don't use the cryptic Perl-legacy variables denoting last regexp group 3772 | matches (`$1`, `$2`, etc). Use `Regexp.last_match(n)` instead. 3773 | [[link](#no-perl-regexp-last-matchers)] 3774 | 3775 | ```Ruby 3776 | /(regexp)/ =~ string 3777 | ... 3778 | 3779 | # bad 3780 | process $1 3781 | 3782 | # good 3783 | process Regexp.last_match(1) 3784 | ``` 3785 | 3786 | * 3787 | Avoid using numbered groups as it can be hard to track what they contain. 3788 | Named groups can be used instead. 3789 | [[link](#no-numbered-regexes)] 3790 | 3791 | ```Ruby 3792 | # bad 3793 | /(regexp)/ =~ string 3794 | # some code 3795 | process Regexp.last_match(1) 3796 | 3797 | # good 3798 | /(?regexp)/ =~ string 3799 | # some code 3800 | process meaningful_var 3801 | ``` 3802 | 3803 | * 3804 | Character classes have only a few special characters you should care about: 3805 | `^`, `-`, `\`, `]`, so don't escape `.` or brackets in `[]`. 3806 | [[link](#limit-escapes)] 3807 | 3808 | * 3809 | Be careful with `^` and `$` as they match start/end of line, not string 3810 | endings. If you want to match the whole string use: `\A` and `\z` (not to be 3811 | confused with `\Z` which is the equivalent of `/\n?\z/`). 3812 | [[link](#caret-and-dollar-regexp)] 3813 | 3814 | ```Ruby 3815 | string = "some injection\nusername" 3816 | string[/^username$/] # matches 3817 | string[/\Ausername\z/] # doesn't match 3818 | ``` 3819 | 3820 | * 3821 | Use `x` modifier for complex regexps. This makes them more readable and you 3822 | can add some useful comments. Just be careful as spaces are ignored. 3823 | [[link](#comment-regexes)] 3824 | 3825 | ```Ruby 3826 | regexp = / 3827 | start # some text 3828 | \s # white space char 3829 | (group) # first group 3830 | (?:alt1|alt2) # some alternation 3831 | end 3832 | /x 3833 | ``` 3834 | 3835 | * 3836 | For complex replacements `sub`/`gsub` can be used with a block or a hash. 3837 | [[link](#gsub-blocks)] 3838 | 3839 | ```Ruby 3840 | words = 'foo bar' 3841 | words.sub(/f/, 'f' => 'F') # => 'Foo bar' 3842 | words.gsub(/\w+/) { |word| word.capitalize } # => 'Foo Bar' 3843 | ``` 3844 | 3845 | ## Percent Literals 3846 | 3847 | * 3848 | Use `%()`(it's a shorthand for `%Q`) for single-line strings which require 3849 | both interpolation and embedded double-quotes. For multi-line strings, prefer 3850 | heredocs. 3851 | [[link](#percent-q-shorthand)] 3852 | 3853 | ```Ruby 3854 | # bad (no interpolation needed) 3855 | %(
Some text
) 3856 | # should be '
Some text
' 3857 | 3858 | # bad (no double-quotes) 3859 | %(This is #{quality} style) 3860 | # should be "This is #{quality} style" 3861 | 3862 | # bad (multiple lines) 3863 | %(
\n#{exclamation}\n
) 3864 | # should be a heredoc. 3865 | 3866 | # good (requires interpolation, has quotes, single line) 3867 | %(#{name}) 3868 | ``` 3869 | 3870 | * 3871 | Avoid %() or the equivlant %q() unless you have a string with both `'` and 3872 | `"` in it. Regular string literals are more readable and should be preferred 3873 | unless a lot of characters would have to be escaped in them. 3874 | [[link](#percent-q)] 3875 | 3876 | ```Ruby 3877 | # bad 3878 | name = %q(Bruce Wayne) 3879 | time = %q(8 o'clock) 3880 | question = %q("What did you say?") 3881 | 3882 | # good 3883 | name = 'Bruce Wayne' 3884 | time = "8 o'clock" 3885 | question = '"What did you say?"' 3886 | quote = %q(

"What did you say?"

) 3887 | ``` 3888 | 3889 | * 3890 | Use `%r` only for regular expressions matching *at least* one '/' 3891 | character. 3892 | [[link](#percent-r)] 3893 | 3894 | ```Ruby 3895 | # bad 3896 | %r{\s+} 3897 | 3898 | # good 3899 | %r{^/(.*)$} 3900 | %r{^/blog/2011/(.*)$} 3901 | ``` 3902 | 3903 | * 3904 | Avoid the use of `%x` unless you're going to invoke a command with 3905 | backquotes in it(which is rather unlikely). 3906 | [[link](#percent-x)] 3907 | 3908 | ```Ruby 3909 | # bad 3910 | date = %x(date) 3911 | 3912 | # good 3913 | date = `date` 3914 | echo = %x(echo `date`) 3915 | ``` 3916 | 3917 | * 3918 | Avoid the use of `%s`. It seems that the community has decided `:"some 3919 | string"` is the preferred way to create a symbol with spaces in it. 3920 | [[link](#percent-s)] 3921 | 3922 | * 3923 | Use the braces that are the most appropriate for the various kinds of percent 3924 | literals. 3925 | [[link](#percent-literal-braces)] 3926 | - `()` for string literals(`%q`, `%Q`). 3927 | - `[]` for array literals(`%w`, `%i`, `%W`, `%I`) as it is aligned with 3928 | the standard array literals. 3929 | - `{}` for regexp literals(`%r`) since parentheses often appear inside regular 3930 | expressions. That's why a less common character with `{` is usually the best 3931 | delimiter for `%r` literals. 3932 | - `()` for all other literals (e.g. `%s`, `%x`) 3933 | 3934 | ```Ruby 3935 | # bad 3936 | %q{"Test's king!", John said.} 3937 | 3938 | # good 3939 | %q("Test's king!", John said.) 3940 | 3941 | # bad 3942 | %w(one two three) 3943 | %i(one two three) 3944 | 3945 | # good 3946 | %w[one two three] 3947 | %i[one two three] 3948 | 3949 | # bad 3950 | %r((\w+)-(\d+)) 3951 | %r{\w{1,2}\d{2,5}} 3952 | 3953 | # good 3954 | %r{(\w+)-(\d+)} 3955 | %r|\w{1,2}\d{2,5}| 3956 | ``` 3957 | 3958 | ## Metaprogramming 3959 | 3960 | * 3961 | Avoid needless metaprogramming. 3962 | [[link](#no-needless-metaprogramming)] 3963 | 3964 | * 3965 | Do not mess around in core classes when writing libraries. (Do not 3966 | monkey-patch them.) 3967 | [[link](#no-monkey-patching)] 3968 | 3969 | * 3970 | The block form of `class_eval` is preferable to the string-interpolated 3971 | form. 3972 | [[link](#block-class-eval)] 3973 | 3974 | - when you use the string-interpolated form, always supply `__FILE__` 3975 | and `__LINE__`, so that your backtraces make sense: 3976 | 3977 | ```ruby 3978 | class_eval 'def use_relative_model_naming?; true; end', __FILE__, __LINE__ 3979 | ``` 3980 | 3981 | - `define_method` is preferable to `class_eval{ def ... }` 3982 | 3983 | * 3984 | When using `class_eval` (or other `eval`) with string interpolation, add a 3985 | comment block showing its appearance if interpolated (a practice used in Rails 3986 | code): 3987 | [[link](#eval-comment-docs)] 3988 | 3989 | ```ruby 3990 | # from activesupport/lib/active_support/core_ext/string/output_safety.rb 3991 | UNSAFE_STRING_METHODS.each do |unsafe_method| 3992 | if 'String'.respond_to?(unsafe_method) 3993 | class_eval <<-EOT, __FILE__, __LINE__ + 1 3994 | def #{unsafe_method}(*params, &block) # def capitalize(*params, &block) 3995 | to_str.#{unsafe_method}(*params, &block) # to_str.capitalize(*params, &block) 3996 | end # end 3997 | 3998 | def #{unsafe_method}!(*params) # def capitalize!(*params) 3999 | @dirty = true # @dirty = true 4000 | super # super 4001 | end # end 4002 | EOT 4003 | end 4004 | end 4005 | ``` 4006 | 4007 | * 4008 | Avoid using `method_missing` for metaprogramming because backtraces become 4009 | messy, the behavior is not listed in `#methods`, and misspelled method calls 4010 | might silently work, e.g. `nukes.launch_state = false`. Consider using 4011 | delegation, proxy, or `define_method` instead. If you must use 4012 | `method_missing`: 4013 | [[link](#no-method-missing)] 4014 | 4015 | - Be sure to [also define `respond_to_missing?`](http://blog.marc-andre.ca/2010/11/methodmissing-politely.html) 4016 | - Only catch methods with a well-defined prefix, such as `find_by_*` -- make your code as assertive as possible. 4017 | - Call `super` at the end of your statement 4018 | - Delegate to assertive, non-magical methods: 4019 | 4020 | ```ruby 4021 | # bad 4022 | def method_missing?(meth, *params, &block) 4023 | if /^find_by_(?.*)/ =~ meth 4024 | # ... lots of code to do a find_by 4025 | else 4026 | super 4027 | end 4028 | end 4029 | 4030 | # good 4031 | def method_missing?(meth, *params, &block) 4032 | if /^find_by_(?.*)/ =~ meth 4033 | find_by(prop, *params, &block) 4034 | else 4035 | super 4036 | end 4037 | end 4038 | 4039 | # best of all, though, would to define_method as each findable attribute is declared 4040 | ``` 4041 | 4042 | * 4043 | Prefer `public_send` over `send` so as not to circumvent `private`/`protected` visibility. 4044 | [[link](#prefer-public-send)] 4045 | 4046 | ```ruby 4047 | # We have an ActiveModel Organization that includes concern Activatable 4048 | module Activatable 4049 | extend ActiveSupport::Concern 4050 | 4051 | included do 4052 | before_create :create_token 4053 | end 4054 | 4055 | private 4056 | 4057 | def reset_token 4058 | # some code 4059 | end 4060 | 4061 | def create_token 4062 | # some code 4063 | end 4064 | 4065 | def activate! 4066 | # some code 4067 | end 4068 | end 4069 | 4070 | class Organization < ActiveRecord::Base 4071 | include Activatable 4072 | end 4073 | 4074 | linux_organization = Organization.find(...) 4075 | # BAD - violates privacy 4076 | linux_organization.send(:reset_token) 4077 | # GOOD - should throw an exception 4078 | linux_organization.public_send(:reset_token) 4079 | ``` 4080 | 4081 | * 4082 | Prefer `__send__` over `send`, as `send` may overlap with existing methods. 4083 | [[link](#prefer-__send__)] 4084 | 4085 | ```ruby 4086 | require 'socket' 4087 | 4088 | u1 = UDPSocket.new 4089 | u1.bind('127.0.0.1', 4913) 4090 | u2 = UDPSocket.new 4091 | u2.connect('127.0.0.1', 4913) 4092 | # Won't send a message to the receiver obj. 4093 | # Instead it will send a message via UDP socket. 4094 | u2.send :sleep, 0 4095 | # Will actually send a message to the receiver obj. 4096 | u2.__send__ ... 4097 | ``` 4098 | 4099 | ## Misc 4100 | 4101 | * 4102 | Write `ruby -w` safe code. 4103 | [[link](#always-warn)] 4104 | 4105 | * 4106 | Avoid hashes as optional parameters. Does the method do too much? (Object 4107 | initializers are exceptions for this rule). 4108 | [[link](#no-optional-hash-params)] 4109 | 4110 | * 4111 | Avoid methods longer than 10 LOC (lines of code). Ideally, most methods will 4112 | be shorter than 5 LOC. Empty lines do not contribute to the relevant LOC. 4113 | [[link](#short-methods)] 4114 | 4115 | * 4116 | Avoid parameter lists longer than three or four parameters. 4117 | [[link](#too-many-params)] 4118 | 4119 | * 4120 | If you really need "global" methods, add them to Kernel and make them 4121 | private. 4122 | [[link](#private-global-methods)] 4123 | 4124 | * 4125 | Use module instance variables instead of global variables. 4126 | [[link](#instance-vars)] 4127 | 4128 | ```Ruby 4129 | # bad 4130 | $foo_bar = 1 4131 | 4132 | # good 4133 | module Foo 4134 | class << self 4135 | attr_accessor :bar 4136 | end 4137 | end 4138 | 4139 | Foo.bar = 1 4140 | ``` 4141 | 4142 | * 4143 | Use `OptionParser` for parsing complex command line options and `ruby -s` 4144 | for trivial command line options. 4145 | [[link](#optionparser)] 4146 | 4147 | * 4148 | Code in a functional way, avoiding mutation when that makes sense. 4149 | [[link](#functional-code)] 4150 | 4151 | * 4152 | Do not mutate parameters unless that is the purpose of the method. 4153 | [[link](#no-param-mutations)] 4154 | 4155 | * 4156 | Avoid more than three levels of block nesting. 4157 | [[link](#three-is-the-number-thou-shalt-count)] 4158 | 4159 | * 4160 | Be consistent. In an ideal world, be consistent with these guidelines. 4161 | [[link](#be-consistent)] 4162 | 4163 | * 4164 | Use common sense. 4165 | [[link](#common-sense)] 4166 | 4167 | ## Tools 4168 | 4169 | Here are some tools to help you automatically check Ruby code against 4170 | this guide. 4171 | 4172 | ### RuboCop 4173 | 4174 | [RuboCop][] is a Ruby code style 4175 | checker based on this style guide. RuboCop already covers a 4176 | significant portion of the Guide, supports both MRI 1.9 and MRI 2.0 4177 | and has good Emacs integration. 4178 | 4179 | ### RubyMine 4180 | 4181 | [RubyMine](http://www.jetbrains.com/ruby/)'s code inspections are 4182 | [partially based](http://confluence.jetbrains.com/display/RUBYDEV/RubyMine+Inspections) 4183 | on this guide. 4184 | 4185 | # Contributing 4186 | 4187 | The guide is still a work in progress—some rules are lacking examples, 4188 | some rules don't have examples that illustrate them clearly enough. Improving 4189 | such rules is a great (and simple way) to help the Ruby community! 4190 | 4191 | In due time these issues will (hopefully) be addressed—just keep them in 4192 | mind for now. 4193 | 4194 | Nothing written in this guide is set in stone. It's my desire to work 4195 | together with everyone interested in Ruby coding style, so that we could 4196 | ultimately create a resource that will be beneficial to the entire Ruby 4197 | community. 4198 | 4199 | Feel free to open tickets or send pull requests with improvements. Thanks in 4200 | advance for your help! 4201 | 4202 | You can also support the project (and RuboCop) with financial 4203 | contributions via [Gratipay](https://gratipay.com/~bbatsov/). 4204 | 4205 | [![Support via Gratipay](https://cdn.rawgit.com/gratipay/gratipay-badge/2.3.0/dist/gratipay.png)](https://gratipay.com/~bbatsov/) 4206 | 4207 | ## How to Contribute? 4208 | 4209 | It's easy, just follow the [contribution guidelines](https://github.com/bbatsov/ruby-style-guide/blob/master/CONTRIBUTING.md). 4210 | 4211 | # License 4212 | 4213 | ![Creative Commons License](http://i.creativecommons.org/l/by/3.0/88x31.png) 4214 | This work is licensed under a [Creative Commons Attribution 3.0 Unported License](http://creativecommons.org/licenses/by/3.0/deed.en_US) 4215 | 4216 | # Spread the Word 4217 | 4218 | A community-driven style guide is of little use to a community that 4219 | doesn't know about its existence. Tweet about the guide, share it with 4220 | your friends and colleagues. Every comment, suggestion or opinion we 4221 | get makes the guide just a little bit better. And we want to have the 4222 | best possible guide, don't we? 4223 | 4224 | Cheers,
4225 | [Bozhidar](https://twitter.com/bbatsov) 4226 | 4227 | [PEP-8]: https://www.python.org/dev/peps/pep-0008/ 4228 | [rails-style-guide]: https://github.com/bbatsov/rails-style-guide 4229 | [pickaxe]: https://pragprog.com/book/ruby4/programming-ruby-1-9-2-0 4230 | [trpl]: http://www.amazon.com/Ruby-Programming-Language-David-Flanagan/dp/0596516177 4231 | [Pandoc]: http://pandoc.org/ 4232 | [RuboCop]: https://github.com/bbatsov/rubocop 4233 | [rdoc]: http://rdoc.sourceforge.net/doc/ 4234 | --------------------------------------------------------------------------------