【Ruby】define_methodについて調べました

はじめに

せっかく調べたのに忘れてしまうため、メモを残しておく。

今回は、ライブラリの挙動を確認していたところ
define_methodが書かれており、復習も兼ねて調べました。

環境

前提条件

  • irbかPryが動作すること

やり方

define_methodに関すること

実行

[1] pry(main)> class Animal
[1] pry(main)*   { cat: 'にゃー', dog: 'わん' }.each do |name, message|
[1] pry(main)*     # 動的にクラスやモジュールを定義でき、defによるメソッド定義をしなくてもよい
[1] pry(main)*     # メソッド本体はブロックで記述する
[1] pry(main)*     define_method(name) do
[1] pry(main)*       message
[1] pry(main)*     end
[1] pry(main)*   end
[1] pry(main)* end
=> {:cat=>"にゃー", :dog=>"わん"}
[2] pry(main)>
[3] pry(main)> puts Animal.new.cat
にゃー
=> nil
[4] pry(main)>
[5] pry(main)> class Animal2
[5] pry(main)*   { cat: 'にゃー', dog: 'わん' }.each do |name, message|
[5] pry(main)*     # ブロックにブロック引数を加えるとブロック引数がメソッドの引数になる
[5] pry(main)*     # ブロック引数:name
[5] pry(main)*     define_method(name) do |num|
[5] pry(main)*       message * num
[5] pry(main)*     end
[5] pry(main)*   end
[5] pry(main)* end
=> {:cat=>"にゃー", :dog=>"わん"}
[6] pry(main)>
[7] pry(main)> # メソッドの引数:2
[8] pry(main)> puts Animal2.new.dog(2)
わんわん
=> nil
[9] pry(main)> class Animal3
[9] pry(main)* end
=> nil
[10] pry(main)>
[11] pry(main)> { cat: 'にゃー', dog: 'わん' }.each do |name, message|
[11] pry(main)*   # ブロックをオブジェクトとして定義する
[11] pry(main)*   proc = Proc.new { |num| message * num }
[11] pry(main)*   # class_evalは、ブロックをクラス定義やモジュール定義の中のコードであるように実行する
[11] pry(main)*   # ブロックの戻り値がメソッドの戻り値になる
[11] pry(main)*   Animal3.class_eval { define_method(name, proc) }
[11] pry(main)* end
=> {:cat=>"にゃー", :dog=>"わん"}
[12] pry(main)>
[13] pry(main)> puts Animal3.new.cat(3)
にゃーにゃーにゃー
=> nil

まとめ

defでメソッド定義しなくてもメソッドを定義するという
初見殺しな面もありますが、メタプログラミングをする上で
扱うものの1つだと思うのでしっかり覚えておきます。

参考資料

define_method (Module) - Rubyリファレンス

【アジャイル】アジャイル(スクラム)をやり始めて5ヶ月ほど経ったので振り返る

はじめに

本エントリーは以下の続きです。

fujiyasu.hatenablog.com

fujiyasu.hatenablog.com

前回のエントリーから今まであったこと

  • プロダクトオーナー(以下、PO)が交代
    • POが認定POを取得
  • スクラムマスター(以下、SM)が交代
    • SMが認定SMを取得
  • チームが成熟されてきたときに起きたこと
    • プロダクトバックログリファインメントの改善
    • スプリントレビューの改善
    • T字型人材への促進
  • スクラムオブスクラムが始まる動きがある

簡単ですが、こんなところでしょうか。
それでは詳しく書いていきます。

プロダクトオーナー(以下、PO)が交代

前回のエントリーで

POがいない問題

というのを書きました。

前のPOも問題詩しており、解決策として
プロダクトに近い立場の人を新POにしました。
ただし、人が変わるということは会話の内容が変わってくるため
最初は認識合わせすることにかなり苦労しました。

しかし、開発をしていくごとに改善してきて
会話できる時間や量も増えて、スプリント中でも
スムーズに意思疎通をすることができるようになりました。

なお、この前後にPOは認定POを取得しており
POとしての基礎固めはできている状態となりました。

スクラムマスター(以下、SM)が交代

前SMが築き上げてきたものを筆者が引き継ぎ、新SMとなりました。
POのときと同様にそれぞれ認定SMを取得した状態です。

交代した理由は「認定SMを取得したのでやってみる」というのも
ありますが、もう1つの理由は「SMは思っている以上に大変」ということだと
思います。
常にチームを観察して、正しい方向に導き細かいタスクをやらなければならないので
1つのことに集中する以上に労力を使う立場です。
そのため、ずっとSMは現実的に難しいと思うので交代はありだと考えています。

