プログラミング初心者がコードレビューで学んだこと【超初心者編】
はじめに
完全未経験からプログラミングを勉強して、約5ヶ月経ちました。
FJORD BOOT CAMP(フィヨルドブートキャンプ)では、fizzbuzzなど初心者向けの課題に取り組んでいる時から、メンターさんに本気のレビューをしていただきます😊
今回は「超初心者編」として、学習1~2ヶ月目にRubyのコードレビューで学んだことを中心にまとめたいと思います。
スペースを適切に入れる
rubocopを導入するまで、半角スペースを入れるのか入れないかをよく迷いました😖
演算子の前後には、半角スペースを入れる。
+
や-
など、演算子の前後にはスペースが入るのが一般的です。私が書いていた、ダメな例がこちらです。
if number%15 == 0 # ダメ if number % 15 == 0 # OK
%
と出会うのが初めてだったため、演算子だという認識がなく、前後にスペースを入れていませんでした。「何が演算子なの?」という時は、確認しておくべきでした。
Ruby入門 - 演算子 - とほほのWWW入門
メソッドと引数の間には、半角スペースを入れない。
上とは逆に、不要なスペースを入れてしまった例です。
"Ruby!".delete ("!") # deleteメソッドと引数の間に半角スペースが入っている。 => "Ruby"
このコードでは、スペースが入っていても動きました。
しかしコードによっては、エラーや意図しない結果になってしまいます。
"Ruby!".delete("!") + ("?") # 正しい書き方 => "Ruby?" "Ruby!".delete ("!") + ("?") # deleteの後ろに半角スペースあり => "Ruby"
下だと「"Ruby!"から"!"と"?"を削除する」という意味になってしまい、想定通りの結果になりません。
Rubyでメソッド呼び出しのかっこの手前にスペースが入るとエラーになる理由 - Qiita
変数・定数をわかりやすく
「名前重要!」というのは毎日聞く言葉ですが、命名についても当然沢山ご指摘を受けました。
変数名に抽象的すぎる名前をつけない
array = [] # ダメな名前 number = 1 while number <= 20 array << number number += 1 end
array
のような変数名をつけてしまうと、読み手に伝わる情報がない上に、別の配列を使う必要が出た場合困ります。
下のサイトではこういう名前は、使ってはいけない名前とされていました😅
data とか info とか list とか item とかいう変数名止めろ - Neo's World
マジックナンバーは、定数として定義する
ボウリングのスコア計算プログラムを作っていた時のコードです。
next_frame = [3, 4] def calculate_spare(next_frame) next_frame[0] + 10 # 次のフレーム1回目の得点に10を足す end def calculate_strike(next_frame) next_frame[0] + next_frame[1] + 10 # 次のフレーム1・2回目の得点に10を足す end
謎の数字(マジックナンバー)の「10」が何度も出てきてしまっています。読んだ人は「この10は一体なに?」と気になることでしょう😣
STRIKE_POINT = 10
という定数を最初に定義することで、読みやすくなりました。
無駄な処理を書かない
うっかり不要な処理が残ったまま提出してしまったことが、何回もありました😅
無駄にデータ型を変換しない
user = { name: 'suzuka', age: 28 } puts user[:name].to_s # 無駄に文字列に変換 puts user[:age].to_i + 1 # 無駄に数字に変換
長い処理を書いているうちに変数の中身がわからなくなり、余計な変換処理をしてしまっていました💦
変数の中身がどのようなデータ型なのか、常に意識しておくべきでした。
デバック用のコードは、削除しておく
require 'debug' # デバッガを有効にする number = 0 total = [] while total.size < 10 total << number binding.break # デバック用のブレークポイントを追加 number += 1 p total # プリントデバッグで変数の中身をチェック end
debug.gemに関係するコードやp
メソッドなど、デバッグで使用するコードが混じっています。他の人がコードを読む際に邪魔なので、削除しておくべきでした。
メソッドの定義をわかりやすく
メソッドを何のために定義するのか、どのように切り出すのかがわからず、悪戦苦闘しました。
メソッドを定義する目的を考える
このような短すぎるメソッドを沢山定義していました。
def sum_numbers(numbers) numbers.sum end current_numbers = [ 1, 2, 3 ] current_sum = sum_numbers(current_numbers) next_numbers = [ 2, 3, 4 ] next_sum = sum_numbers(next_numbers)
「同じ処理をするならメソッドにするのがいいね!」という気持ちで切り分けましたが、逆に読みにくくなってしまいました。
メソッド多い分だけ、コードを読む時に複数の場所を行き来する必要が出てきます。
コードの可読性を上げたり修正しやすくしたりするなど、メソッドに切り出す目的を意識して、単純な処理のメソッドを量産しないようにします😢
暗黙の了解を満たさないと使えないメソッドを定義しない
def calculate_price(drink_order, food_order) # 値段を計算する処理 end drink_order = { name: "コーヒー", price: 100 } food_order = { name: "ケーキ", price: 200 } total_price = unless today.sunday? calculate_price(drink_order, food_order) else drink_order[:price] + food_order[:price] # 日曜日は違う処理 end
注文の値段を計算をするメソッドcalculate_price
を定義していますが、よく読むと使えるのは月〜土のみです😳
「呼び出すときは、暗黙の了解で日曜日以外にしてね」というメソッドは、使いづらくなってしまいます。メソッド名を工夫する、どんな引数でも処理できるようにするなど、わかりやすいメソッドにするべきでした。
条件式・繰り返しをわかりやすく
処理が複雑になるほど、理解が追いつかなくなり、ぐしゃぐしゃのコードを書いてしまうことがありました💧
if
には色々な書き方がある
例えばこのようなコードがあった場合です。
require 'date' current_date = 【日付またはnilが入る】 if current_date.nil? next_date = Date.today + 1 else next_date = current_date + 1 end
next_date =
をif
の前に持ってくることができます。
next_date = if current_date.nil? Date.today + 1 else current_date + 1 end
三項演算子を使って、1行で書くこともできます。
next_date = current_date.nil? ? Date.today + 1 : current_date + 1
状況に応じて、一番良い書き方を選択しましょう。
一つのループ処理の中に、役割を詰め込みすぎない
each
など繰り返しの処理を、沢山使うのは良くない気がして、こんなコードを書いていました。
file_names = ["test.rb", "file1.txt"] file_names.each do |file| # ファイルの詳細情報を取得する処理 # ファイルのサイズの合計を計算する処理 # ファイル名の文字数の最大値を割り出す処理 end
こういうコードは、3つの処理すべての流れを頭の中に入れなければならず、読むのがとても大変です💥
each
の節約をやりすぎず、処理をわかりやすく書くのに必要な分のループを回すべきでした。
感想
過去の自分に対するレビューを見るのは恥ずかしかったですが、成長を実感できました❣️丁寧なレビューをしてくれるメンターさんに改めて感謝です。
今書いているコードを、数ヶ月後に「酷いコードだ」と言えるよう、引き続き勉強を頑張ります💪
時間ができた時に「Webアプリ編」や(いつの日か)「脱初心者編」も書きたいです。