YAPC::Hakodate 2024をやるぞ!と言い、YAPC函館市電LTもやった

※このエントリは、私わいとん 個人 の飾らぬ思いであります。

YAPC::Hakodate 2024の実行委員長という大役を仰せつかってからおよそ7か月、2024-10-04に前夜祭、2024-10-05に本編、2024-10-06にアフターイベントをそれぞれ開催し、無事に閉幕までやり遂げることができました。

たくさんの方々・企業のみなさんに貴重なお時間とお力を割いていただいた結果できたことです。ありがとうございます。私自身も大変楽しませていただきました。

写真コーナー

なかなか当日は忙しいこともあって写真を撮る余力があまりなかったのですが、その中でも撮影したものを載せておきます。雰囲気が伝わるといいのですが。







YAPC::Hakodate 2024はアートである(と私は勝手に思っている)

※ここから先は小難しい話が続きます。面倒な方はここで読み終わりとしてください。

YAPCをはじめとしたイベントはMICE(マイスと読む。Meeting, Incentive travel, Convention, Exhibition の頭文字をとった略語)と呼ばれるものに相当するでしょう。学びを共有するためだったり、コネクションの開拓を促す目的などで開催されることがほとんどではないでしょうか。YAPC::Hakodate 2024(以下、YAPC函館)についてもそのような側面は持ち合わせていますので、これは間違いなくMICEに分類されるイベントであると考えてよいはずです。

一方、YAPC函館はアートであると私は考えます。アートというのは心を豊かにするモノやコトであるとここでは定義します(美術の範囲に限らない広義の用途を意図しています)。

YAPC函館に参加された方は、多少なりとも感情あるいは知的好奇心を大いに揺さぶられたことではないかと想像します。そして次のYAPCにも参加したい、という思いを持ったことでしょう。

この感情・知的好奇心の高まり・思いが生じたことこそが、YAPC函館がアートであることを示しています。人はアートを通じて知的・心的欲求が高まり、次のアートを求めるのではないでしょうか。

YAPC函館がアートであるならば、そのデザイン手法について説明せねばなりません。そうしないと、YAPCは一点ものアートのままになってしまいます。アートであり、かつ工芸品でもあるものにしないと、作り手に依存したままの存在になってしまいます。

ましてやYAPC函館はイベントなので、必ず緩やかに風化していくのが定めづけられています。次に続くYAPC実行委員長(ビキニキさん)が、より楽しくYAPCの企画を推進できるように、YAPC函館と私の事例について共有します。

やるぞ!と言った理由

YAPC函館開催の顛末については概ね YAPC::Hakodate 2024 非公式予習会を開催しました! - inSmartBank に書かれている通りとなります。

しかし「私がYAPC函館をやるぞ」と言った理由についてはちゃんと答えていなかったですね。概ね以下の通りとなります。

  • 函館への経済効果を期待した
  • 函館および北海道の情報技術系の学生/学府との交流を活性化したかった
  • 都市圏の企業に函館をより解像度高く知ってもらい、函館にITの仕事を増やすきっかけを作りたかった

なんでお前はそんなに生まれ故郷にこだわるのか

これについては端的に「涼しくて飯が安くてうまい函館、良いべえ?」と思っているからです。

しかしながら、ITの(に限らないが)仕事が少なすぎるという弱点があまりにも強すぎるため、手放しに「良いべえ?」とは言い切れない。現に私自身が工業高校を出て就職をしようとしたとき(1998年)に、地元企業の求人票が全然なかったことを今でもはっきりと覚えていますし、本当は地元を離れたくなかったけど、当時は仕事のために東京の会社に就職するしかなかったんです。

であればどうすればその弱点を克服できるか、という事をまあまあ度々考えてしまうわけですが、そのための「もがき」なのかもしれないですね。

YAPCのイベントとしてのフレームワーク性

個人的な観点となりますが、YAPCでは以下のフォーマットが踏襲されるべき大きなポイントであろうと思います。

  • 前夜祭を行う場合は不採択となったプロポーザルに復活の機会を与える
  • 本編は休日・祝日
  • メイン会場は最低でも300人程度が一斉に集まれる
  • LTがあり、キーノートがある

上記の他にはスポンサーに関するフォーマットなどが考えられますが、ここでは割愛します。少なくともJPAがこの点についてはしっかりとバックアップしてくれたので大変助かりました。また、実行委員長としては熟知するよりすぐ調べられる状態にするのが現実解かと思いました。

もちろん開催にまつわるドキュメンテーションや数字などを事前にまとめておいて、それを脳に焼き付けておくことがベストだと思いますが、私の能力ではそれがうまくできなかったので、次善策で対処したといったところです。

イベントのデザイン手法

では、今回のYAPC函館をやるぞ!といった理由について実現度を高めるために、私がどんなことを考えていたのかを明らかにしていきます。


前夜祭

前夜祭は以下の事を意識して司会という役割を務めさせていただきました。

  • YAPCで紡がれてきたつながりを引き継いでいく場を提供する
  • シニアエンジニアも学べる場にする

そのために、次のようなイベントデザインを心がけました。

同窓会としてのYAPC前夜祭をデザインしたかった

YAPCは過去に国内で複数回開催されています。元々はPerlのカンファレンスだったのですが、近頃は以前のYAPCで知り合った人同士が再会を果たす「同窓会」のような機能も期待されていると感じています。

それであれば、「同窓会」に参加してくれる人がまた来たくなるようなイベントにする必要が出てきます。下記のような話題は経験豊富なエンジニアやマネージャー、YAPCガチ勢に好まれる傾向にあると考えます。

  • 古いシステム/環境などの話
  • Perlの話
  • マネージメントの話

また、同窓会らしさを演出するのであれば、コミュニケーションをとるためのツールも必要になります。つまり、飲食です。ここはその土地の色を出せるところですので、以下のような選択をするのが良いだろうと考えます。

  • 地元のソウルフード
  • 地元のクラフトビール
  • その他、地元色が出せる食べもの・飲みもの

地元色を出すことで、経済面でも地元への貢献度が向上するので、これは絶対におススメしたいです。

30代/40代がさらに上の世代から学び取る場をデザインしたかった

YAPC自体が歴史の長いイベントであるということを考慮すると、同窓会を期待している人は確実に30代オーバーということになります。ええ、もちろん私も例外ではなく、もう少しで44歳になります。

私も含め、30歳オーバーの参加者がさらに先輩の世代の生の体験談から得られる学びは間違いなく貴重な体験だろうと考え、50代付近の登壇者をピックアップして座談会を企画しました。

YAPCというブランドで紡がれてきたつながりを次の世代にも体験してもらいたかった

アンカンファレンスについてはアイスブレイクとしての役割を持たせたつもりだったのですが、テーマを公開する機会を逸した結果、最初のタイミングでは誰も反応しないという状況でした。あとAIにテーマを作ってもらった結果、思った以上に「重い」という感想をいただいており、このへんはちょっとしくじったな、と。

どうにかしてアイスブレイクさせなくては・・・と悩んでいた矢先に、見覚えのある @moznion 氏が何やら楽しそうにビールを飲んでいたので、つい「レガシーシステムの刷新について何か言いたそうですね?」という無茶ぶりをして登壇させたのでした。彼が登壇してすぐに言っていた通り、これは仕込みナシです。コーナーが終わった後に彼が私に軽く文句を言うであろうところまで私の中では織り込み済みでした。

結局私の目論見は見事に当たり、@moznion, ma.la, @dankogai, macopy, @pastakなど(敬称略)による解説と見解、そして若干の漫談のようなものを交えながら、見事に場が盛り上がったのでした(見ての通り、最初の10分くらいはほぼmoznion自身のコンテンツ力のおかげですが)。

このようなやり取りを見て、特にYAPC初参加の方や学生などの若い世代の人々に、YAPCで紡がれてきたつながりを感じ取っていただけたのであれば本望です。


本編当日

本編は前夜祭とは大きく変わり、以下を重要視していました。

  • 技術について語り合う場にする
  • これでこそYAPCだと思わせる
  • 年齢・属性関係なしに楽しく学べる場にする
  • 前評判や偏見を取り除き、Perlの良さを再確認してもらう
  • 次のYAPCにも参加したいと思ってもらえる会にする

