Alstrocrack Tech Blog

考えたこと、学んだこと など

人間の「仕事」とは

はじめに

AIが世に出てきてから技術記事がAIだらけになっていてつまらないなと思っている一方で、テックブログを謳っておきながら 最近は技術的なことを何も書いてなくて大丈夫かなとも思っています。

そんなことはさておき「仕事」ってなんでしょうか?

  • ソースコードを書くこと?
  • Pull Requestを出すこと?
  • 部下をマネジメントすること?
  • 顧客とミーティングすること?
  • 会社の経営や戦略について考えること?

上記で挙げたものの中には、自分の考える「仕事」も一部含まれています。

私は仕事とは「判断すること」だと思っています。

「判断すること」って?

繰り返しですが、人間の仕事を仕事たらしめるものは、何かに対しての「判断をすること」です。

じゃあ、「判断」って何でしょう?これは「ある程度の責任を持って、自分の頭で考えて物事がAかBかはたまたCなのかを決めること」です。

「判断をする」ことには大なり小なりほぼ必ず責任が伴うはずです。「あなたがこう言ったんじゃないか!」と言われる可能性があるということですね。

「ある程度」といったのはあなたの判断の結果が良くないものになった場合に、最初になんとかしようとするのはもちろんあなたですが、最終的に切腹するのはもっと上の人かもしれないというだけです。途方もない失敗について責任を取るのは、直属の上長だったり、課長、部長、取締役や最高経営責任者が出てくることもあるでしょう。あなたの判断の結果の責任がどこまで波及するかはあなたの職位や判断次第です。

ですが、自分の判断の結果に最初に責任を持つのはあなた自身です。つまり、「仕事≒判断≒責任を取ること」という関係式になるはずだと考えています。

あなたは「仕事」をしていますか?

「判断」と一言でいっても、大小あります。Web系のエンジニアであれば何かしらのモダンな言語で何かの実装を行ったりすると思いますが、「どんな実装方針にするのか」、「どんなメソッドや関数を呼ぶのか?」と、色々なものが「判断」にはあります。

小さい判断であれば気づかないうちにもたくさんしているでしょう。しかも、これらの小さい判断には特段の責任もなかったりします。

ですが、この「判断」こそが人間にとっての揺るがない「仕事」そのものであり、残りはおまけみたいなものです。

これは仮面ライダーWに出てくる主人公:左翔太郎の親分である鳴海荘吉も言っています。

おやっさんが言ってたぜ。「男の仕事の8割は決断だ。そっから先はおまけみてぇなもんだ」ってな

www.kamen-rider-official.com

引用文では「男の仕事」という言い方をしていますが、女性の仕事ももちろん同様です。

逆に言うと、この「おまけ」の部分ばかりしている人、つまり何も自分で決めず、責任を取るような素振りもない人、これは本当の意味での仕事をしていません。

  • あなたは顧客の話、上司の指示や部下の苦言をただ伝書鳩のように誰かに流すだけのことをしていませんか?
  • 重要な局面での判断をみんなの意見の総和のようなものにただただ任せていませんか?
  • プロジェクトに誰をアサインするかの決定をメンバー任せにしていませんか?
  • どうでもいいような資料や書類の整理、意味のないスローガン決めばかりしていませんか?

何も決定しない人、責任ある判断をしようとしない人に価値はありません。まさにAIがリプレイスしようとしているのはこういう「ただのロボット作業者」たちです。

AI時代における「仕事」

「エンジニアがAIにリプレイスされる日も近い」。そんな言説が巷には溢れかえっていますが、私は信じていません。なぜならAIは自身の判断には責任を持てないからです。

最近読んで面白かった「『AIはソフトウェアエンジニアをリプレイスするか』論争にそろそろ終止符を打ちたい」というスライドを参考までに以下で共有します。少し本筋から逸れますが、読んで面白かったという意味での共有です。

hihats.github.io

人間のエンジニアが全く関与しておらず、AIが自発的に実装したWebサービスがリリースされた状況を仮定してみましょう。そして、実はデータストアが誰でも見れる状態になってしまっていて、個人情報が大量に流出してしまったとも仮定します。この場合は一体誰が責任を取るのでしょうか?

AIがWebサービスを実装し、リリースまでしようとしています

裁判になった場合を想定すると、AIを法廷に呼んで実装についての責任を追及しますか?AIを運営しているサービスを訴えますか?果たして、これは正しい責任追及でしょうか?

そのWebサービスをエンジニアリングを何も知らない人間がAIだけで実装して、リリースしたと少し仮定を変えましょう。この場合は、この人間を責任者として追及するでしょう。つまり、最終的には人間の判断や思考に対して、我々は追及し責任を負わせようとします。

このことからAIは「判断」をすることはできますが、現実世界で起こった事象で「責任」を取る能力があるとは見做されていません、少なくとも現在では。

その上、AIはかなり使いこなしている人間の指示でないと、正しい(と思える)判断をしてくれないことも多々あります。現実世界でAIの出力を最終的に「判断」するのは物理的な人間です。

「人間はAIにはない緊張感と責任で判断を行える」という事実にこそ、人間が「仕事」に介在する価値があるのです。AIはタスクを実行する存在に過ぎません。我々はそれを監督する存在です。

別に死ぬわけではない

判断や責任を避ける傾向にある人を私は人生の中で見てきました。それに、そもそも私とて責任を負うことはとても嫌いです。ですが、最初の部分にも書いた通り、私の失敗で首が飛ぶのは恐らく私ではないはずです。私の部門の上長だったり最高責任者だったりします。もし、あなたが会社勤めであり、その会社がまともな会社であれば。

つまり、責任を取るということは必ずしもクビになることはなく、物理的に死を迎える必要は絶対にありません。そもそも遂行責任はあなたや私にあるとしても、説明責任はあなたや私には無かったりします。

www.ntthumanex.co.jp

つまり、死ぬわけでもない責任というものに対してそこまで怯える必要はないということです。

あなたが20代ならば何も恐れる必要はありません。リスクだけを取って色んな判断をすることができます。もちろん、上長への報連相が前提ですが。失敗した場合は、その後処理がキツいものになったりする可能性はありますが、その失敗から何かを学ぶことができれば自分にとっても会社にとっても利益だったりします。会社勤めの良い点は私はここにあると思っています。

30代ならば誰かの責任を少しずつ引き受ける立場になるでしょう。ですが、何度も言っているように死ぬことまではありません。さらに上長がいる立場であれば、なおさら安心です。あなたの手から少しくらい溢れたところで、上長は必ず対応してくれます。というよりもそうせざるを得ません、まともな会社であれば。

それ以上の年齢の人間の仕事については正直経験が無いので分かりませんが、もしかすると、あなたは自分のクビをかけることがあるかもしれません。ですが、物理的なクビではないはずです、まともな会社であれば。

何はともあれ、まともな会社に勤めましょう。

まとめ

「責任」の取れる「判断」こそが人間にとっての価値ある仕事そのものであり、どんなにAIやロボットが発達した未来であったとしても人間が仕事にいる価値です。繰り返しですが、人間の仕事においては、その頭でしっかりと物事を考え自分の意思で物事の白黒をしっかりと「判断」しなければなりません。それが「仕事」であり、あなたが働く「価値」です。

アニメ「ドラえもん」では猫型ロボットであるドラえもんが投獄されるシーンをたまに観ることがありますが、ロボットに自身の判断に対する責任を負わせるという判断をする社会が到来すれば、AIが現在のような作業者の立場を超える日が来るかもしれません。

ドラえもん https://www.tv-asahi.co.jp/doraemon/character/ より

そんな時代になれば、このブログの言説が前提から崩れ落ちるかもしれません。だって、AIが責任ある判断をしてくれるのだから。

NO SILVER BULLET

はじめに

ビジネスを行う上では、解決したい問題のボトルネックを特定し、それを解消することは非常に大切であるはずだ。 私には「ビジネス」というものが完全には分からないが、この認識はおそらく間違っていないだろう。

そして、エンジニアである私のビジネスへの理解が浅いのと同様に、彼らビジネスパーソンにとっても、エンジニアリングを理解することはきっと難しいはずである。

そう感じる理由の一つに、彼らはビジネス上の課題と同様に、エンジニアリングが解決すべき問題に対しても、平然と Silver Bullet、つまり銀の弾丸 を求めてくることが挙げられる。

つまり、エンジニアリングの問題解決においても「ボトルネックを特定し、それさえ解決してしまえば良い」と考えているのだ。これは半分正しいが、半分間違っているように思える。

銀の弾丸

Silver Bullet / 銀の弾丸

Google でこの言葉を検索すると、以下のような AI の要約が出てきた。要するに、問題を完全に解決する一撃必殺技のことだ。

銀の弾丸(Silver Bullet)」は、狼男などの魔物を倒す不思議な力を持つ弾丸という伝承に由来し、転じて「難題を即座に解決する特効薬や万能な解決策」を指す比喩表現です。

