大井町.pmとして大吉祥寺.pm 2026で基調講演してきた

いつもお世話になっております。わいとんです。

タイトルの通り、大井町.pmとしてまいんだーさんと一緒に大吉祥寺.pm 2026にて基調講演を行ってきました。

スポンサー企業さまへ

スポンサー企業の各社さま、大吉祥寺.pm 2026をご支援いただき、誠にありがとうございます!!

皆さまのおかげで、大井町にてビッグな大吉祥寺.pm 2026が大盛況となりました!本当にありがとうございました!!!

大吉祥寺.pm 2026のスポンサー様をご紹介します! - kichijojipm’s blog

上記の吉祥寺.pm公式ブログにて、大吉祥寺.pm 2026のスポンサー企業さまが紹介されております。エンジニア募集をされている企業さまと参加されたエンジニアさんがつながってもらえるなら、基調講演をした者としては冥利に尽きるというものです。

コアスタッフ&当日スタッフの皆さま・JPAの皆さまへ

Magnoliaさんが個人で開催するにしてはもはや巨大なイベントとなった大吉祥寺.pmですが、皆さまのおかげで到達できたイベント大成功だったと思います。ありがとうございます!!

JPAの皆さまについてはこのあとYAPC::Tokyo 2026の開催が控えている中でのご対応だったはずです。ありがとうございます!!

Magnoliaさんへ

Perl Beginnersへご参加いただいたのがおよそ14年ほど前でしょうか。当時Kichijoji.pm立ち上げ前で、イベントをやりたいと言い出したMagnoliaさんの後押しをした記憶がありますが、あの時全力で後押ししたことを今でも誇りに思っています。

そして、大井町で開催するという選択をしていただいたこと、本当にありがとうございます!!ご家族のカルマポイントをお互い気を配りながら、今後も楽しくやっていきましょう!

漫談形式という伝統芸能

参加された皆さま、基調講演、楽しんでいただけましたでしょうか?

大井町.pmということでイベントで皆さんの前に登場する際、だいたい漫談形式をとることがほとんどです。今回の大吉祥寺.pm 2026においても漫談形式での基調講演という形をとりました。ちなみに漫談形式って最初に言い出したのはまいんだーさんです。

今回はトップバッターということもあり、まずは場を沸かせてイベント自体の熱量を高めていくことが重要だと思考えました。漫談形式であれば、これまでの実績値から一定盛り上げることができるのではないかということで、基調講演ながら漫談、というかなり斬新なものになったと思っています。

ところで、この漫談形式での登壇には以下のような系譜があります。

そして今回の大吉祥寺.pm 2026での基調講演へとつながっている次第です。

Xでの事前のマシュマロ募集と回答

今回の登壇では「お悩み相談」ということで、Xで事前にマシュマロを募集していました。募集開始当初、どこまでマシュマロが投稿されるのかまったくわからない状況でしたが、2~3日であっという間に20件を超えるマシュマロ投稿があり、最終的にはスライドで発表した通り、59件のマシュマロが集まりました。

正直なところ、ここまでたくさん集まるとは思っていませんでした。とてもではないが、15分間のセッションで59件のマシュマロに回答するのは無理(うれしい悲鳴)!

…ということで、急遽ひとり1日1マシュマロを目安にまいんだーさんと私でXに事前回答するということをしていました。見ていただけてましたかね?

記念撮影してきた

RubyKaigi 2026のローカルオーガナイザーとしてご一緒させていただいたいかるがさんと記念撮影。

印象にのこった発表

大前提として、どのトークも素晴らしかったです!超高密度な内容だったと感じています!

まず前夜祭から、「かわらないもの」を抱きしめて、大切な人たちとつぎの時代へ (micchieさん) 。このトーク、まずスライドがめちゃくちゃかわいいんです!あと「大切な人を、大切にする」というメッセージ、これは刺さりました。最近結構食らっちゃったこともあってか、なおさらだったかもしれません。

そして本編からは論語・武士道・産業革命から見る かわるもの、かわらないもの (ナカミチさん)。論語と武士道についてはいわゆる思想・哲学の領域にあたるものだと思いますが、産業革命という歴史的事実から変わらないものを論語・武士道に求めたのは鋭いなと思いました。発表内容の良さもあって「こっちが本当のキーノートじゃないですかーやだー!!」なんて思っちゃうくらいでした😅

さいごに

もう細かいことはいいや、めっちゃよかったです!!!!

みんなありがとう!!!

RubyKaigi 2026にLocal Organizerとして参加した

いつもお世話になっております。わいとんです。

私事がかなり立て込んでしまい、また体調を崩すというできごともあり、このエントリを書くまでにかなり時間が経過してしまいました…ひとまず今は無事に生きていますし、健康面でも従前どおりそれなりによろしくやっております。

さて、本題です。さる2026-04-22から2026-04-24の間に開催されたRubyKaigi 2026に、Local Organizerとして参加しました。

※当日はだいぶ余力なくて良い写真が取れなかったので、朝のバス乗り場「若松町バス乗降場」の写真を載せておきます

RubyKaigiとは?

わたしもRubyKaigiそのものには初参加でしたので、なかなかこの説明があっているかと言われると「私はそう理解してます」っていう回答になっちゃうんですけど、だいたい以下のようなイベントだと思ってもらえるとよいと思います。

  • Ruby言語に関する世界最大の国際カンファレンス。
    • Rubyの作者まつもとゆきひろ氏(Matz)をはじめとした錚々たるRubyistたちが世界中から集う。
    • Rubyに関する最新情報、Rubyを使ったたのしいHackなど、Rubyを軸にしたセッションが目白押し。
  • 開催都市をRubyで盛り上げる祭典でもある。
    • 有志や参画企業などによる前夜祭やDrink Upなどのサイドイベントが多数。
    • 街全体をイベントでジャックするような広告・施策もたくさんある。
    • キッチンカーやお弁当など、地元の味を現地で楽しむことができる。

Local Organizerとは?

RubyKaigi自体が毎回開催都市を変えて開催しているため、その開催都市ごとの事情に詳しいスタッフが必要となります。

Local Organizerは開催都市の事情に詳しい地元民や出身者の中でも、Rubyコミュニティに造詣のある人やテックカンファレンスのコアスタッフ経験者、あるいは関係する地元有志などで構成されるスタッフです。

※でもたぶん明確な基準はないんじゃないかな、わかりませんが。必要なのは情熱だと思います。

今回わたしは、函館出身者でありかつ、テックカンファレンスのコアスタッフ経験者ということもあり、このLocal Organizerとしての参加となりました。

わたしとRubyの関係性

わたしのことをよくご存じの方々の中には「わいとん、お前Perlの人間じゃないのか?Rubyなんて触ったことあるのか?」という疑問をお持ちの方もいるのかもしれません。はい、そこまで触ったアピールをできるほどRubyを使った経験があるわけではありませんが、一応合計すると2年ほどRubyを使っていました、ということになります。

まあしかし私自身は頻繁に触る言語ではないのですが、言語としてはよくできていると思いますし、一時期AIにアプリケーションを生成させる際にRubyを選んでいた時期もあります。

…という程度の関係性ではあります。なのでずぶの素人ではないんじゃないかな、と。

参加のきっかけ

NT函館2024での出来事

以前、NT函館2024にて出展側として参加していた際、NT函館コアスタッフのジャンボさんが、函館にRubyKaigiを誘致した塩山さんと引き合わせてくれたんです。

その際、塩山さんから「YAPC::Hakodate 2024の実行委員長だって聞きました。RubyKaigiもぜひご協力お願いします」とお声がけいただき、参加すると決めました。

感謝したいこと

まず塩山さんの話を聞いた時点でかなり驚きました。YAPC::Hakodateの計画よりも前にすでにRubyKaigiの函館開催が決まっていたらしく、偶然とはいえ、テクノロジーで函館を盛り上げるという熱い思いは一緒だった。誘致してくれた上にお声がけまでしてくれた塩山さんには本当に感謝しています。また一緒に何かやりたいって思っています。

