LoginSignup
0
0

プロを目指す人のためのRuby入門を読んでみて

Posted at

はじめに

今回Rubyを学習する上で使用した参考書の
プロを目指す人のためのRuby入門の感想について書いていきます。

良かったところ

各章で特定の分野について深いところまで解説してくれているのが良かったです。
コードの書き方を機械的に覚えてしまうことは多いと思うのですが
なぜそのような書き方になるのかなども丁寧に解説しています。
また本書籍では例題を通して実際にコードを書きながら学習ができるのですが
そのコードも現場を意識してより良いコードにするリファクタリングについての説明もしてくれるのがありがたいですね。

学んだこと

2章:Rubyの基礎を理解する

  • 変数を宣言する際はスネークケース。
  • 数字から始まる変数は宣言できない。
  • 文字列作成の際はシングルクオートかダブルクオートを使用する。文字列の中で\nで改行を入れる際はダブルクオートを使用する。
  • ダブルクオートの中で#{}を使用すると式展開を使用できる。式展開で文字列の中に変数の値や式の結果を埋め込める。
  • nilとfalseは偽の値。それ以外は真の値。
  • requireでライブラリを読み込める。しかし、自作のプログラムを読み込む際はrequire_relative

3章:テストを自動化する

  • テスティングフレームワークを使えばテストを自動化して実行結果を目視で確認する作業を省け、どこが間違っているかも教えてくれる。
  • テストコードのクラス名は慣習としてキャメルケースでTestで始まるか、Testで終わる形にする。
  • テストコードのファイル名はスネークケースでクラス名と合わせる。

4章:配列や繰り返し処理を理解する

  • ブロック
    • メソッドに渡せるブロックは一つ。
    • ブロックの戻り値はメソッドと同様に最後に評価された式。
    • ブロック内で宣言した変数はブロック内のみで使用可能。
    • ブロック外で宣言された変数やメソッドはブロック内で参照可能。
    • ブロックを書く際は以下のようにdoendで書くパターンと{}で閉じるパターンがある。前者はブロックが長くなる時に使い、後者の方は一行でコンパクトに書きたいときに使うケースが多い。
      code
      sample.each do |n|
        sum += n
      end
      
      code
      sample.each {|n|sum += n}
      
  • 範囲(Range)
    • 1..3のような書き方で値の範囲を表現できる。'a'..'c'のように文字列でも使える。
    • 1..3で最後の値を含み、1...3で最後の値を含まない。
    • 以下のように配列の中の特定の値を取り出すときに便利。
      code
      irb(main):001> a = [1,2,3,4,5]
      => [1, 2, 3, 4, 5]
      irb(main):002> a[1..3]
      => [2, 3, 4]
      

5章:ハッシュやシンボルを理解する

  • ハッシュ

    • ハッシュはキーと値の組み合わせでデータを管理するオブジェクト。
    • 以下のようにeachでハッシュのキーと値を一気に取り出せる。
      code
      sample.each do |key,value|
      #ブロックパラメータにキー、値の順で入っていく
        puts "#{key}":"#{value}"
      end
      
      code
      sample.each do |key_value|
      #ブロックパラメータが一つの場合はキーと値が配列として格納される。
        key = key_value[0]
        key = key_value[1]
        puts "#{key}":"#{value}" 
      end
      
    • **を使うとハッシュの要素を展開できる。
      code
      irb(main):001> h = {us:'dollar',India:'rupee'}
      => {:us=>"dollar", :India=>"rupee"}
      irb(main):002> {japan:'yen',**h}
      => {:japan=>"yen", :us=>"dollar", :India=>"rupee"}
      
  • シンボル

    • シンボルはkey:valueのように特定の文字列と対になるオブジェクト。
    • イミュータブルなオブジェクトで破壊的な変更は不可能。
    • ハッシュのキーとして使用されるケースが多い。

