#
794
2026/7/23
今日のトレンド

Go標準UUIDとTabキー問題

どうも、マイクです。おはようございます。
二千二十六年七月二十四日、金曜日の朝七時を回りました。
ここからの時間は「zenncast」、きょうはZennでいまトレンドになっている技術記事を、ゆったり紹介していきたいと思います。

きょうは全部で五本の記事をお届けします。Go、フロントエンドのアクセシビリティ、Rustの内部仕様、AIを使った開発フロー、そしてちょっと変わり種のJVM向けドメインモデリング言語まで、幅広く攻めていきますよ。

まず一つ目。
Goユーザーの方は、けっこう待ってたんじゃないでしょうか。Go一・二七で、ついに UUID パッケージが標準ライブラリ入りする、というお話です。
この記事では、その裏側でどういうプロポーザルの議論があって、最終的にどういう案に落ち着いたのか、理由も含めて整理してくれています。

背景として大きかったのが、googleスラッシュuuidが、Go界隈で本当に広く使われているという事実なんですね。「もうみんなこれ使ってるし、標準に入れるコストより、メリットのほうが明らかに大きいよね」という判断がなされたと。
パッケージ名についても議論があって、「暗号用途だから cryptoスラッシュuuid にすべきか?」みたいな案もあったんですが、将来の拡張も見据えて、あえて単に uuid という名前に落ち着いた、という経緯が説明されています。

対応するUUIDのバージョンも、かなり絞り込まれています。
実利用の多さと、RFCでの推奨を踏まえて、対応するのはバージョンフォーとバージョンセブンだけ。昔のバージョンも全部入れよう、ではなく、「いま、実際に広く使われていて、かつ標準として推したいものだけ」にしたわけですね。
Nil と Max の定数を入れるかどうかも、「別に要らないんじゃない?」という意見もあったそうなんですが、意図を明示したい場面で便利に使えること、それから RFC にも沿っていることから、ちゃんと採用されました。

バージョンセブンに関しては、タイムスタンプの扱いと、UUIDの単調増加をどこまで保証するか、という点がかなり議論されています。
最終的には、十二ビット分の追加タイムスタンプを持たせて、さらに「最後に使った時刻を覚えておいて、もしズレたら補正する」という設計にすることで、ロックを極力避けながら、一つのプロセスの中ではほぼ順序が保たれるようにする、という方針に落ち着きました。

一方で、「UUIDからバージョンとかタイムスタンプを取り出すAPIを標準で提供するか?」という点については、結論として見送られています。
これは、UUIDをあくまで「中身には依存しない、不透明な値」として扱おう、というRFCの考え方に沿った判断ですね。「UUIDの中身をあてにしてロジックを書く」のではなく、「ただの識別子」として使ってほしいという姿勢が見えます。

それから、databaseスラッシュsqlとの連携の仕方もポイントです。
uuid側のパッケージで databaseスラッシュsql のインターフェースを実装しにいくのではなくて、標準の databaseスラッシュsql 側に、uuidを扱うロジックを持たせる設計になりました。
「標準ライブラリ同士だからこそ、こういう依存方向が取れるよね」というのが評価されていて、「拡張ライブラリが標準に依存する」のとは逆向きの関係が、ここではきれいに作られているんですね。
Go一・二七を見据えている方は、UUID周りのコード、今のうちからどう移行するか考えておくと良さそうです。

。。。。

続いて二つ目。
フロントエンド、とくにWebエディタを作っている人には刺さる話題、「Tabキーでキーボードトラップを作っちゃう問題」です。
ブラウザ標準の挙動だと、Tabキーはフォーカス移動、つまり入力欄から次の入力欄へ移るためのキーですよね。ところが、Web上にリッチなエディタを作ると、「Tabでインデント入れたい!」となりがちで、うっかりTabをテキスト入力用に奪ってしまうと、キーボードだけだとエディタから抜けられなくなる、いわゆる「キーボードトラップ」が起きます。

この記事では、筆者がちゃんとW三Cの一次情報を当たりにいっていて、WCAG二・二の「No Keyboard Trap」という達成基準を丁寧に読み解いています。
ここで言われているのは、「キーボードでフォーカスが入った要素からは、キーボードだけで必ず抜けられる必要がある」ということ。ただし、「必ずTabキーでなきゃいけない」わけではない、と。
もし標準的ではない操作、たとえばエスケープキーを押してからTabを押す、とか、コントロールプラス何か、みたいな特殊なコンボが必要になるのであれば、その方法をユーザーにはっきり伝えなければならない、というルールになっています。

