タイトルはどう読まれたいかを決める

最近の投稿 でのタイトルは「AはBである構文」で遊んでいるのが分かると思う。

これは「NFTアートは唯一である」という修辞法から学んで気にいって使っている用法なんだけど思ったより色々な意識の変化があった。

そもそもこのサイトはここ数年何だかよく分からないすごそうな著者だけが興味のある技術トピックの話を延々としていた。

タイトルは論文でもなしエッセイでもなしの雲をつかむような言葉選びで、本人的には内容に即した正確な結論をタイトルにつけるべし的なことをずっと考えていたと思う。

最初の変化としてはタイトルをできるだけ短かくするようにしたので、話を単純化しようとするので他人に関心を持ってもらえそうな話題にフォーカスするようになった。

あとは文字数と文節が限られるので、自分の書く内容を正確に表わそうとするのではなく読む人がどう感じて欲しいのかを想像して書くことになった。

『詳解 人間の気持ち』が必要、と言っていた地点から見るとなかなかいい振り返りではないか。

タイトルによって読まれ方を決める例として:

  1. ○○株式会社を退職致しました
  2. 4月の私の近況

の2つは同じ内容が投稿されていたとしても露骨に読まれ方が変わると思う。

今までは「関心が低いとニュースの読者はタイトルだけ読んで反応する」と思っていたが、タイトルによってあらかじめどう読むのかを決めている、と考えると著者がコントロールできる範囲は思ったより広いのではないか。

100人のトロール

Web日記は止まる では「著者が書くことに白けてしまう」ことについて思いあたりがあると反応している人が結構いた。

ただ、これがどういうことが原因で起きているのかを知るとうまく付き合えるのではないかと思ってるので書きたい。

普段10〜20人ぐらいが読んでいるブログが打ち所が悪くSNSなどでバズったとする。

10000人の閲覧が記事を評価し、5割ぐらいの人が「わかる」「それな」的に共感して、3割ぐらいの人が私見を述べるとする。1割ぐらいの人は異論を唱えていて「AはBではない」と感じて、その中の100人ぐらいが「けしからん!」「文章のてにをはがおかしい」となぜか怒っているとする。

この100人をトロールとする。トロールとは怒ることを目的にしている攻撃的な発言者ぐらいの意味で、ネットゲームの世界で元ネタの用語がある。

白けてしまいがちなブログ著者はこのトロールに対しても説得や弁解を誠実に用意しようとしてしまっていると思う。ただ、いやならみるなというのは不誠実な行動に思えるので躊躇ってしまうのだろう。

なので最初にやることはトロールが怒りを目的にしていることを確認することになる。プロフィールを辿り、色々なニュースにどう反応をしているのかを観察する。大抵のトロールは色んな事象について怒っているが、たまに良いことを言っている人もいるので、その時はなかなか見所のあるトロールだなとあらためて元トロールの意見に耳を傾ける——ぐらいのスタンスでいるのがいいと思う。

ポイントは「トロールに見える対象に自分が好かれたいと思うかどうかを自分が決める」という点にあると思う。好かれたいと思わないトロールはあなたの人生の重要な登場人物ではないので説得や弁解に労力をさく必要はない(元トロさんとは和解してください)。

ただ、世の中には自分以外のほとんど他人がトロールに見えているような人もいて、そういう人はどんどん先鋭化して偏っていきそうなので、向き不向きとか居着く環境の問題とかもあるのかもしれない。

Web日記は止まる

2000年代ぐらいにblosxomtDiaryで熱心にWebに何かテキストを書いていたような人たちは特定の価値観を持っているなと思う。

それがどういうものなのかはすぐ説明できないし、単に特定の人たちのことを指しているのかもしれない。ただ、丁寧に閲覧履歴を見ていけば100人ぐらいは該当するサイト管理人が思い浮べられそうだ。

現在は個人が動画で発信する時代なので、僕の思うこの感覚は次の世代では動画に特別な感情を持ちがちという解釈になっているのかもしれない。

