11月末に出版された「プロを目指す人のための Ruby 入門」を読んだ.12月は少しバタバタしていて,読むのが遅くなってしまったけど,以下の企画に応募をしたら当選した.ありがとうございます👍
はじめに
本書はタイトルに「入門」と書いてあるけど,正確にはプログラミングの入門書ではなく,最低限のプログラミングのスキルと Ruby のスキルが必要になる.まえがきにも似たようなことが書かれていて,その通りだなと思った.とは言え,本書はすごくキレイな流れで解説されているので,じっくり読み進めることで,プログラミング初学者でも十分ステップアップに活用できるようになっていた.なお,僕のスキルレベルとしては Ruby / Rails 歴3年ほどで,インフラの自動化を Ruby で書いたり,個人ツールを Rails で書いたりしている.また,TechAcademy で Rails 講師の副業を1年間続けている.
プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発・デバッグ技法まで (Software Design plusシリーズ)
- 作者: 伊藤淳一
- 出版社/メーカー: 技術評論社
- 発売日: 2017/11/25
- メディア: 大型本
- この商品を含むブログを見る
本書の良かったところ
例題 + テスト駆動開発
本書はほとんどの章に例題があり,実際に写経しながら進めることができる.さらに,テスト駆動開発で進めるようになっていて,テストコードを先に書いたり,テストを通しながらリファクタリングをする.この体験は素晴らしかった.
特に第4章にある「RGB 変換プログラム」のリファクタリングは良かった.最初,固定値でテストを通しつつ,DRY にリファクタリングをしながら変更し,最終的に1行になる.是非写経して欲しい.他にも第6章にある「Ruby のハッシュ記法を変換する」も,第7章にある「改札機プログラムの作成」も,本当に素晴らしい例題だった.
# Before def to_ints(hex) r = hex[1..2] g = hex[3..4] b = hex[5..6] ints = [] [r, g, b].each do |s| ints << s.hex end ints end # After def to_ints(hex) hex.scan(/\w\w/).map(&:hex) end
yield / Proc の解説
Ruby を学んでいると,yield / Proc あたりを理解できていることが中上級者になるポイントかなと思っているけど.本書では第10章で「ワードシンセサイザーの作成」という例題があり,3種類のエフェクトを Effects モジュールに実装し,さらに Proc を返すようになっている.Proc を写経しながら学べるのは非常に良かった.個人的にも yield / Proc を学び直すことができた.
module Effects def self.reverse ->(words) do words.split(' ').map(&:reverse).join(' ') end end def self.echo(rate) ->(words) do words.chars.map {|c| c == ' ' ? c : c * rate}.join end end def self.loud(level) ->(words) do words.split(' ').map {|word| word.upcase + '!' * level}.join(' ') end end end
なお,メタプログラミングをさらに深く学ぶ場合は「メタプログラミング本」を合わせて読むと良いかと!
「Ruby 技術者認定試験」の参考書にもなりそう
既に Ruby 資格の「Ruby Programmer Silver」と「 Ruby Programmer Gold」を取得しているけど,Ruby の言語仕様全般を学べるという意味では,参考書としても使えるなと思った.そのぐらい素晴らしい1冊だった.
本書で学び直せたところ
正直,本書を読んで知った機能,そんなのもあったなーという機能が多くあり,Ruby を学び直すことができた.
Minitest
これまで Rails のテスティングフレームワークは RSpec を使っていたため,実は Minitest を使ったことがなかった.大規模なプロジェクトで使う場合は RSpec にメリットがあると思うけど,今回のように小さなスクリプトをテストする場合は Minitest も十分使えると思った.例えば,以下のように書くだけで,簡単にテストコードを書くことができる.あと,はじめて refute
を見たときは,これはなんだっけ?と思った.
require 'minitest/autorun' class SampleTest < Minitest::Test def test_sample assert_equal 'RUBY', 'ruby'.upcase end end
splat 展開
メソッドの引数で可変長引数を受けるときなどに *
を使うことはあるけど,配列の中に *
を使って Array オブジェクトに展開する記法は知らなかった.今までは Range を使って (1..10).to_a
のように書くことが多かった気がする.
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] p (1..10).to_a # Array p (1..10).to_a.class # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] p [*1..10] # Array p [*1..10].class
.each_with_index
と .each.with_index
配列に対して .each_with_index
を使う場面は今までも多かったけど,添字を 0 以外にする方法があるのは知らなかった.表記が非常に似ているけど each.with_index(10)
と書く.ようするに .each_with_index
は each.with_index(0)
と同じと言える.使う場面あるかな?ドメイン次第ではあるかも.そもそも .each_with_index
で添字を指定できるようになっていても良いような気もするけど.
fruits = ['apple', 'orange', 'melon'] # 0: apple # 1: orange # 2: melon fruits.each_with_index {|fruit, i| puts "#{i}: #{fruit}"} # 10: apple # 11: orange # 12: melon fruits.each.with_index(10) {|fruit, i| puts "#{i}: #{fruit}"}
ブロックローカル変数
ブロック引数で変数名を ;
で区切ることで,ブロック内部のローカル変数を宣言できるのは知らなかった.以下の例で言うと sum
がブロックローカル変数になっている.知っておくと便利そうだけど,使う場面あるかな?OSS を読んでて出てきたら思い出してみようと思う.
numbers = [1, 2, 3, 4] sum = 0 # 11 # 12 # 13 # 14 numbers.each do |n; sum| sum = 10 sum += n p sum end # 0 p sum
例外専用の環境変数 $! と $@
これまた知らなかった.少しでもコード量を減らしたいときに使えそう.特に rescue => e
と書かなくて良いのは便利そう.
begin 1 / 0 rescue => e puts "#{e.class} #{e.message}" puts e.backtrace end begin 1 / 0 rescue puts "#{$!.class} #{$!.message}" puts $@ end
プログラミング初学者にも読んで欲しいと思った第11章
最初にも書いた通り,僕は TechAcademy で Rails 講師の副業をしているため,日々プログラミング初学者に教えている.その中で,汎用的なスキルとして「エラーを楽しむこと」を強く伝えている.特にプログラミング初学者だと,エラーが出てうまく動かない場合にモチベーションが下がってしまうことがある.ただ,職業プログラマでもエラーなんて大量に出るし,重要なのはエラーの原因を特定して解決するスキルなので,バックトレースの読み方だったり,binding.pry の使い方だったりを教えている.また,シンタックスエラーはエディタの機能をフル活用しましょうという話もしている.そういう背景もあり,第11章の「Ruby のデバッグ技法を身につける」という内容は素晴らしかった.ここだけでも読んで欲しいと思った.
まとめ
- Ruby スキルをステップアップするのに最高な1冊だった
- 特に例題が素晴らしく,さらにテスト駆動開発を体験できる点も良かった
- 仕事で Ruby / Rails を書いている人も学び直せる内容が多かった
- 写経したコードは全て GitHub に push した
参考
本書に含まれなかった原稿も既に公開されている.合わせて読むと良いかと!