実際の有名なエディタがどうしているかも紹介されています。
CodeMirror と ProseMirror は、デフォルト状態ではTabキーには何も割り当てません。必要なときだけ、拡張機能としてTab入力を有効にするスタイルです。そのうえで、エスケープからのTabとか、コントロールエムなどで、「いまは入力モード」「いまはフォーカス移動モード」といった切り替えをする方針を取っています。
Monaco エディタは少し違って、標準の挙動としてはTabでインデント入力を行うんですが、その代わり、コントロールエムを押せばエディタの外へフォーカスを抜けられるようにしている。で、「コントロールエムで抜けられますよ」という案内をどう見せるかは、Monacoを組み込むそれぞれのサービス側の実装に任されています。

つまり、「Tabでインデント入れたいからといって、フォーカス移動を全部殺してしまうのはダメで、ちゃんとキーボードだけで出入りできる道を用意して、その存在をユーザーに知らせようね」というのが、WCAG二・二の要求なんですね。
エディタを自作している方や、Monacoなどのコンポーネントを組み込んでいる方は、自分の実装がキーボードトラップになっていないか、一度チェックしてみると良いかもしれません。

。。。。

三つ目の記事は、Rust一・九七・ゼロのお話。
内部の人にはおなじみの「mangling」、日本語だと「名前つぶし」とか呼ばれますが、関数名なんかを機械向けの一意な文字列に変換する、その方式がRust独自のvゼロ形式に切り替わった、というトピックです。

これまでRustは、Cプラスプラス向けに広く使われている Itanium ABI をベースにしたmanglingを使っていました。
その結果どうなっていたかというと、たとえばジェネリクス、いわゆる generic の型情報がmanglingの過程で落ちてしまったり、「これRustでコンパイルしたシンボルなのか、Cプラスプラスのシンボルなのか、見た目からは区別がつきづらい」といった問題がありました。

今回導入された vゼロ mangling では、シンボル名がアンダースコアアールから始まる、新しいフォーマットになっています。
具体的には、関数にジェネリクスを使っている場合、バックトレース上でも、たとえば「ファンク コロンコロン山括弧 アイ三二山括弧閉じ」「ファンク コロンコロン山括弧 アンドストラ」みたいな形で、型パラメータの情報がきちんと表示されるようになりました。
これによって、パニックが起きたときに、「どの型で呼ばれた関数が落ちているのか」がかなり分かりやすくなって、原因調査やデバッグがやりやすくなります。

古いItaniumベースの方式は、今後はナイトリー版にだけ残して、最終的には削除される予定だとされています。なので、ツールチェーン側で古いmangling前提のツールを作っている人は、早めに対応しておきたいところですね。
一方で、Cとの連携をするときには、これまで通り noアンダースコアmangle 属性を付けて、「あえてmanglingを無効化する」ということもできます。そうすると、シンボル名はソースに書いたとおりの名前になりますが、その分、同じ名前をどこかで再定義してしまうと衝突するので、そこは十分に注意しましょう、という話もされています。

Rustを書いていて、「バックトレースが読みにくいなあ」と感じていた方にとって、今回の vゼロ への切り替えは、かなり嬉しい改善になりそうです。

。。。。

四つ目。
ここからは、AIや自動化を使った開発フローのお話です。
「AIで実装が速くなっても、タスク管理だけは手でポチポチ更新している」というの、心当たりある方多いと思うんですが、この記事では、そのギャップを埋めるために、Notion、Linear、GitHubをClaude Codeでつないで、仕様作成から実装・レビューまでを一気通貫で回す方法を紹介しています。

ポイントの一つ目は、LinearのIssueを「作業メモ」のようなざっくりしたものではなく、「チームから進捗が見える最小単位」としてきちんと設計すること。
もう一つが、IssueとGitHubのプルリクエストをIDで紐付けておいて、レビュー依頼やマージのタイミングで、自動的にステータスを切り替えるようにすることです。
これによって、「終わったタスクのステータスを手で Done に変える」とか、「レビュー依頼したからラベルを付け替える」といった、同じ情報を何回も入力する作業から、できるだけ解放されます。

この記事が面白いのは、Issueを単なるToDoではなく、Claudeへの指示文としても設計しているところです。
一つのIssueの中に、「何をやるか」「何をやらないか」「どこまで終われば完了なのか」「どこを見れば仕様が分かるのか」を、しっかり書く。
そうしておくことで、Claudeはまず実装計画を作ってくれて、人間の開発者は、その方針をざっと確認して承認するだけ。そのあと、具体的な実装からプルリク作成までは、サブエージェントも含めたClaude Codeが進める、という流れにできます。

結果として、開発者が本当にやるべき「実装する」「レビューを依頼する」「マージする」というコアな作業に集中できて、「同じことを三回書く」みたいな進捗共有のための事務作業を、かなり減らせるわけですね。
著者は、この連携の本質的な価値は、「AIがコードを書いてくれること」そのものよりも、「日々の開発の流れと、チームの進捗表示が、自然にそろっていくこと」にあると強調しています。
AIを導入してみたけれど、タスク管理がカオスになっているチームには、すごく参考になる内容だと思います。