それから、日本Rubyの会の皆さまには感謝してもしきれません。函館であんなに大規模なテックカンファレンスは、私の知る限りではこれまでなかったと思います。函館で開催すると決めてくれたことに心から感謝します。

あと、スタッフの皆さまにもお礼したいです。当日小ホールスタッフだった皆さまや、私が本業に忙殺されているときにさまざまフォローをしてくださったLocal Organizerの皆さま、とくにいかるがさんやせりまつさん、塩山さん、awaitさんには大変助けられました。ありがとうございます。

そして、登壇者の皆さま、お疲れさまでした。素晴らしい発表をありがとうございました。皆さまのおかげで大盛況でしたし、街が大変賑わいました。

もう一名、ゼッタイに感謝したい人がいます。まつもとゆきひろさん、Rubyを作ってくれてありがとうございます。私はRubyを「たまに触る」程度のプログラマーですが、Rubyというプログラミング言語のおかげで函館にRubyの祭典が開催される運びとなりましたし、そしてRuby製のソフトウェアのおかげで日々の運用業務を助けられています。あなたをバス乗車に誘導したロン毛着流しの中年、それがわたしです。ありがとうございます。

Local Organizerとしてやったこと

バスの手配と乗車案内

バスの手配、これがわたしの主な役割だったと思っています。字面だけで見ると平和そうに見える役回りですが、北海道らしく「試される役割」だったとも言えるかもしれません。

函館という街の特性として、超大型観光船が度々やってくる街だということがあります。これらの船からたくさんの観光客が市中に流入してきますが、彼らはバスツアーを組んで観光をします。この特性を覚えておいてほしいです。

さて、わたしがLocal Organizerとして活動を開始した初日に役割分担を行いました。ここでバスの手配の役割を承ってから知ったのが、**MSCベリッシマの寄港日がRubyKaidyのDay1と被っていた**ことでした。

MSCベリッシマというのは日本の港に立ち寄る客船としてはナンバーワンの大きさ・乗船客数(5,686名!!)を誇るクルーズ客船です。リンク先を見てもらえるとわかると思いますが、街そのものが船としてやってくる、そんなイメージの巨大客船です。

MSCベリッシマ…バスツアーを組んで観光…何が起こるかわかるでしょうか?答えは 「バス会社からバスが枯渇する」 です。

このことから、Day1のバス手配については相当苦労しました。地元バス会社はバスがなく、となり町のバス会社さんが唯一バスを2台出せます、という状況が長く続きました。

一時は室蘭や苫小牧、小樽、青森、網走などからバスを呼び寄せることも検討していた矢先、網走のバス会社さんが実は函館営業所を構えていたことを電話口で教えてくれたのです。

おかげでどうにかとなり町のバス会社さんと網走のバス会社さん(函館営業所)からバスを工面いただき、目標の輸送力を満たすことができたのでした。

市電の車内広告の手配

開催期間中、函館市電に乗車された方は気が付いたかもしれないですが、RubyKaigiの車内広告の手配を担当しました。

5台のうち1台だけ、車内をジャックするような広告配置をしたのですが、市電の車両数自体も結構多めなので、見つけた方はレアかもしれませんね。


ゴミ収集業者の手配と分別指示

ゴミ収集業者の手配も担当しました。以前YAPC::Hakodateでゴミ収集をお願いした業者さんに今回もお願いしたのですが、これには理由がありました。

まず、ゴミ収集業者ごとにゴミ分別のルールがある程度異なるのですが(自治体ごとのものとは別)、この業者さんは再分別プロセスに力が入っているおかげか、現地での分別が比較的細かすぎない点がありがたい。

そして、回収タイミングや回収用機材の調整でかなり小回りが利くわりに、実直な予算で対応してくださる。

イベント運営をする上でのインフラとして大変便利だと感じました。

小ホールの「番長」

開催期間中は小ホールのリーダー、自分の中では「番長」なんて言い方をしてたんですが、これをやらせていただきました。

Day1は空調が微妙だったのと、換気が難しい構造ということもあり、皆さまには暑苦しい思いをさせてしまった点については本当に申し訳なく思っております。Day2とDay3ではこれを受けて、朝一から換気と空調を全力でととのえにかかりました。

なお、小ホールのセッションはことごとくわたしにぶっ刺さる内容でした。なんですか、Rubyで8bitゲームをつくったり、演奏したり…面白すぎましたよ。

すごいと思ったこと

1000人オーバーの参加者数 x 3日間の祭典

イベントで1000人以上も集まることなんて、函館ではまず激レアなことです。それも世界中からRubyistが集まってきていた。

函館で?ほんとかよ?って思ってましたよ。とにかく参加者全員が楽しそうだし、Day3あたりだと地元めしの話をしてた海外勢もいて、いいぞいいぞと心の中でガッツポーズをとったりしてました。

Ruby濃度100%

タイムテーブルを見てほんとうにすごいと思ったのが、Rubyの話をしないセッションが一切ないということ。

これについてはOrganizerの皆さまの矜持と登壇者の情熱を感じますし、言語カンファレンスはこうなっててほしいよな、とも思いました。

また、キーノートで発表されたMatzの新作Spinelについては、Rubyという言語の新しい可能性を感じずにはいられなかった。おもしろいことやってるなあと感じましたよ。

全力の地元グルメ

キッチンカー、お弁当、バーガー、おやつ、等など…とにかく函館の地元グルメをLocal Organizerたち総出で選出したわけですが、圧巻でしたね。

参加された皆さんは何がお気に入りでしたかね?

わたしはとんきのロースかつ弁当をDay1とDay3のお昼に、五島軒のカレーライスをDay2のお昼に、それぞれいただきました!どっちもめちゃくちゃ大好きなんです!

さいごに

とにかく皆さんが楽しんでくれたことが、Local Organizerとして何よりうれしいことです。そして、函館という街も、Rubyコミュニティも大いに盛り上がったと思います。

次のRubyKaigiは宮崎での開催とのことですが、ぜひとも街ごとRubyKaigiが活況になるといいと思っています。わたしも参加するぞ!

MADFLOW - AIによるcalcium言語の全自動開発

いつもお世話になっております。わいとんです。

さて、皆さんはAIで全自動開発やっていますでしょうか?今回のエントリでは、私が実務でも導入をし始めている「AIによる全自動開発」について書いていこうと思います。

MAXAMの開発と「将軍」の登場

わたしが前回公開したエントリでは、MADT(Multi Agent Develop Team)という概念を提唱しましたが、これはAgent Orchestrationという用語で語られるものとほぼ同一のものでした。

そして、その実装としてMAXAMというものを作って利用していました(余談:物のついでに萌えキャラを充ててあげたら、なぜかすごくアイマスっぽいキャラが錬成されましたのでそのまま採用した)。

しかし、先月中旬あたりからこのように思うようになりました。

「エージェントの種類が多いと効率が悪い。」

これについて、今となっては当然ともいえる共通認識が醸成されつつあります。とはいえ、当時はまだAgent Orchestration自体がかなり珍しいものでありました。

一方でそのころ、multi-agent-shogun(以下「将軍」)をはじめとしたオーケストレーターも登場しました。

カオスなMAXAM、もう少し整然とした将軍

わたしはMAXAMを、将軍の登場とほぼ同時期にOSSにしており、開発自体も将軍の公開とほぼ同じ日に開始していました。ただ、そのアプローチが驚くほど異なっていまして…

MAXAMはエージェント同士がテキストチャットでわちゃわちゃとやり取りするように作られており、結構カオスになりがちでした。見ている分には正直かなり楽しかったです。一方、将軍はやり取りのフローが構造化されているので、より実践的だと感じました(見た目的にも家老が過労死しそうになってるのが面白かったり…ね)。

将軍はその構成が大変よくできており、エージェント同士による対話が文字通り組織化されているおかげで、エージェント一人ひとりの役割がはっきりさせることに成功しています。

これは、各エージェントの役割ごとにやり取りする相手が限定されていることが有効に働いているということでして、MAXAMとの決定的な違いでした。

MAXAMでの教訓を受けてエージェントフローを再設計