6章:正規表現を理解する

  • rubyにおける景気表現は/正規表現/の形で作成する。
    マッチした場合は文字列の開始位置が表示される。しなかった場合はnilが返される。
    code
    irb(main):003> '123-4567' =~ /\d{3}-\d{4}/
    => 0
    
    code
    irb(main):004> '12-567' =~ /\d{3}-\d{4}/
    => nil
    
  • scanメソッドで正規表現でマッチした部分を配列に追加する。
    code
    irb(main):006> '123 456 789'.scan(/\d+/)
    => ["123", "456", "789"]
    
  • []に正規表現を渡すとマッチした部分を取り出せる。sliceメソッドでも同様のことができる。
    code
    irb(main):008> text[/\d{3}-\d{4}/]
    => "123-4567"
    
    code
    irb(main):009> text.slice(/\d{3}-\d{4}/)
    => "123-4567"
    
  • 正規表現オブジェクト作成時のオプション
    • /正規表現/iで大文字小文字の区別をしない。
    • /正規表現/mで改行文字にもマッチするようになる。
    • /正規表現/xでスペースや改行文字が無視されてコメントが正規表現ないに記載できるようになる。

7章:クラスの作成を理解する

  • クラスをもとにしたデータの塊をオブジェクトまたはインスタンスと呼ぶ。呼び出したメソッドに対するオブジェクトをレシーバーと呼ぶこともある。
  • 呼び出したレシーバーのメソッドをメッセージと呼ぶ場合がある。これはSmalltallkという言語から影響を受けてのもの。
  • 作成したオブジェクトごとに保持しているデータは異なりそのデータのことを状態(ステート)と呼ぶ。
  • 作成されたオブジェクトから取得できるuser.first_nameのような値のことを属性(アトリビュート、プロパティ)と呼ぶ。
  • クラスないで共有される変数をインスタンス変数と呼ぶ。@で始まる変数名で定義される。
  • インスタンス変数を外部から読み書きできるようにするためにattr_accessorメソッドが使える。また、読み込み専用のメソッドにattr_reader、書き込み専用のメソッドにattr_writerが使える。
  • メソッド名の前にselfをつけることでクラスメソッドが定義できる。インスタンスに含まれるデータを使わない場合に使用する。クラスメソッドはクラス名.メソッド名で呼び出せる。
  • self
    • インスタンス自身を表し、メソッド内部でメソッドを呼び出す際にはself.メソッド名のように使う。また、selfは省略可能。
    • セッターメソッド内ではローカル変数に値を誤って入れてしまうケースがあるため必ずselfを使用する。
      code
      def setter
        name = 'aaa'
        #ローカル変数としてのnameに値が入る
      end
      
      code
      def setter
        self.name = 'aaa'
        #インスタンス変数としてのnameに値が入る。
      end
      

8章:モジュールを理解する

  • module モジュール名でモジュールを定義。以降もクラスの書き方と一緒。
  • is-aの関係の観点から継承を使うのに適していないケースで共通の機能を持たせたいときにモジュールを使う。
  • クラス内にinclude モジュール名でモジュール内で定義したメソッドがインスタンスメソッドとして呼び出せるようになる。
  • クラス内にモジュールで機能を追加することをミックスインと呼ぶ。
  • モジュール内で記載したselfはinclude先のクラスのインスタンスになる。そのためモジュール内でミックスインしたクラスのメソッドと連携することができる。
    code
    module sample
      def sample_method1
        #ミックスインしたクラスのメソッド
        sample_method1
      end
    end
    
  • extend モジュール名でモジュールのメソッドをクラスメソッドとして追加する。
  • クラス名.include/extend モジュール名でもモジュールを呼び出せる。
  • モジュールのメソッド内でミックスイン先のインスタンス変数の読み書きができる。しかしこれは設計として推奨されない。
  • クラスの名前の衝突を避けるためにモジュール内にクラスを作成する名前空間としてモジュールが使われるケースがある。モジュール名::クラス名で参照できる。
  • 名前空間つきのクラスを定義する方法は二通りある。
    code
    #入れ子にして書くケース
    module SampleModule
     class SampleClass
      #処理
     end
    end
    
    code
    #入れ子なしのケース
    class SampleModule::SampleClass
      #処理
    end
    

