ねこものがたり

いちにちいっぽ

Private Use Area

自分の好きな絵文字を作って使いたい!

スマホやPCで文字を打っているとたくさんの絵文字がある*1ことがわかりますが、こんなにたくさんの絵文字があっても本当に私がほしいものはそこにはありません。

それは何か? そう将棋の絵文字です。現在のUnicodeには絵文字ではなく、やや抽象的な図形の記号が4種類あるのみ。

Unicodeにある将棋関係の文字
Unicodeにある将棋関係の文字

現実世界の将棋の駒の種類は14種類。先後で向きが反転するのでそれぞれ2パターン。全部で28パターンの表現が必要です。さらに「王」と「玉」を分けて用意すると15種類(30パターン)になります。 全然足りないので、自分で作って使いたいと思いました。

PUAってのがあるんだって

自分の好きな絵文字を作って使う方法を調べていると、Unicodeが文字を割り当てず利用者が自由に使えるように確保している領域があると知りました。 それをPrivate Use Area(PUA)というそうです。日本語だと私用領域と呼ぶらしい。何となく英語の方が素直に意味が入ってくる気がします。

Wikipediaに詳細があるのですが、コードポイントの範囲で言うと3つのPUAがあるそうです。

名称 範囲 使える数
私用領域(Private Use Area) U+E000〜U+F8FF 6,400
補助私用領域A(Supplementary Private Use Area-A) U+F0000〜U+FFFFD 65,534
補助私用領域B(Supplementary Private Use Area-B) U+100000〜U+10FFFD 65,534

PUA範囲内のコードポイントに好きな字形を割り当てたフォントを作れば、そのフォントが使える環境でその文字を表示できるようになります。

Font AwesomeのようなアイコンフォントもPUAを使っているらしいです*2。それを知ると、私がやりたいことはFont Awesomeと同じことだなということが想像できました。

*1:2025年9月時点でUnicodeには4,000弱の絵文字があるらしい。ソース: 絵文字の統計

*2:数年前のFont Awesomeのバグ修正の記事ですが、https://blog.fontawesome.com/fixing-a-unicode-bug-in-5-14-0/ にPUAについて触れてあります

記録の不可逆性を加味してcreated_at/updated_atだけで本当に事足りるのかを考えたい

経緯

神速さんのポストきっかけで、Railsにおけるテーブルのタイムスタンプについて話が交わされています。

神速さんとはなちんさんは基本的には、必要とされるまではタイムスタンプはRailsのデフォルトを使うのが良いとおっしゃっています。

おそらく、おふたりと同じ考えの人は結構多いのではないかと思います。そして私もこの意見には一定賛成です。

「記録していない事実を後から補完することはできない」ということをDB設計では考えるべきだ、と思う

Railsのレールに乗るのが良いという意見に賛成する一方で、DB設計については私は違う考えを持っています。アプリケーションコードはYAGNIを遵守した方がいいコードになりやすいけど、DBでは後からでは遅いことがあるという理由からです。

「絶対にcreated_at / updated_at 以外のカラムを使うべきだ」というほど極端なことを言いたいわけではありません。 しかし「"事実の記録をしない"という選択は不可逆な選択肢なので、本当にcreated_at / updated_at だけで良いのかは考えるに越したことはない」と思っていて、場合によっては「あった方がいいかも」程度でもDBのカラムに持っておく判断もあり得ると考えています。

一律の正解はなくユースケース次第ではあると思うのですが、だからこそ毎回毎回「今回はどうだろうか」とうんうん唸ってでもちゃんと考えておいて損はないと思っています。(Railsのレールに乗って早く開発するぞという話の否定意見ではなくて、別の視点の話のつもり)

例えば?

神速さんの記事だと、usersテーブルにcreated_atとは別にregistered_atが必要になるケースはほとんどないからcreated_atだけで良いだろうという例と考えが記されています。

これに対して私は「私だったらregistered_atを持つ選択をするかもな」と思いました。 正確にいうと「他の日時カラムが必要かも?というスタンスで設計の検討に入るな」という感じです。