そのためにどのようなことをすればよいか、というのを自分なりに考え、以下のような指針でイベントデザインをしたつもりです。

年代に関係なく学びのある場を作りたかった

例えばエンジニア組織のマネジメントに関する話題は、ある程度成熟したエンジニアにとっては学びとなり得るものだと思います。しかし、これからプログラミングを学んでいく若者にとっては、いきなりそのような話題を聞かされたところで、なんのこっちゃ、となってしまうはずです。

ですので、なるたけ技術的な学びが得られそうなプロポーザルを採択する傾向となりました。これは、技術的な学びについては、技術カンファレンスに来ているのだから、ある程度多くの人が興味があるはずだろう、という考えに基づいた判断です。

YAPCじゃないと聞けない知見を集めたかった

いくら技術的な学びがあったとして、「YAPCで話すことが相応しい」プロポーザルでなければ通すことはできません。これは例えば、そのプロポーザルはほかのカンファレンスのほうが受け入れられるであろうという内容であれば、優先度を下げる必要があったということでもあります。

今回はとくに、Perlについて触れているプロポーザルを積極的に採択しました。しかしそれでも「Perl成分は薄めだった」という感想もあったようで、それだけPerlについて話そうとしたプロポーザル自体が少なかった、ということだと思っています。

様々な技術に対するフラットな視点を持ち帰ってほしかった

YAPCはPerlのカンファレンスですので、Perlに関するトークに触れて、少しでもPerlについて興味を持っていただきたかった、という気持ちがありました。

Perlに対する様々な視点をお持ちの方もいらっしゃることは承知していましたが、それでもひとつの技術としてフラットに捉えてほしいですし、それはPerlに限らずほかの技術についても全く同じことを思っています。

好き嫌いで触る技術を選ぶのも結構なことだと思います。しかし、一辺倒な視点から脱却するには、まったく異なるものをまっさらな意識で触れてみること、そしてそのようなことに慣れる必要があると考えました。

とくに若い世代の皆さんには「温故知新」の精神でPerlをはじめとした技術に触れてほしいと思ったのです。

技術に熱中する人々とその情熱を知ってほしかった

今回のゲストは、アカデミックな世界で活躍されている方々や若き技術者を中心にお声がけをさせていただきました。

これは、その分野の技術に情熱を注ぎ続けている人々とその軌跡を間近で見ていただくことで、技術そのものの面白さと可能性、そして技術に熱中するという生き様を知っていただきたかったのです。


市電LT

私が作って経営している会社 Y.pm LLC が主催となって開催したYAPC函館市電LTですが、こちらについては、以下の点を重視しました。

  • 函館と北海道、路面電車が好きな方を少しでも増やす
  • YAPCというイベントに強烈なインパクトを付け加える
  • 面白い技術者との交流を深める場を提供する

函館市電LTに参加するような遊び心のある人を知っておきたかった

完全に私個人の欲求の話となりますが、そもそもYAPC函館市電LTに参加してくれた人はかなり「覚悟が決まった人」だろうと勝手に思っています。そんな「覚悟が決まった人」を私としては「ぜひとも仲良くしたい」と思っています。

要するに、私は一緒に遊びを全力投球でやってくれる人が好きなんです。

自社の宣伝をしたかった

私の会社をひとことで言い表すと「零細システム開発会社」というものになると思います。

そんなシステム開発をやっている会社にとっては、案件こそが命の源泉なのです。そのために冒頭ちょっとだけ自社の宣伝をしました。会社の予算を使ってやっている以上、これはやらないといけないやつです。


その他

個人的な思いといいますか、若き日の原体験から思ってきたことを最後に書いておきます。このあたりはYAPCとは関係ない文脈になりますが、背景情報として参考になればと思います。

生まれ故郷に元気を与えたかった

正直、函館という街は国内でもかなり苦戦を強いられている斜陽都市のひとつです。ここ最近は某アニメ映画やインバウンドのおかげもあって観光業とその周辺はなかなか景気が悪くない様子ですが、付加価値の高い第三次産業が弱いこともあって、ITに関する仕事も例にもれず大変希少な状況です。

そのため、恐ろしい勢いでの人口流出と自然減、高齢化の進行が深刻な問題となっていて、私が生まれた当初(1980年)はおよそ35万人直前程度の人口がいましたが、現在ではとうとう25万人を割ってしまい、今ではおよそ23.7万人程度となっています。2040年には17.5万人程度になると予想されています。

深刻なのが生産年齢人口の減少です。1980年におよそ23万人の生産年齢人口がいましたが、2025年には大体12.5万人にまで減少するとされています。2040年には10万人を下回り、8.8万人程度まで減少するだろうという予想がされています。

一方、生活ガイド.comの全国住みたい街ランキングでは39位となっており、そこそこ健闘しているなあという風に思いました。

こんな感じで、全般的に衰退する未来が予想されている一方、多少住んでみたいとは思われている(けど実際に住む人は少ない。家族の意見もあり、私自身もいまだに函館には戻っていないですし。)という、なんとも難しい状況なのが私のふるさと「函館」です。

良い面もたくさんあります。涼しいし飯がうまいし安い。人が多すぎない。風光明媚な自然が盛りだくさん。ただ、市民に元気を与える話題がちょっと少なすぎやしないかと。

なので、何らかの大き目なイベントを呼ぶことで街の経済活性につながるのであれば、それにはできる範囲で協力しようと思い、YAPC誘致に名乗りを上げた次第です。

函館に住んでいる若者が函館で働くことをあきらめない未来に近づけたかった

そもそもなぜこんなに生産年齢人口が減少しているかというと、端的に街に仕事が少なすぎるのです。地方都市ではよくある話ではありますが・・・。

それでも、特に情報通信業の有効求人者数は令和4年から比較して令和5年では485.7%にもなっているので、少しずつIT化の波が函館にもようやく届き始めているのかもしれないです。

また、未来大や函館高専という情報系学科をもつ学府が函館には存在しますが、ITに関わる求人数はまだまだ彼らの多くに対してリーチするには少なすぎるというのが現状です。その一方で、開発拠点を函館に置き始める企業も出てきているようです。


まとめ

  • YAPC函館は一点もののアートである
  • やると決めた理由は「函館に元気を与えたかった」「未来大などの情報系学科の学生と大企業のつながりをもたらしたかった」

最後に御礼を

ごちゃごちゃと書きましたが、YAPC函館を無事終えることが出来たのは、以下の皆さまがご協力くださったおかげです。

  • 参加者の皆さま
  • 登壇者の皆さま
  • 当日スタッフの皆さま
  • JPAの皆さま
  • スポンサー企業の皆さま
  • 未来大の角先生
  • 未来大企画総務課の吉田さま
  • 未来大生協の本間さま
  • キッチンカー(函館ナントカ食堂, くいだおれ太閤, てつまるケータリング)の皆さま
  • 清掃事業者の皆さま

皆さま、本当にありがとうございました。そして、コアスタッフ(@__papix__, @karupanerura)の二人には特に感謝しています。

絶対自分のせいで面倒なことになった部分もあったのに、きわめて冷静沈着に状況をよくしようと立ち回った@karupaneruraには本当に助けられましたし、@__papix__には気持ちの面やアイデアが出てこなかった時に心強いフォローをいただきました。

私自身も「必ずやり遂げるし、やるからには絶対に成功させるぞ」という気概をもって取り組ませていただきましたが、彼ら二人の情熱はそれを凌ぐものがありました。でも、健康面にはもう少し気を配ってもいいんじゃないかって思います。さすがに睡眠の質がよろしくなさそうな話を聞いた時には割と本気で心配しました。今は良くなっていることを祈ります。

あと、広島の三次会?で生じた風のうわさを教えてくれた @myfinder にも感謝しています。彼はいつも私の尻に火をつけるのがうまく、今回も私に「YAPC函館の機運が来たかもしれませんよ?これはやるしかないんじゃないですか?」と立ち飲み処で教えてくれました。このムーブがなかったら今回はほかの地域での開催となっていたか、開催が見送りとなっていたのかもしれません。

とにかく、開催できてよかったと思っています。本当にありがとうございました。

書評:アーキテクトの教科書 - 価値を生むソフトウェアのアーキテクチャ構築

「設計ナイト」つながりで、@tyonekuboさんから献本いただきました!

