• ログインログイン
  • 新規登録新規登録

MENU

文系の私がエンジニアになっていくお話(Ruby on Rails編 第9回)

連載文系の私がエンジニアになっていくお話(Ruby on Rails編)

文系出身学生が、Webサービスやアプリ開発に取り組み、エンジニアになるべくどのように学習を進めていったのかの記録を紹介するコンテンツです。Ruby on RailsでのWebサービス開発の学習手順などを解説しています。

前回までのプログラミング学習コラムに続き9回目の勉強内容です。

文系エンジニアコラムの連載をさせていただいている小林寛和(ひろかず)です。Ruby on Railsのコラムの第9回目となります。今回は第8回の流れで、綺麗なコードとは何かについて考えてみましょう。

綺麗なコードを書く4つのポイント

前回のおさらい

前回の例のように、既存のモデルに対して、複数の関連した情報を結び付けたいという事は多々あるかと思います。これらを無理やり既存のモデルに結びつけるとテーブルがごちゃごちゃになり、それによってControllerやView側のコードも拡張性が下がり、可読性が下がることとなりました。そして、それらを新しくモデルを切り分ける事で綺麗なコードにすることが出来ました。

綺麗なコードとはなんでしょう?

では、綺麗なコードとはなんでしょう?出来るだけ少ないコードで書くことですか?コメントを書いてわかりやすくすることですか?

私が今意識しているのは、以下の4点です。

  1. 拡張性(汎用性)がある
  2. 論理的である
  3. 言語の特性を生かす
  4. 可読性の高いコードを書く

それぞれについて解説してみたいと思います。まずは、悪いコードの例を挙げます。どこが悪いコードなのか、ぜひ考えてみて下さい。

def foo(x)
	if (x == 1 || 3)
		return true
	elsif (x == 2 || 4)
		return false
	end
end

foo(1)
foo(2)
foo(3)
foo(4)

1. 拡張性を上げる

拡張性とは、仕様が変更になっても最低限の変更で済む・もしくはそもそも変更しないでも対応出来るということだと考えています。前回の連載の例では、変更しないでも済む書き方で実装出来ました。今回も悪いコードの例を直してみます。ある複数の情報それぞれに2つの処理(分岐有り)を行う場合、どうなるでしょうか。

コードを見ると、メソッドを定義し、共通する処理を4つの数字を引数として行なっています。ここで、もしfoo(5)みたいに仕様変更で拡張しなければならない場合どうなるでしょうか。

  1. まずfooメソッド内に引数として5が入った場合の処理を書きます。つまり、if文の条件が追加されます。
  2. そして、メソッドを呼び出す文としてfoo(5)を追記します。

このように、2箇所の変更が必要となります。このコードをループで回す事で同じような表記を極力減らす様に変更して行きましょう。

コード後半のメソッドを呼び出している部分ですが、出来るだけループで回すことで同じような処理内容を避けましょう。これは、コードを読みやすくするだけでなく、拡張性の工場にも大きく貢献します。下のコードを見て下さい。

nums = [1,2,3,4]

#fooメソッドの定義

nums.each { |num| foo(num) }

もし先ほどのように5を引数にfooメソッドを実行しなければならなくなった場合でも、numsに5を追加する変更だけで済みます。それだけでなく、今後どれだけ数が追加されても同じ場所を変更するだけで済むのです。

2. 論理的である

論理的であるとは、コードが正しく効率的な流れで書かれているかということだと思います。例えばfooメソッドの中身を見て下さい。このif文は論理的に正しくありません。何故ならば、引数xは奇数と偶数で処理が分かれている事に最適化出来ていません。

正しく論理的に書くならば以下のようになるはずです。

def foo(x)
  if (x % 2 == 0)
    return false
  else
    return true
  end
end

if文の条件式がシンプルになりましたね。それだけではなく、論理的に考えると、第1条件文が偽であるならば必ず奇数であり、第2条件文を書く必要がないため、elseで処理している点に注目して下さい。

