Java / PHP など開発経験者に贈る Ruby 入門|研修コースに参加してみた
今回参加したコースは Java / PHP など開発経験者に贈る Ruby 入門 です。
先日は Rails の参加レポートを公開しましたが、今回は Ruby です!
Ruby と言うと Rails 、まつもとゆきひろ さんが思い浮かびますが、これだけ世界的に広がった日本発の開発者向けプロダクトは Ruby と Jenkins ぐらいではないでしょうか( GitHub 上の star 数はどちらも 19.4 k !! )。
また Ruby コミュニティは非常にオープンで、毎年開催されるカンファレンス RubyKaigi は毎年開発者の話題になり、プログラミング好きな方が集まっている印象を受けます。
なぜ Ruby がそれだけプログラミング好きな方々に愛されるのか、不思議に思っていたのですが、このコースに参加してわかりました。 いくつもの書き方ができる自由、極力わかることは書かなくてよい、かゆいところに手が届く便利機能、これらが開発者体験 ( DX ) を上げているのでした!
では、どのような内容だったのか、レポートします!
もくじ
コース情報
想定している受講者 | 他のオブジェクト指向言語( Python / PHP / Java など)の学習経験等があること |
---|---|
受講目標 | Ruby について全般的な知識を習得する(特に他の言語との違い) |
講師紹介
技術領域の広さだけでなく、プログラミング言語も幅広く教えられる 植田崇靖 さんが登壇されました。
「電子回路から機械学習まで、学ぶことが楽しい!」
インストール
まずはインストールからです。
- RubyInstaller for Windows で Download ボタンを押す
- WITHOUT DEVKIT から最新版 ( 今回は Ruby 3.1.2-1 (x64) ) をクリック
- ダウンロードしたファイルを実行(基本はずっと Next ボタンで OK )
念のため、インストールできたか確認してみましょう。
> ruby --version
ruby 3.1.2p20
速く、また簡単にインストール完了です!
動作確認
では、早速、Ruby の標準ライブラリにある REPL 環境、 irb を実行して動作確認してみます!
irb(main):001:0> 1 + 1
=> 2
irb(main):002:0> print "Hello World"
Hello World=> nil
# Ruby では null は nil という
# Ruby では関数を実行すると必ず戻り値がある
Ruby とは
少しだけ Ruby について紹介いただきました。
- まつもとゆきひろ さんが開発
- オブジェクト指向型スクリプト言語
- 自由に書きやすい
- Ruby on Rails が世界的に流行
Ruby on Rails は前回のレポートしましたので、興味がある方はぜひご覧ください!
info_outlineRails の参加レポート
Ruby の特徴
ここからは他の言語にない Ruby の特徴を中心に紹介いただきました!
- 文字列などすべてがオブジェクト
- 文字列でも数値でもオブジェクトでありメソッドが呼べる
irb(main):001:0> 1.to_s => "1" irb(main):002:0> "1".to_s => "1"
ナント。 これは変わってますが、配列にしたりといった処理がやりやすいですね。
- メソッドの表記は
Object.method()
で記述- () を省略してもよい
- グローバルなメソッドは () をつけないのが慣習 ex.
puts 'Hello'
- 終端記号がない
- コメントは
#
を使う - 数値、文字列、配列、ハッシュ(連想配列のこと。 このあと詳しく)、正規表現が使える
- 文字と文字列の違いはない
文字列
先程、チラッと出てきた文字列です。 他の言語にはないメソッドや演算子があって、便利そうです。
- % 記法がある
%q!文字列!
- シングルクォートの代わりに使える
%q!Say "Hello!"!
- シングルクォートの代わりに使える
+
で文字列を連結name = Tom puts "Hello, " + name # Hello, Tom
.join
というメソッドを使うと配列を連結できる[10, 20, 30].join # 102030
*
を使って繰り返す'hello' * 10
- 文字列の一致は
==
を使う- 否定の場合は
!=
- 否定の場合は
- 文字列の長さ(バイト値)を比較できる
'ab' < 'abcd'
変数
どんどん行きましょう。 続いて変数です。
- 型宣言はない
number = 1
- 変数名は小文字スネークケースで書く
- 多重代入ができる
a, b = 1, 2 # a が 1 、 b が 2
- 同時代入ができる
a = b = 'hello' # a も b も 'hello'
- 文字列内での変数展開は
"Hello #{var}"
のようにダブルクォートを使って#{ }
に変数を入れる - 数値と文字列などは暗黙的に変換されない
最後の暗黙的なキャストがないのは、 Ruby の言語の印象からすると、少し意外です。
bool 値と if 文
続いて、制御文です。
- false と nil で偽
- false と nil で比較すると nil が優先される
- if 文
if "条件a" # 処理a elsif "条件b" # 処理b else "上記以外" # 処理 end
- else if ではなく elsif
- then を書いても良い
if "条件a" then # 処理a
ふむふむと聞いていると、ここからちょっとビックリします。
- 戻り値が取れる
country = 'japan' aisatsu = if country =='us' 'hello' elsif country =='japan' 'こんにちは' else '???' end puts aisatsu # こんにちは
- 最後に評価された式の戻り値が返る
puts
で print + 改行
- if 修飾子がある
point *= 5 if day == 1 # *= で point = point * 5
かなり自由にかける印象ですね。 ちなみに if 修飾子に関連してちゃんと三項演算子もあります。
コースでは、このほか case 文にも触れ break はなくてよいなど、自明のことは極力省こうとする思想が伺えました。 いいですね!
配列
- ほぼ他の言語と同じ
- 要素に複数の型が入ってもよい
a<<
で最後の要素に値を代入できるa.delete_at(1)
で 1 つめの要素を消して詰める
配列もオブジェクトなので、最後のメソッドを使えるのは便利ですね。
と思っていると、さらにいい感じ? ちょっと特殊なものを紹介いただきました。
- ブロックとブロックパラメータがある
numbers = [1, 2, 3, 4] sum = 0 numbers.each do |n| sum += n end puts sum # 10
- do ~ end がブロック
|var|
がブロックパラメータ- 要素を 1 つずつメソッドの引数に渡す
- ブロック用のメソッドがたくさんある
- map/collect 、 select/find_all など
- 範囲を示す range
1...5
で 5 を含む1..5
で 5 を含まないa = 'abcdefghijklmnopqrstuvwxyzABCDEF' puts(a[0..5]) # abcdef
これはなかなか使いどころが多くて楽ですね!
ハッシュ、シンボル
- ハッシュとは連想配列のこと
- 特徴的なのがシンボル
- ハッシュのキーによく使われる
- イミュータブルである
:
を使うcurrencies = {:japan => 'yen', :us => 'dollar', :france => 'euro'} # こっちのほうがよく使う currencies = {japan: 'yen', us: 'dollar', france: 'euro'} puts currencies[:us] # 'dollar'
メソッド
関数と呼ぶのではなく、オブジェクトしかない Ruby らしくメソッドです。
- メソッド名も小文字スネークケース
- 戻り値の型は書かない
- return もいらない
- 最後に評価された式の結果が返る
def greet(country = 'japan') if country == 'japan' puts 'こんにちは' else puts 'hello' end end
- メソッドの呼び出しは引数なしならメソッド名のみで () はつけない
- メソッド名? で真偽値を返すことを表すことが多い
- メソッド名! で破壊的に変更することを表すことが多い
a = 'ruby' puts a.upcase # 変化なし puts a # ruby puts a.upcase! # 変化する puts a # RUBY
return が無いなど、自明のことは書かなくてもよい 第 2 弾です。 いいですね!
ですが、演算子の種類と有無で戻り値が変わるのは、ちょっと独特で、個人的には意図が読みにくい気がします。
クラス
続いて、クラスです。 植田さんからは「あまり他の言語と変わりない」ということでしたが、見てみましょう。
- レシーバという言い方がある
User.first_name
- 普通: User の first_name メソッド
- レシーバ: first_name メソッドのレシーバは User
- クラス名は必ず大文字
- キャメルケースで書く
- インスタンス化には new メソッドを使う
new Class()
ではないUser.new
- new でコンソトラクタ initialize が動く
- new はコンソトラクタ引数を使える
User.new(var1, var2)
- インスタンス変数(他の言語で言う属性やプロパティ)には
@
をつける- 外部からは呼び出せない
- 参照 / 更新用メソッドを用意する
- getter/setter のような get_ set_ はつけない
- もしくは attr_accessor メソッド(他にもある)を使う
class User attr_accessor :name def initialize(name) @name = name end # 外部から参照するためのメソッド def output puts @name end end
- 参照 / 更新用メソッドを用意する
- 外部からは呼び出せない
- メソッドは クラスメソッド と インスタンスメソッド の 2 つ
- クラスメソッド(他の言語で言う static メソッド)の 2 つの書き方
- self. をつける
class << self
からend
の中に書くdef self.create_users(names) # 処理 end class << self def create_users(names) # 処理 end end
- クラスメソッドの呼び出し
User.create_users()
- インスタンスメソッドは new メソッドでインスタンス化すると使えるメソッド(他の言語と同じ)
users = User.new puts users.hello
- クラスメソッド(他の言語で言う static メソッド)の 2 つの書き方
- 定数は大文字
self.
は他の言語で言う this と同じ
続いて、クラスの使い方です。
- 基本は単一継承
- 継承の書き方は
class User < Model
- メソッドのオーバーライド可能
- 継承を使わずにインスタンスメソッドを共用できるモジュールという機能もある
module Message def say_hello puts "Hello" end end class LastMessage include Message end puts LastMessage.new.say_hello # Hello
- PHP の trait のようなもの
- Java の Interface で default 句をつけたメソッドの共有と同じ
植田さんのおっしゃる通り、クラスはそれほど他の言語と違うということはありませんね。
例外処理
プログラミングでは必須の例外処理にも触れます。 まずは書き方を見てみましょう。
begin
# 例外が起こるかもしれない処理
rescue
# 例外が発生したときの処理
end
実際、用意されたサンプルコードで例外処理で使えるメソッドを確認します。
begin
1 / 0
rescue NameError # 合致するエラーなら処理を行う。 NameError は未定義の変数、定数があったときに発生
puts "未定義の変数、定数があります"
rescue => e # e という変数に例外オブジェクトを格納
puts "エラークラス:#{e.class}"
puts "エラーメッセージ:#{e.message}"
puts "バックトレース:--------------"
puts e.backtrace
puts "----------------------------"
end
実行結果はこちらです。
エラークラス:ZeroDivisionError
エラーメッセージ:divided by 0
バックトレース:--------------
exception_handling.rb:14:in `/'
exception_handling.rb:14:in `<main>'
----------------------------
これも特に他の言語と異なるところはありませんね。
ちなみに、他の言語でよく使われる try catch に似た catch throw という構文が Ruby にはありますが、これはエラー処理に全く関係ないものでした。 紛らわしい(笑)。
yield 文
他には、ちょっとめずらしい yield も紹介いただきました。 PHP や Python の yiled (ジェネレータ)とも違うものなので、戸惑うところかも知れません。
def greet
puts 'good morning'
yield
puts 'good night'
end
# 紐付けられたブロックを実行する
greet do
puts 'Hello'
end
コースではそのほか、デバッグに使うメソッドやライブラリをインポートするときは require
を使うなど、補足説明をいただきました。
テスト
Ruby は自由な書き方を許すので、その分テストが充実しています。 最後に、そのテストを実際書いてみます!
- Ruby の標準ライブラリとして minitest が入っている
- ファイル名はスネークケースで書く sample_test
- クラス名はキャメルケースで書く SampleTest
- メソッド名は test_ から始める
- assert_equal 期待するテスト結果, テスト対象のメソッド
FizzBuzz でテストコードを書いてみよう
有名な FizzBuzz のコードでテストコードを書いて実行してみましょう。
まずは FizzBuzz のコードです。
def fizz_buzz(n)
if n % 15 == 0
'Fizz Buzz'
elsif n % 3 == 0
'Fizz'
elsif n % 5 == 0
'Buzz'
else
n.to_s
end
end
続いて、テストコードです。
require 'minitest/autorun'
require_relative '../src/fizz_buzz.rb' # 相対パスでテスト対象を呼ぶ
class FizzBuzztest < Minitest::Test
def test_fizz_buzz
assert_equal '1', fizz_buzz(1)
assert_equal '2', fizz_buzz(2)
assert_equal 'Fizz', fizz_buzz(3)
assert_equal '4', fizz_buzz(4)
assert_equal 'Buzz', fizz_buzz(5)
assert_equal 'Fizz', fizz_buzz(6)
assert_equal 'Fizz Buzz', fizz_buzz(15)
end
end
assert_equal の書き方はシンプルでわかりやすいですね。
では、テストを実行してみましょう!
$ ruby test_sample/test/fizz_buzz_test.rb
Run options: --seed 55556
# Running:
.
Finished in 0.008680s, 115.2127 runs/s, 806.4888 assertions/s.
1 runs, 7 assertions, 0 failures, 0 errors, 0 skips
この他にもエラーが発生するコードとテストを実行してみました。
このテストを終えたところで、このコースは修了しました。
まとめ
他の言語でオブジェクト指向プログラミングを経験済みの方向けに、3 時間でザッと Ruby に入門しました。
植田さんがおっしゃる通り、同じ結果を得るのにいくつもの書き方を許す自由さがあり、これが「表現力が高い」と形容される所以かと実感しました。 同じプログラミング言語でも Python は複数のやり方を言語として用意していなかったり、 Go の go fmt のように書き方を統一したりと、まったく思想が異なりますね。
Ruby にプログラミングが好きな方が多いのも納得でした。
プログラミングが好きな方はもちろん、 Ruby + Ruby on Rails での開発もできるようになっておこうという方にはオススメのコースです!
label SEカレッジを詳しく知りたいという方はこちらから !!
IT専門の定額制研修 月額 28,000 円 ~/ 1社 で IT研修 制度を導入できます。
年間 670 講座をほぼ毎日開催中!!
SEプラスにしかないコンテンツや、研修サービスの運営情報を発信しています。