TECH PLAY

プログラミング

イベント

マガジン

技術ブログ

こんにちは。プロダクト開発部の森 @jiskanulo です。 2026年4月22日から24日までRubyKaigi 2026 Hakodateが開催されました。 rubykaigi.org 函館アリーナを3日間に渡って貸し切る大規模イベントの運営をしていただきましたスタッフの皆様に感謝を申し上げます。 ファインディ株式会社もPlatinumスポンサーとして協賛しました。 私もブースに立って出展やファインディ各サービスのご案内をさせていただきました。 お話しをしていただいた皆様にも重ねて感謝申し上げます。 ブースに立つ合間にセッションを聞いて自分でやれそうなことに思いを馳せたり、他社様のブースを回ってプロダクトのお話をしたり、昔の同僚や知人と再会したりと個人的にもいい刺激の多い3日間でした。 さて、4月24日、最後のセッションのMatzさんのキーノートにてRubyファイルをネイティブバイナリにコンパイルする Spinel が発表されました。 早速Spinelを使ってみた感想とつかいどころを記します。 Spinelとは 検証環境とセットアップ 動かしてみた Hello, World! eval / requireの挙動:エラーにならず無音で間違う eval は no-op に置き換わる require は文ごと消える 現時点での注意点 Spinelを使ってみる requireなしでJSONを扱う ハマりどころは個別に踏みに行く価値がある Spinelを試すときの判断基準 個人的所感 おまけ: Spinelの由来 おわり Spinelとは SpinelはRubyのAOT (Ahead-Of-Time) コンパイラです。 RubyソースコードをPrismでパースし、全プログラム型推論を行いCのコードに変換してネイティブバイナリを生成します。 パイプラインは次のとおりです。 Ruby → Prism → AST → 全プログラム型推論 → Cコード → ネイティブ実行ファイル リポジトリのREADMEによると、miniruby比で約11.6倍、Conway's Game of Lifeでは86.7倍という性能が示されています。 またバイナリサイズもmrubyを含めずに数十KBに収まるので容量が厳しい環境にも適用できるとのことです。 実体としての ./spinel はPOSIX shell wrapperで、内部で spinel_parse → spinel_codegen → cc を直列に呼び出している、という作りです。 検証環境とセットアップ 検証は手元のmac環境で行いました。 4月24日公開直後にmacで動かそうとしたタイミングでは malloc.h が存在しないなどでエラーになったのでDockerでUbuntuのコンテナを起動して操作しましたが、現在は対応されています。 土日で函館観光しているうちにコントリビュートが進んでいますね。コントリビュートのチャンスですね。 mac build対応 https://github.com/matz/spinel/commit/4593581eb87cea45b59fb28b9dcf2cd75a9bcbab windows対応 https://github.com/matz/spinel/commit/1fe3136aa9bf834b5f37176faca7346503fb1446 環境は次のとおりです。 macOS (arm64) Apple Clang Spinel masterブランチ(2026-04-28時点) ビルドと実行の基本フローはシンプルです。 spinel をmakeし、 spinel にrubyファイルをわたせば実行形式バイナリが出力されます。 make deps # 初回のみ: libprism 取得 make # spinel_parse / spinel_codegen / ランタイムをビルド ./spinel app.rb # Ruby → 実行形式(./app) ./app 動かしてみた Matzのキーノートとも被りますがサンプルコードを動かしてみました。 またキーノートで話があったとおり eval と require はサポートしていないとのことです。 eval, requireを使うと具体的にどうなるのかも試してみました。 Hello, World! 最小の動作確認はそのまま動きます。 # hello_world.rb puts " Hello, World! " ./spinel hello_world.rb ./hello_world # => Hello, World! eval / requireの挙動:エラーにならず無音で間違う 2026年4月28日の現時点では コンパイル時にエラーにならず、warningも出ず、しかし実行すると無音で間違った出力 を返すという挙動です。 具体的に2つのケースを見ていきます。 eval は no-op に置き換わる 次のRubyコードをSpinelでコンパイルして実行します。 # test_eval.rb code = " 1 + 2 " result = eval (code) puts result $ ./spinel ./tmp/jiska/samples/test_eval.rb ./tmp/jiska/samples/test_eval.rb -> test_eval 実行すると結果は 0 です。 $ ./test_eval 0 生成されたCのコードを見ると eval() の呼び出しがno-opに置き換わり、戻り値は型推論で決まったゼロ値( mrb_int のため 0 )になります。 const char *lv_code = "1 + 2" ; mrb_int lv_result = 0 ; // mrb_int = int64_t typedef lv_code = "1 + 2" ; lv_result = 0 ; // ← eval() 呼び出し自体が消滅、0 を代入するだけ printf ( " %lld\n " , ( long long )lv_result); mrb_int はmrubyのような」命名に見えますが lib/sp_runtime.h で int64_t のtypedefとして定義されたSpinelランタイムの整数型です。 https://github.com/matz/spinel/blob/64105ec86d08c9edc92c3d17bf059126ceaa15d3/lib/sp_runtime.h#L53 require は文ごと消える 次は require "json" と JSON.generate を使うケースです。 # test_require.rb require " json " puts JSON .generate({ name : " spinel " , year : 2026 }) こちらも実行すると 0 になります! $ ./spinel ./tmp/jiska/samples/test_require.rb ./tmp/jiska/samples/test_require.rb -> test_require $./test_require 0 require の行は生成されたCのコード上で文ごと消えます。 続く JSON.generate もSpinelから見れば未定義メソッドであり、 eval と同じくゼロ値を返す呼び出しに化けます。 最終的に puts には 0 が渡って表示される、という流れです。 現時点での注意点 現時点では「コンパイルが通った」「実行ファイルができた」「実行できた」の3点だけを見ていると間違った結果を吐いていることに気づけません。 Spinel向けにRubyを書くときは README を都度確認することが重要です。 Spinelを使ってみる 次に実際のユースケースを想定してみます。 実例として、GitHubのPR一覧JSONを入力に取り、各PRの number と author を表示するスクリプトを書いてみました。 入力はARGV、stdinの優先順で受け取ります。 requireなしでJSONを扱う require "json" が使えないので標準の Regexp と String 操作だけで処理を組む必要があります。 なお、ここで示すコードは正しいJSONパーサではありません。 require "json" が使えないSpinelの制約下で、入れ子オブジェクトや }, を含む文字列値が現れない、フラットな配列形式の固定データから number と author をアドホックに取り出す例として読んでください。本格的なJSON処理が必要な場合は、入れ子・エスケープなどで容易に壊れるため、この実装は使えません。 実際のRubyファイルは次のとおりです。 多少トリッキーなところは感じますが、こうした限定的な用途であれば、RegexpとStringの標準機能だけで実装できることがわかりました。 if ARGV .length > 0 input = ARGV [ 0 ] else input = readlines.join end records = input.split( / }, / ) results = [] records.each do |chunk| if chunk =~ / "number" \s* : \s*(\d+)/ num = $1 if chunk =~ / "author" \s* : \s* " ([^ " ]+) " / auth = $1 results << " # #{ num } by #{ auth }" end end end if results.length == 0 $stderr .puts " Error: failed to parse JSON (no matching number/author pairs found) " exit 1 end results.each do |line| puts line end 実行サンプルは次のとおりです。 引数渡し、パイプ、リダイレクトそれぞれに対応しています。 JSONを展開できない場合は標準エラーへエラーメッセージを出して exit 1 します。 SAMPLE='[{"number":1,"author":"Findy"},{"number":2,"author":"jiskanulo"}]' # 1) 引数渡し ./pr_extract "$SAMPLE" # 2) パイプ echo "$SAMPLE" | ./pr_extract # 3) リダイレクト ./pr_extract < sample.json # それぞれの出力: # #1 by Findy # #2 by jiskanulo $ ./pr_extract "not json" Error: failed to parse JSON (no matching number/author pairs found) $ echo $? 1 なお、引数もパイプもなしで ./pr_extract を起動すると readlines がEOF待ちでブロックします。 最初は $stdin.tty? で判定してUsageを表示しようとしましたが、実機で試すとTTYでもパイプでも両方 0 が返ってきました。これも eval / require と同じく、Spinel未対応のメソッドが silent failしている例です。 # test_tty.rb puts $stdin .tty? $ ./test_tty # TTY実行 0 $ echo "" | ./test_tty # パイプ実行 0 Spinelで標準入力を扱うときは $stdin.tty? に頼った分岐ができないため、引数で渡すかパイプ・リダイレクトで明示的に流し込む運用に倒すのが安全です。 ハマりどころは個別に踏みに行く価値がある 実装してみると String#<< でmutable化すると Regexp#scan に渡せない、 Regexp#scan(/(...)/) { |m| ... } のキャプチャは効かない...などとハマりどころがいくつかありました。 ただ、現時点での詳細を解説しても開発が活発に進んでいるのですぐに風化してしまうので詳しくは記しません。 Spinelを試すときの判断基準 ここまで触ってみた感触から、Spinelを触るときの判断基準を次にまとめます。 成功体験を得やすいのは次のようなコードです。 入出力が puts / printf で完結する 標準ライブラリに依存しない 数値計算・文字列処理・正規表現( =~ + $1 )で書ける範囲 逆に、現時点で踏むと詰まる、もしくはsilent failになるのは次のような領域です。 require を前提とするコード(標準ライブラリの利用) eval を含むメタプログラミング 未対応メソッドに依存する処理(呼び出しがゼロ値返却に化ける) 「コンパイルが通ったから動いている」とは限らない、というのが現時点での最も大事な感触です。 CRubyとSpinelの両方で実行して出力をdiffする運用を組むのが安全です。 個人的所感 ローカル環境のlintやチェッカーなど今までワンライナーでやっていたことを置き換えて使ってみたいですね。 コンパイル済みのバイナリを配布できるのであれば環境構築の手間も減るかもしれません。 まだ少し触っただけですが、Spinelに可能性を感じています。また、こういうワクワクするものを提供してくれるMatzさんの凄さをあらためて実感します。 これから機能が拡充されていくのが楽しみです。 自分でもコントリビュートしていきたいですね。 おまけ: Spinelの由来 Rubyと同じく宝石つながりでSpinelなのかなあとはじめ思っていましたが、漫画アニメ『カードキャプターさくら』のスピネル・サン(スッピー)から名前をとっているそうです。 相棒はルビー・ムーンなのでここでもRubyに繋がってきますね。 由来聞いた時はそっちか〜〜!!となりました。かわいい。 おわり ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
前回は、アウトプットがなぜ「強力な学習手段」なのかについてお話ししました。アウトプットをゴールではなく「インクリメント」として捉え、リズムを決めて始めることが大切だ、というところまで整理しました。 今回は「では、具体的に何をどう書けばいいのか」という話に踏み込みます。 記事一覧:【連載】社内外を往復するアジャイルQAの育ち方 【第1回】アウトプットが続かない本当の理由:「完成品」を手放して最初の一歩を踏み出す [全文公開中] 【第2回】社内の仕事が記事になる瞬間:実践知を言語化する型と習慣 「何を書いたらいいか分からない」問題 アウトプットの意義は理解できた。リズムを作ろう。そう思ったものの、いざ書こうとすると手が止まる。多くの人がぶち当たるのが「何を書いたらよいかわからない」という壁です。 エンジニアブログのようなコンテンツでは、以下の3点を基本構成として意識するのがおすすめです。 目的 :解決したいイシューや背景 実際に取り組んだこと :起きたことなどの生の体験、一次情報 そこから得られた学び :分かったことや教訓 この「目的・取り組み・学び」の3点セットを型として持っておくと、書くべきことが自然と見えてきます。 この構造は、研究論文の報告形式であるIMRaDや、軍発祥の振り返り手法「After Action Review」にも通じるものがあります。学術の世界でも実務の世界でも、「伝わり、再利用される知識の形」として効果が認められてきた構造です。 一次情報の価値 ここで強調しておきたいのが、一次情報としての具体的な体験の価値です。 個別具体のケーススタディや取り組みなど、実際に手を動かした生の体験そのものに大きな価値があります。しかし、これを抽象化・一般化すると、どこかで見たことのある情報になっていきます。著名人や書籍がすでに語っている内容と大差がなくなり、「自分が書く意味」が薄れてしまいます。 今の時代、一般的な知識や情報はAIに聞けば手に入ります。書籍の要約も、技術的な概念の解説も、AIが十分にカバーできるようになりました。しかし、個別具体のケーススタディはあなただからこそ書ける情報です。具体的であるからこそ、読者が自分の状況と照らし合わせて参考にできるリアリティがそこにはあります。 だからこそ、まずは自分が実際に経験したことをそのまま書く、ということを意識してください。 ただし、実際に行ったことを時系列に並べるだけでは不十分です。何のためにそれをやったのか、どのような結果になり、どんな学びが得られたのかという情報がなければ、読者にとって価値のある記事にはなりません。先ほどの型(目的・取り組み・学び)を意識しましょう。 仕事と発信を「1サイクル」にする この「型」を、日々の業務やプロジェクトなどの区切りの良い単位で実践してみてください。仕事が一段落したら、その概要や取り組み、学びを振り返る形でブログ記事にまとめる。この一連の流れを「仕事の1サイクル」として捉えることから始めてみましょう。 仕事と発信をセットで捉えるようにすると、アウトプット駆動で仕事に取り組む意識が芽生えてきます。常に読み手・聞き手を意識し、自分の活動の意義や狙いを言語化しようとすることは、発信の質を高めるだけでなく、日々の何気ない業務の中に新たな気づきをもたらします。「これ、どう説明するんだろう」と考える習慣が、仕事そのものを深める。これが、発信と実践を循環させることの本質的な価値だと思います。 私自身の経験を二つ紹介します。 一つ目は、スクラムマスターとして参加していたチームでの話です。レトロスペクティブ(振り返り)で議論している中で、チームとして重要な気づきが得られることがありました。「この学びは社外にも共有できるのではないか」というアイデアが自然と生まれ、次のスプリントのアクションアイテムとして「気づきをブログにまとめて発信する」というアクションにつながったこともあります。 二つ目は、マネージャーとしてスクラムマスターのメンバーと日々の1on1をしていたときのことです。最近の取り組みや悩み、そこからの学びを聞く中で、「これは他の人にとっても参考になりそうだ」と思ったものについては、「アウトプットしてみませんか?」と提案するようにしていました。 また、あるチームではスプリントの最終日を「アウトプットデー」と定め、スプリントレビューでのデモ準備と並行して、そのスプリントでの学びをブログ記事としてまとめるという活動を行っていました。 このように、日々の業務の一部としてアウトプットを組み込んでいくのがおすすめです。アウトプットによる自己変容は、筋トレに近いところがあります。1回やれば恒久的に変わるものではなく、適切な強度の取り組みを定期的に繰り返すことで、少しずつ鍛えられていくものです。だからこそ、仕組みを整え、一度きりではなく継続的な営みとして回していくことが大切です。 フィードバックを活用する 書き上げたら、一人で抱え込まず、積極的に他者からフィードバックをもらいにいきましょう。 他者によるレビュー は、最も直接的な方法です。上司や同僚に実際に読んでもらい、違和感のある表現や、解釈がぶれるような点を指摘してもらいます。他者がどのように解釈するのかという情報は貴重ですし、フィードバックを受けてブラッシュアップすることで、記事の質が高まり、自身の学びもより豊かなものになります。 生成AIの活用 もぜひ検討してみてください。私自身、執筆活動全体でAIをフル活用していますが、おすすめの使い方は大きく3つあります。 まず 執筆前の壁打ち です。書きたいネタは断片的に頭の中にあるものなので、「こんな記事を書きたいのだけど、対象読者と持ち帰れる学び、骨格となる論点の整理を手伝ってほしい」とAIに相談し、アウトラインを整えていきます。 次に 執筆中のペアライティング です。AIエディタを使い、ペアプログラミングのような感覚で一緒に書き進めます。コツは、AIをただの作業者ではなく、有能な同僚のように扱うことです。例えば、「このセクションは冗長だから削除して」とただ指示するのではなく、「このセクションは冗長に感じるのだけど、どう思う?」と聞く。するとAIは文章全体を踏まえて「このセクションには構成上こういう役割があるので、簡略化した上で位置を調整するのがよいのでは」と提案してくれたりします。 そして 書き上げた後のレビュー です。まず論点としての大きな穴や全体の整合性をチェックしてもらい、全体の構造を整えてから日本語のブラッシュアップに入る、という順序がおすすめです。 ただし、執筆そのものをAIに任せるのはおすすめしません。前回触れた通り、構成を考え、言葉を選ぶプロセスそのものが学びの核です。あくまで自分で書き、AIは壁打ちとレビューのパートナーとして活用するのがよいバランスだと思います。 「マサカリ」への備え方 フィードバックを経て公開する際、「ツッコミが怖い」という懸念もあるかと思います。私自身も昔は、不用意な記述によっていわゆる「マサカリ」が飛んできて苦い思いをしたことが何度もあります。 ツッコミが入りにくい発信の仕方を身につけることが大切です。これについては「 防御力の高い技術ブログを書こう 」という記事が非常に参考になりますので、ぜひご一読ください。 私が個人的に意識しているのはシンプルで、 読み手の感情的な反射を引き起こさないよう配慮する ということです。具体的には以下の2点です。 事実と解釈を明確に区別する 特定の人・組織・ツールを名指しで批判するような表現を避ける メリット・デメリットの比較が必要な場合は事実として淡々と行い、感情的な反応を引き起こしやすい表現を控える。読み手が最後まで冷静に読めるよう整えることが、アウトプットをする上での誠実さではないでしょうか。 まとめ 書き方の型を持ち、フィードバックを取り入れながら続けていく。それだけで、アウトプットは確実に仕事の質を底上げしていきます。 ここまで2回にわたって、アウトプットの意義と実践的な書き方についてお伝えしてきました。次回は少し視点を変えます。テキストのアウトプットに慣れてきたら、次は「外の世界」に出てみましょう。コミュニティやカンファレンスでの登壇・発表も、アウトプットの一形態です。そこで得られるフィードバックの質と量は、ブログとはまた異なります。外に出ることで検査と適応のサイクルがどう広がるのか、次回お話しします。 【連載】社内外を往復するアジャイルQAの育ち方 【第1回】アウトプットが続かない本当の理由:「完成品」を手放して最初の一歩を踏み出す [全文公開中] 【第2回】社内の仕事が記事になる瞬間:実践知を言語化する型と習慣 The post 【第2回】社内の仕事が記事になる瞬間:実践知を言語化する型と習慣 first appeared on Sqripts .
はじめに 本記事は、先日開催された「RECRUIT TECH CONFERENCE 2026」より「和田卓人氏と語る、"開発現場"の

動画

書籍