Message Passing

このサイトに辿りつくような人たちはプログラム雑談ポッドキャストの188回以降のエピソードのWebに何かテキストを書くことについての話は共感できるのだと思う。

anchor.fm

Message Passingというのは以下のサイトのことで、ガー社とかファー社とかで就労経験のあるような日米のプログラマーかつ、元々Webで何かテキストを書いていた仲の良い人たち同士で寄稿して運営されていた。

messagepassing.github.io

Webに何かテキストを書くことを一旦ブログと呼ぶが、このMessage Passingの話の中で「ブログを書くにはSNSに投稿する時とは別の能力が必要で、それは筋力のように使ってないと衰えるのではないか」という説が出てくる。これは頷ける部分があるので僕も意識するようにした。

ブログを熱心に書いていた書き手がフェードアウトしてしまう問題については、家庭や職場環境が変化すると活動にさける時間が変わるのかも——というのは一般的に言われてもいるしそのとうりだと思うけど、自分としてはブログを書いて得ていた体験が、社内やクローズドな環境で起こる別の行動によって満されてている、という状況があると思っている。

技術的な話題のできる同僚に恵まれていないとあるプログラマーが、別の職場へ転職したら自分と同じような話が合う人が回りに増えたので、わざわざ外に向って発言する必要がなくなった。とかを想像すると分かりやすい。

ただ生活や環境が変わって書く習慣がなくなる人は次の周期で戻ってもくる、という実感があるのであまり問題視してない(自分が数年おきに繰替えしている行動を見るにそうというのもある)。

それよりは最近は第三者の反応によって書くことに白けてしまい習慣がなくなるという例が結構あって深刻というか残念だなと思う。

Firebaseは難しい

Firebaseを使うと簡単に開発がはじめられる一方思ったように使いこなすのは大変という問題がある。

この大変さは以下のように分けて考えている

  1. Firebase特有の機能を正しく理解するのが難しい
  2. ドキュメント指向データベースで開発していくのが難しい

1. Firebase特有の機能を正しく理解するのが難しい

Firebaseを使って開発する時に

  • データベースにCloud Firestoreを使い
  • ブラウザやネイティブアプリからSDKでアクセスし
  • ユーザー認証をする

という要件を満そうと思うと

が付いてくる(厳密にはFunctionsなしにできるケースもある)。

SDKでFirestoreにアクセスするにはクライアントサイドでクエリを実行しデータを取得する。

このクエリでアクセス制御を実現するためにAuthenticationでアクセス元ユーザーを特定し、Security Rulesを設定しクエリに登場するパスごとの権限を設定する。

要するに従来サーバーサイドで行っていた処理をプラットフォームとクライアントサイドで分担することで、データを取得するための認証やAPIエンドポイントの中身の実装を開発者が省けるようになっている。

このSecurity Rulesの設定自体はドキュメントや開発ツールもありよくできた仕組みではあるんだけど、意図した動作にするためにDBのドキュメント構造も含めて試行錯誤しないといけないので従来のサーバーサイドのWebフレームワークを使って実現するのと比べるとハードルが高い。

なのでそれを回避するために、Cloud Firestoreは使うがAPIエンドポイント内のアクセス制御ロジックは自分でコードで実装しSecurity Rulesは使わないという方法を好む人もいる。

その場合クライアントサイドのSDKが用意したオフラインキャッシュ解決やデータ変更のリアルタイム監視の機能などもあきらめることになる。

2. ドキュメント指向データベースで開発していくのが難しい

リレーショナルデータベースは正規化したデータを要求に応じて柔軟にクエリで読み書きしていくが、ドキュメント指向データベースではデータモデルを要求に合わせないといけないという事情がある。

加えて取得する対象のドキュメントにどんな値が格納されているのか、とかドキュメントの定義を変更したら既存のデータを新定義に移行、などをデータベースへの命令ではなくてアプリケーション側で管理する必要がある。