また、前回のエントリーで

すでにローンチ済みのサービスのため、本番の調査依頼などが入ってくる

というのを書きましたが、POがすぐに対応できない場合
SMとして間に入ってSMがまず調査をすることにしていました。
どうしてもわからない、時間がかかる場合はPOに相談して
開発チームのリソースを使うということをしました。

チームが成熟されてきたときに起きたこと

プロダクトバックログリファインメントの改善

改善点

  1. 一つのストーリーに費やす時間が多かったのでキッチンタイマーを導入して10分の制限を設けた。
  2. 議論が白熱した際、SMが間髪入れず間に入って状況を整理する。
  3. リファインメントでは詳細な機能の話はしない。詳細に考えなければいけないのを含めてポイントを出す。
  4. 毎日1時間やっていたリファインメントを週にまとめて2時間にして効率化を目指す。

上記のおかげで今までストーリーポイントすらなかった状態が
見積もりされたバックログがある状態となってきました。

スプリントレビューの改善

改善点

  1. スプリントレビューのやり方を調べてチーム展開して、共通認識を行った。
  2. 大きなモニタを使って全員で画面を見れるようにした。
  3. 離れた場所から参加する人がいたので、TV会議システムを使い同じ画面を見れるようにした。

スクラム以外でもレビューというのは行ってきましたが
全員集まってレビューというのは勝手が違う感じがしたようなので
最初は戸惑いもあったようですが、改善をした結果確かな手応えを
チーム全体で感じられたようなので良かったです。

T字型人材への促進

開発メンバーは、それぞれ得意分野というのがあり
そちらを伸ばして行く人が多い感じでした。
しかし、それだけでは属人化してしまうため一部のメンバーだけですが
ペアプロを実施していくようになりました。

現在進行系でやっていましたが、とても効率的であり
楽しくプログラミングをやっている印象を受けました。

スクラムオブスクラムが始まる動きがある

実は、別のチームでスクラムをやっているところがあり
それぞれのチームの知見を共有しようという話になってきました。
チームの文化というのは同じスクラムでもまったく違うので
お互いノウハウを共有していければと思います。

この辺は。また展開があったときに書きたいと思います。

まとめ

本当はもっとあったと思うのですが
詳しく書いてしまうと、それぞれの内容で1つのエントリーに
なってしまうレベルなので簡単に書きました。

スクラムチームとなって3ヶ月以上が経って
そろそろ半年になるにあたり、成熟度も増してきたので
今後、さらに良いチームになっていくと思います。

最後にSMとなって、参考にした書籍を列挙しておきます。

アジャイルな見積りと計画づくり ~価値あるソフトウェアを育てる概念と技法~

アジャイルな見積りと計画づくり ~価値あるソフトウェアを育てる概念と技法~

アジャイルレトロスペクティブズ 強いチームを育てる「ふりかえり」の手引き

アジャイルレトロスペクティブズ 強いチームを育てる「ふりかえり」の手引き

【Ruby】文字列リテラルのダブルクォートとシングルクォートの違いについて

はじめに

せっかく調べたのに忘れてしまうため、メモを残しておく。

今回は、メソッドの引数に関することで
文字列リテラルのダブルクォートとシングルクォートの違いを調べました。

環境

前提条件

  • irbかPryが動作すること

やり方

文字列リテラルのダブルクォートとシングルクォート

文字列リテラルのダブルクォートとシングルクォート

実行

[1] pry(main)> # ダブルクォート
[2] pry(main)> # ・バックスラッシュ記法と式展開が有効になる
[3] pry(main)> str1 = "式展開も試してみます"
=> "式展開も試してみます"
[4] pry(main)> puts "ダブルクォートのサンプル文字列です\n\nそして、#{str1}"
ダブルクォートのサンプル文字列です

そして、式展開も試してみます
=> nil
[5] pry(main)>
[6] pry(main)> # 文字列内でダブルクォートを使いたい場合、エスケープ文字を入れる
[7] pry(main)> # ※「サンプル文字」をダブルクォートで括ってみる
[8] pry(main)> puts "ダブルクォートの\"サンプル文字列\"です\n\nそして、#{str1}"
ダブルクォートの"サンプル文字列"です

