スクラムフェス大阪2020でLTセッションを担当した。
6/26、27に開催されたオンラインカンファレンス「Scrum Fest Osaka」で、ハッカーライフラボとしてLTセッションを担当しました。
オンライン開催決定後、ハッカーライフラボを運営している岩切さん*1から
旅するAgile本箱で何か一緒にやりませんか?
というお誘いを頂き、今回の企画に至りました。 たしか今年のデブサミの頃からこういうイベントをしたいという話をしていたのですが、具体的にやる機会を今回得られたのでとても良かったです。
旅するAgile本箱は、翔泳社の岩切さんが始めた活動です。 スクラムを実践する人たちが読むと良い本を、実践者の人たちが選んで集め、それをスーツケースに詰めて一定期間貸し出すというものです。 この本箱に入っている本それぞれには、その本を選んだ人が「勧めたい!」と感じたストーリーがあると思いました。 特に、それは「本から勇気づけられた」といった話なのではないかと私は想像しました。 そこで、本に後押ししてもらったストーリーを話すLTセッションを企画しました。
8人のトーカーと6つのストーリー
こんなLTセッションで話をしたい人なんて誰もいないんじゃないか、と思いつつも、「やってみなければわからない」ということで募集しました。 その結果、8名のエントリー!中には現在のAgile本箱に入ってない本の話もあって、非常にありがたい収穫でした。
セッションの動画は後日ハッカーライフラボで公開するので、是非チャンネル登録をお願いします。
トーカーとタイトルについてはこちら。
- 「『SCRUM BOOT CAMP THE BOOK 増補改訂版』コラムニスト3人分の学び」, 森 一樹(@viva_tweet_x), 飯田意己(@ysk_118), Koji Sudo(@su_kun_1899)
- 「一万年の旅路 ネイティブアメリカンの口承史」, 懸田 剛 (@kkd)
- 「カイゼン・ジャーニー」, 井内 聡(@superSatoshiKun)
- 「旅するAgile本箱をシェアして会社の仲間と読んだ体験から得たこと」, 常松祐一 (@tunepolo)
- 「チームが「サイロ化」しないための仕掛け(増補版)」, ふかやみわ(@miwa719)
- 「未来を変えるためにほんとうに必要なこと――最善の道を見出す技術」, 石井智康
トップバッターは長年愛され続けている『SCRUM BOOT CAMP THE BOOK』。
出版されて7年目の今年に増補改訂版が出版されました。 そのコラムを書いたコラムニストのうち3名が、それぞれの経験から生まれたコラムについて紹介していただきました。この本を読んで感銘を受けた3人が、増補改訂版にあたり、それぞれが歩んできた経験をコラムに込めているのが最高にエモい話でした。2番手は、アジャイル459トラックでも登壇していた懸田さんが、「一万年の旅路 ネイティブアメリカンの口承史」を紹介してくださいました。
- 作者:ポーラ アンダーウッド
- 発売日: 1998/05/26
- メディア: 単行本(ソフトカバー)
3番手のいっちーさんからは、「カイゼン・ジャーニー」から始まるいっちーさんのジャーニーのお話。
いまさら紹介する必要ないくらいに、多くの方が手にとっている本です。 その中の言葉の1つに、それで、あなたは何をしている人なんですか?
という言葉に考えさせられた人はたくさんいるのではないでしょうか。いっちーさんもその一人。 何もできていなかった自分自身に気づき、社内でスクラムの勉強会を開催したり、部署を超えた活動も始めるなどの行動を起こしています。 さらっと「人生を変えた一冊」とおっしゃっていて、これは著者やこの本に関わっった人たちを泣かせる言葉ですね。
4番手の常松さんのLT「旅するAgile本箱をシェアして会社の仲間と読んだ体験から得たこと」では、旅するAgile本箱を実際に利用したRettyさんで起きたことの話です。 Agile本箱を借りると何ができて、何が起こるのか、ということを話していただきました。 LTで話していただいた内容の一部は、Retty Tech Blogで読むことができます。
本当は弊社はRettyさんの次に借りる予定だったのですが、非常事態宣言などもありキャンセルしました。Rettyさんで行われた社内ビブリオバトルなどの話をきいて、やっぱりまた借りてみようと思えました。
5番手のみわさんのLT「チームが「サイロ化」しないための仕掛け(増補版)」の話は、下記ブログの内容の増補版です。動画を視聴する前に読んでおくとより楽しめます。
このLTの中で触れている本はこちら。 leanpub.com
「仕掛けの仕掛け」、「心理的安全性はやってこない」や「チームは概念上のもの」など、刺さる話がたくさんありました。最後のオチも素敵でした。「チーム間の情報共有ができてないー」とか言ってるマネージャーの人はじっくりこの話を聞いたらいいんじゃないでしょうか。 いや、ほんと。
トリは石井さんによる「未来を変えるためにほんとうに必要なこと――最善の道を見出す技術」。
未来を変えるためにほんとうに必要なこと――最善の道を見出す技術
- 作者:アダム・カヘン,Adam Kahane
- 発売日: 2010/04/20
- メディア: 単行本
誰もがお世話になった石井食品の社長に登壇していただきました。セッションの翌日が株主総会というお忙しい中、ご参加いただけて本当に感謝しています。 この本は民族紛争解決の本です。石井さんは、心が折れそうなくらいに辛い状況になったときの心の処方箋として、この本を使っているそうです。「もっと酷い状況でも頑張っている人がいる」ことを知ることで、ちょっと前まで辛いと思っていた状況が「なんだそんな大変じゃないや」といった気持ちに切り替えられるということです。どんなつらい状況であれ、アパルトヘイト後の南アフリカやゲリラのリーダーが参加するワークショップなんかに比べたら楽勝ですよね。 そして、この本のタイトルにある「未来を変えるために必要なこと」は、「力(Power)と愛(Love)」であると書かれています。実現するために行動する力とバラバラなものを統一させようとする力を表しています。 組織運営においてはどちらも重要という話をされていました。
どの方の話も濃厚な内容で、一人ずつ45分のセッションが組めたんじゃなかったのかな。 でも、「もっと聞きたい」と思わせられたらLTとしては成功だと思うので、このセッションは個人的には成功でした。 だって、少なくとも自分はもっと聞きたいと思ったので。
当日ご参加いただいた皆様、そして何よりもここでストーリーを紹介してくれたトーカーの皆様、大変ありがとうございました。
Scrum Fest Osakaを終えて。
この2ヶ月くらいは、Scrum Fest Osakaに対しては、よく思ったりそうでもなかったりと悶々としていました。 最初にScrum Fest Osakaがオンライン開催すると聞いたときは、とても嬉しかったのを覚えています。 ですが、開催場所のDiscordを覗いてみると、大阪だけでなく様々な地方のトラックが乱立していて、一体何の会なのかわからなくて、混乱しました。 その趣旨が見えず、正直、「うっ」と思いました。 ただ、今後、こういうオンライン開催でのカンファレンスは増えていくだろうし、新しいあり方を受け入れなければいけないのかもしれない、と思ってもいました。 そんな時にちょうどよく声をかけてくれたのが岩切さんでした。 これまでイベントに参加する際は、単独での講演か、普段一緒に仕事しているチームメンバーと出ることが殆どでした。 今回はハッカーライフラボの皆さんと一緒に準備から当日運営までやらせていただきました。 前に進めるためにワイワイとできて良いチームだな、って思いました。 そこに混ぜてもらえて、大変感謝しています。
と、色々書きましたが、要するに楽しかったということです。
LTセッションの動画は、ハッカーライフラボのYoutubeチャネルで公開される予定ですので、ぜひともチャンネルの登録をよろしくお願いします。
「みんなでアジャイル」を読んだ。
みんなでアジャイル ―変化に対応できる顧客中心組織のつくりかた
- 作者:Matt LeMay
- 発売日: 2020/03/19
- メディア: 単行本(ソフトカバー)
開発のプラクティスに特化しているわけではないので、エンジニア以外の人たちでも十分にわかるような内容だと思う。 むしろ、そういった人たちがアジャイル開発というのに関わる場合に始めてに手に取るといいのかな。 「アジャイルって何?」という人にどういうことをやるかという話をしても頭に疑問符が残りそうだ。 そういったときに、この本に書いてあるように「何のために」「なぜやるのか」といった説明があると理解してもらいやすそうだ。
色々プラクティスを試してみてるけど何かモヤモヤっとしている人にも良さそうな本だと思う。 アジャイル開発を導入すると決まってプラクティスを始めてみたが、何か腑に落ちないといった場合に、各章の最後にある「良い方向に進んでいる兆候・悪い方向に進んでいる兆候」を読んで振り返ってみると改善策が出てきそう。 もちろん、これは導入し始めたチームだけでなく、その周りにいる経営層含めた関係者も同じように兆候を理解しておくために、良い本だと思う。
「リモートワーク時代のモブプログラミング」勉強会でLTしてきた
もうそろそろ一週間経ってしまいそうなのですが、「リモートワーク時代のモブプログラミング」という勉強会(?)でLTをしてきました。
最初はただのネタっぽい感じの話にしようかと思っていたのですが、わりと真面目に考えても良い話とも思っています。 このLTをした翌日にSlackがダウンしました。 いくつかの開発の現場ではチームでのコミュニケーションが途絶えたのではないでしょうか。 幸いなことに、短時間であったし、そんなに頻繁に起こることでは無いのかもしれないです。 けれど、zoomなどで常時接続していなければ開発ができない、という状態は問題ないのだろうか。ネットワークが常に安定していることは望ましいけれど、そうでなければリモートでのモブワークはできないのだろうか。低速なネットワーク環境で無理してモブを続けるだけでなく、諦めて別々のタスクに分かれて仕事をする方が良い場合があるのではないだろうか。
このようなことを少し考えてみることも意味があるのではないかと思いました。 上の疑問に対する自分の解答ははっきりとありません。悶々としています。
捕捉できなかった例外を勝手にググってくれるUndine をリリースしました
開発中のコードを試しに実行してみたところ、思いがけない例外が出てしまった。 そういう時はどうするだろうか。 出てきたエラーメッセージを読み、何が原因なのかを探るのではないでしょうか。 自分もgoogleなどで検索して、例外に関するドキュメントを探したりします。
その手間を助けるために、コード内で捉えられなかった例外が出た場合に自動でブラウザを起動してエラーメッセージをキーワードとして検索してくれるgemを作りました。
使い方
インストール
下記のようにgem
コマンドでインストールできます。
gem install undine
bundlerをお使いの方はGemfile
に下記の一行を追加し、bundle install
を実行するとインストールできます。
gem 'undine', group: :development
使い方
お使いのRubyスクリプトのはじめの方に以下のコードを追加します。
require 'undine' Undine.load
これだけで、どこにも捕捉されなかった例外が出たときに、例外メッセージを検索するgoogle のページがブラウザで開かれます。
既存のスクリプトに手を入れたくない場合は、undine/autoload
を実行時に指定してください。
ruby -r'undine/autoload' your_script.rb
bundlerを利用している場合は、Gemfile
中のgem
メソッドにrequire
オプションを追加してください。
gem `undine`, require: 'undine/autoload', group: :development
バグ報告、ご意見はこちら
利用してくださった皆様からの感想、ご意見、バグ報告なんでもお待ちしております。 何かございましたらGitHub Issueから連絡いただけると助かります。
Typetalkに通知を送るGitHub Actionを作った: Typetalk Notify
無料プランがあるということでなんとなくTypetalkを使い始めてみた。 Slackなんかと同じようにAPIやWebhookなどがありカスタマイズが可能で、GitHubとの連携もサポートされている。
GitHubと連携することで、ブランチのプッシュ、Issueやプルリクエストの作成・変更が起きる度に通知がTypetalkのトピック(Slackのチャネルに相当)に届くようになる。
しかし、リリースなどどうやらサポートされていないイベントが一部あり、またメッセージをカスタマイズしたいことがある。 ということで、GitHub Actionsを作ってみた。
使い方
オプションについてはREADMEを参照してほしい。 同じREADMEに記載されているworkflowファイルの記述例を載せる。
name: Release announce on: release: types: [published] jobs: steps: - uses: satoryu/typetalk-notify@v0.0.1 with: token: ${{ secrets.TYPETALK_TOKEN }} topic_id: 165952 # Replace your topic's id message: "${{ github.repository }} ${{ github.ref }} has been released :tada: :white_flower:"
この設定ファイルをリポジトリの.github/workflows/
ディレクトリ以下にrelease_announce.yml
などのようにして保存する。
その後に、release tagを作ると、以下のような通知がTypetalkのトピックに投稿されるようになる。
上に書いた設定を変更すれば、push時やissue作成時など別のGitHub上のイベントが発生した時に好みのメッセージを投稿することができる。
おまけ: GitHub Hackathon にエントリー
ちなみに、3/31までGitHub Hackathonが開催されていて、GitHub Actionsがテーマになっている。 ちょうど良かったので今回作成したActionでエントリーしてみた。
Rails のGeneratorのデフォルト値はどこから来るのか
ことの発端
Rails のController generator で不要なrouting が書き込まれてしまうので、毎度--skip-routes
オプションを付けるようにしている。
けれど、オプションを付け忘れることもあって、面倒なことになることがよくあった。
調べてみると、 config/application.rb
などでconfig.generators
を以下のように指定することでデフォルトのオプションとして指定できることがわかった。
config.generators do |g| g.skip_routes = true end
該当の変更だけを見ても、仕組みが理解できなかったので調べてみた。
TL;DR
controller generator にオプションの渡し方は、以下の3通り。
config.generators.controller = { skip_routes: true }
config.generators.rails = { skip_routes: true }
config.generators.skip_routes = true
個別のgeneratorのためのオプションとして最優先されるのは1の設定の仕方。 2と3は同等の扱いで、他のgeneratorとも共有される。
探求編
コードを読んでいく方針として次の順で行った。
- 参照側:
ControllerGenerator
のoptions[:skip_routes]
はどこを見ているのか - 設定側:
Rails::Application.config.generators
に指定した値はどこに入るのか - 上記2つはどこでつながるのか
参照側
module Rails module Generators class ControllerGenerator < NamedBase # :nodoc: argument :actions, type: :array, default: [], banner: "action action" class_option :skip_routes, type: :boolean, desc: "Don't add routes to config/routes.rb." # # 中略 # def add_routes return if options[:skip_routes] return if actions.empty? routing_code = actions.map { |action| "get '#{file_name}/#{action}'" }.join("\n") route routing_code, namespace: regular_class_path end
add_routes
メソッド内で、options[:skip_routes]
を見ているので、options
がどこから来るのかを探る。
ControllerGenerator
自身は持っていないので、継承しているNamedBase
を見てみるがこれもoptions
を持っていない。更に上位クラスのRails::Generators::Base
を見ると、これがThor::Group
を継承していることがわかる。
RailsのgeneratorなどCLIは、CLIを作成するDSLを提供するthorを使用している。
Thorのドキュメントを見ると、Thor::Group
がincludeしているモジュールThor::Base
にoptions
メソッドが存在していることがわかる。
ControllerGenerator
のコードを再度見ていくと、skip_routes
オプションをclass_option
で定義している。
これもまたthorに存在するメソッドである。しかし、デフォルト値を指定するためのdefault
をキーに持つハッシュが引数に渡されていない。
Rails::Generators::Base
を見ると、class_option
メソッドをオーバーライドしている箇所がある。
def self.class_option(name, options = {}) #:nodoc: options[:desc] = "Indicates when to generate #{name.to_s.humanize.downcase}" unless options.key?(:desc) options[:aliases] = default_aliases_for_option(name, options) options[:default] = default_value_for_option(name, options) super(name, options) end
これは、Thor::Base.class_option
をsuper
で呼ぶ前に、デフォルト値を設定している。
default_value_for_option
は以下のようになっている。
def self.default_value_for_option(name, options) # :doc: default_for_option(Rails::Generators.options, name, options, options[:default]) end
さらにdefault_for_option
を呼び出している。
def self.default_for_option(config, name, options, default) # :doc: if generator_name && (c = config[generator_name.to_sym]) && c.key?(name) c[name] elsif base_name && (c = config[base_name.to_sym]) && c.key?(name) c[name] elsif config[:rails].key?(name) config[:rails][name] else default end end
これは以下のようにデフォルト値を決めている。
config
(ここだとRails::Generators.options
)の中にgenerator名(ここだとcontroller
)をキーとして持っていて、なおかつその値がハッシュでname
(ここだとskip_routes
)をキーとして持っていると、その値をデフォルト値とするconfig
の中にbase_name(ここだとrails
)をキーとして持っていて、なおかつその値がハッシュでname
をキーとして持っていると、その値をデフォルト値とするconfig
の中にシンボルrails
をキーとして持っていて、なおかつその値がハッシュでありそのハッシュがname
をキーとして持っている場合、その値をデフォルト値とする- 以上のどれにも当てはまらない場合、引数の
default
をデフォルト値とする
つまり、Rails::Generators.options
がどのようになっているのかで決まる。
この順番で先に見つかった値が使われる。
設定編
Rails Guideに、Generatorの設定についての記述があり、そこに下記のサンプルコードがある。
config.generators do |g| g.orm :active_record g.test_framework :test_unit end
Rails::Engine::Configuration#generators
を見ると、
def generators @generators ||= Rails::Configuration::Generators.new yield(@generators) if block_given? @generators end
Rails::Configuration::Generators
をブロックに渡している。
Rails::Configuration::Generators
はmethod_missing
が定義されていて、任意の名前で設定値を与えることができる。
下記のように4通りの記述が可能である。
config.generators.controller = { skip_routes: true }
config.generators.controller skip_routes: true
config.generators.rails = { skip_routes: true }
config.generators.skip_routes = true
1、2は同じ扱いで、controller generator固有のオプションを設定している。 3、4もまた同じ扱いで、controller generatorのオプションのデフォルト値だけでなく他のgeneratorからも参照される可能性がある。 「可能性がある」というのは、先述のようにgenerator固有の設定(つまり上の1、2で指定された値)を優先するためである。
どこでつながるのか
これで一件落着のように感じるが、Rails::Generators.options
の中を見ると、以下のようにDEFAULT_OPTIONS
にあるハッシュを返しているだけである。
def options #:nodoc: @options ||= DEFAULT_OPTIONS.dup end
rails generator
コマンド実行時にRails::Configuration::Generators
に設定された内容をRails::Generators.options
に入れている。
rails/generate_command.rb at c0d91a4f9da10094ccdb80e34d1be42ce1016c9a · rails/rails · GitHub
このload_generators
はRails.application.load_generators
を呼んでいるだけのメソッドである。
Rails.application.load_generators
の実体はRails::Engine#load_generators
で、この中で下記を実行している。
Rails::Generators.configure!(app.config.generators)
引数のapp.config.generators
は、設定編で解説した設定で生成したRails::Generators
オブジェクトである。
レシーバーのconfigure!
の中で、Rails::Generators.options
の値に、Rails::Configuration::Generators.options
の値をmerge
している。
ということで、このように設定した値がController Generatorから参照されていることがわかった。
Generatorを自分で作成する必要がありそのGenerator固有のオプションを持つ場合、そのオプションのデフォルト値はconfig.generators.my_generator = { my_option: 'foobar' }
といったように作成したgenerator名に値を与えることで設定できる。