大吉祥寺.pm参加録でも書いた通り、本書(通称:オレンジ本)の著者である米久保剛さん(@tyonekubo)から献本いただきました。この場を借りて改めて御礼申し上げます。ありがとうございます!!!

せっかく献本いただいたので、これは読んでブログに書くしかない!ということで、本書の書評を書きます。

本書の概要

アーキテクトの教科書 価値を生むソフトウェアのアーキテクチャ構築 (米久保 剛 | 翔泳社)

本書は、アーキテクトとしてのスキルを身につけるための教科書です。アーキテクトとは、ソフトウェアのアーキテクチャを設計し、開発チームに指針を示す役割を担う人のことを指します。

全6章からなる本書は、以下のような内容になっています(以下目次より引用)。

  1. アーキテクトの仕事
  2. ソフトウェアの設計
  3. アーキテクチャの設計
  4. アーキテクチャの実装
  5. 品質保証とテスト
  6. アーキテクトとしての学習と成長

よくもまあここまで絞り込んだものだと思います。本来はもっと内容を盛り込みたい、という欲があると思うのですが、それを抑えてこの6章にまとめたのは、著者の経験と知見が詰まっているからこそだと思います。

推しポイント

実コードを交えた説明が簡潔

本書は、アーキテクチャの設計や実装に関する説明が大変簡潔でわかりやすいです。特に、実コードを交えた説明が多く、理論だけでなく実際のコードを見ながら学べるのが良いですね。

Javaがコード例として使われていますが、かなりシンプルなコード例ですべて説明しきっているため、他の言語を使っている人でも十分に理解できると思います。

数多くの図表があってイメージしやすい

アーキテクチャの設計や実装に関する説明は図表が多く登場し、イメージしやすいです。アーキテクチャごとの違いや目的、考え方の違いがそのまま視覚的に示されているため、理解が深まります。

これは、アーキテクチャの設計や実装に関する知識が浅い人にとっては、非常にありがたいですね。

実践的なアーキテクチャの設計に関する知識が得られる

ベテランが読んでも役に立つレベルの内容が書かれていると思いますが、初心者が読んでも理解できるように書かれているのが良いですね。

私もそこそこ長いことIT業界でエンジニアとして働いていますけど、名前は聞いたことがあっても触れる機会がなかったアーキテクチャについて、本書を読んで理解が深まりました。

また、過去に自分がやってきた設計についても該当するアーキテクチャがあって、利点について再認識できたのも良かったです。

分厚すぎず、デカすぎない。何度も読める手軽さ

本書は、分厚すぎず、デカすぎないサイズ感が良いです。何度も読み返すことができるボリュームで、繰り返し読むことで理解が深まると思います。

さらに、この手の書籍にしては2,800円という破格で、アーキテクトとしての第一歩を踏み出すための教科書としては、非常にコスパが良いと思います。

本書をこんな人におススメしたい

  • 2年目~5年目くらいの経験を持つエンジニア
  • 設計で迷いに出くわした経験があるエンジニア
  • 設計がぐちゃぐちゃなプロジェクトに携わっているエンジニア
  • 様々なソフトウェア設計について学びたいエンジニア

私個人の意見としては、DDDについて深掘りする前に本書を読め、と言いたいです。実践的なアーキテクチャの設計や実装に関する知識を得ることができ、頭でっかちではない、地に足の着いたアーキテクトになるためのヒントが詰まっているからです。

まとめ

本書はアーキテクトとしてのスキルを身につけるための教科書として、非常に優れた内容になっています。また、アーキテクトのみならず、エンジニアとしてのスキルを高めたい人にもおススメできる内容になっていると思います。

優れた設計ができるエンジニアがいるプロジェクトでは、保全性の高いソフトウェアが生まれることが多いです。そのため、本書を読んで設計のスキルを高めることは、エンジニアとしてのスキルアップにつながると思います。

大吉祥寺.pm 参加録

7/13(土)に開催されたオフラインイベント「大吉祥寺.pm」に参加したので、その記録や感想となります。

前夜祭「生存者バイアスナイト」

7/12(金)の夜、吉祥寺のビアバー「P2B Haus」で前夜祭が開催されました。お料理、ビール、トークともに大満足の内容でした。

ただ、あまり大っぴらにしづらい話題もあり(この会はそういう会でもある)、ほかの方の発表については詳細を伏せさせていただきます。一つ言えることとしては「結構考えさせられる内容だった」ということでしょう。

なお、本来登壇予定だった@studio3104さんが病欠とのことで、急遽代打を務めさせていただきました。私の発表については特におおっぴらにしても何ら困らないものですので、こちらで共有しておきます。

本編

本編は武蔵野公会堂にて開催されました。以下、聞いたセッションの中でも特に印象に残っているものについて、感想を簡単にまとめます。

基調講演 - @yasuhiro_onishi

テーマが「黒歴史」でなかなか不穏なはじまり方でしたが、その後の話を聞いていると、ようはここで言う「黒歴史」というのは「失敗を恐れずに挑戦し続けること」であるということがわかりました。

かなり意外だったのが、某ホビー系ショップの草創期に大西さんが関わっていたというのが驚きです。

むしろ大西さんにも「生存者バイアスナイト」で発表してほしかった。というか、大西さんの発表が「生存者バイアスナイト day 2」だったのかもしれません。

多様性の時代を生き抜くキャリアプラニング - @tyonekubo

「中長期のキャリアがイメージできない」「どうしたら評価があがるのか?」という質問をしたことがある人、あるいはされたことがある人、双方にとって有益な内容だったと思います。

「ゴールデンサークル理論」(Why→How→Whatの順で話すと人心に訴えかけることができるという理論)に基づき、その一番内側にある「Why」を見つけることが重要であるという話が印象的でした。

また、国内と海外におけるキャリアラダーの違いについても話されておりました。私は海外での就労経験はないのですが(かつて出張で北京に行ったくらい)、なかなか言われてみると結構な差があるんだなと感じました。

技術力でビジネスに貢献するための公式(技術力×ソフトスキル=技術貢献力)というのもなかなか刺さる内容でしたね。

開発部に不満を持っていたCSがエンジニアにジョブチェンしてわかった「勝手に諦めない」ことの大切さ - @saku_rye

Q, なぜエンジニアになったんですか?
A, 開発部に不満があるのに、何もできない自分が悔しかったからです。

冒頭からこの感じで、エンジニアになるきっかけや、エンジニアになってからの経験談が語られていました。エンジニアになるためには「勝手に諦めない」ことが大切であるという話が印象的でした。

また、エンジニアになってからの経験談として、開発部に不満を持っていたCSがエンジニアにジョブチェンしてからの話も興味深かったです。エンジニアになることで、自分の意見を形にできるようになったというのは、なかなか感慨深いものがありますね。

一方でエンジニアとしてある程度視座が広がってきたからこその苦悩もあったようです。エンジニアになる前は「エンジニアになれば解決できる」と思っていた問題が、エンジニアになってみると「エンジニアになったからこそ見える問題」があるというのは、なかなか共感できる話だと思います。

個人的には、「勝手に諦めない。分かり合えるまで根気よく接し続ける。」というのは結構なことだと思う一方、皆が皆それだけの胆力を持ち合わせているわけではないと思うので、個々人の胆力に依存しない方法も模索していく必要があるのかなとも思いました。

組織のスケーリングと持続性 - @tunepolo

事業成長の結果、人手が足りなくなった状況下で、開発チームをスケールアウトする際のオーバーヘッドを仕組みで補うという方法とそれ以外の方法が分水嶺となるという話がありました(エンジニアの開発力を向上させる、アウトソーシングをする、人数を増やさない、の3つ)。

スケールアウトする場合も、職能ごとのチームにするのか、フィーチャーごとのチームにするのかで分けられるという話もありました。

一方、人を増やしても売上が増えない場合の逆回転についても触れられており、これはなかなか苦い経験をされたのだろうなと感じました。

共感できる部分も多かったですが、売り上げが上がっていないチームについては人を増やさない、というのが鉄則じゃないのかと思いました。仮に投資を受けて事業を大きくするタイミングで、しかし売上は伸びていない状況であれば、アウトソースをするか人を増やさずに仕組みで売上を伸ばす方法を模索していくのがいいのではないかと思いました。

その他

大井町放談というランチタイムセッションで、@myfinderさんとともに大井町.pmとして雑談タイムで登壇させていただきました。