MAXAMでは以下のような問題が発生していました。

  • メンションベースでエージェント間のやり取りを実現していた。
    • エージェントがメンションを忘れる
      • 作業がとまる
      • やりとりが断絶する
      • 他のエージェントがツッコミを入れる
      • ツッコまれたエージェントがツッコミを入れたエージェントとやり取りをし始める
      • 本来やり取りする相手が置いてけぼりを食らう
  • どのエージェントも等しくどのエージェントに対してもコミュニケーションをとることができた。
    • 雑談を始める
      • 本来のタスクをこなさなくなる
      • さぼり方を相談し始める
      • 本来の仕様を無視・改ざんしようとする

使えるかい、こんなもん。

ごもっともです。私も途中で頭に来まして、2月下旬には別のオーケストレーターを設計し始めました。

それがMADFLOWです。

※ごめんなさい、使い方はリンク先見てほしいです。そんな難しくないです。なんとかclawよりはセットアップも楽です。

エージェント同士のやり取りは最小限に。GitHubのissueに対して作業を行う。

MADFLOWはエージェントの構成を最小構成にしました。つまり、エージェントとしては「監督(superintendent)」と「エンジニア(engineer)」だけとし、

監督 : エンジニア = 1 : N 

となるようにしました。やり取りもエンジニア同士は行わない。監督とエンジニア1 : 1のやり取りだけです。

また、GitHubのissueをポーリングすることにしました。これにより、issueを立てるだけで監督がissueを検出し、エンジニアに指示を行い、エンジニアがドキュメント整備・テストコード&実装コードの錬成を行うようになりました。

GitHubのissueで指示を出せるようになると、もはやスマホさえあれば開発がガンガン進むのです。

コードレビューは廃止。テストコードとQAで仕様担保。

もともとMAXAMではコードレビュアー専属のエージェントを用意してましたが、これが異常にコストがかかる割には品質担保として意味がないと気が付きました。どういうことかというと、品質担保は結局動作確認しなければ得られないのと、テストコードで担保できるのは「数学的正しさ」による正当性の範囲である、ということです。

AIによる全自動開発を推し進めることで、以下のことが明確化できたと思っています。

  • 「人間がレビューすれば品質担保できる」というのは幻想。
    • 人間が一番レビュー漏れをやらかす。
      • ただし、AIもレビュー漏れをやらかす。
      • つまり、レビュー自体は品質担保を目的にやるものであってはならない。
      • テスト・CI・型システム等の自動検証の積み重ね。これらが品質担保に対しての施策。
  • なぜレビューするのか?
    • 設計判断の共有
    • 知識移転
    • 属人化の分散
    • メンテナンス性の保持
    • 誤った実装の予防
    • … これらは全部「コードを作ったのが人間」だから意味のあること
    • AIに設計判断を共有する方法はほかにある。markdownに書きましょう。
    • AIに知識移転する方法もほかにある。markdownに書きましょう。
    • AIで全自動開発するなら属人化は起こらない。なぜなら人ではなくAIに依存しているから。
    • AIが作るコードはメンテナンス性が低いか→ダウト。設計意図を同梱させないからメンテナンス性が低下するのである。
    • AIは実装を誤る→ダウト。AIに出された指示が誤っている。
  • ドキュメント(とくに要件定義書)は腐る
    • →その通り。ただしテストコードは要件定義の写像。
    • つまるところ、要件定義からテストコードを起こし、テストコードから実装を写像として起こす。これ。
    • 後からテストコードをいじる → ダウト。要件定義を先に修正する必要がある。

ちょっと文章にすると長くなるので箇条書きにしちゃいましたが、意図は汲み取ってもらえるのではないかと思います。

Calcium言語をMADFLOWで実装中

最近もちまちまとMADFLOWに指示を出すことでCalcium言語を実装しています。が、最近はちょっと小休止中といったところ。言語としては一通り動くところまではできたかと思います。

完全に全自動で開発できており、富士五湖バイクツーリングの休憩中に指示を出して、次の休憩ポイントにつく頃には実装が完了してdevelopブランチにマージされている、という体験が得られました。developブランチへのマージまで自動でやります。CI/CDが通っていればマージ。簡単な事前レビューはしますけど、実装漏れを防止する観点のものであり、品質担保はCI/CDとmainブランチへのマージの前にAIが簡単な動作確認を行うことで担保としています。

調査や検証、レポート作成もMADFLOWで自動化

つまり、MADFLOWをGitHubレポジトリでドキュメント類を管理・編集するものと捉えることもできます。

裏でコマンド類を実行してくれますから(きょうびのAIなら当然やります)、大抵のCLIでできることはできる。それでもってGitHub経由で調査・検証・レポート作成してくれるわけです。

まとめ

疲れたんでこの辺にしておきますが、ざっくりまとめると以下の通りです。

  • 将軍とMAXAMからいろんな示唆を得た。
  • MADFLOWで全自動開発やろうと思えばできるっぽい。
  • AIによる全自動開発では品質担保の意味や方法が変わる。
  • 調査・検証・レポート作成もMADFLOWで全自動化。

ちなみにMADFLOWはGo製のワンバイナリとなります。利用したいプロジェクトでお使いいただければ、比較的簡単にGitHub issueドリブンの全自動開発が始められます。READMEをよく読んでお使いください。あと自分用に作ったものでもあるので、そのあたり自己責任でお願いします。

おまけ:MADFLOWで便利なissue

あと、上手な使い方の一つとして、issueをたくさん立てさせるissueを作ると、非常に便利です。以下のタイトルのissueを私はよく立てます。タイトルだけで大体何とかしてくれます。

  1. 「このプロジェクトの要件定義を確認し、実装計画を立てる」
  2. 「実装計画に基づき、実装完了までのイシューをすべて作成する」

1→2の順番でissueを処理させると、あとは黙ってても実装してくれます。作業が滞ることもありますが、大抵はLLM APIのスロットリングを受けて休憩している状態となります。

MADT: Multi Agent Development Team はすぐにやってくる

いつもお世話になっております。わいとんです。

1人で開発チームを回せたらなぁ、って思ったことありませんか?

要件定義、実装、レビュー、QA、それぞれ別の視点が必要じゃないですか。でも人を雇うのは大変だし、コストもかかる。

MADTはその答えになるんじゃないかって思っているんです。

MADTとは

MADT (Multi Agent Development Team) は、複数のAIエージェントが協調して開発業務を遂行するチーム構成のことです。私がここではじめて提唱する概念です。

各エージェントが専門の役割を持って、人間のチームみたいに連携します。私の観測範囲では、これに該当するものもいくつか開発されているようで、すでに実運用されているものもあると思います。

構成例

私が構築したMADTは4人構成です(これについては現状クローズドソース)。ざっと以下の通り。

名前 役割
Mei 要件定義 + PM
Yuki 実装 + インフラ
Priya レビュー + セキュリティ + QA
Amara 分析 + 改善提案

各エージェントはClaude CodeをMCP (Model Context Protocol) 経由で操作して、独立したプロセスとして動きます。

アーキテクチャ

1
2
3
4
5
6
7
8
9
10
┌─────────────────────────────┐
│ Orchestrator (Go) │
│ - Slack/GitHub連携 │
│ - エージェント管理 │
│ - チームチャット │
└──────────────┬──────────────┘
│ MCP (stdio)
┌──────────┼──────────┐
▼ ▼ ▼
[Mei] [Yuki] [Priya] [Amara]

エージェント間のやり取りはチームチャットでやってます。人間も同じチャットに参加できるので、自然にチームの一員として会話できます。

特徴

1. 役割分離による品質担保

実装者とレビュアーが別なので、馴れ合いが起きません。Priyaは遠慮なくYukiのコードに指摘を入れます。

2. 自己改善

すべてのやり取りはログに残ります。Amaraがそれを分析して、改善提案をCLAUDE.mdに反映します。これでチームが自律的に成長していくようになる。

3. 無限ループ対策

レビュー差し戻しが3回を超えたら、上流 (設計や要件) に問題があると判断してエスカレーションします。下流で無理に解決しないようにするためです。