もちろん検討した結果、最終結論が「created_at だけで良い」となる場合も多々あるかと思います。それでも、一旦立ち止まる価値はあるはずです。

「(これから作ろうとしているアプリケーションの処理を考えると)userレコードが作られた段階では会員の"登録"はまだ終わっていない」ということがusersテーブルの設計時点で明らかだとすると、

  • ①usersにステータスカラムを持たせ、ステータスに「登録」という値を持つ
  • ②usersテーブルに登録日時カラムを持たせる(アプリケーションではそのカラムに値が入っていれば登録済みとして扱う)
  • ③登録イベントをエンティティ(別テーブル)として定義する

あたりの選択肢は出てきそうです。

何度も前置きすると言い訳がましいかもしれませんが、どの選択肢が絶対に正しいというものはないはずです。 状況ややりたいこと次第でどの選択肢が最適かは変わるはずではありますが、「データが記録されていないと、流れ去っていった過去の事実を遡って復元することは絶対にできない」という点は、どの選択肢を選んだとしても共通して言えることかと思います。

この点を踏まえると、私はこの中だと②を選ぶ余地はかなりあるのではないかと思います。

「updated_atの上書き」で消えていく事実

「userレコードが作られた段階では会員の"登録"はまだ終わっていない」ということが明らかなusersのテーブル設計で、①usersにステータスカラムを持たせ、ステータスに「登録」という値を持つ選択をしたとします。 登録日時は、登録した時点のupdated_atということになります。

しかし登録完了後に他のカラムを変更した場合、updated_atは別の日時に変わってしまい、「いつ会員登録したのか」はわからなくなります。

初期のうちはこれで問題なく動くでしょう。そのうち、マーケターやPMに「登録から初回購入までのタイムラグを集計したい」「月別の登録ユーザー数の推移を正確に出したい」と言われたとします。この時、既存の登録済みユーザーがいつ会員登録を済ませたのかが全データ分残っているとは限りません。*1

だからこそ、記録ロジックやUI(機能)までは初期段階で作らなくても、「いつその事象が起きたか」を保持する registered_atといった NULL許容のカラムをDBに定義する判断 には、大きな価値があると思っています。

おわりに

冒頭でも触れた通り、私は「Railsのレールに乗って素早く開発する」というアプローチを否定したいわけではありません。 不要なコードを書かないYAGNI原則は、Webアプリケーション開発において強力な指針です。それに、DBでも、いきなり何でもかんでも考慮・想像して過剰な実装になってしまうのはいいとは言えません。

しかし、「後からいつでも書き直せるアプリケーションコード」と「一度失われたら二度と復元できないDBの蓄積データ」では、YAGNIを適用する際のリスクの重みが異なるように思います。

  • とりあえずデフォルトの created_at / updated_at で素早く作る
  • 「本当にこのイベントの日時は後から追わなくて大丈夫か?」と一瞬立ち止まり、必要ならカラムを追加しておく

瞬間瞬間の開発コストの差はほんのわずかなものでしょうが、数年後のプロダクトやチームに与える影響の差は決定的になり得るんじゃないかと思います。

テーブルを新規作成するその一瞬に、「記録していない事実は後から補完できない」という不可逆性を頭の片隅に置いて考えていくことで、見えてくる何かもあるのかなと思っています。

実際の開発時には、まだ世の中に正解はなくて自分たちで考えて選んでやっていくしかないってことばかりですし、開発の速さは正義みたいなところもありますし、未来は誰にもわからないから、YAGNIに反する選択をするにはよっぽど強い根拠が必要ですし、でもレールに乗ってても「あーあの時こうすればよかったなー」って思うことがあるのも事実で、色々ひっくるめて「自分たちは今どういう選択をするのが良いかを考えるようにしたいと思っている」というのが率直なところなので、この記事をまとめてみました!

*1:この例だとアプリケーションログを漁れば残っている可能性はあるかもしれませんが、保管不可能な事例もあるだろうということが伝われば幸いです