技術の話、キャリアの話、お金の話と3つのテーマで話をしましたが、参加した皆さんに新たな気づきを与えることができていたら幸いです。

まとめ

大吉祥寺.pmは、技術者としての視座を広げることができるイベントでした。主催の@magnolia_kさん、スタッフの皆さん、登壇者の皆さん、参加者の皆さん、ありがとうございました。また、このようなイベントを開催していただいたことに感謝いたします。

その他

わいとん「あっ、バレましたか・・・」

「設計ナイト」つながりで、@tyonekuboさんから献本いただきました!

ありがとうございます!!!

@a_suenamiさんに「焼肉」をご馳走になりました!

すえなみチャンス!(概念)

ありがとうございました!

YAPC::Hiroshima 2024 参加録

広島で開催されたYAPC::Hiroshima 2024に「フル参加」してきました。フル参加って言っているのは要するに「前夜祭」「本編」「YAYAPC」の3日間に参加したということです。

なんと今回、本編については何の役割も持たずに気ままに参加したのですが、これは何時ぶりですかね…たぶんYAPC::Hokkaido 2016 SAPPORO以来のことではないでしょうか。

前夜祭

前夜祭ではHono v4に関する発表があるという事で大変集中して聞いていました。いま現在、Honoでご飯を食べている私にとっては大変重要なものですからね・・・

  • v4ではクライアントサイドにも手を伸ばしており、Reactと同一の構文でコンポーネントを書くことができる
  • HonoとViteをベースにしたフルスタックフレームワーク HonoX
  • バックエンド観点でのHonoはその互換性に手を加えることなくそのままv4に移行できる

それからキャッシュバスターズの発表もありました。こちらは晩酌をしながら聞いていたのであまり覚えていませんが、聞いていて「あるあるー」「ですよねー」という感じでした。みな同じような悩みを抱えているんだなあと。

本編

今回はスピーカーでもスタッフでもなく一般参加者として参加しました。スポンサーチケットを使っても良かったのですが、直前に念のため一般参加チケットを自費購入しており、スポンサーチケットは社員におすそ分けとしました。

今回聞いたセッションは以下の通りです。割と廊下でのんびり談話していたり個人的なハックをしていたので、聞いたセッションは少なめです。

2024年冬のPerl

charsbarさんのセッションで、まさかのリモート登壇。久々にご本人にご挨拶できると思っていたのですが、おあずけになってしまいました。

主にPerlエコシステム(とくにミラーとかセキュリティなど)に関する話題と、5.38以降の新機能についての解説がありました。

  • Security Issue(SSL証明書の検証に関する問題)があるため、HTTP::Tinyは最新版(0.083 or later)にアップデートしましょう →CVE-2023-31486
  • SSLがコアに入る未来が来るかも
  • UnicodeとWindows周りでperlにもセキュリティ対応のための更新が入るのでは
  • Strawberry Perlが復活!
  • 5.38以降の新機能 (詳しくはモバイルファクトリー社のテックブログ にも書かれている)
    • 個人的には export_lexically 関数が強すぎるなーと思いました。
    • モジュール末尾に 1; を書く必要がなくなったのは感慨深いです。
  • 今後来そうなやつ
    • 特殊変数の別名 → English モジュール相当のものかな
    • 文字列テンプレート → qt<ほげ{$val}ふが> みたいにかけるっぽい
    • 条件付きアロー演算子 → $obj?->method みたいなやつ
    • メタプログラミング → Class::MOP を現代風にしたやつかな
  • 5.8.1がツールチェーンのサポート下限から脱落
    • 今後は10年以内のものをサポート
    • 今は例外的に5.16を下限とする
    • PlackやIO::Socket::IPなどが既に5.12を下限にしている
  • Rakuについて

大変久々にPerl成分を摂取できたので、大満足でした。

Go to Cloudflare Workers ~ 移行から 0.5 年以上運用する

codehexさんのセッション。Cloudflare Workersに以降してから半年経過したというNOT A HOTELのAIアシスタント周辺の話を聞きました。

  • いくつかのフェーズを経て、Cloudflare Workersに移行した
  • デプロイが速くてまるでオフライン開発みたい
  • wrangler dev だけで環境構築が終わるので簡単
  • エッジノードで処理が行われるので、レイテンシが低い
  • アプリケーションはHono
  • monorepo構成、pnpmで管理
    • .code-workspace で複数アプリをどれもプロジェクトルートとして扱える
  • 運用にはログ・監視・トレースが必要
    • 基本的にはこれらの基盤は自作かカスタマイズか
      • (後で聞いた話だとこのあたりをサポートするサービスがCloudflareにはあるらしい)
    • リクエストの最後にログのキューを作成するHono middlewareを作成
  • pnpm patch で外部ライブラリを改造
  • cloudflare discordにへばりついてバグレポなどをしているらしい。胆力がすごい。

古い技術について—SMTP現代事情つまみ食い—

azumakuniyukiさんのセッション。SMTPについての話でした。というか、もうSMTPと言ったらこの方、この方と言ったらSMTPですよ!

メールに関する技術も最近触らなくなってきていたので、情報のアップデートができてよかったです!

YAYAPC

YAYAPC::Hiroshima。実質上のDay2とか、帰ってきた大人のYAPCとかなんとか。そんな会の司会を仰せつかっており、大人のYAPCと同様に細かいことはシェアできませんが、当日の様子を一つのツイートで表したものがこれです。

欽ちゃんのスコアボードについてはこちらがベースとなっており、私のほうでWebSocket対応をさせた次第です。もっと余力があったら審査員用の物理ボタンを用意するところだったのですが・・・

広島飯&おみやげ

正直なところ、広島飯って本当にお好み焼きと牡蛎しか知らなかったんですが、実際に行ってみると広島飯はお好み焼きと牡蛎以外にも結構バラエティに富んでいて、3日間ではまだまだ食べきれないくらいのものがありました。

お好み焼き

まぜそば

尾道ラーメン

ぷよまん

「生きとったんかワレェ!!!」

その他

まかまかさんと一緒に「広島ミックスあゆむバー」さんにお邪魔したのですが、入店するや否や女装子なあゆむさんとお客さんがテストコードの話をしていたりと、広島の懐の深さに触れることができました。聞くところによるとCOBOLerが結構いらっしゃるとかなんとか・・・あゆむさんありがとうございました!

それから、銭湯に行ったらこんなことも。銭湯民族、考えることは一緒ですね。

振り返りなど

今回は本編については特に何もせず、ただただ参加していたのですが、大変楽しい3日間でした。

広島という街の素敵さにも触れることができ、また、YAPCというイベントの素晴らしさも改めて感じることができました。

次のYAPCはどこで開催されるのでしょうか。楽しみですね。

そして広島はまたいつか行くぞ!

写真

うつ・ひきこもりの人に向けて、ITエンジニアとして働くことについて話してきた

昨年の12月に、うつ・ひきこもりの人に向けて、ITエンジニアとして働くことについて、オンライン講義という形式で話してきました。

事の発端

昨年の10月ころに、私の地元である函館にある就労支援事業所の「Ponte函館」さんから、講師をお願いしたいという依頼をメールでいただいておりました。

テーマは「うつ・ひきこもりの人に向けて、ITエンジニアとして働くことについて」ということでした。私の生まれ育ちや社会人経験をざっくりまとめたライフヒストリーと、ITエンジニアとして働くうえで必要なスキルや心構えなどについてを話しました。

資料について

スライドを以下に公開します。パワポ芸だったり、キャッチーな言葉を意識的に使っていることもあり、だいぶ情報商材っぽいうさんくさいスライドになってしまった点は反省しております。ただ、思ったことをそのまま書いているので、まあいいかという感じです。

色々ご意見等あろうかと思います。その場合は、Twitterにてどうぞ。但し、生産的ではないと思われる言論には反応しません。ご了承ください。

まとめ

私自身は少なくともひきこもりではないですが、過去にうつの傾向があった時期があります。そのような経験を踏まえて、今回の講義をさせていただきました。

より多くの方がITエンジニアとして働くために、何かしらのヒントになれば幸いです。

SAFE Stackで立ち上げてみる

※このエントリはF# Advent Calendar 2023の17日目の記事です。

※F#歴2週間かつ趣味で触っている程度(つまり経験値は実質2日ほど)の人間が書いています。