Firebaseでのアプリケーション開発はクライアントサイドに寄っているので、時系列のことなるドキュメント同士をクライアントサイドジョインしたり、データモデルを都合よく調整するためにCloud Functionsでの非同期処理を繋ぎあわせて工夫したりと、ここが実際に開発している時に難しいと感じている点になっている。

リレーショナルデータベースでのORMなどの周辺ツールの充実によってある程度楽になりそうな予感はあるけど今のところ自分は難しい。

初心者に薦められがち問題

Firebaseはフロントエンドのみで無料でサーバー構築なしに開発を始められるので、プログラミング学習コンテンツのデプロイ先として薦められることが結構ある。

しかし前述のようにFirebaseは難しいので、安全でないアプリケーションが世に放たれるとか、開発の継続や引き継ぎが困難になることを懸念している声もある。

クラウド破産問題

Firestoreはしばしば「実装の問題で高額請求が発生してしまった」というニュースを見かけることがある。

現状DynamoDBのプロビジョニングモードようにキャパシティを設定してコストをコントロールする機能がないので、「閾値アラートを飛して監視」ぐらいしか手段が用意されていない。

個人開発のコストはDB次第

個人でWebサービスを継続的に運用するのは金がかかってかなわんという問題がある

「個人開発」だと定義が曖昧なので自己資金かつ赤字のプロジェクト(Webサービス)ということにする。

そういうプロジェクトではプロダクトオーナー=自分、開発者=自分、予算管理者=自分というロールになるので予算管理者としてコストを図る必要がある(ここでいうコストはWebサービスを実現するアプリケーションのランニングコストのこと)。

通常はみんな自分の人件費を0として計算していると思う(逆にいうとそれが負債という考え方もできると思う)。

ただしメンテナンス時間とコストのトレードオフもあるので、人件費0ではあるけど有限の時間は別軸として管理しているのが普通だと思う。極端な例だと「コスト削減できるけどメンテナンス時間10倍になる」というのは避けられる。

仮に個人開発のプロジェクトの予算を月数千円から高くても1万円ぐらいかなーと見込むことにする。

ではこの1万円をどこに割り振っていくかというと一般的なWebサービスではコスト最適化のボトルネックはDBになりがちである。それはCPUやメモリと違いストレージ領域のリソースが24/356の時間に対して発生するからであり、現在の次元で暮している限りそうそう変化しそうにない。

開発者に無料のPostgreSQLサーバーを提供しているfly.ioの人も以下のようにストレージ領域の特殊性を説明している

Stored data occupies space all the time, though, whether your app is running or not. Recovering data from hardware failure means you have to be storing it with some redundancy. You need replication and backups. This means more disk space, but it also means more management. Disks are not easy! https://fly.io/blog/free-postgres/

ではDBのコスト削減を目指す個人開発者の戦略としてどうするのがいいかというと以下が一般的な方法だと思う

  1. SQLあきらめる
  2. DBサーバー使い回す
  3. DB自分で立てる
  4. 実行環境でDBに接続しない
  5. 安いSQLを使う

1. SQLあきらめる

SQLあきらめる」というのはマスターデータの保存先をMySQLPostgreSQLなどの馴染みのあるDB製品を使わずにドキュメント単位のスケールを前提としたDBを活用する。個人開発は規模が小さく収まるのでコストも抑えられるという考え方になる。

実際によく利用されているDB製品は以下がある

  • Cloud Firestore(Fibaseのバックエンド)
  • Amazon DynamoDB(AWS Amplifyのバックエンド)
  • MongoDB Atlas(次点)

自分はFirestoreでReadクエリが1日に3-4万回、Writeクエリが1万回程度の小規模なサイトを管理しているけど無料枠の範囲内なのでDBのコストは月¥5になってる(¥5て)

Firebase プロジェクトの費用

(データの大半はGoogle Driveに逃がしているので、それもFirestoreに含めたらもっと上がると思う)

ただこれらのDBは現在広く普及しているRailsやLaravelやSpringなどのWebフレームワークがSQL互換DBとの連携を基盤にしているので、それらから見たら非主流なWebフレームワークを使うことになる。