実績

ところで、これをCalciumっていう自作言語の開発に投入したんですが、だいたい3時間で6つのPRがマージされました。

  • コマンド追加
  • オプション追加
  • バグ修正
  • ドキュメント同期

人間1人でやったら数日〜1週間かかる量ですよね。

人間の役割

じゃあなんだい?MADTがあれば人間は不要なのかい?と疑問が浮かんできますよね。でもそうじゃないんです。

人間はスーパーバイザーとして:

  • アーキテクチャ判断
  • エスカレーション対応
  • 最終的な品質担保
  • 顧客とのハイレベルなコミュニケーション

を担います。手を動かすのはAI、判断するのは人間の役目です。

まとめ

MADTは「AIに仕事を奪われる」じゃなくて「AIとチームを組む」っていう発想・概念です。

1人でも開発チームを持てる時代が来てるってことです。しかも爆速で開発してくれる。見えてくるものが変わってくるやつだと思いませんかね。

Calciumというプログラミング言語を作り始めた

いつもお世話になっております。わいとん(@ytnobody)です。

新年も25日が経過し、月日の流れの速さを感じるこの頃です。

さて実は2~3日前くらいからCalciumという言語を作り始めておりまして、今回はその紹介をしておこうということで筆をとった次第です。

Calciumという言語の特徴

ではCalciumの特徴をばばっと列挙しましょう。

  • 100%AIドリブン開発
  • Goで作られている
  • バイトコードへのコンパイル
  • 動的型付け・関数型
  • イミュータブル
  • 制約という仕組み
  • 副作用の可視化
  • 制御構文は基本matchmapだけ
  • 関数の制限
  • イベントドリブンな待ち受け構文

100%AIドリブン開発

Calciumの開発は100%Claude Opus 4.5で行われております。というか、AI以外にコミットさせるケースはほぼないです。今後もほぼ100%AIによってコードが書かれることになります。

これには大変重要な理由があり、もちろんAIもミスをしますが、人間である私はさらにしょっちゅうミスをするから、というものです。人間の中でも私は極めておっちょこちょいですから(注意力3万しかない)、これを信用仕切るのはリスクが大きすぎる。それならまだAIのほうが信用できるというものですし、AIのミスを私が指摘するということもすでに行われていますので(当然逆のほうが多いけど)、昭和的な言い方をするなら、常にダブルチェック体制で開発されているということになります。

あと、AIのほうがコードを素早く作成します。私のように40代半ばの体力が衰えているおっさんなどよりもはるかに素早い。なので、自分の役割はAIに仕様を伝えて設計の伴走をするということに徹しております。

Goで作られている

コンパイラ、トークナイザー、パーサー、レクサー、などなど…いま疲れてるのでアルファベットを打ち込むのが面倒でついついカタカナで書いちゃいましたが、これらのものをすべてGo言語で実装してあります。単純にいろんなOSやCPUアーキテクチャに対応させるうえで、Goは手早く開発できるという経験則があります。

また、AIにとっても比較的書きやすく、学習量も相応にあります。成果物も単体バイナリとなりますから、配布する上で非常に好都合。実行速度も比較的軽快な傾向にありますし、プログラミング言語を作るうえで大変実用的な言語だなあと。私にとってはそれがGoだったのです。

バイトコードへのコンパイル

Calciumは専用VM上で動作する言語として開発をはじめました。そのため、ソースコードをバイトコードへコンパイルする機能があります。

一応REPLもありますし、その気になれば単一実行バイナリを生成することも可能です。

バイトコードへのコンパイル時に、実行速度やコンパイル後の重複コードの最適化も行われます。そのため、一見ムダが大きそうな以下のような処理もほどほど悪くない速度で動作するようになる、と思われます。

1
2
3
4
5
6
7
8
9
use core.io!;

// 2つの値を加算するだけの関数
func add(x, y) = x + y;

// ↓同じ引数で同じ関数を2度コールするがコンパイル時に最適化が行われる
func my_calc(x, y) = add(x, y) * add(x, y);

[2, 3]... |> my_calc !> io.say; // <--- 25

動的型付け・関数型

Calciumは関数型言語でして、いっぽう今さらながら動的型付け言語です。そう、Elixirなんかと同じですね。

でも動的型付けにしたのには私なりに考えがあるんですよ。私、普段はGoやTypeScriptをAIに書かせることがほとんどなんです。しかしですね…PerlやRubyなんかも気まぐれにAIに書かせてみると、これが予想以上にスルスルと意図した通りのコードを生成してくれる。おまけにトークン消費量がTypeScriptやGoなんかよりもだいぶ少ないんですよ。

これは私の体感によるものかなあと思っていたのですが、実際のところ大マジメに検証した人がいるらしく、その結果が以下のポストにチャートとして表わされていました。

ということで、AIフレンドリーにしたいなあ、という欲もありましてこのような選択をしたわけです。

イミュータブル

変数への再代入も厳に禁じました。関数型言語にした理由とも被るところがありますが、やはりAIフレンドリーにしたいという点もありますし、そもそも状態をプログラムの責務として偏在させたくないという思いがあります。

なお、どうしても状態管理(というかイベントドリブンな待ち受け)が必要なシーンではどうするべきか、というのは後で紹介する機能 async.stay でカバーさせることにしました。

制約という仕組み

Calcium言語は動的型付け言語ですから、無対策では関数にどんな値が入ってくるのかわからず、コンパイルする利点がだいぶ薄れてしまいます。

ところが変数への再代入を禁じた上でこの「制約」という仕組みを利用することで、型とは違う方式で安全性を担保しつつ、コンパイル時にも最適化が働くといううまみを得ることを狙いました。

1
2
3
4
5
6
7
8
9
10
use core.io!;

// 0より大きい値であることを制約する
constraint Positive(n) = n > 0;

// 100はPositive制約に準拠している
100 |> Positive? !? {
success(v) => "OK: ${v}" !> io.say
failure(e) => "NG: ${e}" !> io.say
}; // --> OK: 100

なんだよ、ただの名前付きバリデーションじゃないか、と思ったそこのあなた!実に察しがよろしい、その通りなんです!でも、これなら型パズルでAIトークンを消耗することもないですし、ビジネスロジックをそのまま制約として記述できますよね。

ただ、今のところ関数の引数に対してこの制約を適用する機能は未実装です(実装予定はあります)。

副作用の可視化

この言語の結構大きな特徴のひとつがこれ。副作用を可視化することで、ビジネスロジックを純粋に保つことが可能となります。

そのための手段として、関数定義自体がfuncfunc!の2種類ありまして、!が付いている方は副作用があります!という風になっているというわけです。

パイプライン演算子についても|>!>があり、こちらも!が付いている方は右辺に副作用があることを示します。

さらに、モジュール名にも副作用が含まれる場合には!が付く。さっきから例示しているコードにあるuse core.io!;という行ですが、これにも末尾に!が付いている通り、副作用が含まれるモジュールとなります。だいたい標準出力も副作用ですからね。このあたりはとても厳格です。

1
2
3
4
5
6
7
8
use core.io!;

func add(x, y) = x + y;
func my_calc(x, y) = add(x, y) * add(x, y);

[2, 3]...
|> my_calc // <-- これは純粋関数なので普通のパイプライン演算子でコールする
!> io.say; // <-- これはio.sayが副作用をもつ関数なので、副作用パイプライン演算子でコールする

上記の例ではio.sayのところを普通のパイプライン演算子でコールすると以下のように怒られます。

1
2
3
4
5
6
$ ./calcium run ./foo.ca 
./foo.ca: error
line 8, column 5:
|> io.say;
^
cannot use '|>' with effect function; use '!>' instead

制御構文は基本matchmapだけ

この言語の非常にとがった特徴がこのあたりでしょう。if, else, for, while, switch。これらは全部ありません

if, else, switchのかわりにmatchがありますから、そちらを使っていただくということで頑張っていくという言語です。

またwhileasync.stayで代用が可能(なんとコアモジュールに追い出されています!)でして、forのかわりにmapを使ってください、ということです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
use core.io!;