目標

SAFE Stackというものがあるようなので、SAFE StackとF#に入門してみることにしました。

SAFE Stackとは何なのか?

Isaac Abraham氏による解説を見てみましたが、どうやら以下のようなものらしいです。

Throughout this week, we've published a series of articles contributed by some well-known people within the F# community focused on web and cloud programming. Today, we're announcing the launch of the SAFE stack initiative, which brings all of the elements together as a cohesive story:

- `Saturn` model for server-side web programming
- `Azure` for cloud-based systems
- `Fable` for Javascript-enabled applications
- `Elmish` for an easy-to-understand UI programming model

Saturn, Azure, Fable, Elmishの頭文字を取ってSAFE Stackと呼んでいるようです。

Saturn - F#におけるMVCフレームワークの一つ

公式サイトによると、以下のような特徴があるようです。

- Modern programming model
  - Saturn combines the well known MVC pattern with the power of FP and F# to make web programming fun and easy.

- High performance
  - Saturn builds on top of highly optimized, and battle tested technologies such as ASP.NET Core, Giraffe and Kestrel.

- Developer experience
  - Saturn provides set of tools, templates and guides that makes creating and maintaining applications seamlessly.
  
- Created by Community
  - Saturn is created and maintained by well known members of the F# OSS Community and supported by industrial users.

要約すると、MVCパターンと関数型言語のアプローチを組み合わせた書き方ができ、パフォーマンスはGiraffeやKestrelに根ざした最適化済みのものであり、開発者向けのツール・テンプレが用意されていて、しかもOSSである、とのことです。最初の項目しか頭に入ってきていませんが、なかなか良さそうですね。

Azure - Microsoftのクラウドサービス

公式サイト

SAFE Stackの中では飛びぬけて有名なので、説明は省略します。

Fable - F#からJavaScriptを生成するコンパイラ

公式サイトを見て驚きました。まさか、F#からJavaScriptを生成するコンパイラがあるとは。Fableを使うと、F#で書いたコードをJavaScriptに変換して、Webブラウザ上で動かすことができるようです。 ちょっと凄すぎてよくわかりません・・・

Elmish - Elmの「Model View Update」を参考にした抽象化機構?

公式サイトを見てみましたが、いまいちピンと来ず。。。
もう少し深く調べてみたところ、Elm Architectureなるものがあるらしく、ElmishはそれをF#で実装したもののようです。

これらの情報から、ElmishはElmの「Model View Update」を参考にした抽象化機構っぽいな?という程度の理解しかできませんでした。

ともあれ、一旦これでSAFE Stackについてはなんとなくわかったようなわからんような感じになりました。

事前準備

VSCodeのインストールとDev Container Extensionのインストール

まずVSCodeが必要となりますので、インストールします。

次に、VSCodeの拡張機能であるRemote - Containersをインストールします。これを次の環境構築で使います。

環境構築

devcontainerを使って環境構築を行っていきます。

devcontainerの作成

まず、ブランクのディレクトリ(ここではディレクトリ名を fsharp-practice とします)を作成し、VSCodeで開きます。

次に、VSCodeのコマンドパレットを開き、 開発コンテナ―: コンテナ―機能の構成 を選択したら、イメージとして F# on Fedora を選択していきます。featuresには Node.js (via nvm), yarn and pnpm (node) を選択します。

その後、 開発コンテナ―: コンテナ―でリビルドして再度開く を選択します。しばらく待つと、 fsharp-practice ディレクトリがコンテナ―内にマウントされた状態でVSCodeが開きます。これで環境構築は完了です。

つくってみる

SAFE StackのQuickstartを参考に、 Hello, world! を返すJSON APIを作ってみます。

SAFE Stackのテンプレートをインストールする

以下のコマンドで入ります。

1
dotnet new install SAFE.Template

SAFE Stackのテンプレートを使ってプロジェクトを作成する

これもコマンドだけでOKです。

1
dotnet new SAFE

この時点で、以下のようなファイル構成になっているはずです。

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
vscode ➜ /workspaces/fsharp-practice $ tree
.
├── Build.fs
├── Build.fsproj
├── fsharp-practice.sln
├── global.json
├── Helpers.fs
├── package.json
├── package-lock.json
├── paket.dependencies
├── paket.lock
├── paket.references
├── README.md
├── src
│ ├── Client
│ │ ├── App.fs
│ │ ├── Client.fsproj
│ │ ├── index.css
│ │ ├── Index.fs
│ │ ├── index.html
│ │ ├── paket.references
│ │ ├── postcss.config.js
│ │ ├── public
│ │ │ └── favicon.png
│ │ ├── tailwind.config.js
│ │ └── vite.config.mts
│ ├── Server
│ │ ├── paket.references
│ │ ├── Properties
│ │ │ └── launchSettings.json
│ │ ├── Server.fs
│ │ └── Server.fsproj
│ └── Shared
│ ├── paket.references
│ ├── Shared.fs
│ └── Shared.fsproj
└── tests
├── Client
│ ├── Client.Tests.fs
│ ├── Client.Tests.fsproj
│ ├── index.html
│ ├── paket.references
│ └── vite.config.mts
├── Server
│ ├── paket.references
│ ├── Server.Tests.fs
│ └── Server.Tests.fsproj
└── Shared
├── paket.references
├── Shared.Tests.fs
└── Shared.Tests.fsproj

11 directories, 39 files

ローカル開発に使うツール群をインストールする

何やら色々入るようです。

1
dotnet tool restore

こんな感じのログが出ます。NuGetで4つほどパッケージが入っているようです。

1
2
3
4
5
6
7
8
Skipping NuGet package signature verification.
Skipping NuGet package signature verification.
Skipping NuGet package signature verification.
Skipping NuGet package signature verification.
Tool 'paket' (version '8.0.0') was restored. Available commands: paket
Tool 'fable' (version '4.1.4') was restored. Available commands: fable
Tool 'femto' (version '0.18.0') was restored. Available commands: femto
Tool 'fantomas' (version '6.2.3') was restored. Available commands: fantomas

ローカル開発サーバーを起動する

ここまで来たら起動もしていきましょう。

このコマンドでビルドもやってくれるようです。

1
dotnet run

最初20秒くらいは何も起きませんでしたが、その後、以下のようなログが出てきました。

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
run Run
Building project with version: LocalBuild
Shortened DependencyGraph for Target Run:
<== Run
<== InstallClient
<== Clean

The running order is:
Group - 1
- Clean
Group - 2
- InstallClient
Group - 3
- Run
Starting target 'Clean'
/workspaces/fsharp-practice/src/Client> "dotnet" fable clean --yes (In: false, Out: false, Err: false)
Fable 4.1.4: F# to JavaScript compiler
Minimum fable-library version (when installed from npm): 1.1.1

Thanks to the contributor! @zaaack
Stand with Ukraine! https://standwithukraine.com.ua/

This will recursively delete all *.fs.js[.map] files in /workspaces/fsharp-practice/src/Client
No files have been deleted. If Fable output is in another directory, pass it as argument.
Finished (Success) 'Clean' in 00:00:00.4986175
Starting target 'InstallClient'
.> "/usr/local/share/nvm/versions/node/v20.10.0/bin/npm" install (In: false, Out: false, Err: false)
npm WARN deprecated querystring@0.2.1: The querystring API is considered Legacy. new code should use the URLSearchParams API instead.
npm WARN deprecated querystring@0.2.0: The querystring API is considered Legacy. new code should use the URLSearchParams API instead.
npm WARN deprecated uuid@3.2.1: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.

added 171 packages, and audited 172 packages in 15s

21 packages are looking for funding
run `npm fund` for details

3 moderate severity vulnerabilities

To address all issues (including breaking changes), run:
npm audit fix --force

Run `npm audit` for details.
npm notice
npm notice New patch version of npm available! 10.2.3 -> 10.2.5
npm notice Changelog: https://github.com/npm/cli/releases/tag/v10.2.5
npm notice Run npm install -g npm@10.2.5 to update!
npm notice
Finished (Success) 'InstallClient' in 00:00:15.7005897
Starting target 'Run'
/workspaces/fsharp-practice/src/Shared> "dotnet" build (In: false, Out: false, Err: false)
MSBuild version 17.8.3+195e7f5a3 for .NET
Determining projects to restore...
Restored /workspaces/fsharp-practice/src/Shared/Shared.fsproj (in 163 ms).
Shared -> /workspaces/fsharp-practice/src/Shared/bin/Debug/net8.0/Shared.dll