00-10年代はSQL互換サーバーを使った開発に慣れてしまっているのでこのギャップを越えられる人は多くない。

整合性やトランザクションなどのDB特性を考慮して避ける例もあるが、エンタープライズ領域ならまだしも個人開発でそれらを気にしている人は少数派である。

個人開発界隈でのここの選択肢はNode.js系の独壇場で例えば以下がある

  • Next.js + サーバーレス何か
  • Nuxt.js + サーバーレス何か
  • Express.js, Flask, Sinatra, Go等のマイクロフレームワーク

デメリットとしては規模に応じて従量課金されるので、SQL互換DBの方がコストが抑えられる分岐点がくるというのがあると思う。むしろその時を向かえたことがないので大ヒットサービスを運用している人に感想を聞きたい。

2. DBサーバー使い回す

プロジェクト間で同じDBインスタンスを使う方法。プロジェクトが増えるごとにコスト優位になる。

デメリットとしてはプロジェクト間の依存関係を受け入れる必要がある。これは想像に難しくないのでこのぐらの説明でよさそう

3. DB自分で立てる

アプリケーションサーバーとDBサーバーを物理的に分散させず、同じVMVPS環境にインストールして動かす。パブリッククラウドが主流になるまで取られていた懐しの手法。

デメリットとしてはマネージドサービスではないのでDBサーバーのメンテナンスを自分で行う必要がある。

これは自分的には「コスト削減できるけどメンテナンス時間10倍になる」方法だと認識しているので避けてる。

4. 実行環境でDBに接続しない

静的サイトをして書き出しあとはフロントエンドの実行コードでなんとかする手法。Jamstackとか呼ばれがちである。

例えばDBにマスターデータを保存して管理画面で管理して利用しつつ、サイトにデプロイする時だけビルドサーバーからDBに接続できればいい、という考え方になる。

Webアプリ向けの方法だと思われがちだけど例えば /api/items.1.json に直接レスポンス実体を置いておく、などをしてバックエンドAPIとしても構築できる。

デメリットとしてはWebサービスの要件が限られる。最も顕著なのは実行時に書き込みを伴うUGMのようなサービスは作れない。

いかがでしたか?

いかがでしたか? SQLをあきらめよう

5. 安いSQLを使う

新興のPaaSはパブリッククラウドのプラットフォームより価格が低いことが多いのでそれを使うという方法もある*1

具体的には選択肢としては以下がありそう

(各社フリープランは本番運用を想定していなさそうなので省いた)

デメリットとしては価格は変わる可能性があるのと、利用実績がAmazon RDSやGoogle Cloud SQL等より少ないから個別の問題解決の機会が発生することもあるという感じでしょうか。

自分は月1万予算と言わずできるなら1千円ぐらいまで最適化したいので、このあたりは選択肢に入れてなかった。

Aurora Serverless*2については以前試した時はVPC内のアプリケーションから接続しないといけなくシステム総合でコストがどの程度になるのか見積れてないのでどのぐらいの金額になりそうか不明。最近v2になっていろいろ環境は変わっているので知ってる人は教えて欲しい。

いかがでしたか? SQLをあきらめるな

ドキュメントベースではないWebアプリケーション

Four Eras of JavaScript Frameworks

JSのアプリケーションフレームワークを4世代に分けて解説する記事

今のSPAはGoogle Maps等の始祖的なAjaxアプリケーションから直接由来したというより、スマートフォンアプリのユーザーインターフェイスの再現が下地にあると思っているので近い考えた書かれていて同意した。

ユーザーが操作する範囲をWidgetとして定義する開発方法から、開発者が分割単位をコントロールするコンポーネントベースのGUI開発や関数型プログラミングの適用も、XAMLでMVVMと言われ出した頃から僕も知ったので近い時代感を受けた。

新興のフルスタックフレームワーク世代のものはMPAへの回帰が進んでいると思う。