9章:例外処理を理解する

  • シンプルな例外処理の構文。実際のプログラムではあまり好ましくない
    code
    begin
      #例外が起きうる処理
    rescue
      #例外が発生した際の処理
    end
    
  • messageメソッドで例外発生時のエラーメッセージを表示する。
    code
    begin
      #例外が起きうる処理
    rescue => 例外オブジェクトを格納する変数(exeptionの省略形のeexが使われることが多い)
      #例外が発生した際の処理
      puts e.message
    end
    
  • backtraceメソッドでバックトレース情報(メソッドの呼び出し履歴)表示する。
    code
      begin
        #例外が起きうる処理
      rescue => 例外オブジェクトを格納する変数(exeptionの省略形のeexが使われることが多い)
        #例外が発生した際の処理
        puts e.backtrace
      end
    
  • 例外オブジェクトのクラスが一致した場合のみ例外を捕捉することができる。
    code
    begin
      #例外が起きうる処理
    rescue 例外クラス(ZeroDivisonErrorNoMethodError等)
      #例外が発生した際の処理
      #rescue節は複数記載可能
      puts e.backtrace
    end
    
  • raise エラーメッセージメソッドで意図的に例外を発生させることができる。
  • full_messageメソッドで例外のクラス名、エラーメッセージ、バックトレースを一度に取り出せる。
  • ensure節を組み込むことによって例外の有無にかかわらず行う処理を加えられる。
    code
    begin
      #例外が起きうる処理
    rescue 
      #例外が発生した際の処理
    ensure
      #例外の有無にかかわらず行われる処理
    end
    

10章:yieldとProcを理解する

  • yield
    • 作成したブロックを呼び出せる。
      code
      def sample
        puts 'aaa'
        yield
      end
      
      code
      sample do
        puts 'bbb'
      end
      
    • yieldに渡した引数に過不足になってもエラーは発生しない。
    • &をつけることによってブロックをメソッドの引数として使える。引数を実行する際callメソッドを使う。
      code
      def sample(&引数)
        引数.call
      end
      
  • Proc
    • ブロックをオブジェクト化できる。Stringクラスでの文字列、Integerクラスの整数を表す。
    • Proc.newにブロックを渡してProcのインスタンスを作成。呼び出す際はcallメソッドを使用。
      code
      Proc.new do
      #処理
      end
      

11章:パターンマッチを理解する

  • rubyにおけるパターンマッチの基本構文。
    code
    case 
    in パターン1
      #in節ではローカル変数の宣言や代入は=を使わずに行われる。パターン1がここではそれを指す。
      パターン1にマッチした時の処理
    in パターン2
      パターン1にマッチせずパターン2にマッチした時の処理
    else
      どちらにもマッチしなかった時の処理
    end
    
  • ローカル変数にハッシュを使うときにin {キー:}のように値を省略するとキーと同じ名前のローカル変数が作成される。
  • パターンマッチではいずれの条件式にも当てはまらない場合は例外が発生する。
  • パターンマッチではインスタンス変数が使用不可。

12章:Rubyのデバック技法を身につける

  • バックトレースはプログラムが実行されてエラーが発生するまでのメソッド呼び出し履歴を示した情報。これを読み取ることがエラーの早期解決へつながる。
  • コード内の変数に期待した値が入っていない時にはprintデバッグが有効。rubyではputsp、メソッドを使って出力される値の確認を行う。
  • デバッガを使用することでプログラムを1行ずつ実行しながら変数の中身の確認などができて効率が上がる(irbみたいなもの)。rubyのデバッガには標準ライブラリのdebugや外部ライブラリのByebugがある。
  • 公式リファレンスは情報として網羅性が高いため不明点があれば確認するのはエンジニアとして避けては通れない。
  • テストコードを書いておけばデバッグにかかる時間を短縮できる可能性がある。また、短縮できなかったとしてもテストコードを書いておくことは良い習慣。

13章:Rubyに関するその他トピック

  • 現在TimeクラスとDateTimeクラスの機能に差はなくrequireの必要があるDateTimeクラスは非推奨となっている。
  • 非推奨機能を使った場合はrubyの2.7.2以降では警告が出ない。よってプログラムの実行をW:deprecatedオプションで行うかプログラム内でWarning[:deprecated]=trueと記載する必要がある。
  • Bundlerで大量のgemをどの環境でも同一のバージョンでインストールできる。これによりチーム内での開発環境の差異を小さくできる。

難しかったこと

本書籍で学習するには前提としてある程度プログラミング等の基礎知識が必要です。
例えば6章では正規表現を扱うのですが、
正規表現についての詳細な説明は省かれており知識のない方は事前学習が必要です。
私自身正規表現の学習が必要であったため該当の章に差し掛かった際には
正規表現について別に学習をしました。

最後に

読了して最初に思ったことが「難しかった。」でした。
ですがインプットに使う書籍としては情報量、説明のわかりやすさに関しては
間違いないと思います。今後は不明点があった際のリファレンス用の資料としても
使っていきより良いRubiestを目指していきたいです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0