Build succeeded.
0 Warning(s)
0 Error(s)

Time Elapsed 00:00:03.69
server: /workspaces/fsharp-practice/src/Server> dotnet watch run
client: /workspaces/fsharp-practice/src/Client> dotnet fable watch -o output -s --run npx vite
/workspaces/fsharp-practice/src/Server> "dotnet" watch run (In: false, Out: true, Err: true)/workspaces/fsharp-practice/src/Client> "dotnet" fable watch -o output -s --run npx vite (In: false, Out: true, Err: true)

server: dotnet watch ⌚ Polling file watcher is enabled
client: Fable 4.1.4: F# to JavaScript compiler
client: Minimum fable-library version (when installed from npm): 1.1.1
client: Thanks to the contributor! @sasmithjr
client: Stand with Ukraine! https://standwithukraine.com.ua/
client: Using polling watcher.
client: Parsing Client.fsproj...
client: .> dotnet restore Client.csproj -p:FABLE_COMPILER=true -p:FABLE_COMPILER_4=true -p:FABLE_COMPILER_JAVASCRIPT=true
client: Determining projects to restore...
client: Paket version 8.0.0+6bcb14ec191f11e984ff0e58016f5987a5cfa8f6
client: The last full restore is still up to date. Nothing left to do.
client: Total time taken: 0 milliseconds
server: dotnet watch 🚀 Started
client: Paket version 8.0.0+6bcb14ec191f11e984ff0e58016f5987a5cfa8f6
client: Restoring /workspaces/fsharp-practice/src/Client/Client.csproj
client: Starting restore process.
client: Total time taken: 0 milliseconds
client: Restored /workspaces/fsharp-practice/src/Client/Client.csproj (in 214 ms).
client: 1 of 2 projects are up-to-date for restore.
server: Unhandled exception. System.ArgumentException: An item with the same key has already been added. Key: /workspaces/fsharp-practice/src/Server/obj/Debug/net8.0/staticwebassets
server: at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
server: at Microsoft.DotNet.Watcher.Internal.PollingFileWatcher.<CheckForChangedFiles>b__23_0(FileSystemInfo f)
server: at Microsoft.DotNet.Watcher.Internal.PollingFileWatcher.ForeachEntityInDirectory(DirectoryInfo dirInfo, Action`1 fileAction)
server: at Microsoft.DotNet.Watcher.Internal.PollingFileWatcher.ForeachEntityInDirectory(DirectoryInfo dirInfo, Action`1 fileAction)
server: at Microsoft.DotNet.Watcher.Internal.PollingFileWatcher.ForeachEntityInDirectory(DirectoryInfo dirInfo, Action`1 fileAction)
server: at Microsoft.DotNet.Watcher.Internal.PollingFileWatcher.ForeachEntityInDirectory(DirectoryInfo dirInfo, Action`1 fileAction)
server: at Microsoft.DotNet.Watcher.Internal.PollingFileWatcher.CheckForChangedFiles()
server: at Microsoft.DotNet.Watcher.Internal.PollingFileWatcher.PollingLoop()
client: Some Nuget packages contain information about NPM dependencies that can be managed by Femto: https://github.com/Zaid-Ajaj/Femto
client: Project and references (67 source files) parsed in 10372ms
server: warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
server: Storing keys in a directory '/home/vscode/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed. For more information go to https://aka.ms/aspnet/dataprotectionwarning
server: info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[62]
server: User profile is available. Using '/home/vscode/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
server: info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[58]
server: Creating key {b2652658-4977-45a5-809c-2f3f8a9cc018} with creation date 2023-12-16 16:56:54Z, activation date 2023-12-16 16:56:54Z, and expiration date 2024-03-15 16:56:54Z.
server: warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
server: No XML encryptor configured. Key {b2652658-4977-45a5-809c-2f3f8a9cc018} may be persisted to storage in unencrypted form.
server: info: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[39]
server: Writing data to file '/home/vscode/.aspnet/DataProtection-Keys/key-b2652658-4977-45a5-809c-2f3f8a9cc018.xml'.
server: warn: Microsoft.AspNetCore.Hosting.Diagnostics[15]
server: Overriding HTTP_PORTS '8080' and HTTPS_PORTS ''. Binding to values defined by URLS instead 'http://localhost:5000'.
server: info: Microsoft.AspNetCore.Server.Kestrel[0]
server: Unable to bind to http://localhost:5000 on the IPv6 loopback interface: 'Cannot assign requested address'.
server: info: Microsoft.Hosting.Lifetime[14]
server: Now listening on: http://localhost:5000
server: info: Microsoft.Hosting.Lifetime[0]
server: Application started. Press Ctrl+C to shut down.
server: info: Microsoft.Hosting.Lifetime[0]
server: Hosting environment: Development
server: info: Microsoft.Hosting.Lifetime[0]
server: Content root path: /workspaces/fsharp-practice/src/Server
client: Loaded Feliz.HookAttribute from ../../../../home/vscode/.nuget/packages/feliz.compilerplugins/2.2.0/lib/netstandard2.0/Feliz.CompilerPlugins.dll
client: Loaded Feliz.ReactComponentAttribute from ../../../../home/vscode/.nuget/packages/feliz.compilerplugins/2.2.0/lib/netstandard2.0/Feliz.CompilerPlugins.dll
client: Loaded Feliz.ReactMemoComponentAttribute from ../../../../home/vscode/.nuget/packages/feliz.compilerplugins/2.2.0/lib/netstandard2.0/Feliz.CompilerPlugins.dll
client: Started Fable compilation...
client: Fable compilation finished in 8173ms
client: .> npx vite
client: Watching ..
client: VITE v5.0.5 ready in 1074 ms
client: ➜ Local: http://localhost:8080/
client: ➜ Network: use --host to expose
client: ➜ press h + enter to show help

ブラウザで確認する

ブラウザで http://127.0.0.1:8080 にアクセスすると、以下のような画面が表示されました。

テキストエリアに文字列を入れてから Add ボタンを押すことで、その内容がリストに追加されるようです。簡易的なToDoアプリでしょうか。

まとめ

本当はこのあとロジックの修正とかまでやってみたかったんですが、なかなか手が付かず、SAFE Stackなアプリケーションの立ち上げまでやっただけでした。

出来上がったソースコードを読んだりいじりながら、SAFE StackとF#の理解を深めていくことにします。

本当に初心者が書いたエントリですが、何かお役に立てれば幸いです。

HonoをAzure Functionsで動かす

※このエントリはHono Advent Calendar 2023の10日目の記事です。

Azure Functionsとは

Azure Functionsは、MicrosoftがAzure上で提供する、サーバーレスな関数を作成するためのサービスです。Azure Functionsは、以下のような特徴があります。

サーバーレス

Azure Functionsは、サーバーレスなサービスです。サーバーレスとは、サーバーを意識せずに、コードを実行できることを指します。Azure Functionsでは、コードを実行するためのサーバーを意識する必要がありません。また、コードを実行するためのサーバーを自分で用意する必要もありません。

イベント駆動

Azure Functionsは、イベント駆動なサービスです。Azure Functionsでは、以下のようなイベントをトリガーに、コードを実行することができます。

  • HTTPリクエスト
  • メッセージキュー
  • データベースの変更
  • タイマー

今回はHTTPリクエストをトリガーにコードを実行する方法となります。

言語の選択肢が豊富

Azure Functionsでは、以下の言語を利用して、コードを実行することができます。

  • C#
  • Java
  • JavaScript
  • TypeScript
  • PowerShell
  • Python

その他にも、カスタムハンドラーDockerコンテナ を利用して、さらに多くの言語を利用することができます。

HonoをAzure Functionsで動かす

まずAzure Functions Core Toolsを利用して、ローカルな環境でHonoをAzure Functionsで動かしてみます。

今回はすぐに動作を試せるように、サンプルを使いましょう。サンプルはこちらで公開しています。

Dev Containerで開発環境を構築する

まずは、開発環境を構築します。開発環境はDev Containerで構築します。Dev Containerという拡張機能を利用しますので、Visual Studio CodeにDev Containerをインストールしてください。