そして、式展開も試してみます
=> nil
[9] pry(main)>
[10] pry(main)> # シングルクォート
[11] pry(main)> # ・\\ (バックスラッシュそのもの)と \' (シングルクォート) を覗いて、文字列の中身の解釈しない
[12] pry(main)> str2 = "式展開されないことを確認します"
=> "式展開されないことを確認します"
[13] pry(main)> puts 'シングルクォートのサンプル文字列です\n\nそして、#{str2}'
シングルクォートのサンプル文字列です\n\nそして、#{str2}
=> nil
[14] pry(main)>
[15] pry(main)> # シングルクォートの場合、中身の会社はしないのでエスケープ文字を入れなくてもそのまま表示される
[16] pry(main)> puts 'シングルクォートの"サンプル文字列"です\n\nそして、#{str2}'
シングルクォートの"サンプル文字列"です\n\nそして、#{str2}
=> nil
[17] pry(main)>

まとめ

ダブルクォートとシングルクォートの違いに気づかず、シングルクォートで式展開を書いてしまっていて
なぜ展開されない?と数分考え込んでしまったので、簡単ですがまとめみました。

基本、ダブルクォートを使うのが良さそうなのでこちらを使っていきます。

参考資料

リテラル (Ruby 2.4.0)

【Ruby】キーワード引数

はじめに

せっかく調べたのに忘れてしまうため、メモを残しておく。

今回は、メソッドの引数に関することで キーワード引数を調べました。

環境

前提条件

  • irbかPryが動作すること

やり方

キーワード引数(デフォルト値あり)

キーワード引数(デフォルト値あり)のサンプルソース

実行

[6] pry(main)> # 引数を元にメッセージを表示する
[7] pry(main)> def display_message(name: 'Smith', message: 'Sample')
[7] pry(main)*   p "#{name} : #{message}"
[7] pry(main)* end
=> :display_message
[8] pry(main)>
[9] pry(main)> display_message
"Smith : Sample"
=> "Smith : Sample"
[10] pry(main)> display_message(name: 'John', message: 'Hello')
"John : Hello"
=> "John : Hello"
[11] pry(main)> display_message(message: 'Hello', name: 'John')
"John : Hello"
=> "John : Hello"
[12] pry(main)> display_message('John', 'Hello')
ArgumentError: wrong number of arguments (given 2, expected 0)
from (pry):8:in `display_message'
[13] pry(main)>

デフォルト引数を定義することで、何も受け取らなかった場合
デフォルトのものが表示されていることがわかります。

また、引数を設定するとその値にとなり、引数の順番を変えても
問題なく表示されていて便利です。

ただし、引数の値だけではエラーとなってしまいキーワードは必須です。

キーワード引数(デフォルト値なし)

キーワード引数(デフォルト値なし)のサンプルソース

実行

[13] pry(main)> # 引数を元にメッセージを表示する
[14] pry(main)> def display_message(name:, message:)
[14] pry(main)*   p "#{name} : #{message}"
[14] pry(main)* end
=> :display_message
[15] pry(main)>
[16] pry(main)> display_message(name: 'John', message: 'Hello')
"John : Hello"
=> "John : Hello"
[17] pry(main)> display_message(message: 'Hello', name: 'John')
"John : Hello"
=> "John : Hello"
[18] pry(main)> display_message
ArgumentError: missing keywords: name, message
from (pry):16:in `display_message'
[19] pry(main)> display_message('John', 'Hello')
ArgumentError: wrong number of arguments (given 2, expected 0)
from (pry):16:in `display_message'
[20] pry(main)>

デフォルト値なしの場合、エラーとなってしまったので
こちらを使った方がいい場合もありそうです。

まとめ

今まで意識して使ったことなかったのですが、明確に記述したい場合などがあったら
積極的に使っていきたい機能だと思いました。

ただし、参考資料先でも書かれている通り、冗長になる可能性が十分あるので
適材適所として使っていきます。

参考資料

改訂2版 パーフェクトRuby

改訂2版 パーフェクトRuby

ruby-rails.hatenadiary.com

robots.thoughtbot.com

【Ruby】可変長引数と配列の展開

はじめに

せっかく調べたのに忘れてしまうため、メモを残しておく。

今回は、メソッドの引数に関することで 可変長引数配列の展開を調べました。

環境

前提条件

  • irbかPryが動作すること

やり方

可変長引数

可変長引数のサンプルソース

実行

[12] pry(main)> # 引数を元にメッセージを表示する
[13] pry(main)> def display_messages(name, *messages)
[13] pry(main)*   messages.each do |message|
[13] pry(main)*     p "#{name} : #{message}"
[13] pry(main)*   end
[13] pry(main)* end
=> :display_messages
[14] pry(main)>
[15] pry(main)> # 実行
[16] pry(main)> display_messages 'John', 'Hello', 'Goodbye', 'Thank you'
"John : Hello"
"John : Goodbye"
"John : Thank you"
=> ["Hello", "Goodbye", "Thank you"]
[17] pry(main)>

値を個別に渡していますが、2つ目以降は配列として受け取られているのがわかります。

可変長引数

配列の展開のサンプルソース

実行

[39] pry(main)> # 引数を元にメッセージを表示する
[40] pry(main)> def display_messages(name, message_first, message_second)
[40] pry(main)*   p "#{name} : #{message_first}"
[40] pry(main)*   p "#{name} : #{message_second}"
[40] pry(main)* end
=> :display_messages
[41] pry(main)>
[42] pry(main)> # 実行(正常動作)
[43] pry(main)> messages = %w(Hello Goodbye)
=> ["Hello", "Goodbye"]
[44] pry(main)> display_messages 'John', *messages
"John : Hello"
"John : Goodbye"
=> "John : Goodbye"
[45] pry(main)>
[46] pry(main)> # 実行(例外発生)
[47] pry(main)> # 受取先のメソッドの引数以上に渡した場合、エラーとなる
[48] pry(main)> messages.push 'Thank you'
=> ["Hello", "Goodbye", "Thank you"]
[49] pry(main)> display_messages 'John', *messages
ArgumentError: wrong number of arguments (given 4, expected 3)
from (pry):50:in `display_messages'
[50] pry(main)>

