フォトシンス エンジニアブログ

株式会社Photosynth のテックブログです

面倒くさいを潰し続けたら、開発がループになった話

こんにちは。Esperna です。

組み込みファームウェアの開発をしています。この記事は、AIに開発を投げて、自分は別の仕事をする。そんな働き方にたどり着くまでの話です。想定読者は「AIコーディングを日々の開発にもっと組み込みたい」と思っているエンジニア全般で、組み込みの前提知識は要りません。

面倒なことを一つずつ潰していったら、私の開発は最終的に二段のループになりました。開発そのものを回すループと、そのループを回す道具つまりスキル自体を改善するループです。そして、それぞれのループには必ず制約を付けています。このループと制約という形が、この記事を通して言いたいことです。

改善のきっかけ

きっかけは、ごく個人的な「嫌だ」でした。

commit して push する。しばらくしてCIが落ちる。直す。また push する。この往復が、とにかく時間の無駄で嫌だったのです。

自分のセッション履歴を振り返ってみると、失敗の大半は派手なバグではありませんでした。多かったのは、フォーマット崩れ(clang-format)と静的解析(cppcheck)の細かい指摘です。軽い。軽い内容なのにパイプラインは失敗する。「Format On Save なり、これくらいは push する前に片付けておきたい」と思わされる類のものでした。

であれば、push する前に全部終わらせてしまえばいい。そう考えて、手を動かし始めました。

push まわりを先に片付ける

最初にやったのは、push 前の工程です。

まず、push 前チェックを一気通貫にしました。実装してテストを生成し、静的解析とビルドとテストを回す修正ループを通して、最後にフォーマットをかける。ここまでをひとつにまとめました。ポイントは2つあります。

  • 修正ループは最大3サイクルで止める。直しては壊し、を延々と繰り返してAIが暴走しないための制約です。3回試して直らないなら、それは人間が見るべきサインだと割り切りました。
  • テストは実装直後、同じコンテキストで生成する。実装の意図がまだコンテキストに残っているうちに書くほうが、意図した挙動を正確に写し取れるからです。コードの挙動をその場で固定する万力としての価値が高い。ただし同じコンテキストは、実装に引きずられてバイアスがかかる裏返しでもあります。そのバイアスのない検査は、あえて次のレビュー工程に分けて持たせています(このあと触れます)。

次に手を付けたのは、レビューです。ここで一つ学びがありました。自分の実装コンテキストのままレビューさせると、レビューが甘くなるのです。書いた本人も、相棒のAIも、どうしても自分の実装に引きずられます。

そこで、レビューは隔離した別エージェントに見せることにしました。しかも、

  • コード差分そのものへのレビュー
  • 変更ファイル全体へのレビュー
  • MR(説明文の文脈を含む)へのレビュー

の3系統を別々のエージェントに並列で担当させ、結果を統合したうえで、もう一体の「Redチーム」役エージェントに全体整合の観点から深掘りさせています。各エージェントは自分の担当範囲しか見ないので一発で浅くなりがちですが、観点を分けて重ねることで、人間が一人で見るより漏れにくくなりました。

todesking さんが書いているように、大事なのは「AIが書いたかどうか」ではなく「検品と責任を果たしたか」だと思います。だから、書く工程はAIに任せても、検品の工程は別エージェントと私とで二重に持つようにしています。

あわせて commit 後には、TODO や「仮」「暫定」、命名規約から外れた snake_case といったやり残しをスキャンさせています。

最後に、push の先も自動化しました。MRを作る、チケットを更新する。この手作業が手間に見合わないと感じたからです。成果物のMRは、説明欄とコメントの二重に記録させています。同じ処理を何度流しても結果が壊れない、いわゆる冪等になるよう作ってあるので、安心して任せられます。

これで、実装からレビュー、後工程までが一つのループになりました。

ボトルネックはコンテキスト整理へ移った

ところが、全部自動化して気づいたことがあります。ボトルネックは消えませんでした。移動しただけでした。

push 周りが楽になった結果、今度は「AIに渡すコンテキストを整理する」工程に時間を取られるようになったのです。

たとえば、こんなプロンプトをその都度手で書いていました。

再起動コマンドが送られてきたら再起動したい。そのために決めるべきことを洗い出して設計を詰めたい。少なくともコマンドのパケットは決める必要がある。再起動中に再起動要求が来たらどう扱うか(受け付けなくてよいと思う)も整理したい。過去製品ではどんなケースで再起動していたか、現行の設計資料に再起動への言及があるかも確認したい。最終的に、作るべき設計ドキュメントとブランチをチケットの説明欄に書いてほしい。使えるところは並列で進めて。

実際はもっと具体的に書くのですが、毎回、書く中身は違うのに、書いている「型」はいつも同じでした。要求を整理し、過去を調べ、現状を確認し、成果物を定義する。この骨格を手で書き直し続けているのが、どうにもDRY原則違反な感じがして嫌だったのです。

そこで、この「型」自体をスキルに切り出していきました。