彼らビジネスパーソンはいつも銀の弾丸を探している。 ビジネスの世界ではこの魔法の弾丸が工場で大量生産されており、手頃な価格で入手でき、彼らを悩ます問題に対して撃ち込むだけで、たちまちその問題は完全に消滅してくれるのだろう。

だが、エンジニアリングにおいて、基本的に銀の弾丸は存在しない。

余談だが、私はルパン三世が愛用している拳銃、ワルサー P38 で実弾を撃った経験がある。その経験から言えるのは、銃は誰もが簡単に使いこなせる代物ではないということだ。その音や衝撃は凄まじい。気軽に撃って、簡単に命中させられるものではないという点にも注意したい。

「エンジニアリングに銀の弾丸は存在しない」という言説は、以下の名著にも記されている。それもかなり最初のページである。ぜひ読んでみると良いと思う。

プリンシプル オブ プログラミング 3 年目までに身につけたい 一生役立つ 101 の原理原則

80:20 の法則と、切り捨てられる 20%

世の中には「80:20 の法則(パレートの法則)」と呼ばれるものがあり、これはビジネスパーソンの大好きな言葉の 1 つである。「全体の数値の 8 割は、全体を構成する要素のうちの 2 割が生み出している」といったアレだ。

ja.wikipedia.org

ビジネスパーソンは直面している問題のボトルネックを解消しようとする。それは間違っていないし、むしろ真っ当なアプローチなのだが、彼らは「ボトルネックとなっている 80%の問題さえ解消すれば良い」と考えているフシがある。つまり、銀の弾丸を撃ってしまえば、残りの 20%にはあまりこだわらない傾向にあるのだ。

まさにここに、ビジネスとエンジニアリングの折り合いが悪い原因があるように思える。

エンジニアは 80%のボトルネックを解決する一方で、残りの 20%の改善に対しても関心を持っている。そして、その 20%は大体において、ビジネスパーソンが理解に苦しむ「リファクタリング」や「整理整頓」といったものである。確かに、これらは直接お金を生まないし、短期的な観点ではただの無駄に見えるかもしれない。

これは正直、無理もないことである。なぜなら、人は自分が経験したことのない概念や苦しみを、真に理解することは難しいからだ。

だが、長期的な視点で見ると、これらはビジネスの存続に大きく関わってくる。 特に SaaS のような、長期で運用していくデジタルサービスを扱っているのであれば尚更だ。

焦点の違い

問題は「複利」で増える

ではなぜ、エンジニアは「20%」の問題の放置にそこまでこだわるのだろうか。それは、問題が複利で大きくなっていくからだ。

利子にもまた利子がつくこと。 - 複利とは|知るぽると

www.shiruporuto.jp

利子は、貸し手か借り手かという立場によって利益にも損失にもなるが、いずれにしても雪だるま式に増えていく性質を持つ。つまり、想像よりも早く、手強い問題になりうるのである。

ビジネスパーソンが切り捨てた「その時の 20%」は、複利の効果でエンジニアリング領域を侵食し始める。そして、やがて次のボトルネックとなる「80%の原因」へと成長していくのである。

20%の取りこぼしは80%になって牙を剥いてくる

整理整頓しておかなかった関数は、色んな場所から呼びだされるたびにオプションの数が増えていき、その時に一緒に張っておけばよかった index がないために RDB 内の検索は日を追うごとに遅くなっていく。

「効率」の定義の違い

ここまで読んでもビジネスパーソンの中には「そうか、でも 80%になってからでも良いじゃないか、とりあえず当面のボトルネックはもう解消したから、次に行くぞ」と言う人がいるかもしれない。だが、それはちょっと待ってほしい。なぜなら、その「残りの 20%」を今のうちに撃退しておけば、将来それが「80%の問題」になった際に解消しようとするのと比べて、消費するリソース量は劇的に少なくて済むはずだからだ。

よく彼らは「効率」とか「生産性」とかいう言葉を使うが、こういったエンジニアリングに関する意思決定に関しては、なぜかいつも効率の悪い選択をする傾向にある。今ここで対応してしまえば、少しのリソースで最大の効果を得られるはずなのに、「効率厨」であるはずの彼らは、なぜかその問題が 20%残っている状態で早々と「解決済」のレッテルを貼ってしまうのだ。

エンジニアリングにおける「ボトルネック

ここまで、「単純なボトルネック解消だけでは不十分だ」というような言い方をしてきたが、現実的かつ具体的な観点としては、エンジニアリングにもボトルネックというものは当然存在する。 Web API のレスポンスが遅い時は大体重いクエリを発行しているし、開発スピードが遅い時は大体既存のソースコードがあまり整理整頓されていない。

私たちは MELT(Metrics, Events, Logs, Traces) を確認し、原因を仮説立て、検証し、改善する。こういったエンジニアリングの定石を踏んで問題を解決するというわけである。結果として、遅かったレスポンスタイムは数十秒から数ミリ秒まで向上する。

ここで、ビジネスパーソンは胸を撫で下ろす。「やれやれ、問題が片付いたぞ」と。そして、続け様に次の機能開発に関する話を始める。

だが一方で、エンジニアは、周辺のソースコードの無秩序さやログを追うための複雑な手順といったものに対して、依然として改善の余地を見出している。 ソースコードの無秩序さは次の不具合を招き、ログの確認のしにくさは今回と同様に次の MTTR(平均修復時間)を長くするだろう。

繰り返しになるが、問題を 100%解決する銀の弾丸は基本的には存在しない。得てして、問題は複数の要素が絡み合う構成をしている。つまり、その問題の「80%」を解決しただけでは、その問題は終わりではない。その「20%」に対する見逃しが次の苦しみを生むので、その時点でぜひ撃退してしまいたい、そう言いたいのである。

鉛の弾丸

その上で、我々は「銀の弾丸」ではなく「鉛の弾丸」 を撃ち続けるしか無い。そもそも前提として、我々は鉛の弾丸しか持っていない。銀の弾丸に見えても、大体はピカピカに磨かれた鉛の弾丸でしかないのだ。

鉛の弾丸

例え、ありふれた鉛の弾丸であっても、問題の急所に当てることができればかなり良い効果が得られるだろう。だが、急所に弾丸を当てたとしても、その問題はまだ息をしている可能性がある。続け様に鉛の弾丸を撃ち込まなければ、問題は完全には倒れない。

それでも、我々はそうするしかないのである。地道で小さい改善の連続でしか、エンジニアリングの問題を倒すことはできないのだから。

まとめ

エンジニアリングの世界はビジネスとは違って「80%」を解決すれば終わりではなかったりする。少なくとも私の経験上はそうだ。

だからこそ、80%を解決したその先の、解決するべき「20%」にも焦点を当てたい。一撃で「100%」を解決できる銀の弾丸はない。地道に鉛の弾丸を撃ち込みながら、早め早めに問題を潰していくことが、複利の効果となってビジネスに素晴らしい成果を返してくるのである。

余談

もちろん、問題が完全に 0% になることはないだろう。よくよく虫眼鏡で見てみると、切り捨てられて 0% になったように見えていたものの陰で、0.5% の小さな芽が「次の 20%」になろうとしていることもある。

ここに対応するかどうかは正直、開発チーム次第だと考えている。0.5% を切り捨てるのは問題ない様に思えるし、それがもし仮に 20% になってから対応しても遅くはないかもしれない。いずれにしても巨大化した 80% を倒すよりはマシだろう。ビジネスのフェーズにおいては、0.5% にこだわるよりも新しい機能を追加する方が圧倒的にビジネスのためになるだろう。

そもそも 0.5% は、複利の効果をもってしても、次の 20% に成長するまでは、まだまだ時間がかかるはずだ。そして、ここまで読んでもらって気づいたかもしれないが、改善のサイクルは 1 度で終わりではない。永遠に続くのである。

data-migrate gemの使い方

はじめに

Ruby on Rails でのアプリケーション開発を行う際にrails db:migrateコマンドを実行して、RDB の schema 変更を行うことがあると思います。

これと同じように RDB 内に作成するデータそのものを migration 操作できる gem が存在します。

github.com

RDB 内でのマスターデータの操作には、手動で SQL を実行したり rake などを書いたりすることもあるでしょう。私が現在所属している開発チームでは、RDB 内のマスターデータの管理などにはこの data-migrate gem を利用しており、私もこの gem でのデータ操作に慣れてしまいました。

今回は自分への備忘録も兼ねて、この data-migrate gem の基本的な使い方を記載しておこうと思います。

と言っても、使い方は実は Rails オリジナルの db:migrate 系のコマンドのdbdataにするだけです。

Installation

Gemfile への追加は以下です。もちろん、Gemfile への追加後にbundle installを実行します。

# Gemfile

gem 'data_migrate'

# "Support Rails 6.1 through 8.0"
# "For Rails 6.0 support, please use gem version 9.1.x:"
# READMEに上記のように記載があるので、古いバージョンのRailsを使っている場合には、それに応じたgemのバージョンを指定しないといけない

gem 'data_migrate', '~> 9.1.0'

How to use

新しい migration を実行