ただし現在のJavaScriptアプリケーションはブラウザの描画とDOM操作の手続きで表現するドキュメントベースの従来のアプリケーションから、ダウンロードしたコードをオンザフライ方式で再生してグラフィックを描画するデスクトップアプリケーションに段々変わっていっている。

よく槍玉に上りがちな、Rails vs SPAな議論だとこのドキュメントベースではないWebアプリケーション開発の変化にあまり焦点が合わないなーと日々感じてる。

Edge Functionsはブラウザ

Cloudflare Workers

Cloudflare Workersのようなサーバーレスなコンピューティングプラットフォームとしてここ数年活発な「エッジサーバーでプログラムを実行する環境」(呼び方が定まらないので一旦Edge Functionsとする)でアプリケーションを作る*1とブラウザが通信する先にもう1つブラウザが存在するような妙な感じを覚えていた。

例えばNext.jsのAPI Routesなら書いたコードはNode.jsで動くので頭をサーバーサイドモードにすればいいが、Cloudflare Workersで動くエンドポイントを書く時はそうでない…… おまえ、ブラウザなのか? みたいな

でもよく考えたらこれらのプラットフォームはSpiderMonkeyやらV8やらのブラウザと同じJavaScriptエンジンを組み込んだ実行環境を持っていて、APIも環境の制限(TCP接続とかファイル読み書きとか)も似ているからそう感じても当然かと思った。

1年ぐらい前のThe Changelog PodcastでRyan Dahlが出演してDenoやDeno Deployについて語っていた回でDenoはブラウザのAPIとの互換性を持たせるデザイン意図を語っていた

changelog.com

And by the way, I should be explicit - Deno is trying not to have an API. Deno is trying to be the web browser API. Deno is trying to not have a specific Deno API, but just - if you want to encode a string into a uint array you use a text encoder. We don’t have a special Deno API for that. https://changelog.com/podcast/443#t=01:04:08.04

だからWeb Workersのようなメインスレッド以外で動いてドキュメントの描画には関与しない処理がたまたまリモートにあって、レスポンスを返してくる。と考えるようにした。

developer.mozilla.org

ブラウザの中のさらにその中のWeb APIの一部だろうという話はあるんだけど「Edge Functionはブラウザ」のがタイトルとしてカッコよかったのでいいじゃないですか。

開発者から見たメンタルモデルは上記とも言えるんだけどアプリケーションのユーザーからして見たら実行コンテキストは外部だし、取り扱うデータもすべてのユーザーを横断するものの可能性もあるしで若干ミスリードかもしれない。

ブラウザじゃなくてもEdge Functionsはフロントエンド領域だろうという例で、時雨堂 SaaSの技術スタック解説でCloudflare Workersはフロントエンドに分類されているというのもある

zenn.dev

Web APIまわりの議論

最近特に"なんとかEdge Functions"がたくさんリリースされているように見えるのはDeno Deployの仕組みを他社(SupabaseやNetlifyのこと)に提供する拡大戦略が背景にあるようだ。

https://deno.com/deploy/docs/subhosting

Node.jsやDenoでブラウザと汎用プログラミング環境用のAPI互換性を上げることの是非についても議論があり、以下を読んだ

yosuke-furukawa.hatenablog.com

scrapbox.io

Edge Functionsのような環境でブラウザ向けのコードを取り込もとしている時流があると思うので関連しそうだ。

一方Cloudflare WorkersではNode.jsのランタイムにあるAPIを独自に互換性を持たせるような動きもあって、これは逆のアプローチだなと思う。

blog.cloudflare.com

Edge Functionsでアプリケーションを作ることを中心に考えると、VercelなどはNext.jsでがっつりNode.jsのAPIに依存しているからこっちのが都合が良さそうで、Remix陣営は後発の利でいろんなPaaS向けのアダプタをサポートする用にデザインされており(間も無くDeno Deployも使えるようになる)そんなに恩恵はなさそう。

*1:Edge Functionsで動くアプリケーション: https://github.com/laiso/isucholar_cfworkers とか