当然このスクリプトが何の目的で書かれているか分からない為、単純に奇数と偶数で処理を分岐させるのが正しいかは分かりませんが、今回は前提条件の指定が無いため、与えられた条件からもっとも効率的な記述をするとこの様になるかと思います。

3. 言語の特性を生かす

言語の特性を生かすというのは、2の論理的であると近しいものかもしれません。何故ならば、論理的に書く前提には言語の特性を理解し、その上で特性を生かして書くことでもあるからです。

例えばRubyの場合、今回のコードを改善するにあたり、以下の特徴を利用してはどうでしょう。

  • if文にカッコをつけなくても条件式を書くことが出来る
  • return文でreturnを省略できる

上の特徴を生かすと下のようなコードで書くことが出来ます。

def foo(x)
  if x % 2 == 0
    false
  else
    true
  end
end

大分スッキリしましたね。でも、次の特徴を使うとまだまだ綺麗になります。

  • 「条件式 ? 真の場合の処理 : 偽の場合の処理」という書き方で三項演算子が使える

この特徴を用いて書きなおしてみます。

def foo(x)
  x % 2 == 0 ? false : true
end

なんと1行にまで縮めることが出来ました。個人的には、2分岐くらいのif文は三項演算子で書いてしまいたいです。5行のコードが1行で済むので。ちなみに、三項演算子は値を返す場合に使うことが多い気がします。この様に、言語の特性を生かすとここまで綺麗に書くことが出来るのです。

まだ改善の余地がありました。最後の特徴を見てみましょう。

  • RubyのFixnum(数字の)クラスには、予め偶数かを判断する「even?」メソッドが用意されている
  • 返し値がbooleanの場合、返し値の明示しなくてもいい

これらを踏まえ、とどめを刺してみましょう。以下のようになります。

def foo(x)
  x.even?
end

なんと7文字で済んでしまいました。

引数xに対してeven?メソッドを実行することで、偶数ならtrue、奇数ならfalseが返ってきます。それをそのまま返してあげればいいので、return文を書く必要もif文を書くことも必要なくなるのです。ここまで来ると、メソッド化する意味がありませんね。。

4. 可読性を上げる

今一度最初のコードと3までを実行した結果を比べてみましょう。

まずは最初のコード

def foo(x)
	if (x == 1 || 3)
		return true
	elsif (x == 2 || 4)
		return false
	end
end

foo(1)
foo(2)
foo(3)
foo(4)

次に改善されたコードです。

nums = [1, 2, 3, 4]

def foo(x)
  x.even?
end

nums.each { |num| foo(num) }

一目見てどちらが綺麗ですか?どちらが読みやすいですか?

物にもよりますが、ほとんどのコードは他人が読むものです。他人が読んで一番理解しやすい書き方で書くことが、可読性を上げる一番のポイントです。

また、この場合の他人には自分も含まれます。つまり、上のコードを書いて3年経過し、どうしてもこのコードを再利用しなければならなくなった時、あなたはほとんど他人と同じ目線や理解度でこのコードと対峙することになります。そんな時、すぐに理解できるコードを書けるようになりたいですね。

まとめ

今回は番外編の様な形で綺麗なコードを書く4つのポイントについて書いてみました。

  1. 拡張性(汎用性)がある
  2. 論理的である
  3. 言語の特性を生かす
  4. 可読性の高いコードを書く

でしたね。まだまだ未熟な文系エンジニアの私ですが、今私が意識しているポイントをまとめてみました。Clean Codeリーダブルコードなんていう素晴らしい本もあるので、是非読んでみて下さい。

次回予告

次回はRailsの話に戻り、第8回の続きを書いていきます。

オススメ記事一覧

もっと見る
完全無料!

1で登録完了!

エンジニアの仕事・年収や選考ノウハウ記事が読めるほか、
会員にはプログラミング講習やES・面接対策などリアルな無料サポートも充実。
ここだけの求人情報も多数。

今すぐ新規会員登録
Page Top