新しい migration を実行する場合の手順は以下です。これは db:migrate 系と全く同じです。

  1. data_migrationファイルの生成
  2. data_migrateコマンドによる migration の実行

以下で実際に実行してみます。

# ちなみにschema変更の際には以下のコマンド
# $ rails g migration AddPartNumberToProducts

# 新しいdata migrationファイルを追加
$ rails g data_migration add_this_to_that
      create  db/data/20260124062455_add_this_to_that.rb

出力にあるように、新しい migration ファイルがdb/data以下に作成されています。 ファイルの中身は以下の通りです。

# db/data/20260124062455_add_this_to_that.rb

# frozen_string_literal: true

class AddThisToThat < ActiveRecord::Migration[7.2]
  def up
  end

  def down
    raise ActiveRecord::IrreversibleMigration
  end
end

migration ファイルに、操作したい内容を up と down に記述します。例えば、こんな感じです。

# frozen_string_literal: true

class AddThisToThat < ActiveRecord::Migration[7.2]
  def up
    Item.create!(id: 1, name: 'test')
  end

  def down
    Item.find(1).destroy!
  end
end

そして、db:migrate 系と同様にdata:migrateコマンドを実行します。

$ rails data:migrate
== 20260124062455 AddThisToThat: migrating ====================================
== 20260124062455 AddThisToThat: migrated (0.0546s) ===========================

これで RDB に新しいデータを追加することができました。

migration のステータス確認

これも$ rails db:migrate:statusとほとんど同じです。status に応じて up か down かが記載されているはずです。

$ rails data:migrate:status

database: db/development.sqlite3

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20260124062455  Add this to that

migration のバージョンを巻き戻す

migration を 1 バージョン分、巻き戻したい場合はこちら。

$ rails data:rollback
== 20260124062455 AddThisToThat: reverting ====================================
== 20260124062455 AddThisToThat: reverted (0.0303s) ===========================

特定のバージョンを巻き戻したい場合は以下のどちらかを実行します。

$ rails data:rollback VERSION=20260124062455
== 20260124062455 AddThisToThat: reverting ====================================
== 20260124062455 AddThisToThat: reverted (0.0137s) ===========================
$ rails data:migrate:down VERSION=20260124062455
== 20260124062455 AddThisToThat: reverting ====================================
== 20260124062455 AddThisToThat: reverted (0.0267s) ===========================

使い方がわからなくなった場合

ヘルプの確認は以下のコマンドから。

$ rails -T data
bin/rails data:abort_if_pending_migrations          # Raises an error if there are pending data migrations
....

よく使うコマンドのセット

# migrationの追加
$ rails g data_migration add_this_to_that

# migrationの実行
$ rails data:migrate

# migrationのステータス確認
$ rails data:migrate:status

# migrationの巻き戻し
# 前のバージョンへ巻き戻す
$ rails data:rollback

# 特定のバージョンを巻き戻す
$ rails data:rollback VERSION=20260124062455
$ rails data:migrate:down VERSION=20260124062455

まとめ

繰り返しですが、基本的に db:migrate 系コマンドのdbdataに置き換えるだけです。このことからも分かるように、できることも db:migrate 系と同様です。

Ruby on Railsのログを良い感じに構造化する

はじめに

Hubble Advent Calendar 2025の 2 日目の記事を少し書き直しています。

これまでの Rails で構造化ログを自動で吐き出させるには少し苦労していましたが、Rails 8 系ではログの構造化がしやすくなるようです(詳しくはおググりあれ!)が、今まではログを構造化するのに少し労力がかかりました。2 年前くらいまでは Hubble 社のログは特に構造化などはされていませんでしたが、Rails.logger.levelを Hash の引数と一緒に呼ぶだけで構造化ログが出力されると嬉しいなと思っていました。

# こんな感じでログが吐き出されると嬉しい
Rails.logger.info({ user_id: 1, org_id: 100 })
# => "{\"user_id\":1,\"org_id\":100}"

実際に試行錯誤しながら(ほぼ)理想の構造化ログを導入してみたので、今回はその実装の内部を紹介してみようと思います。

なぜログを「構造化」すると嬉しいのか?

今回は Ruby on Rails アプリから吐き出すログに焦点を当てますが、どんなログであっても構造化することには大きな意義があると考えています。なぜなら、Datadog といった監視ツールとの親和性が高いからです。親和性が高いということはどういうことなのでしょうか?

Datadog を使って、実際の画面を見ながら説明して行きます。

show.png

ポイントは赤枠で囲ってある「Fields & Attributes」部分です。この画像のように構造化ログを Datadog へ送信すると、良い感じに attributes として表示してくれます。

また、DataDog の場合(他の監視ツールでも概ね同様かと思います)は、この Attributes をキーにしてログを「フィルタリング」することができます。

index.png

赤枠で囲ってある箇所がログを探すためのプロンプトですが、@action:pdfと入力することにより、Rails の action でログを上手く「フィルタリング」できています。

つまり、この Attributes で user_id、controller、action や操作対象オブジェクトの id などを用いて「いつ、誰が、何に対して、どんな操作をした」といったログの捜索をより正確な表現で絞り込むことが可能であることを意味します。

他の監視ツールなどでも同様の操作ができるはずです。私の前職では GCP の Cloud Logging で同様に構造化ログ使用していました。(だったはず、、、、、)

え?それだけですか?

はい、それだけです。 ですが、このありがたみを知るために、同様の条件を構造化されていないログから検索してみると仮定してみてください。もしくは今、自身が所属されている開発チームのログが構造化されていない場合は日々の開発を思い起こしてください。

この場合、プロンプトにどのように入力しますか? 仮にuser_id = 100であると仮定しましょう。100 という数字を素直に打ち込めば、use_id = 100に関するログだけが素早く正確に出力されるでしょうか?恐らくそうではないはずです。user_id 100とちょっと工夫して検索したところで、user_id = 1001に関する情報などが出力されたりします。

本番に障害が起きた際にuser_id = 100のユーザーの操作を追いかけたい場合に、ほとんどがノイズだらけのログの中から関連するログのみを早く正確に取得することが本当にできますか?一刻も早く問題を収束させたい焦りと不正確でノイズだらけのログの中で?

確かにログを出力する際の規約を決めるというのは一つの手っ取り早い解決策です。 ただ、果たして開発者は必ずuser_id = 100と記述してくれますか?user_id=100と記述するのは NG ですか?

「検索」ではなく「フィルタリング」を

個人的な思想ですが 「検索」 を信用してはなりません。「検索」をするためには、要素を index したりなどの労力がかかる割にはやや信憑性を欠きます。 Google 検索はあなたの思い通りの検索結果を美しく正確に全て出力してくれますか?(もちろん、Google は偉大なプロダクトですよ)顧客から「どんな操作が何回実行された結果でこうなりました?」という質問に対して、検索しただけのログで果たして自信を持って答えられますか?

賢い我々は 「フィルタリング」 をしましょう。あらかじめ決まったフォーマットで監視ツールに送ることをコミットする代わりに、フィルタリングによって、より正確に全ての目当てのログを探し出すのです。

それに、ゴチャゴチャと雑多なログが出てくるよりも、json フォーマットで出力される方が美しい、要は美意識です。

じゃあ、Lograge 使うか

github.com

構造化ログ = Logrageという図式を Ruby on Rails 界隈では感じますが(私だけですか?)、Lograge では構造化対象になるのはリクエストログのみです。

qiita.com

ですが、我々はリクエストログ以外にも重要な処理の内部状態がどうなっていたのかをログで吐き出したいという欲求も持っています。しかも正確に絞り込みたい、それもできるだけラクして。

じゃあ、こんな感じにしてみるとどうでしょうか?

  • リクエストログ
    • Lograge
  • それ以外のログ
    • 別の仕組みで何とかする?

ただこれは少し冗長な感じがします。「それ以外のログ」が何とかできるのであれば、リクエストログも同じ仕組みを使えばいいだけです。できるだけ、色んなログが一括で構造化されるようになると嬉しいです。我々は KISS の原則を忘れてはならず、DRY にできるところは DRY にしましょう。

logger に求める要件