一つ目は要求整理スキルです。「何を作るか」より「なぜ作るか」を掘ることに振り切りました。何を・なぜ・どこまでという観点で曖昧さを自分で判定し、足りないところだけ私に質問してきます。逆に「どう作るか」は聞いてきません。そこはAIの仕事だからです。

二つ目は実装計画スキルです。設計ドキュメントが複数に散っていて参照が面倒だったので、計画をチケットに書き出して参照させるようにしました。ここでは設計と現状のギャップを、file:line 付きの表で出させています。実装済みの行まで明示させるのがコツです。

実装計画でもう一つ大事なのが、分割です。大きいまま出すと、いわゆる巨大MRになってレビューしづらい。だから分割します。

ただ分割には、「どのMRを土台(main)にして、どれを積み上げる(stacked)か」という関係設計が要ります。ここを間違えると、レビューでの修正が別のMRに反映されない、といった抜け漏れが起きます。だから、修正やマージの順序まで計画に含めます。

そしてここにも制約です。計画には「触るファイル数の概算」を書いておき、実装ループ側は実際の変更がその概算の約2倍に膨らんだら、いったん止めてスコープを問い直します。さらに、計画そのものを工数・依存・リスクなどの観点から攻撃する「自己批判役」のエージェントを1体挟み、出した計画を一度疑わせています。

自動化して変わったこと

要求整理、実装計画、実装。この3つが揃うと、仕事の仕方が変わりました。

[要求整理] → [実装計画] → [実装(テスト・実機spec生成まで)]
   なぜ作るか   何を・どう分けて   ループで自動的に回る

以前は、AIとずっと壁打ちを繰り返して、ペアプログラミングをしているような感覚でした。もちろん今も壁打ちや議論はします。でも、一度コンテキストを作ってしまえば、実装計画から先はほぼ任せきりです。しかも可能な限り、複数のトピックを同時にAIへ投げて並列で走らせています。

ただし、同時に走らせる重めのタスクは1つだけと決めています。残りは、スキルの小さな改善や重複排除、軽いリファクタリング、テスト追加、ドキュメント拡充といった、大きな判断を要さない軽めのタスクに絞る。

似たことは Peter Steinberger さんも書いていて、RAG やサブエージェントのような凝った仕組みより「ただ対話しろ(Just talk to it)」だと言い切っています。変更の影響範囲(blast radius)を見ながら複数を並列で回す感覚も近いなと思いました。

手を動かす時間は減り、代わりに指示を出す時間が増えました。投げた作業はループとして設計してあるので、単体テストと別エージェントのレビューが通るまで、勝手に進み続けます。ここでも形は同じ、ループと制約です。

体感で言うと、残業が1時間は減った気がします。私は早く家に帰る、寝る。その間もAIは働いている。これはなかなかいい状態です。

そして今、実機テストもループに入れようとしています。いわゆる HW in the Loop です。組み込みなので、最後は実物のデバイスで動かさないと安心できません。今のところは、

  • テストの spec を自動生成する
  • スクリプトで JLink を起動する
  • 人間がデバイスに ICカードをかざす(あるいはシェルコマンドを叩く)
  • そのログをAIが判定する

という形です。AIが司令塔で、人間がアクチュエータ、という役割分担になっています。

AIが「次はこの操作をして」と指示し、人間が物理的な手足としてカードをかざす。役割が逆転していて、最初は少し変な感じがしました。 もちろんこの辺りは Arduino を始めとしたマイコン、ラズベリーパイなどでモーターを回せばよい、という話はあるのですが、それでもまだボトルネックは残ります。試作機の台数に限りがあり、自動チェック専任の機械には仕立てられていません。ただ、フェーズが進めば、CIの回帰テストを「実機で正しく動くこと」まで含む形に持っていきます。

もう1つのループ

開発をループにする話は、ここまでです。あとになって、もう1つループがあることに気づきました。 それは道具(スキル)そのものを改善するループです。

たとえば、他の人の書いた記事を読んで、ためになるなと思ったらそこで得た知見を自分のスキルに取り込む。これも専用のスキル(記事取り込みスキル)にしてあります。さらに、日々の作業で得た学びを、スキル自身が「改善候補」として溜めていく仕組みを入れています。 ただ、AIが暴走して勝手に自分のルールを書き換えていくのも嫌なので、

  • 改善候補は、一定回数以上・一定期間以上観測されて初めて昇格する(すぐ上げたいと思ったときは、その場で更新します)
  • しばらく使われなければ降格する
  • そして何より、書き換えは必ず人間がチェックする。これで、触ってはいけない凍結ルールを絶対に書き換えさせないようにしています

ここでも結局、形は同じでした。ループと制約です。

おわりに

振り返ると、私がやってきたのは「面倒くさいを一つずつ潰す」だけでした。その結果として、開発のループと、そのループを育てるループという二段構えに行き着きました。