func fizz(n) = match n % 3
0 => "Fizz"
_ => "";

func buzz(n) = match n % 5
0 => "Buzz"
_ => "";

func fizzbuzz_or(result, n) = match result
"" => to_string(n)
_ => result;

func fizzbuzz(n) = fizz(n) + buzz(n)
|> fizzbuzz_or(n);

"FizzBuzz (1-15):" !> io.say;
range(1, 16)
|> map(fizzbuzz)
!> io.say;

上記の例ではFizzBuzz問題を解いていますが、場合分け処理が必要なfizz,buzz,fizzbuzz_orの3つの関数でifなどではなくmatchがつかわれています。

また、数値配列に対して順番に処理を行うためループ処理を行いますが、forではなくmapをつかっています。

関数の制限

なんと、Calciumでは関数はシングルステートメントに限定されます。つまり!2つ以上の処理をしたければパイプラインを使うか、関数を分けるしかないということになります!

なぜそんな制限を設けているのかというと、マルチステートメントをサポートすることで関数自体の複雑度が爆上げしてしまうので、それをなくしたいという思いからこのようになっています。

パイプラインであれば、どこからが副作用でどこまでが純粋なのか一目で把握できます。ビジネスロジックに副作用が入り込んでいることがわかれば、ビジネスロジックのテスタビリティを向上させるために副作用を分離したくなるというものでして、そのようなリファクタを行いやすくするためなのです。

イベントドリブンな待ち受け構文

言語の基本機能ではなくコアモジュールの機能ではあるのですが、いわゆるwhileループの代わりになるのがasync.stayです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
use core.io!;
use core.schedule!;
use core.async!;

// async.stayでwhileループのように待ち受ける。waitは状態変数、5000が初期値。
result = async.stay(wait: 5000) {
src = schedule.timeout(wait); // <-- 5秒経過したらsrcがsuccessとなるか、どこかのタイミングでfailureとなる。
handler = async.expects(ev => async.leave("completed"), src); // <-- srcを監視し、trueになった瞬間にasync.leaveする。
handler.ready() // <-- srcを監視し始める。
};

// resultに結果が入っているので、出力する。
result !? {
success(v) => io.println("Result: " + v)
failure(e) => io.println("Error: " + e)
};

上記の例ではasync.staywhileループのような役割を行っています。async.stayブロックには引数としてkey: valueの形式で複数の値を状態変数として渡すことが可能です。

なお、ひとつのasync.stayに対して複数のasync.expectsを設定することが可能です。async.leaveがコールされた時点で、特段の指定がなければasync.stayは処理を終了します。

複数のイベントをこの構文で待ち受け可能ということです。

Calciumの現状

はっきり言ってまだ作り始めてから数日ですから、粗もバグもあると思います。しかし、いったん動作させることには成功していると言える状態には持ってきたと思います。

また、エコシステムも現状開発中でして、近いうちにモジュールレジストリboneyardとモジュールマネージャーboneが連携して動作するようになる予定です。

バイトコードへのコンパイルとバイトコードの実行は現時点で概ね動作していますが、外部モジュールのバンドル等についてはまだ現時点では実装ができていません。

まとめ

ひとまず、AIに色々指示を出してCalciumを作っている、という状況です。また進展があったらエントリを書くと思います。気長にお待ちいただけますと幸いです。

AirGit 0.0.3 has been released

いつもお世話になっております。わいとん(@ytnobody)です。

今年もいよいよ終わりが近づいてきましたね。私はいま、お花摘みを我慢しながらこのエントリを書いています。

さて、この度私はAirGitというソフトウェアを考案・公開しましたので、お知らせいたします。

AirGitというものを作りました。

AirGitというのは、ブラウザから直接Gitリポジトリを管理できる軽量なWebベースのGitクライアントとなります。push、pull、branch作成、remote管理など、モバイルフレンドリーなUIで操作可能となっているのが特徴です。

リモートホストにあるGitレポジトリたちを、スマートフォンからブランチ操作をしたり、pushしたりタグを作ったりしたいなー、という要求を満たすために作りました。

AirGitの特徴とできることは以下の通りです。

  • ワンタップ操作を重視したモバイル最適化UI
  • 複数リポジトリ管理(ローカルファイルシステム)
  • ブランチ完全管理(一覧表示、作成、チェックアウト、削除)
  • Gitタグ管理(一覧表示、作成、プッシュ)
  • Git操作(プッシュ、プル、ステータス確認)
  • リモート管理(追加、更新、削除、選択)
  • リポジトリの初期化と作成
  • コミットの先行/遅延追跡
  • モバイル最適化UI(下部ナビゲーションバー)
  • PWAサポート(オフラインキャッシュ、ホーム画面アイコン)
  • コミット履歴表示(過去20件)
  • User-mode Systemdサービスへの登録と管理
  • 設定メニューによる構成

(AirGitの見た目。きわめてシンプル。)

正直なところ、Ubuntu Linux以外での動作はまったく確認しておりませんので、何か問題があればIssueでお知らせください。

Goで作られていますから、リリースバイナリをDLし、実行するだけでアプリケーションが起動します。

amd64なCPUのLinuxの場合は…

1
2
$ chmod +x airgit-linux-amd64
$ ./airgit-linux-amd64

これだけで http://localhost:8080 が立ち上がるようになっています。

vibe-kanban + tailscale + AirGit = スマホだけでvibe coding

AirGitは、その真価をvibe-kanbanおよびtailscaleと組み合わせたときに発揮できるものとなります。

vibe-kanbanは、カンバンのような見た目のボードでvibe codingを行うツールです。vibe-kanbanにレポジトリを追加し、カンバンに新しいタスクを登録すると、AIがコードを仕上げてくれるという優れもの。ちょっと前までは結構不具合も多かったのですが、ここ2か月くらいで安定して使えるようになった感があります。

但し!vibe-kanbanだけではgit pushをはじめとしたgitレポジトリの操作ができないのです…(仮にできたとしてもボタン一発、とはならない)。

そこでAirGitを使って、スマホからgit pushしてやろうぜ、という目論見です。

(vibe-kanbanのカンバンボード。AirGit開発中のもの。)

一方、tailscaleはVPNを構築するためのツールであり、iOS, Android, Linux, Windows, MacOSなどなどに対応しています。

つまり、vibe-kanban、AirGitを開発マシン(Linux)に立ち上げておき、tailscaleを開発マシンとお手持ちのスマホに入れておけば…スマホだけでvibe codingが可能な環境を作り上げることができちゃう、というわけです。

AirGitはvibe codingの産物

ところでもうすでにお気づきの人もいると思いますが、AirGitはvibe-kanbanによるvibe codingだけで作られています。

途中からAirGitそのものを使ってレポジトリ管理をしていますから、実際のところはドッグフーディングしながら作ったことになります。

その気になれば、AirGitにvibe codingの機能を組み込むことも可能でしょう。今のところ、そこまではやろうと思っていませんが。

なおすでにvibe-kanbanには2つのissueを起票しておりまして、vibe-kanbanでgitレポジトリの操作ができるようになれば、AirGitはお役御免になると思います。が、そこまで待ってられないので、AirGitを作ったんです。

まとめとか雑感とか

AIにGo書かせるのいいですね。TypeScriptよりも正確かつ実用的なものが素早く安価に得られていると思います。

今後、こういう感じで自分が欲しいツールは小さくまとめてAIに作らせていく、というのが開発スタイルの主流になりそうな気がします。

AirGitについては、もし試しに使ってみたという方がいれば、感想や要望などお聞かせいただけると嬉しいです。

MCPとかTOONとか

いつもお世話になっております。わいとん(@ytnobody)です。

さて、ただいま宿泊先のホテルのロビーでほろ酔い気分でこのエントリを書いています。Perl Advent Calendar 2025のday 6となります。

みなさんはMCPサーバーというものを使ったことはありますでしょうか?AIにコードを書かせているような人は間違いなく使ったことがある側の人だとおもいます。

ではMCPサーバーを作ったことはありますか?私はこのエントリを書くまではまったくありませんでした。もっぱらMCPサーバーについては使うばかりでした。