ここで一度、ログに対する要望を整理してみます。

  • リクエストログには何も意識しなくても必要なメタデータを搭載しておきたい
  • trace も意識したくない(trace についての参考: https://newrelic.com/jp/blog/how-to-relic/metrics-events-logs-and-traces
  • Rails.logger.level({ user_id: 100 }.to_json)は冗長なので、Rails.logger.level({ user_id: 100 })とかでいい感じに構造化ログが出てきて欲しい
  • 例外を rescue した際にRails.logger.error(e)とアッサリ記述されただけの箇所が多いのでだけで、そういう箇所では backtrace もいい感じにログ出力しておきたい
  • ただ別に無理に構造化しなくていい時もあるので、logger の引数をただの文字列だけで渡す怠惰な瞬間も残しておいてほしい(人間が読むための従来のようなログも搭載したい)

色々と調査した結果ではこれらの要望を叶えるためには、自前で実装をするしかないという結論に至りました。 そんな技術記事がないかなとインターネット上をガサガサ探すと良い感じの記事が出てきました。

探し出した解決策

インターネットをガサガサした結果、探し出した答えがこちらです。詳しくは上記の資料を確認してください。

kaigionrails.org

やりたいことは Ruby on Rails のオリジナルの logger を少し改造して、思った通りの構造化ログが何も意識しなくても出力されるようにしたい」 です。

そのヒントとして、上記の資料中では 「Lograge の基本戦略」 として以下のような記載があります。

  • Rails が出力する Request 関連のログを無効にする
  • 自前の LogSubscriber を attach してログ出力

この「Lograge の基本戦略」と同様のことをすれば、Lograge と同じように「ログを中継して思った通りのフォーマッターで出力」することができそうです。

このスライドには有り難いことに、実装の例も示していただいています。これらの情報を元に実装してみましょう。

実際の logger 実装の中身

では、具体的に logger 改造のコードを見ていきましょう。

基底コントローラーとして定義したApplicationControllerappend_info_to_payloadメソッドを用いることによって、リクエストログの出力時に良い感じに payload を上乗せしましょう。

append_info_to_payloadは、リクエストに情報を載せるために使用されるメソッドですね。

ちなみに、before_action@cur_item@cur_userなどに値を入れる処理を書くことがよくあるのですが、そういった値があれば勝手にログに含めるようにします。

# app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
    # ...
    def append_info_to_payload(payload)
        super

        # リクエストログに含めたいメタデータ系をセット
        payload[:referer] = request.referer
        payload[:params] = request.params

        # 誰が何に対してといった情報が取得できれば自動でログに載せる
        cur_user = @cur_user || @current_user || nil
        if cur_user.present? && cur_user.is_a?(User)
            payload[:cur_user_id] = cur_user.id
        end

        return unless @cur_item.present? && @cur_item.is_a?(Item)
        payload[:cur_item_id] = @cur_item.id
        # ...
    end
    # ...
end

また、ログをどのように出力するのかを定義するフォーマッターを実装します。Rails.logger.level(msg)msgが、どのクラスのインスタンスかによって処理を変えています。

# lib/json_log_formatter.rb

require "ddtrace"

class JsonLogFormatter < Logger::Formatter
  def call(severity, time, _prog_name, msg)
    correlation = Datadog::Tracing.correlation

    # Datadogでtraceさせるためにtrace_idを入れておく
    # 他の監視ツールでも同様のtraceの仕組みがあるはずなので組み込む
    log = {
      trace_id: correlation.trace_id,
      span_id: correlation.span_id,
      time: time.iso8601(6),
      level: severity
    }.compact

    # loggerの引数によって、msgの扱いを分岐させる
    #
    # String -> jsonログのmessageプロパティに引き渡す
    # Hash -> デフォルトで設定している項目に追加してjson化する
    # Exception -> messageとtraceをいい感じにセットする
    # それ以外 -> String化してmessageプロパティに引き渡す
    if msg.instance_of?(String)
      log[:message] = msg
    elsif msg.instance_of?(Hash)
      log.merge!(msg)
    elsif msg.instance_of?(Exception)
      log[:message] = msg.message
      log[:backtrace] = msg.backtrace
    else
      log[:message] = msg.to_s
    end

    # ログをjson化する
    "#{JSON.generate(log, ascii_only: false)}\n"
  end
end

そのフォーマッターを使うように設定してみましょう。同時に Ruby on Rails アプリ内の logger の基本的な設定も同時にここで行います。

# config/environments/application.rb

require "#{Dir.pwd}/lib/json_log_formatter"
# ...
# logの設定
config.logger = ActiveSupport::Logger.new(STDOUT)
config.logger.formatter = JsonLogFormatter.new
config.logger.level = 0
config.log_level = :info
# ...

次に LogSubscriber です。

ここではApplicationController#append_info_to_payloadで引き受けたプロパティを再度セットします。(もうちょっと上手いやり方がありそうな気がするので、知っていれば教えてください)

また、リクエストログに関しては、これまではどんなステータスであろうと、ずっとinfoレベルでログが出ていました。しかし、リクエストログのレベルをここで決めちゃって、今後はより正確なログレベルで出力されるようにしましょう。

# lib/custom_log_subscriber.rb

# frozen_string_literal: true

class CustomLogSubscriber < ActiveSupport::LogSubscriber
  def process_action(event)
    # ApplicationController#append_info_to_payloadの内容をここで拾う
    log_message = {
      method: event.payload[:method],
      db: event.payload.key?(:db_runtime) ? event.payload[:db_runtime].to_f.round(2) : nil,
      # ...
      user_id: event.payload[:cur_user_id],
      org_id: event.payload[:cur_org_id],
      item_id: event.payload[:cur_item_id],
    }.compact

    # リクエストログに関してはここでlevelを決めてしまう
    level = case event.payload[:status].to_i
            when 500..599
              Logger::ERROR
            when 400..499
              Logger::WARN
            when 100..399
              Logger::INFO
            else
              logger.level
            end

    logger.add(level, log_message)
  end
end

CustomLogSubscriber.attach_to :action_controller

次に独自 logger を定義します。これは「lograge の次を考える」の資料でも出てきたことを、そのまま記述しています。

# lib/custom_logger.rb

class CustomLogger
  def initialize(app)
    @app = app
  end

  def call(env)
    @app.call(env)
  ensure
    ActiveSupport::LogSubscriber.flush_all!
  end
end

controller の logger を先ほどの独自 logger に挿げ替えてあげましょう。

# config/initializers/log_settings.rb

require "#{Dir.pwd}/lib/custom_logger"
require "#{Dir.pwd}/lib/custom_log_subscriber"
require "#{Dir.pwd}/lib/json_log_formatter"
require "action_controller/log_subscriber"

ActionController::LogSubscriber.detach_from :action_controller
Rails.application.middleware.swap(Rails::Rack::Logger, CustomLogger)

これで実装は完了です!

ドキュメントの記載

最後に logger の使い方をどこかに書き記しておきましょう。せっかく、良い感じに logger を改造したのに、使われないのでは悲しいので。

私は以下のように Notion に記載をしました。

screencapture-notion-so-hubbleteam-hubble-api-logger-32d1e54d3a4e45ab9809e110c2008bcd-2025-11-23-18_17_33.png

まとめ

現代のシステム開発においては Rails アプリケーションに限らず、各所から出てくるログは構造化しておくとより良いと考えています。人間が読むためのログもその中に入れられますし、まさに機械と人間にとって win-win と言えるかと思います。

ただ、Rails 8 系ではデフォルトでログを構造化できると聞いたので、この記事はすぐに不要になるかもしれませんが、知見を共有すること自体は悪いことではないと思うので悪しからず。詳しくはこちらから。

railsguides.jp

お前には関係ない

はじめに

※決して特定の誰かの話ではなく今までの自分の人生で思い続けたことです。

「あなたのためを思って…」とか「良かれと思って…」とかいう言葉をたまに聞きますが、私はこの類の言葉が大嫌いです。なぜなら、自分勝手で恩着せがましいアドバイスをするためのエクスキューズに使われがちだと感じるからです。

確かに素敵なアドバイスは、受け取った人を幸せにするかもしれません。そんなアドバイスを人が受け取った時は、きっと感謝の言葉が自然と出てくるでしょう。

一方で、「お前のためを思って…」みたいな言葉は、的を射た指摘よりも理不尽な説教などの最中によく聞くのではないでしょうか。

聞いてもいないことで勝手にアドバイスしてくる人間も世の中にはいます。彼らも決まって言います、「あなたのためを思って!」と。

私の人生とあなたの人生

まず「私の人生は私の人生、あなたの人生はあなたの人生」です。他人の人生にいらないアドバイスをする前に、まずはあなた自身の人生に集中してみてください。

自分の人生に集中する

SNS上で芸能人のアカウントやポストに要らない誹謗中傷をしている人がいます。確かに彼らは不倫をしたり、覚醒剤をやったり、番組内でヒール役をすることがあります。

「批判されて当然だ!」と思う気持ちももちろん分かります。でも、それはあなたの人生には関係ありません。私は著名人が誹謗中傷に苦しんだ挙句、自死を選んだことを忘れません。彼らの行いがどのようにあなたに映ったとしてもそれは当事者内での話であってあなたの話ではありません

www.chunichi.co.jp

note.com

あなたはあなたの人生の中で起こることに関心を持つべきです。

 

- いずれ海外留学して現地でたくさん友達を作りたい

- 起業して世界を変えるプロダクトを手がけたい

良いですね、素敵な関心事だと思います。

 

あなたは「強いて言うなら『近所にできた新しいカフェに行ってみたい』とか『新発売されたゲームで遊びたい』とかかな?そんな高尚なものは自分にはない」と言いますが、それらも良いじゃないですか。別に、全ての人間に高尚な夢を持てと言ってるわけではないです。

きちんと境界線を引く

「自分の人生」と「他人の人生」にきちんと線を引きましょう。

「嫌われる勇気」というベストセラーの本にも同様のことが書いてあり、「課題の分離」という題目で出てきます。

www.diamond.co.jp

繰り返しになりますが、あなたはあなたの人生に集中してください。

私はそもそも自分の人生だけで手いっぱいなので、私の人生と並行して他人の人生に首をつっこむ余裕はありません。他人の人生に無駄な介入をするタイプはよっぽど器用か、その人の人生がつまらないかの二択だと私は思っています。

私はあなたの人生には介入しません。なので、私の人生にも介入しないでください。

もしも…

あなたがリオネル・メッシなら

ja.wikipedia.org

仮にあなたがリオネル・メッシであって、私がプロサッカー選手を目指している状況なら、あなたの自分勝手なアドバイスは大いに聞く価値があるでしょう。サッカー界を席巻し、バロンドールを8回獲得している正真正銘の成功者です。その成功哲学を聞かせてもらえるのであれば、お金を払ってでも聞きたいです。その一方で、現実のあなたは一体何者ですか?

他人の人生に対してドヤ顔でモノを言ってくるあなたの人生はそんなにも「成功」しているのでしょうか?確かに「成功」と漠然に言っても定義は人それぞれですし、「『成功』とかそんな物差しで測っていないよ」という人もいるでしょうが。

あなたが配偶者なら

これはだいぶ話が変わってきます。なぜなら、私の人生がもう私「だけ」の人生ではなく、私の決断は配偶者のあなたの人生にも少なからず影響を及ぼすからです

私の決断は地球上に存在するほとんどの人には影響を及ぼしません。ですが、私の決断とその結果に対して、一緒に責任を負ったりする人たちがいたりします。その一例として配偶者を挙げました。責任範囲が被っているのであれば、その人はあなたの人生に介入する権利を当然持っています

あなたが私の配偶者なら勝手に私の人生に首を突っ込んで、アドバイスなり介入なりをするべきです。

それって責任取れますか?

「人生の責任」の話になったので、ここから話を続けましょう。

あなたが他人の転職に関する話を聞いていると仮定してみます。あなたはその人の転職活動につい口を挟みたくなってしまい、アドバイスをしました。あなたのアドバイスを素直に聞いた結果、その人は転職を強く希望していた会社の選考に落ちてしまいました。

あなたはこの責任を取れますか?少なくとも私には取れません。

確かにその人にも「そのアドバイスを受け入れた」という選択による責任はありますが、あなたにも少なからず責任はあると思います。

仮定の話として転職の話をしましたが、他にも色々なシチュエーションがあるでしょう。

基本的には他人の人生に対して責任を取れません。あなたがその人の納得のいく補填をできる覚悟があるなら、それでも良いでしょう。

じゃあ、お前は人から助けてもらわなくても良いってこと?

それでも他人の人生に興味津々のあなたはこんなことを言い出すかもしれません。

そんなことは一言も言っていません。あなたの拡大解釈です。「聞いてもいない自分勝手」なアドバイスが不要なのです。

ヘルプの要求

私の人生で困難に直面した際にはできる限り私自身の力で乗り越えようとしますが、あまりにも手に負えないと思ったら適切だと思える人にヘルプを要求します。

そのような状況になったら、できる限りで私を助けてください。これは当然、逆もまた然りです。私のヘルプが必要であればヘルプを要求してください。私のアドバイスを必要だと思うならアドバイスを要求してください。私のできる限りであなたを助けようとします。

自力で乗り越える

これは私の考え方ですが、そもそも人は自力である程度のことを何とかする賢さや力を持っています。名付けるならば「性賢説」であり、「人は生まれながらに賢い」という意味です。

小さい子どもが靴下を履こうと悪戦苦闘している間に大人が介入をしてしまうと、子どもが自分で課題を解決する瞬間を奪うという話を聞いたことがあります。これに少し近しい気がします。基本的には人間は自分で何かを乗り越えられますし、そのような成功体験を積んでいくべきです。

逆に他人に立ちはだかる問題にいちいち介入して解決してあげようとすることは、巡り巡ってその人のためにはならないはずです。困難に直面した際に自分で解決する術を知らない、もしくは他人が介入してきてくれると信じてただ待っている、そんな人間をあなたは育てるつもりですか?

ヘルプを求められたら、その時は助けてあげましょう。でも、自分でやるって言っている内は放っておいても良いじゃないですか。

それに、人間が自分の力で何かを乗り越える能力を持っていなければ、多分、人間はここまで地球上に溢れておらず、もっとバタバタと人が倒れているはずです。

ちなみに「自力で困難を乗り越える能力」という意味の言葉も存在するようです。

bizfreak.co.jp

虐待されている赤ん坊はヘルプを要求できるか

あなたは偶然、虐待されているとある赤ん坊の存在を知ったとしましょう。この場合、言葉もまだ話せない赤ん坊があなたに向かって「私は虐待されています。助けてください」と毅然とヘルプを要求することはないでしょう。

この場合はヘルプを求められていないので助けなくて良いのでしょうか?いえ、そんなはずはありません。

これは助けましょう。児童相談所に駆け込むなり、警察に通報するなり、里親を探すなり、自分が親代わりになるなりしましょう。「暴力を受ける人生は決して幸福ではない」。そう決めてかかって介入する判断は正しいと私も思います。

でも、あれ?今、あなたは「そこまでするのは面倒だ…」って言いました?

人の人生に介入するのが好きな人は介入しなくて良い人生にばかりに介入し、本当に介入した方が良い人生には介入しようとしません。なぜなら、本当に介入するべき人生は大体厄介だからです。

確かにこれは少し極端な例であり、いい年こいた大人に対して得意げな顔で「アドバイス」のような何かを講釈を垂れるのとは次元の違う話なので、最早ここで語られるべき次元の話ではないとも思いますが。

聞いてもいない人生のアドバイスをしてくる人は

可哀想なお前に対して

私の経験上、求めてもいないアドバイスをしてくるあなたは、他人のことを下に見ている傾向があるように思えます。「自分の人生の方が優れている」とか「自分の方が色んな世界を経験してきた」とか「自分の方が~を乗り越えてきた」みたいな自己承認欲求とともに話しかけてきます。「自分の方がお前よりも素晴らしい人生を生きているので、可哀想なお前に対してありがたいアドバイスをしてあげる」というスタンスですね。

「これを知っていた方が幸せに生きられる」

あなたのアドバイスが不可解な憐れみの心からではなく「このことを知っていたらもっと楽に人生を生きていけるはず」というあなたの親切心からの発言だと仮定しましょう。ですが、それはあなたの物差しであり、他人の幸福をあなたの物差しで測ってはいけません。この思考も、どこかでその人を見下しているように私には思えてしまいます。

「自分勝手なアドバイス」なんかよりも

「今やれよ」論

私には人生の中でやってみたいことがいくつかあります。それを色んな人に話した際に「何で今からやらないの?」みたいな現代の自己啓発書によく出てくるような「今やれよ」論を偉そうに言ってくる人がほとんどでした。

ですが、やりたいことには準備期間が必要であるものもあり、そういったものは今すぐに実行することが難しいです。私は「今やれよ」論は「やってみたい」と口では言いながら本当に何もしない人への叱咤激励のようなものであり、きちんと準備しながら時を待っている人に使う言葉ではないと思っています。

ふとした一言に

私の経験上、そんな数多のお節介なアドバイスよりも、会話の途中にポロリとあなたの口から漏れる一言の方が、より私の人生のためになったりします。

かつて1人だけ「やりたいことにはその人のベストタイミングがあるからね。自分は逆にやりたいことを後先考えずにパッとやっちゃったことを後悔している。もう少し待てば良かった。」と懺悔の念をこぼした人がいました。冷静でポロッと出てきたアドバイスでも何でもないただの後悔の言葉が、大して役にも立たない数多のアドバイスの中で強烈に私の印象に残っています。大体の人間は「こうした方が良い」と経験したこともないことに鼻息荒くアドバイスしていって満足げな顔で帰っていきます。

肯定するだけで良いじゃないですか

私は人のやりたいことは必ず肯定するようにしています。「でもそれって〜でしょう?」とついつい言ってしまうこともありますが、自分で意識してできるだけ最終的には肯定するようにしています。だって、その人のやりたいことは私とは無関係です。やりたいことがある?それって、ただただ良いことじゃないですか!法に触れたりしない限りは。

私はただあなたとくだらない話をしたい

私はただあなたとくだらない話をしたい

こんなことを書くとあなたは「じゃあ、何も話すことがない」と言い出しそうな気がします。

ですが、私は人生のアドバイスをあなたから受けたいのではなく、あなたとただただくだらない話をしたいだけなのです。

あなたと飲みに行こうかなと思うのは、あなたの人生の武勇伝や素晴らしい知識によるありがたいアドバイスを得るためではなく、最近見たドラマや面白かった話、何回擦ったか分からない鉄板ネタでケラケラ笑いたいだけなのです。

私は飲みの場に人生相談をしにいくことはあまりありません。確かに私は人生相談をすることもありますが、それは私が適任だと思う人にお願いしています。だけど、あなたも私のことを心配してくれてありがとう。

私は捻くれた底意地の悪い人間ですか?

残念ながら私はそうは思ってはいません。むしろ、真っ当な人間の感覚だと思っています。

他人の人生を生きるのではなく、自分自身の目標や夢に向かって尽力する。他人からヘルプを求められれば、もちろんできる限りで助けます。その一方で、介入する必要のない他人の人生には、無駄に介入することはしません。

私も今までの人生の中で色々なことを言われてきましたが、私だって「結婚したいんだったらその性格直した方がいいんじゃない?」とか「やりたいことあるって言ってる割にはお前は何かやってんの?」とか思ってはいます。でも、それは私の人生ではありません。各々がそれぞれの人生に注力し続けていくのが、健全な社会だと私は信じています。

ヘルプを要求する「スキル」

適切なタイミングで人にヘルプ要求を出せる人は優秀だという言説をたまに聞きます。

私もこれには同意です。我々が行うべきは「他人の人生への無駄な介入」ではなくて、「ヘルプ要求を出せるように人に教育すること」だと思っています

これは仕事にも通じると思います。納期のギリギリまでヘルプ要求を出さない人を見かけることがあるかもしれません。その人のタスクの状況を覗いてみると「なんじゃこりゃ、もう手遅れやないかい…」みたいなことを思った経験をしたことがあるかもしれません。

我々は結婚でもしない場合、そんな人といつも一緒に居ることはありません。そうであるならば、その人の課題に介入するよりも、適切に「ヘルプを出すスキル」を覚えさせる方がよっぽどその人のためになるでしょう。そのスキルを身につければ、たとえ、あなたがいなくなったとしても、その人のその後の人生において周囲の人間にヘルプを出し続けることで、その人は人生の困難をきっと乗り越えていけるようになるはずです。

最後に

私の考えについてツラツラと述べましたが、物事の全てはグレースケールで語られるべきであり、結局は程度の問題に収束します。

とどのつまり「他人の人生の介入にはちょっと気をつけましょう」ということです。

それでもまだ「お前のためを思って…」とか言ってくるあなたへ

私のことを「思ってくれる」行為は、基本的にはお金でしかないと思っています。私のためを思うなら、あなたの口座の有り金すべてを私の口座に送金してください。手数料くらいは私の方で負担します。

実は今、事情があって、めちゃくちゃお金に困っています。今こそ本当に「私のこと」を思うときです。お金ください。口座情報をお教えします。

Kaigi on Rails 2025 初セッション記

見出し画像

こんにちは、株式会社 Hubbleで Backend Engineer をしているうるしです。
Kaigi on Rails 2025において人生で初めて、大きいテックカンファレンスでのセッションをしてきました。

kaigionrails.org

今回は、自身にとっての初セッション体験記を記したいと思います。前提、相当ビビりながら CFP に応募し、自身の発表のレベル感に悩みながら本番までを過ごしました。

同じように初セッションを考えている方 && CFP に応募するかを悩んでいた数ヶ月前の自分へ届くと良いなと思います。

テックカンファレンスで発表をする意義

まず「そもそもテックカンファレンスで発表をする意義」について整理しておきたいのですが、もちろん、これは人によって異なると思います。ちなみに、私は以下の 4 つでした。

  1. 自身のキャリアに箔がつく
  2. 会社から報奨金が出る
  3. 会社の広報活動に対する貢献
  4. 非同期 job の謎エラーにタイムリーに悩んでいる開発チームへの貢献

つまり、自分、会社、聴衆にとっての「三方良し」ですね。
あとなんかカッコいいじゃないですか、登壇って。

何かしら自分の中でセッションをする意義があると、心は折れにくいと思います。まぁ、何事もそうですが。


それでは、本編のセッション体験記を時系列で見ていきましょう。

1 年前の Kaigi on Rails 2024

画像

スポンサーのボード前にて

去年のKaigi on Rails 2024で初めて、このテックカンファレンスに参加しました。最初はセッションの聴き方(自分で聴きたいセッションを選んで、ホールを移動しながら聴くこと)もよく分からなかったのですが、それまでに知らなかったことや、面白いセッションをたくさん聴くことができました。素直にテックカンファレンスっていいなと思いました。

色んな方達のセッションを聞いてて自然と「自分も発表してみたいな」と思ったので、翌年には自分もプロポーザルを出してみようと心に決めていました。

CFP への応募まで

とはいえ、いつから Kaigi on Rails の CFP の募集が始まるのかを知らなかったので、公式の X(@kaigionrails)をフォローしながら待っていました。

すると、ある日その X のアカウントで募集開始のお知らせが、私の TL に流れてきました。

画像

会社の Slack の #kaigi -on-rails2025 チャンネルにて

ですが、この時「セッション内容を考え始めている自分」「セッションすることにビビっている自分」の葛藤が心の中で起こっていました。

「本当に自分のプロポーザルが選ばれたら、準備が大変そうだな、、、」
「周りはめちゃくちゃレベルの高いセッションをするんだろうな、、、」
「本番が近づくにつれて、めちゃくちゃ緊張しそう、、、」

「まぁ、頑張って書いても審査を通るかどうかは分からないし、なるようになるんじゃないか」という説明の難しい心持ちのまま、各種 AI に相談しながら、最終的には 2 つのプロポーザルを提出することにしました。

画像

Asana の AI への質問

画像

ChatGPT への質問

過去のタスクなどから、「アレがいいかな?コレがいいかな?」みたいに思ったことを、フワッと AI に投げてみて絞り込みながら形にしていくようなイメージで、AI と一緒にセッション内容を決めていきました。やっぱり、AI はこういう時に便利ですよね。

余談ですが、当初は 1 つだけ出そうと思っていたのですが、同じく今回発表していた弊社の TechLead が「念の為 15min と 30min で 2 つ出すわ」と言っていたので、自分もそうしようと思い 2 つ提出することにしました。

その TechLead のセッションはこちら

kaigionrails.org

正直、4~5 ヶ月前のことなので、はっきりくっきり覚えているわけではないのですが、自分はビビリな性格なので、本当に出すのかをギリギリまで悩んでいた気がします。

ただ、いざ出そうと思った時に、時間切れにならないように「一応提出する準備だけしておこう、AI に聞くだけだから」みたいなメンタリティでやっていました。最後は「もうとりあえず出してしまえ」という感じで提出しました。

ただ、この段階で悩んでも正直どうしようもない気がします。なぜなら、提出したとしてもそれらのプロポーザルが全滅すれば、この悩みは時間の無駄だったことになります。

最終的に提出したのは以下の 2 つです。

  • 非同期 job を transaction 内で呼ぶなよ!絶対に呼ぶなよ!(15 分)
  • 2 つの Ruby on Rails アプリを 1 つに統合してみた話(30 分)

この時点では、通過するとしたら「2 つの Ruby on Rails アプリを 1 つに統合してみた話」の方だと思っていました。なぜなら、自分が調べた範囲内では、過去に同様のセッションは無さそうだったからです。大体は「統合」ではなく「分離」の話をすると思います。

結果発表

と言うわけで、CFP へ提出してから 2~3 週間ほど待ちました。
ある日、例の TechLead が「提出したプロポーザルのうちの 1 つが通った」と Slack にポストしていたので、私も自分のメールを見てみることにしました。

「どうせなら、もうどっちかは通っていてくれ、、、!」メール、パカッ!

画像

ファ!?

画像

おお、、、!?

タイトルだけ見た感じだと、片方は通っていそうです!

「どっちだ?まぁ多分、統合の方だろうな」

画像

え?

結果は以下の通りでした

  • ✅ 非同期 job を transaction 内で呼ぶなよ!絶対に呼ぶなよ!(15 分)
  • ❌ 2 つの Ruby on Rails アプリを 1 つに統合してみた話(30 分)

「え?そっちが通るの?」が正直な反応でした。嬉しいような残念なような複雑な気持ちでした。

ですが、通ったものは通りました。
さて、どうするか。

結果のメール内に記載があったのですが、引き受ける場合には CFP の提出ページから accept ボタンを押さないといけないそう。

「ここでボタンを押さなければ、まだ引き下がれる、、、」

この後に及んでまだそんな心持ちでしたが、「ダサいセッションになったとて、セッションはセッションだ、、、」と思って accept を押しました。数日は押すか押さないかで悩んだ気がします。

【余談】 結果の考察

  • 非同期 job を transaction 内で呼ぶなよ!絶対に呼ぶなよ!(15 分)

    • ✅ accepted
  • 2 つの Ruby on Rails アプリを 1 つに統合してみた話(30 分)

    • ❌ not accepted

私は結果を知っただけで十分だったのですが、例の TechLead が「面白そうな記事を見つけた」と言い、私のプロポーザルの結果についても考察してきました。

※注意
以下で引用させていただいている記事(【炬燵編】Kaigi on Rails のプロポーザルを評価するときに考えていること、求めていること)につきましては、「炬燵さん独自のプロポーザル評価基準」であり、「Kaigi on Rails 運営による公式のプロポーザル採択基準」ではありません。記事における内容を満たせば、そのプロポーザルが必ず採択されることを保証するものではありません。こちらの点だけご留意いただいた上で、続きを読んでいただけますと幸いです。

非同期 job を transaction 内で呼ぶなよ!絶対に呼ぶなよ!(15 分)

彼曰く「多分これが理由で採択されたのでは?」とのこと

是非初学者に聞かせなくてはならないと思わされる

【炬燵編】Kaigi on Rails のプロポーザルを評価するときに考えていること、求めていること

どのくらいの方がこの事象について知っているのかを私は知らないですが、恐らくこのセッションの内容は初学者向けだと判断されたのでは?ということだそうです。

2 つの Ruby on Rails アプリを 1 つに統合してみた話(30 分)

こちらは以下の理由で落とされたようです。

発表内容について、途中であると明記されている

【炬燵編】Kaigi on Rails のプロポーザルを評価するときに考えていること、求めていること

これは明白でした。なぜなら「作業途中ですが発表までには頑張って終わらせます」と明記していたからです。「作業はすでに終わっていて、発表資料も作れますよ」みたいな雰囲気で書いても良かったのですが、ウソはいかんかなと、ウソは。

今となっては、このプロポーザルは通らなくて良かったと言えます。なぜなら、お察しの通り、この作業は今現在も全然終わっていません。

やはり、作業途中のものを提出するのはリスキーすぎます。進捗にもよりますが、「この作業は一旦置いておいて、別のこっちの作業をやらないと」みたいなことは十分に起こりえますよね。

発表準備

7 月末に accept ボタンを押したので、発表本番までは残り 2 ヶ月ほど。
しかし、私はこの時点で下記のようなイベントが控えていました。

- 8 月末に 1 泊 3 日の韓国旅行
- 9 月頭に 1 週間ほどの北米旅行
- 北米旅行の次の次の日には結婚式への出席

「舐めていたら絶対に間に合わない」と思っていたので、accept ボタンを押してからすぐに発表スライドに取り掛かりました。正直、この判断は正しかったです。結局、発表の前夜まで、ずっと何かしらの修正を行っていたからです。

そして、8 月の中旬には大体のスライドができていました。

ただ、「タスクの最初の 80%は全体の 20%の時間で終わるが、残りの 20%を仕上げるのに 80%の時間がかかる」みたいなことが一般的に言われていると思いますが、本当にその通りで、ここからが長かったですし同時にプレッシャーとも闘っていました。

「本当にこんなセッションでいいのかな?」
「運営の方が、どこかのタイミングで『発表準備はどうですか?』とか進捗確認してくれるよな?そこでダメ出しされたらどうしよう、、、」(ちなみに進捗確認などは特にはありませんでした)

でも、「自分のプロポーザルは正当に選ばれた訳だし、他の人間と比べていてはどんどん不安になるだけ」だと、気持ちを切り替えて準備をしていました。

旅行やら仕事やらで、なんやかんや本番の日はどんどん近づいてきます。

おー、こわ

画像

Figma Slides でのスライド

Speakers & Schedule の発表

正直、本番までの時間の中で、この瞬間が一番テンションが上がりました。自分の名前がまた一つインターネットに刻まれるのです。しかも、けっこう色んな人に見られるだろうなとも思っていました。

同時に Schedule を見て
「発表は 2 日目か、、、1 日目に発表を終えて 2 日目はプレッシャーから解放された状態で他のセッションを楽しみたかったな」
とも思ってました。

前日の発表練習

そうこうしているうちに、2025/9/25、つまり Kaigi on Rails の前日になりました。この日は例の TechLead を誘って、会社の会議室で発表練習を行いました。

画像

発表練習の様子 taken by @naxano__

発表練習はとても大切です。なぜなら、それなりの入場料を参加者の方々からいただいた上で開催しているカンファレンスの発表において、セッションの時間が守れていなかったりすることは如何なものかと思っているからです。

私は、会社でも家でも練習しました。ちなみに、LT での登壇も 2 回ほど経験しているのですが、どちらも時間が守れていなかったので、今回は特に練習しました。また、発表練習は心の中で読むとかではなく声に出した上で、できる限り本番の条件に近づけた方が良いです。

体感ですが、15 分の発表だと練習時点では14 分かそれに満たないくらいで終えられると良いと思います。
本番は意識してゆっくり話すべきである && 緊張でいつも通りの動作でもモタつく可能性があることを考慮すると、練習時には余裕があるくらいが良いかなと思っています。

さぁ、明日から Kaigi on Rails 2025 の開幕です。

Kaigi on Rails 2025 開幕

画像

Speaker ネームプレート

はい、今日から Kaigi on Rails 2025 開幕です。

この日は Hubble ブースの運営や CTO & TechLead のセッションを聴いたり、他の気になったセッションを聴きに行ったりしていました。

「とりあえず初日の発表を聞いて、ライバル(ライバルではなく志を同じくした Speaker の方々)たちのレベル感を確かめるか、、、」と思いながら色んなセッションを聴いていたのですが、その結果

「やっぱり他の Speaker はすげぇ、、」
「オレの発表なんて、とっくにみんな知ってて鼻で笑われるのではなかろうか、、、」

と思っていました。

ですが、ここで「やっぱり発表やめた!」とかはできません。

自分だって発表資料には少なからず時間を割いた訳ですし、ここまで来れば何はどうあれ発表するしかありません。

初日が終わって帰宅してから、スライドの内容を AI に再確認したり、GitHubRails のレポで source や issue を再確認しました。そこで、
「ちょっとこの言い回しだと語弊があるかも?」
「ここはやっぱり事実とは異なるかも?」
となった箇所がいくつかあったので、その部分を修正しました。

画像

ブース担当時
まだ運用手順などを読んでいなかった、、、すみませんでした、、、

ちなみに

初日のセッションの中では、MOROHASHI さん(@moro)の「dynamic!」が一番印象に残りました。

「ソフトウェアは継続して改善していくべきもの」というメッセージを私は受け取ったのですが、このメッセージにめちゃくちゃ同感です。「めちゃくちゃ」です。私にとってはそういう意味での「dynamic!」でした。

speakerdeck.com

開発されたサービスなどは基本的には何年も運用されることになる(はず)です。そうなると、リリースした機能のソースコードは歳を取っていき、その時に整えたインフラは時代遅れになっていきます。機能リリース時に急いで開発したのなら尚更です。

エンジニアの仕事はただの機能開発ではありません。サービスなどを通じたビジネスへの寄与であり、そのサービスを成長させるために存在しています。そうであるならば、古くなったり時代に見合わなくなった部分を見直し、改善し続けることは長期間のサービス運用のためには必然です。

逆に考えると短期間の運用しか考えていない(本当に??)のであれば、継続的な改善などは不要だと思います。そんなことは気にせずに、ガンガン機能を搭載していくべきです。

このことを理解している優秀なビジネスパーソンを、私はあまり見たことがありません。ですが、これは逆もまた然りです。ビジネスもエンジニアリングもできる人間というのは、私が見てきた限りではとてもレアな存在です。なので、こういったことはエンジニアが啓蒙をするしかないのです。そして、我々エンジニアが最もこのことを理解している必要があります。

Kaigi on Rails 2025 2 日目 ~発表の日~

画像

セッションの様子
会社の方に撮っていただいていました

私のセッションは Hall Red で 14:10 からでした。

午前中は他のセッションを聞いていたのですが、非同期 job 系のセッションだけは聞かないようにしていました。
そういったセッションを聞くことで、発表直前に「あれ?もしかして自分の内容は間違っているかも?」ってなったら怖いじゃないですか。
「そうなるくらいだったら、知らないまま堂々と発表しちゃった方が良いな」と思っていたからです。

ランチ休憩が終わる直前に接続確認を行いました。接続確認は入念に行なったつもりです。本番で何か上手くいかなかったら、焦りまくると思ったので。

発表の時間

ついに自分の発表の順番が回ってきました!

登壇直前にセッションの始め方と終わり方のレクチャーを受けました。でも、その時は緊張で話があまり入ってきませんでした。でも、覚えていた情報の断片から、指示通りに発表できたのではないかなと思います。

発表中はできるだけゆっくり話すこと && 目線を時々、聴衆に向けることを意識していました。メンタル的にはそこまで緊張しなかったのですが、震えていた手を壇につきながら話していたので、壇上に置いていたペットボトルが揺れていました。

発表時間については、原稿にある程度のベンチマークを記載していて、それに沿って発表できたので、ちょうど良かったのではないかなと思います。スマホのストップウォッチでは 14:47 くらいだったような。

画像

こんな感じで原稿下部にベンチマークを設けていた

それと、発表の序盤に、最前列のスタッフの方の「マウスを下に動かして」というカンペが見えた時に、何のことか分からなくて少し焦りました。
「画面内にマウスカーソルが表示されちゃっているので、見栄え的にマウスカーソルを動かして画面外に出してくれ」的な意味合いだったようです。途中で理解した自分、ブラボー。

そんなこんなで無事発表を終えたのですが、その後も手は震えていました。なので、息抜きに会社のメンバーと近くのスタバへコーヒーを買いに行きました。CTO、いつもありがとうございます。

発表を終えて

社内の方々から「発表良かったよ」と声をかけてもらえたり、X で発表資料を Speaker Deck にアップロードした報告のポストに「いいね」を多くもらえたりと反響は一定あった気がします。ありがとうございます。

これで職務経歴書に堂々と「テックカンファレンスでの登壇歴あり」と書くことができます。この事実を使い倒そうと企んでいます。

このセッション体験記で伝えたいこと

「CFP に応募しましょう!」ということです。

以下、いくつかのパートに分けて記述していきます。

セッションレベルのさらなる向上

運営の方も言っていたような気がしますが、カンファレンスは公募セッションによって成り立っています。色んなプロポーザルが提出されれば、自然とセッションのレベルもより向上していくはずです(今回の Kaigi on Rails が低かったとかではないです)。

ちょうど、地球上の無数の生物たちが、その種族ごとにユニークかつロジカルな生存戦略を取ってきた中で、環境に適応した素晴らしい戦略を携えた種族だけが連綿とその DNA を後世まで残していき、それ以外の種が淘汰されていったように。


世界に対して何かを働きかける

「自分から世界に対して何かを働きかける」と言うのは、勇敢で素晴らしいことだと私は思っています。例えば、歴史にその名を残してきた偉人たちはただ単にボケッと生きていただけではないはずです。彼らは自分の持っているもので世界に何か(信念、知識、成果 etc.)を働きかけてきたのです。例外もありますが。


発表のレベルについて

自分と同じように以下のようなことを考えている方もいるのではないかと思っています。

「こんな発表意味ないよな、、、みんな知ってるよな、、、」
「レベル低いかな、他の人はレベル高かったよな」
「自分のレベルだと、どうせプロポーザル通らないでしょ」

まず、あなたの発表のレベルは決して低くはありません。

正々堂々と CFP へ応募した上でセッションの権利を勝ち取ったのであれば、その時点でレベルはしっかりと認められているので悩む必要はありません。そもそも、レベル感の判断は我々の知るところではなく、運営の関心事です。もちろん、発表の準備には全力を尽くさねばならないですが。

それと、プロポーザルは基本的には通らないものだと思うので、通らないことでへこたれる必要は全くないと思います。今回の Kaigi on Rails 2025 では、プロポーザルの通過率は 34/179 なので、単純に考えると約 19%です。へこたれるのでなくプロポーザルを磨き込みましょう。

余談ですが、私はシェアハウスに住んでいます。
そこには、とある強々エンジニアが住んでいます。彼のはてなブログには読者が 1000 人弱、X でのフォロワーも 1 万人を越えており、色んなカンファレンスで登壇しているようです。ただ、そんな彼の去年のプロポーザルの戦績は 0/3 だったようです。へこたれる必要はありません。


間違ったことを発表してしまうことへのプレッシャー

自分の発表が間違っていることを発表していたら、どうしようと思う人は多いと思います。私もそんなプレッシャーと闘いながら、発表前日までスライドを修正していました。

しかし、個人的は少しくらい間違っていることを発表しても良い気がします。

だって考えてもみてください。
人類の歴史上でこれまで何回のカンファレンスが行われて何人の人間が登壇したと思っているのですか?
その中で果たして全員が全員、100%正しいことを言ってきたと思っているのですか?
そんなはずはありません。
多分、中にはめちゃくちゃ間違っていることを言ってた人もいるはずです。

だからといって、もちろん堂々とウソをついていいわけではありません。
準備は準備です。しっかり裏を取りましょう。つまり、メンタルの話です。


「書物をかくということは恥をかくということである。」

今回のセッションの発表準備中に、X で流れてきたこのポストがめちゃくちゃ自分に刺さりました。

砂川重信「書物をかくということは恥をかくということである。それは、その時点における著者の理解のレベルを天下に公表することだからである」

とある高専卒業生(@subarusatosi)さんのポスト より

セッションも同じだと思います。その時点で「自分の知ってることを発表する」のです。それで良いと思います。誰だって何もかもを知っていて、何もかも正しいことを言えるわけではないのです。何か間違っていることを言っていれば、誰かが「それは間違ってるよ」って言ってくれるはずです。

逆に言うと、我々も誰かが間違ったことを言っていたり、より良い方法を知っていれば、それを優しく伝えてあげればいいのです。

誰も何も発表しない世界では、知識や知恵の共有がないはずなので、当然、人類は進歩していきません。知っていることを共有し、間違っていることを訂正してきたからこそ、今日の我々があるのです。

また、誰も知らないことを無理に発表しようとしなくても良い気がします。確かに「こんな施策を行った」みたいな情報は、事前に公表されていない限り外部の人間は誰も知らないかもしれません。ですが、純粋に技術の話になった際は、そんな情報は少なくともテックカンファレンスにおいてはほとんどないと思います。


最後に

仮面ライダー Wで、私が尊敬している登場人物である鳴海荘吉も以下のように言っています。(正確には本人が口頭で言っているわけではありませんが)

Nobody’s Perfect

仮面ライダー W 32 話 「風が呼ぶ B / 今、輝きの中で」 より

仮面ライダー W がサイクロンジョーカーエクストリーム(W の最終形態)に初変身する際に、主人公である左翔太郎に相棒のフィリップが川辺で話しかけた文脈の中で登場します。感動しましたね、あの回は。大の大人が何回見ても泣きそうになりますよね。W に変身できなくなってしまってへこたれている左翔太郎に対して、フィリップが「もう一度、W として一緒に戦おう」と伝えたライダー史に残る伝説の回です。

画像

仮面ライダー W サイクロンジョーカーエクストリーム
東映公式ホームページより拝借

まぁ、そんなことは置いておいて。
発表準備はもちろん全力でやります。しかしその結果、少し間違っていたことを言っていたり、みんながすでに知っているようなことを言ったっていいと思います。

うだうだ悩むよりも良さげなテーマを選んでさっさと CFP へ提出しましょう。それが通れば発表してみればいいのです。

Nobody’s Perfect なのですから。

結論ですが、仮面ライダー W を見ましょう。Prime Video で全話見れます。冗談です。

www.amazon.co.jp

ではまた。

なぜエンジニアは「設計」するのか?

はじめに

なぜエンジニアは「設計」という工程を踏むのだろうか?当たり前と言えば当たり前なのだが、「設計」を行う意義を個人的に考えたのでこの Tech Blog の一発目として記載していきたい。

なぜエンジニアは「設計」するのか?

それはソースコードは必ず変更されるから

ソースコードを変更する上で既存の振る舞いを壊さずに安全に機能追加などを行う、つまり変更容易性や拡張性を持たせるのは至上命題である。だからこそ、きちんと設計しておくことで、これらの変更容易性や拡張性の担保を行うべきである。

ソースコードは必ず変更される

繰り返しになってしまうが、ソースコードは必ず変更される

以前、ある Web サービスに携わっていた際にある機能の改修を担当することになった。ただ、そのコードの解読にとても苦労した。メソッドの間の依存に振り回され、何がどこに記述されているのか全然分からなかった(Backend エンジニアとして最初の現場だったので私の経験不足も大いにあるが)。

その実装者に機能の実装について質問した際に「この機能を改修するとは思っていなかった」と言われた。想像だが、将来の変更についてはあまり深く考えずに実装したのだろう。

これだと設計を行なっていないのと同義である。責めるつもりは全く無いが、ソースコードは必ず変更されると思っておくと良い。

じゃあ、必ず変更されなかったら設計しなくても良いの?

捻くれている考えだけど絶対にそのソースコードが変更されないのであれば、設計工程は踏まなくても良いと思っている。

100%の確率で将来の変更がないのであれば、多少メチャクチャなソースコードを書いても良いと思ってるし、自動テストも必要ないと思っている。だって、ソフトウェアは良くも悪くも「動けば良い」し、動くことが最大の正義。将来の変更がなければ変更容易性や拡張性を考える必要はない。

ただ、実際にはそんなことは起こり得ない。最低でも依存パッケージや言語のアップデートという変更はありうるし、上記で記述したようにソースコードは必ず変更される。社内の業務効率化のために適当に実装した 100 行もないソースコードでさえ変更されるのだから。

じゃあ、そもそも設計って何ですか?

設計は未来を観ることだと思う。

将来の変更や拡張を予期し、その際に大きな障害を残しておかないようにすること。ある機能を 0 から実装する際に、ある程度の将来の変更や拡張がすでに分かっている場合はあったりする。そういったものに備えておき、また予想できない将来も多少は気にかけておきたい。オーバーエンジニアリングにならないように程々に。

結論

設計って結構めんどくさいよね。私も業務のソースコード以外では適当に書いちゃうこともあるから。