まとめ

最初見た時は「なんだこれ?」と思いましたが、コーディング量が減るのはいいことで
使えるところには積極的に使っていきたいです。

ただ、変数名などをちゃんとしないと変に勘違いする可能性もあるかな?と思ったので
要注意のものだと感じられ巻いた。

参考資料

改訂2版 パーフェクトRuby

改訂2版 パーフェクトRuby

【Rails】Hash(key)をシンボル形式にする

はじめに

せっかく調べたのに忘れてしまうため、メモを残しておく。

今回は、APIなどで取得したHash値をRails側で処理しやすいようにするため
deep_symbolize_keysを調べました。

環境

前提条件

  • Railsアプリケーションのひな形が作成された状態で、Railsコンソールが起動できること

やり方

サンプルデータ

{
    "name": "Taro Tanaka",
    "gender": "male",
    "age": 24,
    "frends": [
        {
            "name": "Hanako Tanaka",
            "state": "NY"
        },
        {
            "name": "Jiro Tanaka",
            "state": "LA"
        }
    ]
}

実行

[1] pry(main)> response = {"name"=>"Taro Tanaka", "gender"=>"male", "age"=>24, "frends"=>[{"name"=>"Hanako Tanaka", "state"=>"NY"}, {"name"=>"Jiro Tanaka", "state"=>"LA"}]}
=> {"name"=>"Taro Tanaka", "gender"=>"male", "age"=>24, "frends"=>[{"name"=>"Hanako Tanaka", "state"=>"NY"}, {"name"=>"Jiro Tanaka", "state"=>"LA"}]}
[2] pry(main)> response.deep_symbolize_keys
=> {:name=>"Taro Tanaka", :gender=>"male", :age=>24, :frends=>[{:name=>"Hanako Tanaka", :state=>"NY"}, {:name=>"Jiro Tanaka", :state=>"LA"}]}
[3] pry(main)>

おぉ、シンボル化されたものになりました。
ちなみに「deep」とあるので、deepではないものを使うとどうなるか確認します。

[3] pry(main)> response.symbolize_keys
=> {:name=>"Taro Tanaka", :gender=>"male", :age=>24, :frends=>[{"name"=>"Hanako Tanaka", "state"=>"NY"}, {"name"=>"Jiro Tanaka", "state"=>"LA"}]}
[4] pry(main)>

なるほど、配列化されたところはそのままということですね。
基本的にはすべてシンボル化するはずなので、deep_symbolize_keysを使うことになりそうです。

参考資料

deep_symbolize_keys (Hash) - APIdock

【アジャイル】アジャイル(スクラム)をやり始めて2ヶ月ほど経ったので振り返る

はじめに

本エントリーは以下の続きです。

fujiyasu.hatenablog.com

報告会とかあっても良さそうなのですが、走り始めなのと
業務時間はチケット消化に忙しいのでその場もなかなか設けられずな状態です。

なので、丁度GWということもあり
整理も兼ねて一度書いてしまおうと思います。

これを元に会社の技術ブログや何かの登壇のキッカケになればいいですね!

スクラムチームメンバー