ここで一番伝えたいのは、自動化に終わりはないということです。一つボトルネックを潰すと、それは消えてなくなるのではなく、別の場所へ移動します。push がボトルネックなら push を潰す。すると今度はコンテキスト整理がボトルネックになる。だから次はそれを潰す。この繰り返しです。

そして、この移動には続きがありました。個人の開発フローを潰しきると、ボトルネックはついに自分自身、つまりAIのアウトプットを判断する人間に移ってきたのです。一度、重めのタスクを3つ同時に走らせてみたら、Claude Code is waiting for you! という催促の声があちこちで同時に鳴り、脳内のコンテキストスイッチが追いつかずに音を上げました。今は、同時に走らせる重めのタスクは1つだけと決めています。

ここから先は、もう一人では潰しきれない気がしています。AIが量産する時代に律速になるのは、結局「検品と判断」です。そしてそれを一人で抱えるほど、詰まる。だとすれば私の次のボトルネックは、検品と責任を、個人で抱えるのではなくチームでどう分担し、共有していくか、という設計なのだと思います。

だからこそ、道具はループと制約で設計し、道具自体も育て続ける。そして人間は、空いた時間でひとつ上のレイヤー、つまり何をどこまで作るかという要求と境界の設計へ移っていく。そうやって人の手を離れても回る範囲が広がっていくのは、素直に良いことだと思います。開発の対象が、プログラムや製品そのものから、それらを生み出す環境作りにシフトしてきた感があります。

次に潰すべきボトルネックは、たぶんもう、コードの中にはあまり残っていないのかもしれません。

参考にした記事

  • Peter Steinberger「Just talk to it」 — https://steipete.me/posts/just-talk-to-it 凝った仕組みより対話を、という実践。複数を並列で回す感覚や blast radius の考え方が、自分のやり方と重なっていて心強かった一本です。
  • todesking「ちょっとしたアイデアをAIで長文記事にして公開するのをやめろ」 — https://zenn.dev/todesking/articles/fba4cc93baf0a9 「AIが書いたかどうかではなく、検品と責任を果たしたか」。本文で書いた制約という発想を補強してくれました(……この記事もそれなりの長さになってしまいましたが、検品と責任は果たしたつもりです)。

株式会社フォトシンスでは、一緒にプロダクトを成長させる様々なレイヤのエンジニアを募集しています。 photosynth.co.jp

Akerunにご興味のある方はこちらから akerun.com

RubyKaigi 2026 参加レポート Part 3

こんにちは、市川です。

この度、RubyKaigi2026に参加してきました。RubyKaigiに限らず、カンファレンスへの参加は初めてでした。

普段はWebエンジニアとしてRailsを触ってはいるものの、正直Ruby本体の中身とか仕組みをあまりちゃんと知っていたわけではなかったので、「自分が行って大丈夫かな…」と若干不安を持ちながらの参加でした。

ただ、ふたを開けてみると、話についていけない部分もあったんですが、それも含めていい刺激を受けることができました。

今回は参加レポートということで印象に残ったセッションについて振り返ります。

Day1

When Can You Skip a Test? Tracking Test Impact

変更の影響を受けないテストをスキップしたいという趣旨の話。Coverage、TracePoint、C拡張の3つを比較してC拡張に落ち着いたとのこと。「15分のテストが9秒になった」という数字は衝撃でした。

AIでの開発でテスト実行回数が増えていて、CIの待ち時間が地味に効いてくる場面が多いので、こういう「そもそも全部走らせなくていいよね」という発想は、とても勉強になりました。

Day2

Surviving Black Friday: 329 billion requests with Falcon!

ShopifyがBlack Fridayを乗り越えた話。週末で3,290億リクエストというよく分からない量のリクエストを完走させたそうです。Black Friday直前まで本番由来のバグを潰していた、という話が印象に残ってます。

今後の展望でRack v3へのバージョンアップとあって、自社でもUnicornを使っていることによって、Rack v3へバージョンアップができていないので、規模は全然違うけど同じような悩みを抱えていたんだなと思いました。

The future of Ruby documentation

RDocを刷新していくという話。ドキュメントツールの裏でこんなに大変なことになっていたのかという素朴な驚きがありました。Prismベースに移行してコード量がほぼ半減(22,000行→12,000行)、パースも30%速くなったとのこと。

あと2008年からデザインがそのままだったテーマが刷新されたという話で、20年もののプロダクトをアップデートし続ける営みが地味にすごいなと思いました。

Day3

Autoresearching Ruby Performance with LLMs

LLMで性能改善を自動化する試みの話。発端は「autoresearchでLiquidを50%高速化した」とPRを公開したことだそうです。ところが、不具合があり実際はほとんどのPRがマージされなかったとのこと。一方で、他の方がautoresearchベースで出したPRはちゃんと取り込まれていて、「やり方によっては機能する」ことが示されていました。

「自分が読めて直せるコードにだけautoresearchを使う」という結論は、AIを使ってコーディングしていくうえで大事なところだと思いました。

Ruby Releases Ruby