次に、Visual Studio Codeで、ytnobody-hono-on-azure-functions-prototypeを開きます。コマンドパレットを開き、Remote-Containers: Reopen in Containerを選択します。すると、Dev Containerが起動します。初回は起動までに結構な時間がかかります。

Dev Containerが起動したら、以下のコマンドを実行して、依存関係をインストールします。

1
npm install

一緒に azure-functions-core-tools もインストールされます。これがAzure Functions Core Toolsです。

Azure Functions Core Toolsを起動して動作確認する

Azure Functions Core Toolsを起動して、動作確認をします。以下のコマンドを実行します。

1
npm run start

このコマンドでビルドも行われ、Azure Functions Core Toolsが起動します。

以下のようなログが出力されましたら、Azure Functions Core Toolsが無事に起動しています。

1
2
3
4
5
6
7
8
[2023-12-09T23:11:32.503Z] Worker process started and initialized.

Functions:

ytnobody-hono-func: [GET,POST] http://localhost:7071/api/ytnobody-hono-func

For detailed output, run func with --verbose flag.
[2023-12-09T23:11:36.744Z] Host lock lease acquired by instance ID '000000000000000000000000E7F5F683'.

Azure Functions Core Toolsが起動したら、ブラウザでhttp://localhost:7071/api/ytnobody-hono-funcにアクセスします。以下のようなJSONが表示されましたら、無事に動作しています。

Alt text

実際にAzure Funtionsでも動作した!

一応実環境でも同じように動作するか確認してみました。以下のURLにアクセスしてみてください(そのうち消します)。

https://ytnobody-hono-on-azure-functions-prototype.azurewebsites.net/api/ytnobody-hono-func

POSTメソッドでJSONを送ると、そのデータが含まれたJSONが返ってきます。

この方法の制約

Honoでアプリケーションを開発する際、複数のハンドラーを実装することが多いでしょう。つまり、 GET /POST /item に対応したいというように、複数のエンドポイントを実装しますよね、という話です。

ところが、Azure FunctionsのHTTP Triggerでは、1つの関数に対して1つのエンドポイントしか設定できません。つまり、 GET /POST /item に対応するためには、2つの関数アプリを作成する必要があります。

また、Azure FunctionsのHTTP Triggerでは、function.jsonというファイルに、エンドポイントの設定を記述します。ここにHTTPメソッドを指定するため、Hono側でHTTPメソッドの指定をしたとしても、Function.jsonの設定が優先されてしまいます。

そのため、Honoアプリケーション側で指定するHTTPメソッドは基本的にはallを指定することになるでしょう。

Hono coreへのPull Request

Hono coreに、今回作成したAdapterを含むPull Requestを送りました。まだDraftの状態ですが、以下のURLから確認できます。

https://github.com/honojs/hono/pull/1797

もうすこしブラッシュアップして、マージできるようにしたいと思います。

もう一つの方法:Docker on Azure Functions

Azure Functionsでは、Dockerコンテナを利用して、さらに多くの言語を利用することができます。これを利用すると、Honoをそのまま動かすことができます。

Dockerコンテナを利用する方法は、以下のURLに詳しく書かれています。

https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-create-function-linux-custom-image

おわりに

Azure FunctionsでHonoを動かす方法を紹介しました。Azure Functionsは、サーバーレスなサービスで、イベント駆動なサービスです。TypeScriptにも対応しており、nodeもv18が使える状態でしたので、Honoを動かすことができます。

また、Azure Functionsで動作するように、Hono coreにもPull Requestを送りました。ブラッシュアップの末にこれがマージされれば、制約はありますがAzure FunctionsでHonoを動かすことができるようになります。

雑なデータ加工に使えるORM:Otogiri

※このエントリはPerl Advent Calendar 2023の3日目の記事です。

※元々は「雑なデータ加工に使える小技5撰」でしたが内容がOtogiriだらけなので、タイトルを変更しました。

Otogiriとは

拙作のPerl製ORM(もどき)です。Otogiri - CPANを参照してください。

特徴として、以下のようなものがあります。

  • スキーマ定義がない(DB/テーブルにあるものを正としている)
  • データは全てハッシュリファレンスかその配列で表現される
  • 端的に言えば DBIx::Sunny + SQL::Maker

MetaCPANに公開されているモジュールですので、cpanm Otogiriでインストールできます。

Otogiriの基本的な使い方

DB接続

podにも書いてありますが、DB接続は以下のようにして行います。以下の例ではmysqlに接続しています。

1
2
3
4
5
6
use Otogiri;
my $db = Otogiri->new(connect_info => [
'dbi:mysql:dbname=mydb',
'dbuser',
'dbpassword'
]);

strictモード

Otogiriはデフォルトでstrictモードで動作します。strictモードはSQL::Makerのstrictモードそのままの制約がつきます。

strictモードはこちらに記載があるようなSecurity Issue(JSON SQL Injection)への対策として、SQL::Makerに実装されています。もしWebアプリケーションにおいて、ユーザーからの入力をSQLに埋め込む場合はstrictモードを有効にすることを強くお勧めします。

strictモードを解除するには、DB接続時に以下のようにします。

1
2
3
4
5
6
7
8
my $db = Otogiri->new(
connect_info => [
'dbi:mysql:dbname=mydb',
'dbuser',
'dbpassword'
],
strict => 0
);

これはselectやinsertの際の記述方法に影響があります。別途、selectやinsertの説明の際に触れます。

データ取得

データ取得はselectメソッドを使います。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
## strictモードが有効の場合
my @rows = $db->select(user => { id => sql_in([1, 4]) });

## strictモードが無効の場合
my @rows = $db->select(user => { id => [1, 4] });

## 以下のようなデータが@rowsに入ります。
## (
## {
## id => 1,
## name => 'ytnobody',
## age => 43,
## created_at => '2023-12-03 00:00:00'
## },
## {
## id => 4,
## name => 'somebody',
## age => 36,
## created_at => '2023-12-03 01:00:00'
## },
## )

単一データを取得する場合はfetchメソッドを使います。

1
2
3
4
5
6
7
8
9
my $row = $db->fetch(user => { id => 1 });

## 以下のようなデータが$rowに入ります。
## {
## id => 1,
## name => 'ytnobody',
## age => 43,
## created_at => '2023-12-03 00:00:00'
## }

データ挿入

データ挿入はinsertメソッドを使います。

1
2
3
4
5
6
7
8
9
10
11
12
13
## strictモードが有効の場合
$db->insert(user => {
name => 'ytnobody',
age => 43,
created_at => sql_raw("datetime(now)"),
});

## strictモードが無効の場合
$db->insert(user => {
name => 'ytnobody',
age => 43,
created_at => \"datetime(now)",
});

データ更新

データ更新はupdateメソッドを使います。

1
2
3
4
5
6
7
8
9
10
11
## strictモードが有効の場合
$db->update(user => {
age => 44,
created_at => sql_raw("datetime(now)"),
}, { id => 1 });

## strictモードが無効の場合
$db->update(user => {
age => 44,
created_at => \"datetime(now)",
}, { id => 1 });

データ削除

データ削除はdeleteメソッドを使います。

1
2
3
4
5
## strictモードが有効の場合
$db->delete(user => { id => sql_in([1, 4]) });

## strictモードが無効の場合
$db->delete(user => { id => [1, 4] });

トランザクション

トランザクションはtxn_scopeメソッドを使います。

1
2
3
4
5
6
7
8
9
10
11
12
my $txn = $db->txn_scope;
$db->insert(user => {
name => 'ytnobody',
age => 43,
created_at => sql_raw("datetime(now)"),
});
$db->insert(user => {
name => 'somebody',
age => 36,
created_at => sql_raw("datetime(now)"),
});
$txn->commit;

もっと複雑な使い方

ここから先はさらに複雑な使い方を紹介します。

データ取得時にカラム指定を行う

Otogiriは基本的にテーブルにある全てのカラムを取得します。これは「雑にデータ取得と処理を行うこと」を主目的としているため、そのままではカラム指定を行うことができません。

ですが、Otogiriにはプラグイン機構があります。これはOtogiri::Pluginというモジュールによって実現されています。

カラム指定を行うプラグインはOtogiri::Plugin::SelectWithColumnsです。

使い方は以下のようになります。