基本に則り、以下のメンバー数となります。

  • プロダクトオーナー(以下、PO)
  • スクラムマスター(以下、SM)
  • 開発チーム(8人)
  • スクラムコーチ(毎日はいない)

アジャイルでやることについては、慣れもあるので
開発チームは段々と成長していくと思います。

SMの存在が1番重要

チームで1番重要だと思ったのが「SM」の存在でした。
開発チームを円滑に進めるための手助けとしているわけですが
結局、人間同士のやり取りとなるので人間として出来ている人
SMとして適任だと感じられました。

もっと具体的に言うと

  1. SMをやる人が自分の部や課の中堅どころであり、
    上長にも一目置かれている
  2. 他の部署にも顔が利き、すぐに連携が取れる
  3. 自分のスキルよりも、まずチームのことを考えて行動できる

上記のスキルを持ったがSMになれば、駆け出しチームでも
チームを成長させていき、軌道に乗せていけると存在であり
スクラムチームを作る上でとても重要だと今回思いました。

開発チーム

今までやってきたものもあるので、現在、得意分野(アプリが得意ならアプリなど)を
担当しているのが現状です。
チームが成熟していくに連れて、その垣根も越えて全員がある程度のことが
できるようになっていくと思います。
※自分は手を広げすぎるとどれも中途半端になりそうなので、
しばらくサーバーサイドかな?と思っていますが。

また、若手が半数、中堅が半数となっており、また半数ずつということで
自然に師匠と弟子という形にもなり、業務を通じての教える、教わるという
体勢ができています。

まさかここまで考えてメンバーを選抜したのか?というぐらい、
うまくいっている感じがしており人員配置を考えた
マネージャーはすごいなと思わされました。

アジャイルプラクティス

導入した大まかなプラクティス

  1. プロダクトバックログ
  2. スプリントプランニング
  3. デイリースクラム
  4. 開発作業
  5. スプリントレビュー
  6. スプリントレトロスペクティブ

初めてやるので「基本に忠実に」ということでやっています。
現在うまくやれているので、チームの成熟度に合わせて
どんどん洗練されていくと思います。

導入した細かなプラクティス

  1. 1日1回のスクラムチームミーティング(期間限定)
  2. プランニングポーカー
  3. バーンダウンチャート
  4. バーンアップチャート

1以外はプラクティスもあるので、説明不要だと思います。
1については、スクラムマスターの判断で導入したものです。

業務をやっていく中で、週1の定例では遅いということで
開発スピードは落ちるにしろ「1日1回問題をキャッチアップする」を
目的にMTGを実施しています。

結果は、やって正解でした。
やはり新しいことをやると必ず問題が出てきて、すぐに議題に上げることが
できるようになり、その場で解決(または相談)することができ
MTGが多くなるにしろスクラムチーム立ち上げ時はなるべくやった方が
いいと思いました。

問題点

もちろん、すべてうまくいっているわけでもありません。
今回やってきた中で問題となっていたものは以下の通り。

  1. チーム立ち上げ時はミーティング多い
  2. すでにローンチ済みのサービスのため、本番の調査依頼などが入ってくる
  3. チケット消化がメインとなっているため、立ち上げ当初に作ったものの見直しがない
  4. POがいない問題

1については、立ち上げ時特有の問題だと考えています。
チーム全員が同じ目線で同じ目標に向かうためには、全員出席で認識合わせを
しなければならないため、根気よくやるべきだと思いました。

2については、自分が携わっているプロダクトの問題なのかもしれませんが
バックログ以外のタスクが割り込みとして入ってきて、進捗に影響しています。
良くはない状況ですが、それを見越してのベロシティを出すのもありと言えばありです。
しかし、割り込みはない方がいいはずなので、そのへんも改善も今後の課題となります。

3については、スクラムに限らず通常のシステム開発でもあるあるだと思います。
ただ「1週間に1回見直そう」というのも短すぎだと思うので、3ヶ月に1回など
その感覚が良いのでは?と思い始めました。今度、スクラムマスターに相談してみよう。

4については、自分のチームだけでなく他のところでもあるあるだと思います。
しかし、この問題はPOもちゃんと認識しており、意識してチームの近くに
いるようにしてもらえています。
当たり前のことだと思わがちですが、ちゃんとPOに問題点を言えて
お互い改善していけてるところがあり「いいチームだな」と認識させられます。

現状とまとめ

2ヶ月ほど経ち、振り返ってみましたがいい感じにまわり始めたと思います。
ただ、スプリントはまだ回数が少ないため、安定したとは言えない状況です。
こればかりは数をこなしていき、安定させ価値あるものをどんどんリリースして
いければと思います。