Rubyのリリース作業の自動化の話。Ruby本体のリリースが裏でどう動いているかなんて考えたこともなかったのでとても新鮮でした。

セキュリティリリースが「5〜6人で深夜5〜6時間」から「1人1時間以内」になったとのことで、ここまで効率化できるんだと素直に驚きました。リリース頻度も年9回から14〜15回に増えたとのことで、自動化の効果がしっかり数字として表れていて印象的でした。

おわりに

普段は素のRubyをあまり意識することはなく、Railsの上で書いている自分にとっては、登場する話題がどれも新鮮で、聞いているだけでも刺激を受けることができました。 何より、Rubyコミュニティの熱量、盛り上がりを肌で感じられた3日間でした。

来年もぜひ行きたいですね。


株式会社フォトシンスでは、一緒にプロダクトを成長させる様々なレイヤのエンジニアを募集しています。 photosynth.co.jp Akerunにご興味のある方はこちらから akerun.com

RubyKaigi 2026 参加レポート Part 2

こんにちは、@yellow-seedです。

この度、RubyKaigi 2026に参加してきました。Python Conferenceには過去に参加経験があるのですが、RubyKaigiは初参加です。

RubyKaigiは言語カンファレンスの中でも特に規模が大きいと事前に聞いていましたが、実際に参加して、たしかにその通りだと肌で感じられました。また、他のカンファレンスは東京で済ませたりすることも多く、日本の各地で実施するご当地イベント感も特色かなと思います。ラッキーピエロを今回知ることができたのが個人的には大きな収穫でした。

今回は初参加レポートとして、Dayごとに印象に残ったセッションを簡単に紹介したいと思います。

Day-4

Day-4 (2026-04-17) に足を怪我したので、あわや松葉杖での参加になるかと思いましたが、幸いにも回復が早く無事に自分の足で参加することができました。あやうく松葉杖で飛行機に乗るところでした。

Day1

Day1はやはりKeynoteである The Journey of Box Building が初っ端から素晴らしかったです。Boxという命名の仕掛けなど、プレゼンとしての完成度の高さが印象に残りました。

「Box」はRuby 4.0に実験的に導入された機能で、Rubyのグローバル空間をプロセス内で分離する仕組みです。

Ruby VM (C実装)についてはまったくの素人なのですが、コントロールフレームスタック(VMの内部構造)とそれにまつわる課題の整理が、発表の技術的な内容の中心でした。

前回、エンジニアブログのネタとして、モジュラモノリスに関する記事を書いたこともあり、Ruby::Box自体はRuby 4.0発表当時から関心を持っていました。今回さらに背景となるC言語の実装とその課題についても聞くことができてよかったです。

