可読性の高いクリーンなコード記載方法

可読性の高いクリーンなコード記載方法
現場で1年弱働いて、可読性の高いクリーンなコード記載を学んだので、備忘録としてこちらにまとめます。

三項演算子を利用して変数に値を設定

food = 'fruit'
food == 'fruit' ? select_food_type = 'フルーツ' : select_food_type = 'フルーツ以外'

↓

food = 'fruit'
select_food_type = food == 'fruit' ? 'フルーツ' : 'フルーツ以外'

# 上記で変数foodに[fruit]が格納されていれば、select_food_typeには[フルーツ]そうでなければ[フルーツ以外]が格納される

また、3項演算子の結果がboolean値で、そのboolean値を変数に格納したい場合は、以下のように書ける

food = 'fruit'
is_fruit = food == 'fruit'

# 上記で変数foodに[fruit]が格納されていれば、is_fruitには[true]そうでなければ[false]が格納される

同じ変数を比較する際は、case文を利用

def fruit_type(fruit)
  return 'りんご' if fruit == 'apple'
  return 'オレンジ' if fruit == 'orange'
  return 'もも' if fruit == 'peach'
enddef fruit_type(fruit)
  if fruit == 'apple'
    'りんご'
  if fruit == 'orange'
    'オレンジ'
  if fruit == 'peach'
    'もも'
  end
enddef fruit_type(fruit)
  case fruit
  when 'apple'
    'りんご'
  when 'orange'
    'オレンジ'
  when 'peach'
    'もも'
  end
end

2つの変数の組み合わせで返り値を返す際にcase文を利用

def like_tuna_and_salmon(is_like_tuna, is_like_salmon)
  case [is_like_tuna, is_like_salmon]
  when [true, true]
    'マグロもサーモンも好き'
  when [true, false]
    'マグロは好きだが、サーモンは嫌い'
  when [false, true]
    'マグロは嫌いだが、サーモンは好き'
  when [false, false]
    'マグロもサーモンも嫌い'
  end
end

# 上記のように配列を使うことで、2つの変数の組み合わせを表せる

if文のネストを浅くするための[早期リターン]や[ガード節]という記法

def number_division_judge(number)
  if number.negative?
    'マイナスの値です。'
  else
    if number < 100
      '100未満の値です。'
    else
      '100以上の値です。'
    end
  end
enddef number_division_judge(number)
  return 'マイナスの値です。' if number.negative?
    
  if number < 100
    '100未満の値です。'
  else
    '100以上の値です。'
  end
enddef number_division_judge(number)
  return 'マイナスの値です。' if number.negative?
    
  number < 100 ? '100未満の値です。' : '100以上の値です。'
end

2次配列の要素を複数の変数に1度で代入する方法

[16] pry(main)> x, y = [1, 2, 3, 4, 5, 6, 7, 8, 9].partition { |number| number & 3 == 0 }
=> [[4, 8], [1, 2, 3, 5, 6, 7, 9]]
[17] pry(main)> x
=> [4, 8]
[18] pry(main)> y
=> [1, 2, 3, 5, 6, 7, 9]

スプレッド構文を使うと配列の要素が配列になっていてもflattenを使ったのと同じ状態にできる

[1] pry(main)> [
[2] pry(main)*   'a',
[3] pry(main)*   'b:cde'.scan(/(?<=:).*/),
[4] pry(main)* ]  
=> ["a", ["cde"]]
[5] pry(main)> [
[6] pry(main)*   'a',
[7] pry(main)*   *'b:cde'.scan(/(?<=:).*/),
[8] pry(main)* ]  
=> ["a", "cde"]
[9] pry(main)> [
[10] pry(main)*   'a',
[11] pry(main)*   *['cde'],
[12] pry(main)* ]  
=> ["a", "cde"]

変数の中身がStringであるものの同士の足し算は、行わない方が良い

[1] pry(main)> a = 'a'
=> "a"
[2] pry(main)> b = 'b'
=> "b"
[3] pry(main)> c = a + b
=> "ab"
[4] pry(main)> a = nil
=> nil
[5] pry(main)> c = a + b
NoMethodError: undefined method `+' for nil:NilClass
from (pry):40:in `__pry__'

# 上記のように変数が万が一nilだった場合にエラーになってしまうからだ。
以下のように記載すると良い!

[6] pry(main)> c = [a, b].join
=> "b"
[7] pry(main)> c = "#{a}#{b}"
=> "b"

sprintfよりはrjustを使ったほうが良い

# rubyのsprintfはrubyのバージョンや与える値、指定コードによって奇妙な動作を引き起こすことがあるので、rubyの標準関数であるrjustなどで同じことができるのであれば、そちらを利用したほうがバグなども発生しずらい為だ

[1] pry(main)> sprintf('%03d', '1')
=> "001"
[2] pry(main)> '1'.rjust(3, '0')
=> "001"

Rubyのbegin-end構文

# nilガードで変数に代入する際に複数行を記述する際に用いる

[1] pry(main)> def test(test1)
[2] pry(main)*   @z ||= begin
[3] pry(main)*     if test1.nil?
[4] pry(main)*       'nilです。'
[5] pry(main)*     else  
[6] pry(main)*       'nil以外です。'
[7] pry(main)*     end  
[8] pry(main)*   end  
[9] pry(main)* end  
=> :test
[10] pry(main)> test(nil)
=> "nilです。"
[11] pry(main)> @z
=> "nilです。"

参考記事

Rubyのbegin-end構文で変数を定義する - その辺にいるWebエンジニアの備忘録

What is use of ||= begin....end block in Ruby? - Stack Overflow