しかし、なんとPerlでもMCPサーバーが書けるということらしいです。どうにか私もMCPサーバーをPerlで書きました。正確には私がAIに指示を出して書いてもらったのですが…

MCPサーバーをPerlで作るには

実はPerlでは非常に人気の高いWebフレームワークとしてMojoliciousが挙げられます。この作者であるSebastian Riedelさんによって、その名もずばりMCPというモジュールが作られています。

Mojoliciousで/mcpパスをMCPサーバーとして公開する場合、以下のようにすればよいようです(SYNOPSISそのまま)。

1
2
3
4
5
6
7
8
9
10
11
12
13
use Mojolicious::Lite -signatures;
use MCP::Server;
my $server = MCP::Server->new;
$server->tool(
name => 'echo',
description => 'Echo the input text',
input_schema => {type => 'object', properties => {msg => {type => 'string'}}, required => ['msg']},
code => sub ($tool, $args) {
return "Echo: $args->{msg}";
}
);
any '/mcp' => $server->to_action;
app->start;

なんか思ったより簡単そう。でも、そもそもHTTPでの通信すら面倒だからSTDIO(標準入出力)でやり取りさせたい。という場合にはSTDIOトランスポートを使うとよいのだそう(SYNOPSISママ)。

1
2
3
4
5
6
7
8
9
10
11
12
use Mojo::Base -strict, -signatures;
use MCP::Server;
my $server = MCP::Server->new;
$server->tool(
name => 'echo',
description => 'Echo the input text',
input_schema => {type => 'object', properties => {msg => {type => 'string'}}, required => ['msg']},
code => sub ($tool, $args) {
return "Echo: $args->{msg}";
}
);
$server->to_stdio;

これならHTTPで公開するわけじゃないから、手元で試すのに便利そうです。

さて、これを参考にClaude Haiku 4.5にオレオレMCPサーバーを作ってもらうことにします(成果物はこのあと紹介)。

MCPクライアントはどうするか

色々調べてみたんですが、やれClineをつかえだの、やれClaude Codeがいいぞだの、色々あるっちゃああるんですよ。

でも、これもPerlで作ったらいいじゃないですか。雑なMCP ClientをPerlで作ってはいけないという決まりはありません。だいたい、ツールを増やしたいわけではなく、自作MCPサーバーとやり取りできるクライアントが欲しいだけなんです。無料でアカウントを作らせようとするおせっかいはここでは不要なんですよ。

で、MCP::Clientというモジュールもあるにはあるのですが、これはHTTPベースのトランスポートしかサポートしておらず、STDIOトランスポートは未サポート。

仕方がないので、これもClaude Haiku 4.5に作ってもらうことにしました(このあと成果物を紹介)。

そういえばちょっと前にTOONというものが話題になったな?

何週間か前くらいにTOON(Token Oriented Object Notation)というデータフォーマットがにわかに話題になっていました。

いわく、LLMのトークン削減に効果的な構造化データフォーマットだー、みたいなことが特徴らしいのですが、まあ良く見ると、なんとPerl向けモジュールがあるとのこと。

老後に趣味のPerlを盆栽のように楽しみたい者としてはニッコリな状況というわけですが、ああ思い出した、これは私が「Perlモジュールがない」という理由で高血圧をこじらせてしまいそうだったので、慌ててClaude haiku 4.5に作らせたのでした。ここでこのData::TOONを作っていなければ、大好きなサウナをまた我慢しなければならないところでした。

ちなみに使い方はこういう感じ(SYNOPSISママ)です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
use Data::TOON;
# Basic usage
my $data = { name => 'Alice', age => 30, active => 1 };
my $toon = Data::TOON->encode($data);
print $toon;
# Output:
# active: true
# age: 30
# name: Alice
my $decoded = Data::TOON->decode($toon);
# Tabular arrays
my $users = {
users => [
{ id => 1, name => 'Alice', role => 'admin' },
{ id => 2, name => 'Bob', role => 'user' }
]
};
print Data::TOON->encode($users);
# Output:
# users[2]{id,name,role}:
# 1,Alice,admin
# 2,Bob,user
# Alternative delimiters
my $encoder = Data::TOON::Encoder->new(delimiter => '|');
print $encoder->encode($users);
# Or with tabs:
my $tab_encoder = Data::TOON::Encoder->new(delimiter => "\t");
# Root primitives and arrays
print Data::TOON->encode(42); # Output: 42
print Data::TOON->encode('hello'); # Output: hello
print Data::TOON->encode([1, 2, 3]); # Output: [3]: 1,2,3

全部混ぜてつくってみた

という、ここまで紹介した要素を全部混ぜてつくってみたのがこちらのレポジトリです。
ざっくり箇条書きで説明するとこんな感じ。

  • MCP::Serverを使ったSTDIOトランスポートなMCPサーバー mcp_server.pl
    • MCPサーバーに必要な基礎機能を全部実装。
    • 足し算、エコー、pingをツールとして実装。
  • まあまあ自力(ではなくAIが全部)実装なMCPクライアント mcp_client.pl
    • クライアントと人間の間のデータ入出力インターフェースはTOONフォーマット。
    • MCPサーバーとのやり取りはただのJSONでやり取り(普通のMCP)。

TOONの意味ねえ!とか、ほかにもツッコミどころだらけではあるんですが、こういうこともできるんすよ、Perlで。って言いたいだけなんで、そこんとこよろしくお願いしたいところであります。

さいごに

MCPで肉体を若返らせることはできませんでしょうか?できませんか、そうですか…

Perlからでもtursoを使いたい!

いつもお世話になっております。わいとん(@ytnobody)です。

さて、ただいま羽田空港の待合所でこのエントリを書いています。Perl Advent Calendar 2025のday 4となります。

内容については、タイトルの通りです。で、それを実現するモジュールを作りました。作ってしまえば、できるのです。

tursoってなんだ?

tursoというのはDB as a Service(DBaaS)の一種です。個人開発勢・小規模開発に特におすすめです。

詳しい特徴等については以下のエントリがよくまとまっていると思います。

ざっくりいうと、めちゃくちゃ安い、SQLiteっぽい、エッジネイティブDBサービスってところでしょうか。なお、正しくはSQLiteではなくlibsqlというもののDBaaSということになるようです。

あと便利機能として、DBスキーマのブランチとマージ機能があるので、Planetscaleっぽくgithubフローに乗ったスキーマ運用が可能だったりします。

今回つくったものたち

で、このtursoですが、公式にはPerlからの接続は基本的にできません。ライブラリの提供もありませんし、ドライバもです。

Perlを老後も趣味で触りたいものとしては、この仕打ちには我慢なりませんでした。このままではただでさえ高い血圧が余計に上がってしまう…

従いまして、これ以上血圧を上げないようにするために以下のモジュールを作りました。

Alien::Turso::CLI

これは要するにtursoコマンドを使えるようにするためのモジュールです。それだけなら、特段このモジュールの必要性はないと思いますが、DBD::libsqlを作るにあたり、ローカルで簡単にturso devを実行できる必要がありました。

このturso devはtursoにアカウントがなくても、とりあえずローカルでtursoサーバーを起動するコマンドです。よって、これを使えばテスト時にモックを作る必要がないのです。

DBD::libsql

さて、これが今回の主役です。

使い方はmetacpanのsynopsisに書いてあるのですが、まあ同じものをコピペしておきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
use DBI;
# Connect to a local libsql server
my $dbh = DBI->connect('dbi:libsql:localhost', '', '', {
RaiseError => 1,
AutoCommit => 1,
});
# Connect to Turso with authentication token (recommended approach)
my $dbh = DBI->connect(
'dbi:libsql:my-db.aws-us-east-1.turso.io',
'', # username (unused)
'your_turso_token', # password field used for auth token
{
RaiseError => 1,
AutoCommit => 1,
}
);
# Alternative: Turso connection with connection attribute
my $dbh = DBI->connect('dbi:libsql:my-db.aws-us-east-1.turso.io', '', '', {
RaiseError => 1,
AutoCommit => 1,
libsql_auth_token => 'your_turso_token',
});
# Create a table
$dbh->do("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)");
# Insert data
$dbh->do("INSERT INTO users (name) VALUES (?)", undef, 'Alice');
# Query data
my $sth = $dbh->prepare("SELECT * FROM users WHERE name = ?");
$sth->execute('Alice');
while (my $row = $sth->fetchrow_hashref) {
print "ID: $row->{id}, Name: $row->{name}\n";
}
$dbh->disconnect;