後追いで、Featureのリクエストのチケット(#19744#21311)も見つけたので、色々と読んでいきたいと思います。

アプリケーションやライブラリやmonkey patchを隔離された空間に分離するというアイデアは、モジュラモノリスの文脈だったり、カナリアリリースの文脈だったり、様々な文脈で応用できそうだなと感じています。同日のLT(joker1007さんの「Do Ruby::Box dream of Modular Monolith?」)でも言及がありましたが、実際のRailsサーバへの適用においてはまだまだ課題もありそうに見えています。今後の発展に期待したいと思います。

昨年モジュラモノリスへの方針検討のためにあれこれ調べ回った身としては、導入のあかつきにはpackwerkと組み合わせるのがやはり筋が良さそうというのが個人的な所感にはなります。

Day2

RubyKaigiは、日英の言語でセッションが行われます。

英語セッションで印象に残ったのはDay2のSurviving Black Friday: 329 billion requests with Falcon!でした。

FalconはFiberを活用した非同期I/OベースのWebサーバーで、単一プロセスで数千の並行リクエストを効率よく処理できる設計になっています。Shopifyでは本番投入前に段階的なスケールテストを繰り返し、ボトルネックを一つずつ潰していったとのことでした。

ピークで85 million RPMというとんでもない規模のリクエストをFalconでいかに効率よくさばくのか、当日までにどんな準備をしているのか、という趣旨の発表でした。

ShopifyクラスのRuby界のフロントランナーでもかなり直前まで泥臭くトラブルシューティングをしている様子が伝わってきて、非常にリアルな発表であると同時に、親近感も湧きました。Falconの切り戻し構成がUnicornというのも、Shopifyでもいまだに一定現役なのかと同じく親近感を覚えました。

発表でも言及されていた、UnicornだとRack v3系にアップデートできないという課題はまさに悩みどころで、自社でもプロダクション環境でPitchforkを導入するか、Pumaを導入するかは今後のテーマのひとつです。そういうテーマで書かれた記事が今後でるかもしれません。

Day3

Day3は、Ruby Releases Rubyが印象に残りました。

労働集約的だったRubyのリリース作業がRubyを使っていかに自動化されているのか、という趣旨の発表でした。

具体的な成果として印象的だったのは、リリース作業が「5〜6人で5〜6時間の深夜作業」から「1人で1時間以内」に短縮されたという点です。「タグを打つ」「アナウンスを出す」以外は全て自動化されており、リポジトリディスパッチによる連鎖実行でパッケージ生成からDockerイメージ、Webサイト更新まで一気に走るとのことでした。年間リリース回数も9回から14〜15回へと増え、自動化の恩恵が数字にも表れています。

別にRubyで書く必要のないRubyスクリプトが社内にもあり、個人的には他の言語で書いた方がよいのでは? と感じることもあるのですが、Rubyという言語のリリースにおいてはむしろなんでもRubyで書くことで検証する機会を増やす(Rubyのドッグフーディング)というのは、腑に落ちました。

どのような目的をもって、そのプロセスを設計するのか、というのは正解がない問いであり、少なくとも自分は言語のリリースにおいて、いわゆるデプロイメントのベストプラクティスを遵守するよりも、極力全てのスクリプトをRubyで書き切るアプローチに理があると感じています。

おわりに

普段はRailsを中心にRubyを触っているので、RailsではないRubyの視点や機能に着目する良い機会となりました。紹介したセッションではないですがWASM, Ractor, PicoRubyなどなど。特にPicoRubyはIoTサービスの企業に所属している身としては触っていきたいと感じました。Matzも言っていましたが名前が可愛い。

PRK Firmware は自作キーボードのファームウェアをRubyで書けるプロジェクトなので気になりますね。Integration of PRK Firmware and R2P2 でRubyKaigiのセッションのトピックでもあったようですが、こちらは他講演の方に出ていて聴きそびれてしまいました。Funicular: A Browser App Framework Powered by PicoRuby.WASM もPicoRubyをwasmで動かすというテーマで、PicoRubyの初学者的にはなかなか気になる題材に後から感じます。こちらも別講演の方に参加していたので聴けずじまいでした。後から振り返ると、聴ければよかったです。こういうのはキリがないですね。

そしてどうやら社内に、Raspberry Pi Picoがあるらしいという情報が出てきました。電子工作サークルが社内にあるので、いずれかのタイミングで実機でのお試しもできる機会がありそうです。

初参加の反省としては、初日は会場にトートバッグ一つで参加したのですが、想像以上にブースでノベルティをもらったので、素直にリュックを持っていけばと思いました。(2日目以降はリュックを使いました。) あとは、なかなか聴きながらメモを取るのは難しいですね。記事にしようとすると、自分の手元のメモ程度ではいかに役に立たないかを痛感しました。(そして、RubyKaigiのアーカイブ動画の公開が遅いということも。。。)

次回の宮崎もぜひ行きたいですね。


株式会社フォトシンスでは、一緒にプロダクトを成長させる様々なレイヤのエンジニアを募集しています。

career.photosynth.co.jp

Akerunにご興味のある方はこちらから

akerun.com

RubyKaigi 2026 参加レポート

こんにちは、 AkiAbe's My Page - Qiita です。

RubyKaigi2026 函館 に参加してきました!!
人事の方にも協力してもらって、フォトシンスはゴールドスポンサーとして協賛をしました。 こういうテック系イベントにスポンサーしたのは、僕が入ってからは多分初めてです。

Sponsors - RubyKaigi 2026

僕自身、Ruby は 17 年ほど前に windows で動くスクリプトを作ったりメンテしたりで利用してました。
たぶん Ruby1.9 くらいだったと思う。
昔は CICD みたいなの充実してなくて、自前でビルドしてテストするようなツールを作ってました。

Rails はチュートリアルをなぞったことがある。程度の知識。
ほぼ初心者みたいなもんなので、セッションについていけるかとても不安でした。

出てみた感想としては、「すぐに使えるTips紹介」みたいなセッションはほとんどなくて、低レイヤーの話も多い。
自分が選んでいたセッションが組み込み寄りだったせいもあるけど、Ruby と同じくらい C の説明がされていてめちゃくちゃ意外でした。
ruby コミッターすごい。

ということで、時系列で Day1 まで振り返ります。


Day -1

大きな地震が、三陸沖でありました。 避難指示もでている?開催できるの?と少し不安になりました。

news.yahoo.co.jp

Day 0

前日の地震とは関係なく、朝から飛行機のトラブルがありました。 X で #rubykaigi のハッシュタグ追っていると、諦めて新幹線移動に切り替えたりしている方もいるようでした。 我々は午後の飛行機が飛ぶのを信じて待ちました。 結果、20 分遅れで移動できたのでよかった! (朝の便は 3時間遅れとかだった。)

news.yahoo.co.jp

とりあえず移動はできて、夕方くらいに現地着!
空港にも広告が!すごい。

弊社メンバーはみんな初参加。ドキドキワクワクしながら懇親会をして終了。

Day 1

会場へ

電車すごい人がいっぱい。
そして電車にも広告が、、、!

現地エントランスにある看板、かっこいい。

スポンサーロゴもみつけました!うれしい。

各社さん、ステッカーとかノベルティを置いてます。
我々もステッカーと簡単なパンフレットをおきました。
急遽、マーケの方にも手伝ってもらって作成してもらいました。感謝🙏

さあ、ここからセッション中心に楽しみます!!
自分がみた Day1 セッションとめちゃくちゃ雑な感想などなど。

Ruby::Box — アプリやクラスを隔離する

tagomoris さんのセッション

Ruby::Box という Ruby4.0 からの新機能の話。 アプリケーション・ライブラリ・クラス・メソッドをそれぞれ隔離できる仕組み。 アプリごとにテストモックを作るときなんかに使えそう。 なんとなく、自分が昔にやった Linux のデバドラ開発を思い出した。

テストを効率よく絞るには?

anmarchenko さんのセッション

カバレッジ網羅率だけ追うのではなく、コードの構造に着目して最適なライブラリを選ぶ、というアプローチ。 それによって「有効なテストだけに絞る」ことができ、テスト実行時間が短くなったとのこと。 英語セッションで正直難しかったけど、考え方は面白かった。

test-unit で並列化

tikkss さんのセッション

並列処理を綺麗に作るというよりも、「空いている CPU をうまく活用できるライブラリを作った」という印象。 みんな低レイヤー触っていてすごい。

Z80 を mruby で動かす

yujiyokoo さんのセッション

セガ・マスターシステムを mruby で動かしてるっぽい。なんか楽しそう。

PicoRuby で OS を作る

kishima さんのセッション

PicoRuby で OS を作っているという話。 tick のカウントがうまくできなかったり、割り込み制御がまだ完全じゃなかったりと、リアルな進捗感があってよかった。 バス競合で落ちる課題があるとか、完全に組み込みやん。

CRuby のコードの読み方

youchan さんのセッション

C 言語をあまり知らない人向けに、CRuby のコードをどう読むかという話。 「わかりにくかったら後ろからコードを読め」「戻り値がどのようにセットされているかから読むと読みやすい」という tips はその通り。 今の時代なら AI と一緒に読めばだいたい理解できると思うけど、こういう読み解き方の作法を知っておくのは良いなと思った。

ハードウェア上で md ファイルを使ってプレゼン

harukasan さんのセッション

このデバイス上の md ファイルで発表しているというのがつよい。 pico ruby、mruby が多い中、CRuby でベアメタルしてる人もいるっぽい。 ハードウェア関連のセッションがこんなにあるとは思わなかったので、嬉しかった。

公式パーティには参加できず、、、

公式パーティ、、行きたかったけどチケット取れずで出れなかった。。残念無念。
このあたり、ちゃんと手配してマネジメントしてくれる人が必要ですね。反省。


株式会社フォトシンスでは、一緒にプロダクトを成長させる様々なレイヤのエンジニアを募集しています。

career.photosynth.co.jp

Akerunにご興味のある方はこちらから akerun.com

モジュラモノリスへのリアーキテクチャに向けた準備

この記事はAkerun - Qiita Advent Calendar 2025 -の12日目の記事です。

こんにちは、@yellow-seedです。 アドベントカレンダーに書くのは二度目になります。

フォトシンスのサービスのうち、大半を担うのはモノリスRailsアプリケーションサーバーです。 サービスの規模が大きくなるにつれて、モノリスなアプリケーションの保守性や拡張性が低下してきました。 所属するチームは、このプラットフォームの改善のためのリアーキテクチャを推進するのがミッションのひとつです。 今回はモジュラモノリスへのリアーキテクチャに向けた準備を通じて、チームの2025年の活動を紹介したいと思います。

はじめに

2025年は本格的な着手というよりは、実行に向けた準備の期間となりました。実際に直面した課題ではなく、どのような方針で進めていくのかを決定したのか、その過程を紹介します。

2026年以降の実際の推進を通じてこの当初方針にも修正が入る可能性は十分にありえます。

モノリスサーバーを安全に分解するにあたって、『ソフトウェアアーキテクチャ・ハードパーツ』1の第I部に書かれているアプローチを参考にしています。今回は書籍でとられていたアプローチをどのように実際のプロジェクトに適用したかを紹介します。

ディレクトリ構造などは記事内の説明をわかりやすくするために一部省略・編集しています。

なぜやるのか

運用開始当初のアーキテクチャの想定を超えたサービス利用をつづけたことによるビジネス上の課題が顕在化してきたためです。

運用開始当初のアーキテクチャの想定を超えた例として、以下のような事例がありました。

  • 当初のコア機能であった、入退室管理以外の機能を提供している
  • オフィス以外のビジネスドメイン(住宅向けサービス)でも利用されている
  • サービス開始当初から新規機種が追加されている

これらの事例は

  • 耐障害性とスパイクリクエストに対する弾力性の低下
  • バグの混入リスクの増大
  • 新機能、バグ修正のデリバリー速度の鈍化
  • データベース負荷の増大

として、ビジネス上のリスクをもたらしています。

どう取り組もうと考えたのか

端的には

  1. 『ソフトウェアアーキテクチャ・ハードパーツ』の第I部のアプローチによるコンポーネントの特定
  2. Packwerkを用いたコンポーネントベースのディレクトリ構造への整理

の2段階で進めることにしました。順番に説明します。

1.コンポーネントの特定

分解の方針

歴史あるモノリスの分解戦略は

の2種類に分けられます。

予期せぬ機能への不具合の前例と現状の開発チームごとの責任範囲の曖昧さを鑑みて、いきなり戦術的フォークをして、サービスベースのアーキテクチャに移行するのはリスクが高いと判断しました。書籍の例と同様に、まずはコンポーネント分解によるアプローチを選んだということになります。

コンポーネントの候補の洗い出し

分解戦略をまず決めたので、今度は分解するコンポーネントは最終的にどのようなカテゴリに分類すべきかを決めます。

まずは、チームのメンバーで分担してAPIベースでリクエストの処理を追うことにしました。それぞれの処理内で、どのデータリソースにアクセス、操作しているかを調べて、全APIについて、以下のような調査表を作成しました。

APIパス (Path Pattern) ネームスペース 調査担当 コンポーネント名の案
/app/login (POST) app 担当者 XX login.mail
/app/login/mfa (POST) app 担当者 XX login.mfa
/app/login/sso (GET) app 担当者 XX login.mfa
/app/logout (DELETE) app 担当者 XX logout
/akc/login/recovery (POST) akc 担当者 YY login.recovery_code
/akc/user_password/reset (PUT) akc 担当者 YY user.password
/akc/user_password/update (POST) akc 担当者 YY user.password
/akc/logout (DELETE) akc 担当者 YY logout

コンポーネントの特定

コンポーネント名の案を洗い出した後、最終的にはコンポーネント名のルートレベル(上記の例でいう.のつかない属性名)が10程度にまとまるように、統廃合を行いました。上記の例で言うと login, logoutのコンポーネント名はauth、userはaccountとして集約されることになりました。

2.ディレクトリ構造を整理する

コンポーネント名の整理方針が決まったところで、コンポーネントを実際の実装に落とし込むために必要な要素を決定します。

がポイントになります。

これらの決定についてはGitHub Discussionsを利用して、Architecture Decision Record (ADR)として記録していて、いつ誰がどのようなトレードオフ条件を理解したうえで、この方針を決めたのかが追跡しやすいようにしてあります。

どの技術を使うのか?Packwerkにする

Packwerk自体はすでにさまざまなRailsアプリケーションを開発する企業テックブログで紹介されている2gemになるので、ここでは割愛します。

モジュラモノリスアーキテクチャにおける適応度関数としての重要な役割を果たします。

Rails標準ではない学習コストのデメリットを理解しつつも、以下のメリットがコンポーネント分割の目的にかなうと判断しました。

  • あくまでLintのgemでしかないので、導入自体が容易で既存動作に影響を及ぼさない。
  • package_todo.yml で警告無視もできるため、段階的な導入ができる。
  • CIに統合してドメイン規約違反をシステムとして検知できる。属人性を下げられる。

Packwerkのアーキテクチャのゴール像をあてはめる

分解したコンポーネントを実際のディレクトリ構成に落とし込みます。Packwerkに変更した際の実現予定のディレクトリ構造を対応させました。

将来的にクライアントごとにも分割することも想定していることから、コントローラーは従来通りのディレクトリ構造を維持しつつ、Packwerkのpacksディレクトリ以下にコンポーネントごとの責務を整理する方針としました。以下のようなイメージ構造を想定しています。

app/
  assets/
  controllers/
    app_controller.rb ※モバイルアプリAPI
    app/xxx_controller.rb 
    ...
    akc_controller.rb ※web管理システムAPI
    akc/xxx_controller.rb
    ...
  jobs/ ※基底クラスのみ
    application_job.rb
  mailers/ ※基底クラスのみ
    application_mailer.rb
  models
  policies/
  serializers/
  validators
packs/
  account/
    app/
      public/
        account/
          public_account_interaction
      interactions/
      jobs/
      models/
    lib/
      tasks/
  ...

その他の実装ルールの決定

Serviceクラス、Formオブジェクトのインターフェースがバラバラなままその時々の開発者による増築が続けられている状況だったため、今後はActiveInteractionのgem3でそういった責務のクラスを実装していく方針、実装ルールも合わせて決めました。

現時点で予想される今後の困難さ

本来Packwerkを利用する場合は、ControllerもPackwerkのpackageディレクトリ以下に配置することが推奨されています4が、前述の通りそれを採用しないことにしました。

これは、Railsの標準的な水平アーキテクチャドメイン中心の垂直アーキテクチャの折衷案を採用することになります。ディレクトリ構造を通じた説明の仕方をすると、以下のようになります。

Railsの典型的な水平アーキテクチャは端的に以下です。

# Horizontal(典型的なRails構成)
app/
  controllers/  # すべてのコントローラー
  models/       # すべてのモデル
  serializers/  # すべてのビュー

一方で、ドメイン中心の場合は以下のようなディレクトリ構造になります。

# Vertical(ドメイン中心でPackwerkの標準構成)
app/
  domains/
    users/
      user_controller.rb
      user.rb
    devices/
      device_controller.rb
      device.rb

これらを踏まえると、採用しようとしている方針が両方の特徴を持っていることがわかります。

# 今回の方針は上記の折衷案(Vertial&Horizontal)
app/
  assets/
  controllers/
    app_controller.rb ※モバイルアプリAPI
    app/xxx_controller.rb 
    ...
    akc_controller.rb ※web管理システムAPI
    akc/xxx_controller.rb
    ...
  models
  policies/
  serializers/
  validators
packs/
  account/
    app/
      public/
        account/
          public_account_interaction
      interactions/
      jobs/
      models/
    lib/
      tasks/
  ...

本来の用途をあえて活かしきらない方針で実際の実装を進めていく過程では、いろいろと悩む場面は出てくるのだろうと予想しています。

まとめ

モノリスアーキテクチャのモジュラモノリスへの移行推進以外にも、ログデータの蓄積によるデータ肥大化の解決に向けた取り組みなど、サービスの継続にともなう種々の課題が山積み状態となっています。

これらの課題の解消のための取り組みを引き続き進めていきたいと思います。


株式会社フォトシンスでは、一緒にプロダクトを成長させる様々なレイヤのエンジニアを募集しています。 career.photosynth.co.jp

Akerunにご興味のある方はこちらから akerun.com

AWS Security Hub 検出結果をフィルターするときに軽くハマった

この記事は Akerun - Qiita Advent Calendar 2025 - Qiita の24日目の記事です。

皆さんこんにちは。フォトシンス エンジニアの ps-k-itoh - Qiita です。
フォトシンスで SREチームとして、SRE / AWS インフラ周りを担当しています。

アドベントカレンダーもラスト2日、まだ枠が空いていて、ちょうどブログのネタが降ってきたので書きます。

今回もAWS関連の小ネタです。

Security Hub 検出結果をフィルターしたいが項目が見当たらない

Security Hub の検出結果をフィルターしたいのですが、
一覧に表示されている項目に対応するフィルター項目が見当たらず、軽く困りました。

図の画面から、

  • 検出結果 : Lambda.1 Lambda function policies should prohibit public access
  • 重大度 : CRITICAL

の条件でフィルターしたいのですが...

「検出結果」が見当たらない。どれでしょう?
試しに「検出結果の例」を選択したところ、true か false しか選べないのでこれじゃない。

「重大度」も見当たらない。
「重度」があったので選択したところ、数値しか入力できず、レンジで -100〜100 とか入れても抽出0件になってしまいます。


解決策

 検出結果 → 「タイトル」
 重大度 → 「重要度ラベル」
をそれぞれ選択することでフィルターできます。



以上です。
何かのお役に立てれば幸いです。

一緒にSRE施策や、AWS環境の改善、構築や運用を進めてくれる仲間を募集中です!
↓↓↓


株式会社フォトシンスでは、一緒にプロダクトを成長させる様々なレイヤのエンジニアを募集しています。 photosynth.co.jp Akerunにご興味のある方はこちらから akerun.com

AWS CloudShell 「Error when retrieving credentials from container-role」エラー

この記事は Akerun - Qiita Advent Calendar 2025 - Qiita の23日目の記事です。

皆さんこんにちは。フォトシンス エンジニアの ps-k-itoh - Qiita です。
フォトシンスで SREチームとして、SRE / AWS インフラ周りを担当しています。

弊社の正式な会社名は「株式会社Photosynth」と英字表記です。
でもカタカナの方が分かりやすそうですし、いつもイベント参加などの申し込みフォームで、
英字で登録するかカタカナで登録するか悩みます。

さて今回はAWS関連の小ネタです。

CloudShell を使っているときの謎のエラー

ある日、AWS CloudShell でコマンドを一つ一つ実行していったのですが、
急にこんなエラーが出るようになり、コマンドをどう変更しても解消しません。

Error when retrieving credentials from container-role: Error retrieving metadata: Received non 200 response 500 from container metadata: <?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
  <title>500 - Internal Server Error</title>
 </head>
 <body>
  <h1>500 - Internal Server Error</h1>
 </body>
</html>


解決策

調べてみるとこんな記事がありました。

今回は同時実行ではないですが、どうやら一定数以上のコマンドを実行すると発生する、認証情報の取得に失敗するエラーのようです。

対応法についても、記事をヒントに、 一度CloudShellのタブを閉じて、再度メニューから開き直し たところ、
事象が解消され、コマンドが実行できるようになりました。



以上です。
何かのお役に立てれば幸いです。

一緒にSRE施策や、AWS環境の改善、構築や運用を進めてくれる仲間を募集中です!
↓↓↓


株式会社フォトシンスでは、一緒にプロダクトを成長させる様々なレイヤのエンジニアを募集しています。 photosynth.co.jp Akerunにご興味のある方はこちらから akerun.com