。。。。

そして最後、五つ目の記事。
これはかなりマニアックで面白いです。「Souther」という、小さなJVM言語のお話。
何をする言語かというと、業務システムの「ドメインモデル」、つまり業務上の値や状態や処理を、型と制約でガチガチに表現するための専用言語です。

ソースファイルはドットsouという拡張子で、そこに業務データの定義、値の条件、状態遷移、それから外部の依存関係までをまとめて書きます。
それをコンパイルすると、Javaから利用できるクラスとメソッドの形で出力される、という構成になっています。

Southerのコアになるのが、data と invariant、それから behavior という仕組みです。
data と invariant を組み合わせることで、「従業員ID」とか「金額」といった業務の値を、それぞれ独立した型として扱います。そして、「不正な値はそもそも作れない」ようにしてしまう。
たとえば、「金額はゼロ以上」とか、「従業員IDは一定の桁数とフォーマット」といったルールを invariant として宣言しておくと、その条件を満たさない値はコンパイル時点、ないしは生成時点で弾かれる、というイメージです。

behavior では、業務上の状態遷移と、「どんな型の値を作ってよいか」を宣言します。ここがまた特徴的で、失敗を例外で投げるのではなくて、「Rejected」のような通常の値として返すんですね。
複数の処理をつなぐときも、いわゆる成功・失敗のフラグで条件分岐するのではなく、特殊な演算子、「大なりハイフン大なり」みたいな記法、この記事では「にじゅうまる矢印」として >-> と書いていますが、これで処理をつなぎます。
意味としては、「型に合うものだけ、次の処理へ流す」――つまり、成功か失敗かではなく、「このフローに乗せていい形のデータだけが先に進む」という感覚で、業務ロジックをルーティングしていきます。

データベースや現在時刻の取得といった外部処理は、Southerからは直接は呼べません。
それらはJava側で実装して、behavior に「注入」するスタイルを取ります。
これにより、「どの部分が外界に触れているか」が requires で明示的に追跡できて、ドメインロジックの部分は、外部状態に依存しない「純粋な計算」として保たれます。

さらに面白いのが、ドットsouファイルの中に書いた example が、コンパイル時に実行されることです。
これによって、「仕様としてこういう例があるよ」というものと、実際の実装がズレていないかをチェックできる。ドキュメントとテストと実装が、かなり強く結びついた形になるわけですね。

例外やnull、それから任意のJava API呼び出しといったものは、あえて言語からは排除されています。
業務ルールをどう組み立てるか、その経路と制約、依存関係を、言語の枠の中にきっちり閉じ込めることに特化した設計になっています。
既存のJavaアプリケーションをすべてSoutherに書き換える、というよりは、申請や審査、在庫の引き当てなど、「入力と業務判断と、その結果」が中心になる部分だけをSoutherで書くことを想定している、と記事では説明されています。
ドメイン駆動設計が好きな方には、かなり刺さるコンセプトじゃないかなと思います。

。。。。

そろそろお時間です。きょうのzenncast、おさらいしておきましょう。
まずは、Go一・二七で UUID パッケージが標準ライブラリ入りするにあたって、バージョンフォーとセブンに絞った理由や、Nil・Max定数、databaseスラッシュsqlとの連携方針まで、プロポーザルの議論を追った記事。
つづいて、WebエディタでTabキーを奪うことで起きるキーボードトラップの問題と、WCAG二・二の「No Keyboard Trap」を踏まえた、CodeMirror、ProseMirror、Monacoの設計。
三つ目が、Rust一・九七・ゼロでmangling方式がRust独自のvゼロ形式になり、ジェネリクスの型情報がバックトレースで見えるようになった、という話題。
四つ目は、Notion、Linear、GitHubをClaude Codeでつないで、「Issue=指示文」として扱いながら、実装からレビューまでのフローとチームの進捗表示を自然にそろえる開発プロセス。
そして最後に、業務ドメインを型と制約で固める小さなJVM言語「Souther」で、.souファイルからJavaクラスを生成し、外部依存をJava側に注入することで、業務ロジックを純粋な計算として保つ、というお話でした。

気になる記事があれば、詳しい内容はショーノートにまとめてありますので、ぜひそちらから元の記事もチェックしてみてください。
この番組「zenncast」では、皆さんからの感想や、「こんなテーマを扱ってほしい」といったリクエストもお待ちしています。
それでは、きょうも良い一日をお過ごしください。お相手はマイクでした。また次回お会いしましょう。

Related episodes

内容の近いエピソードを推薦しています