mysqlやpostgresqlなんかとあまり変わらないと思いますが、接続時にusername相当が空文字だったり、パスワードにtursoトークンをつかうなど、ちょいちょい違う点があります。

でも、それ以外は他と一緒です。拙作のORMもどきであるOtogiriとも組み合わせられますし、他のORMでも使えると思います。

さいごに

最近かいたモジュールはほとんどClaude Sonnet 3.5かClaude Haiku 4.5に書かせておりまして、私自身は設計こそしていますが、細かいコード実装を書いていません。それでもこれだけのモジュールを作ることができますし、AIを使うことを躊躇してる場合じゃない、と思う次第です。

ちなみに、このモジュールはYAPC::Fukuoka 2025でkobaken(@kfly8)さんによって作られ提供されていた「令和最新版Perl掲示板」にて使用されていました。

YAPC::Fukuoka 2025で共同登壇&スタッフをしました

#yapcjapan タグを見てくださいよ。めちゃくちゃ盛り上がりましたね、YAPC::Fukuoka 2025!

そんなわけで、まずスタッフと福工大の山澤先生、スポンサーのみなさん、参加者のみなさん、本当にありがとうございました&お疲れさまでした!!

こばけんさん (@kfly8) と共同登壇しました

Perlの生きのこり というタイトルで、こばけんさんと共同登壇しました。

この発表自体は きのこカンファレンス2025 でやったものではあるのですが、YAPC::Fukuoka 2025向けにかなり研ぎ澄ましておりまして、より本質的な発表となったかと思います。登壇資料についてはこばけんさんから共有があると思いますので、それをお待ちいただきたいと思います。

追記:直後にスライドの共有をいただきました!こばけんさんありがとうございます!!!

きのこカンファレンスの時と違ったのは、漫談風にしながらももう少し変化の歴史と最新の書き方にフォーカスを絞った、ということと、私自身が素面で登壇した(ここ重要)という点でしょうか。

CGIってなんなの?とか、そもそもlighttpdっていうサーバーがあったんだ、みたいな過去の経緯があって今に至っているんだなぁということ。そして 令和最新版Perl BBS を通じて、今どきのPerlってこう書くのか、というのを観測いただけたら幸いです。

あと、資料ぜんぶこばけんさんが書いてくれたので、感謝しかありません。ありがとうございました!

(令和最新版Perl BBS動作の様子)

「Sledgeについて触れないのはいかがなものか」

そういえば@ssig33さんから「Sledgeについて触れていないのはいかがなものか」という旨のご意見をいただいていましたが、あれは大まじめに入れたくても入りきらないというものだったので、どうか勘弁してくださいって会場で半土下座させていただきましたね。

歴史について深堀りするなら、間違いなくSledgeについては避けて通れないとは思いますし、SledgeがあったからRuby on Railsのようなフレームワークが出てきたんだよね、ということについては間違いなくその通りだと思います。2000年代初頭にPerlが絶大な人気を誇っていた理由のひとつであると言っても過言ではないでしょう。

せめてここで参考リンクを紹介するという形で、落穂ひろいとさせていただければと思います。

まず開発元のlivedoorによるGitHubレポジトリがありますので、入手はこちらから可能です。歴史を感じることができると思いますので、ぜひ見てほしいです。

現代においては、@karupaneruraさんによる下記ブログエントリが参考になると思います。

また日経クロステックには、Sledge作者のひとりの@miyagawaさんによる案内記事が残っていましたので、こちらもあわせて紹介いたします。

Track Cの番長やってました

もうひとつ、今回はスタッフとしての参加でもありました。基本的にはTrack Cに張り付いて場を管理する役割を帯びておりまして(通称「番長」)、副番長の @chanyou さんに大きく支えられながら、なんとか無事に役割を全うすることができました。部屋付きのスタッフの皆さんにも大変助けられました。ありがとうございました!

さて、そのような都合もあって、実はあまりTrack C以外のトークをみることができていないのですが、その中でも私が感心してみていたのは以下のトークでした。

なぜインフラコードのモジュール化は難しいのか - アプリケーションコードとの本質的な違いから考える by 宮下 剛輔 | トーク | YAPC::Fukuoka 2025 #yapcjapan - fortee.jp

私自身がTerraformを最近ようやく触ることがあったのですが、この発表では私がTerraformになんとなく感じていたモヤモヤの原因が解像度高く言語化されておりましたね。

あのモヤモヤ対する適切な対処がきっちりと提示されつつも、ほどほどにやっていくことの大切さが語られていました。行き過ぎた最適化は負担となりうるということを示してくれた、貴重な発表でした。

Amazon ECSデプロイツールecspressoの開発を支える「正しい抽象化」の探求 by 藤原俊一郎 | トーク | YAPC::Fukuoka 2025 #yapcjapan - fortee.jp

こちらも実は最近ようやくECSを触る機会があったのですが、あの若干行き届いていない感じをecspressoがうまくいなしてくれるんだな、と理解しました。

また、その開発にあたっての設計哲学と「あえて設計しない」というやり方について、凄みを感じましたね…つい設計しちゃいそうなところだと思うのですが、そこは熟練の肌感なんだろうなあと。本当に感心します。

飛行機の都合で懇親会の途中で帰ることに… 😭

ところで、私はケチな旅行が大好きです。飛行機代をどうすれば圧縮できるのか。電車賃は?宿代は?もちろん、豪華なホテルもいいと思いますし、私もごくまれに値段を気にせずに旅をすることがあります。しかし、普段は超ドケチスタイルでやらせてもらっています。

で、今回はANAのセールでチケットを購入しつつ、ホテルもカプセルホテルを押さえるという形で対応しました。移動と宿泊についての費用としては以下の通り。

  • ANAセールによるチケット
    • HND-FUK:片道7,700円(税込)、往復15,400円
  • ファーストキャビン博多
    • 1泊あたり3,630円(税込)、2泊で7,260円
  • 福岡市営地下鉄1日乗車券
    • 640円
  • そのほか交通費
    • 2,800円
  • 合計:26,100円

それなりにドケチ旅行と銘打つことが許される価格帯ではないかと思うのですが…どうでしょうかね。

ところが、土曜日の宿泊と日曜日の航空券がどうあがいても取れない!!!ということで、泣く泣く懇親会を中座するという羽目になったのでした…いやあ、これは反省です。

さいごに

YAPC::Hakodate 2024で実行委員長をしたときびきニキさんにYAPC::Fukuoka 2025をバトンタッチしたのですが、まじですごいの一言に尽きます!

懇親会のごはんがめちゃくちゃおいしいし、ヘルプページの整備という形で案内をまとめたのはさすがだなあと。#yapc_memorial の提唱と盛況ぶりは彼女が呼びかけなければ起こりえないことです。実行委員長という大役、お疲れ様です!ありがとう!

ところでこれは余談なのですが、「次回はビッグサイトだ」と聞いたので、真っ先に目の前にいた@dankogaiさんに「海外からもスピーカーを呼びましょうよ!」と、半ば強請りのような勢いで懇願に行ったのは体が勝手に動いてしまった結果です。

でも、当時のYAPC::Asiaを追い越すイベントを一緒にやりませんか、弾さん!

The Essential System Layers(本質的システム階層)

混沌とするシステム技術の世界における羅針盤

AIの台頭、ローコード/ノーコード(LCNC)の急速な普及、そして絶え間なく進化するフレームワークやインフラ技術。現代のソフトウェア開発を取り巻く環境は、まさに「混沌」と表現するのが相応しいでしょう。新しい技術が次々と登場し、あっという間に古くなる、そんな変化の波に乗り遅れまいと、多くのエンジニアが表面的なトレンドに目を奪われがちです。