1
2
3
4
5
6
7
8
9
10
11
use Otogiri;
use Otogiri::Plugin;
my $db = Otogiri->new(connect_info => [...]);
$db->load_plugin('SelectWithColumns');

my @rows = $db->select_with_columns(
'some_table',
['id', 'name'],
{'author' => 'ytnobody'},
{order_by => 'id ASC'}
);

select_with_columns というメソッドが使えるようになり、その第2引数でカラムを指定することができます。

スキーマ定義をしてデータクラスを指定する

Otogiriの特徴には「スキーマ定義がない」というものがありましたが、その気になればスキーマ定義を書くこともできます。

perl-5.38以降であれば class 構文を使うことでスキーマ定義を書くことができます。

1
2
3
4
5
6
7
8
9
10
11
12
class Book {
field $id :param;
field $title :param;
field $author :param;
field $price :param;
field $created_at :param;
field $updated_at :param;

method title {
return $title;
}
};

実際に単一取得を行う場合、事前にrow_classメソッドでスキーマ定義を指定することで、スキーマ定義に従ったオブジェクトを取得することができます。

1
2
my $book = $db->row_class('Book')->single(book => {id => 1}); 
say $book->title;

敢えてrow_classを無効にしたいシーンでは、row_classメソッドの代わりにno_row_classメソッドを使います。

1
2
my $book = $db->no_row_class->single(book => {id => 1});
say $book->{title};

inflate/deflate

Otogiriの機能で最も複雑なのがinflate/deflateです。これはDBから取得したデータを予め指定した関数に基づいて変換したり、DBに格納するデータを予め指定した関数に基づいて変換したりする機能です。

inflate/deflateは以下のようにして使います。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
use JSON;
use Otogiri;
my $db = Otogiri->new(
connect_info => [...],
inflate => sub {
my ($data, $tablename, $db) = @_;
if (defined $data->{json}) {
$data->{json} = decode_json($data->{json});
}
$data->{table} = $tablename;
$data;
},
deflate => sub {
my ($data, $tablename, $db) = @_;
if (defined $data->{json}) {
$data->{json} = encode_json($data->{json});
}
$data;
},
);

inflateはselect(), search_by_sql(), fetch()がコールされた後に呼ばれ、取得データを加工します。
deflateはinsert(), update(), delete()がコールされる前に呼ばれ、格納データを加工します。

直近のOtogiriについて

基本的にはOtogiriのメンテははっきり言ってのんびりしています。ですが、row_class の機能は最近追加されたばかりです。

また先ほど、DBURLへ対応をさせるためのPull-Requestを作成したところです。

もしこれが取り込まれたら、以下のようにDB接続情報をURLで指定できるようになります。

1
2
my $dburl = 'mysql://dbuser:dbpassword@dbhost/mydb?someOption=someValue&otherOption=otherValue';
my $db = Otogiri->new(dburl => $dburl);

Otogiriの今後

基本的には「雑にデータ取得と処理を行うこと」が主目的なのは変わらずで、そのための機能を追加していく予定です。

ぜひ、Otogiriを使ってみてください。そして、Pluginの作成やPull-Requestの作成など、Otogiriの開発にも参加していただけると嬉しいです。

函館市電LT大会というイベントでLTしてきた

9/18(祝)に開催された函館市電LT大会というイベント参加してきました。

函館市電LT大会?

そもそもどんなイベントなのかをひとことで説明すると、「函館市電を貸し切って、函館市内を走行する市電車両の中でLT発表会を行う」というものです。うん、まだ意味不明ですね。

函館市電とは?

函館市電というのは函館市が運営する路面電車です。函館市企業局交通部という市の部署が運行からメンテナンス等、路面電車を運行するためのあらゆる業務を担当しています。

以下がその路線図となります。(函館市電の公式から画像を拝借しました)

函館市電路線図

運行系統としては2系統と5系統があり、湯の川~十字街の間は全く同じ場所を走ります。十字街から先は、2系統が谷地頭まで、5系統が函館どつく(これで「はこだてどっく」と読みます)まで、それぞれ走ることになります。

それぞれの駅(正しくは停留所)の間は概ね2分程度での移動が見込まれています(ここ、あとで重要になります)。

LT大会??

ライトニングトーク(LT)をする大会ということなのですが、厳密にはLTは5分間という決まりがあります。

ところが当イベントでは時間制限の区切り方がだいぶ特殊でして、「市中を走行する路面電車内でのLT」ということもあって、5分間という区切りの代わりに「3区間で無慈悲に発表終了となる」というルールが採用されました。

例えば湯の川からLTを開始した場合、3区間先までとなりますから、駒場車庫前に到着した時点でLT強制終了となります。

停留所の間は概ね2分程度ですので、大体6分くらいが持ち時間としての期待値となります。しかし、普通のLTと比べて時間が読みにくく、停留所どうしの間隔が長かったり短かったりする区間もありますし、路面電車という交通手段の都合上、どうしても信号や自動車との兼ね合いで時間がブレるわけです。

そのため、ちょうど良いタイミングでLTを終わらせるには、函館市電をどれだけ使いこなしているかが試されるのです。

路面電車の車両を1両まるごと貸し切り???

このイベントの突飛なところは公共交通機関を丸ごと1両借りてしまうというその豪快さにあるでしょう。企画を目にしたときには「なんてめちゃくちゃな!」と思ったものです。

ところがこの函館市電、過去には地元企業の慰労会等でカラオケ電車なるものを運行していた実績があります。そして、今もなお「1運行:大人20000円」で貸し切り運行を受け付けています。

要するに10人も集まれば、一人当たり2000円程度で貸し切り運行ができてしまうのです。全然めちゃくちゃじゃなかった。

どんな発表があったか?

一部を取り上げると、以下のような感じのものがありました。

  • Arduinoを使った心拍数を計測するデバイスの実演とバグ修正
  • 積ん読をひたすら推奨する話
  • 道南地区のロードサイドについて掘り下げる話
  • 鉄道模型のコントローラーの話
  • 自作Dvorakキーボードの話

どんな話をしたのか?

私の発表は「ビジネスロジックを純粋関数で実装する」的な話です。

その他

  • 工業高校のOBが途中参加。文字通りの飛び入り参加で場を沸かせる。
  • はこだて未来大学の角教授が「なんか面白そうなことをしているな?」と言いつつ終点の駒場車庫に登場。写真を存分に撮影してくださった。
  • イベント後は松陰町のラッキーピエロで懇親会。

とにかくめちゃくちゃ楽しかったです!来年もやるんですよね?やりましょう!

twitter(X) のハッシュタグ #函館市電LT #函館市電LT大会 もみてみるといいです!

※9/19 函館空港のビジネスコーナーにて、羽田行の最終便を待ちつつ執筆。

湘南.pm#1に参加してきた

※だいぶ時間経過しちゃったけど、エントリだけ書いてあって公開してなかったので公開します。

8/26(土)に開催された湘南.pm #1に発表者として参加してきました。

発表内容

スライドはこちらです。適当に revealjs 等で見てください。

最近やっているコンポーネント構成とエンジニア育成について話した

特に初学者と呼ばれる人がプロジェクトに参加しやすくすることを考慮したコンポーネント構成について話しました。ざっくり箇条書きにすると以下のような感じです。

  • そもそもプログラミングは難しいものだし、その中でもオブジェクト指向プログラミングは初学者に教えるのも、また理解してもらうのもコストが嵩む。
  • とはいえ、初学者だからと言ってプロジェクトに参加させない、という選択をし続けることにも限界がある。
  • そこで、初学者にもわかりやすいコンポーネント構成を考えることにした。
  • 結果としてオブジェクト指向プログラミングを捨てたコンポーネント構成となった。
  • コンポーネント間の依存方向を一方通行にしたり、副作用の有無によってビジネスロジックを明確に分離する、といった工夫をした。

また、今回発表したコンポーネント構成を Perl で実装したものがこちらです。dev-container を使っているので、ローカルに Perl をインストールする必要はありません。

ちなみに最近は Typescript で開発しているので、Perl で開発するのはかなり久しぶりでした。

その他

  • いっぱい飲んだ。いっぱい人と話した。楽しい。
  • YAPC::Hiroshima ぶち上げていこう!!!
  • 藤沢、面白い街だなぁ。また行きたい。
  • @papix おめでとう!