長年のキャリアの中で、私は「技術は常に変化する」という現実を肌で感じてきました。しかし、だからこそ、目先の技術に囚われず、「本質」を見極め、変化の激しい時代を生き抜くための確固たる思考の軸が必要だと強く感じています。

このエントリでは、私自身の経験と試行錯誤の中でたどり着いた、システム構築における「The Essential System Layers(本質的システム階層)」をご紹介します。これは、技術を単なるツールの羅列としてではなく、それぞれの層が論理的に連携し、システム全体を構成する「必須」の要素として捉えるための、私なりのメタ認知フレームワークです。

「The Essential System Layers」が示す、システム構築の7層構造

私の提唱する本質的システム階層は、システムの根源にある「なぜ作るのか」という問いから、ユーザーが実際に触れる「最終的な成果」に至るまでを、段階的かつ相互依存的な7つのレイヤーとして表現します。各層は「選択」と「行使」のプロセスを内包し、全体として一貫したシステム構築の流れを示します。

第0層: 根源層(Root Layer): 仕様 & ビジネスドメイン

この層は、システムが作られる以前から存在する、システム構築の「前提」となるものです。7つのレイヤーに含めることで、技術的な選択が常にビジネスの目的と要件に基づいて行われるべきであることを強調しています。

  • 役割: システムの存在意義と目的を定義する、すべての出発点。「何を(What)解決すべきか」「なぜ(Why)それを作るのか」を明確にします。技術的な制約から独立した、純粋なビジネス上の要件、顧客の課題、市場のニーズ、そして最終的なビジネス価値がここに集約されます。

第1層: 論理設計層(Logical Design Layer): ドメインモデリング & アーキテクチャ設計

  • 役割: 第0層のビジネス要件を受け、それを技術的に実現可能な「論理的な形」に落とし込む層です。ビジネスルール、データ構造、システム全体の振る舞い、主要コンポーネント間の関係などを、具体的な技術実装に依存しない形で設計・定義します。システム全体の骨子を決定する、最初の「選択」が行われる場です。

第2層: 実装手段選択層(Implementation Means Selection Layer): 開発パラダイム & 技術スタック選定

  • 役割: 第1層の論理設計を実現するための、具体的な開発手法や主要な技術スタックを決定する層です。開発速度、コスト、複雑性、保守性などを考慮し、最適なアプローチを選定します。

    • AI(コード生成、自動化エージェント)ローコード/ノーコード(LCNC)ツールは、特定のビジネスロジックや定型処理を迅速に実装する際の強力な選択肢です。ただし、この層における安易な選択は、後に不必要なコストや非効率を招くこともあります。
    • 各種プログラミング言語(Python, TypeScript, Goなど)は、より複雑なカスタムロジックや、性能が要求される部分に選択され、きめ細やかな制御を可能にします。

    AIの位置づけについて: 近年注目を集めるAIは、このレイヤーにおいては、あくまで「実装手段の選択肢の一つ」として捉えられます。AIは、特定のタスクを自動化したり、コードを生成したりする強力なツールですが、システムの根本的な設計やドメインモデリングに直接的な影響を与えるものではありません。

第3層: コード・ロジック層(Code & Logic Layer): ソースコード & 個別ミドルウェア実装

  • 役割: 第2層で選択された手段を実際に「行使」し、第1層で定義された論理設計を具体的なコードや設定として表現する層です。

    • プログラミング言語で記述されたアプリケーションコードや、その開発を効率化するフレームワーク(React, Spring Bootなど)がここで活用されます。
    • LCNCツール上での設定や、AIの挙動を制御するプロンプト/モデルの定義、さらにはデータベースのスキーマ定義など、各ミドルウェアがアプリケーションロジックと連携するために必要な具体的な実装や設定もこの層で行われます。ここが、「実装」の主戦場です。

第4層: 実行環境層(Execution Environment Layer): 実行エンジン & コンテナ技術

  • 役割: 第3層で作成されたコードや設定が実際に「動く」ための、抽象化された実行環境を提供する層です。

    • Java Virtual Machine (JVM) や Node.js (V8) といった言語ランタイム、そしてDockerやKubernetesなどのコンテナ技術が、アプリケーションの動作環境を標準化し、隔離します。ここも、「実行環境の選択と設定」が行われる場です。

第5層: インフラ基盤層(Infrastructure Foundation Layer): クラウドインフラ & 仮想化

  • 役割: 第4層の実行環境を稼働させるための、仮想化された、あるいは物理的な基盤を提供する層です。

    • AWS, Azure, GCPなどのIaaSが、サーバー、ネットワーク、ストレージといったITリソースを抽象化して提供します。物理サーバーや仮想化技術もここに属します。

第6層: 物理・制御層(Physical & Control Layer): ハードウェア & オペレーティングシステム (OS)

  • 役割: すべてのデジタルシステムが最終的に依存する、最も低レベルな物理的・論理的基盤です。

    • CPU、メモリ、ストレージなどのハードウェアと、Windows、Linux、macOSなどのオペレーティングシステム(OS)が、上位層のソフトウェアを支える最終的な土台となります。

第7層: 出力・ユーザー体験層(Output & User Experience Layer): 具体的な機能・ユーザー体験

  • 役割: システムが最終的にユーザーに提供する価値、インターフェース、そしてそれによって生まれる体験の層です。

    • 第0層のビジネスドメインが、すべての層を経て具体化され、ユーザーが直接触れ、認識し、利用する最終的な機能やインターフェースがここに現れます。

「The Essential System Layers」がエンジニアにもたらす価値

この本質的システム階層は、単なる技術の分類に留まりません。複雑なシステム構築において、エンジニアが確かな視点を持つための強力なツールとなります。

  1. 適切なツール選択の指針:
    各層の役割と特性を理解することで、表面的なトレンドに流されることなく、目の前の課題にとって本当に最適な技術やアプローチを選択できるようになります。AIやLCNCを過大評価することなく、また従来のプログラミング言語の重要性を見失うことなく、バランスの取れた判断が可能になります。

  2. 問題の特定と解決能力の向上:
    システムで問題が発生した際、それが「仕様理解の不足(第0層)」に起因するのか、「設計の誤り(第1層)」なのか、「手段選択のミス(第2層)」なのか、「コードの実装バグ(第3層)」なのか、あるいは「実行環境やインフラの問題(第4層~第6層)」なのかを、この階層構造に当てはめて素早く特定し、効率的に解決に導くことができます。

  3. キャリアパスの明確化と「本質」を見抜く力:
    自身のスキルがこの構造のどの層に位置し、今後どこを深めるべきか、あるいは広げるべきかを戦略的に考えるための羅針盤となります。技術の表面的な変化に惑わされず、各層の「本質」的な役割を理解することで、エンジニアとして長期的に価値を生み出し続ける力を養うことができます。

  4. 新しい技術の本質とその影響を素早く把握する力:
    昨今のAIやLCNCのように、新しく登場した技術がどの層に位置するのかを見極め、それによりどんなことを解決してくれるのかをスムーズに理解するための一助となります。また、新しい技術が自身のフォーカスする層にどのような影響があるのかを理解し、どのくらいの速度で変化していくのかを見定めるためのツールとなります。

変化の時代を生き抜くエンジニアとして

テクノロジーの進化が加速する現代において、エンジニアはますます複雑な課題に直面します。しかし、このように体系化されたメタ認知を持つことで、私たちは単なる「技術の利用者」から、その「技術を真に理解し、使いこなす設計者」へと進化できるはずです。

例えば、AI技術の進歩と普及は一見何もかもを覆してしまったように見えるかもしれません。しかし、このメタ認知に当てはめて考えるならば、AIは主に第2層(実装手段の選択)に関わる技術であり、システムの根本的な設計やドメインモデリングに直接的な影響を与えるものではない、と冷静に判断することができます。

この本質的システム階層というフレームワークが、あなたのシステム開発における意思決定、問題解決、そしてキャリア形成の一助となれば幸いです。