Runner in the High

技術のことをかくこころみ

2025年を振り返る

今年もお疲れ様でした、ということで1年を振り返ってみる。

テイラーで働き始めて3年経った

なんと気づけば3年が経過していた。自分が入ったときと比べて、2-3倍くらいにはメンバーが増えた気がする。

現在はFrontend PlatformというTailor Platformのフロントエンド基盤全般の開発をやるチームで業務に励んでおり、メンバー構成の都合上業務の半分以上が英語のSlackやディスカッションになった。子供の頃から英語をやっていたよかったと親に感謝する今日この頃。

さて、2025年の大きな変化はなんといっても、つい先日ソースコードもオープンになったTailor Platform SDKの誕生だと思う。

github.com

自分がテイラーに入社して以来、これまでJSON, Cue, Terraformとアプリケーションのマニフェスト定義のための言語をいくつも転々としていたが、これからはSDKを用いてTypeScriptの表現力を持ってTailorDBなどの定義ができるようになり、非常に書き心地が良い。数年前にも何度か「全部TSで書けたらイイのになー」と思うことはちらほらあったが、自分にはその推進力がなかったというか、タイミング的に気が熟しきっていなかった。

しかし、言語としての表現力やエコシステム、AIとの相性など色々なピースが揃い集まり、点と点が繋がってきた。SDKのみならず、JSで書いたコードをデプロイできるFunctionや、それを基盤としてレジューム実行可能な複数のジョブを定義できるWorkflowなど、業務システム開発のために必要な機能がどんどんプロダクションレディーになってきている。これからも、少しづつTypeScript/JavaScriptエコシステムに寄ったツーリングや機能が出てくるだろう。

さらに次のピース... つまり2026年のフォーカスポイントであるが、Tailor Platformのもつ機能を組み合わせて"モジュール"と呼ばれる出来合いのビジネスドメインや外部サービス連携をアプリケーションにパッケージのような形式でプラガブルに組み込める仕組みを導入するべく、自分がPoCをしている。これこそテイラーの目指す "Composability" の第一歩であり、来年はそのスピードをどんどん加速させて行きたい。

趣味開発

セクションを設けるほど何か作っているわけではないが、KyrageというZodのようなTS表現で書けるスキーマベースのSQLマイグレーションツールを作っていた。

izumisy.work

元々は個人開発でDBを扱うアプリを作るのに欲しいなーというモチベーションで育休中に片手間で自分の便利道具として作り始めたのだが、ありがたいことに本業がエキサイティングすぎて特に使う予定がない。なんならTailor Platformを使って作る方が速い説すらある。

しかし、Githubのスターの割に地味に興味を持ってくれる人がチラホラおり、もう少し気合を入れて機能拡充をしていきたい。

あとはKyrageをAIに作らせる過程でMySQL, PostgreSQL, SQLiteなど各方言ごとのイントロスペクションのSQLクエリを自律的に評価できるよう、MCPサーバをサクッと作ったりしていた。

github.com

あとは仕事でもプライベートでも自分はほとんどGithub Copilot + Claude/Codexの組み合わせで満足している。

正直、AIに関してはあまり語ることはないというか、単に仕事用のツールとして可もなく不可もなくイイ感じに便利に使えているという感じ。個人的にはGithub Copilot Agentをもう少し上手く使いたい気持ちがあり、その辺も来年は研究したい。

子供が産まれた

なんと4月に娘が誕生。とにかくカワいすぎる。10月まで半年間の育休もとり、赤ちゃんとのクオリティ・タイムをエンジョイした。

自分に子供が生まれるとは感慨深い。改めてその当事者になると、世の赤ちゃん全てが可愛く見えてくるので不思議である。Youtubeの関連動画に赤ちゃんが出て来すぎる。動物の赤ちゃんにも興味が出てくる。今一番見たいのはゾウの赤ちゃんだが、関東圏だと難しそう。

もうすでに子供にやらせたい習いごとを考え始めている。まず確実に英語... 英語ほどコスパのいいものはない。将来AIが言語をなんでも翻訳できるようになったとしても、直接会話できるのと間に機械を仲介させることの差はゼロにはならない*1だろう。

いずれにしても、とにかく英語には触れさせたい。あとはなんでもいいからスポーツ。

猫との関係

ひとつかわいそうなのはうちの先住猫である。

彼女は基本的に甘えたちゃんなので、赤ちゃんと家の中での存在がカニバってしまっている。赤ちゃん特有の奇声も嫌いらしい。

赤ちゃんと仲良くできる猫もいるようだが、うちは全くそんなことはなく、常に一定の距離で人間のアテンションを要求してくる。何年も家族の姫として扱っていたので、急に競合が現れることのストレスはあるだろう。申し訳ないが、いまは耐えてもらう他ない。

姫としての自覚溢れる猫

*1:脳みそに直接介入する何かが出てくれば話は別か?

プジョー208に2年ほど乗って気になったところ

2023年にプジョー208を買ってから大体2年程度経過したので、色々と気になったことを書き残してみる。

エンジン振動

PureTech3気筒エンジン特有の振動がダイレクトに車内に入ってきていると感じるくらいの振動がある。1度軽井沢まで旅行に行って千葉まで帰ってくるときに渋滞に巻き込まれ3時間以上運転していたことがあったのだが、さすがに振動を受けすぎて手が痺れてくる感覚があった。

208自体が意図的に路面のインプットをダイレクトに伝えるようなスポーティな味付け(?)がされているという話もあり、運転自体が楽しい分、この手の快適性は犠牲になっているという印象。路面の凹凸などの振動も容赦ない。助手席や後部座席に座っている人から苦情が出ることが多いが、そういう車なので仕方がない。

センサーの誤検知

何もないところで反応して赤い衝突警告がでることもちらほら。地味に怖い。

これが怖いのは中低速域でのAACを使った半自動運転で、高速で走っていないとAACによって急にブレーキされることがあり、後続車両が近いときにヒヤッとしたことが2-3回ほどある。街乗りで何度も遭遇しているので、高速道路以外でいろんなものがある場所だと起きがちな印象。これがあってから、高速道路以外の低速域ではあまりAACを使わなくなった。

逆に60Km/hくらいを超えてくるとすごく快適に使えるので、それは便利ではある。が、渋滞など208が不得意なシチュエーションで使うとヒヤヒヤするのは、ちょっと微妙なところ。

ブレーキ周りの挙動

208にはヒルスタートアシストがあるはずなのだが、その挙動がちょっと怪しい。ブレーキを深く踏み込まないと効かないような気がしている。止まっているからといって甘めにブレーキを踏んでいると、坂道でのアクセル時にズルっと下がることがありヒヤヒヤする。坂道ではサイドブレーキ必須。

それから、ブレーキホールドの代わりにサイドブレーキを使って停車するとアイドリングしてくれない。そして、このサイド停車時のエンジン振動がすごい。前述のエンジン振動に関して言えばサイド停車時が一番強く、渋滞でブレーキを踏むのにつかれてサイドで止めていると、振動で手の方も参ってくる。

サイドブレーキ関係なく車にアイドリングさせるにはある程度ブレーキを踏み込む必要があるの。できれば、ブレーキホールドがないぶんサイドで止まっているときもある程度の時間が経過したらアイドリングしてくれると嬉しいのだが...

低速域でのスポーツモード

208は低回転から過給するターボを積んでいるので、だいたい15-20Km/hらへんになると急に加速が入るようなターボラグがある。

これはノーマルモードではそれなりのものだが、スポーツモードだとあまりに非線形すぎるアクセルフィールで、これを街乗りで使うのは恐ろしい。高速や中低速域でブレーキをする必要のない道を走るのはすごく気持ちイイが、ものすごい急発進になることもあり全くもって街乗り用とは言えない。一方で、このモードが208の楽しいところでもあり、一長一短あるのは仕方ない。

その他: 故障など

今年の夏にエアコンのコンプレッサーが故障し、エアコンをつけてアクセルを踏み込むとブオーンブオーンというヤバめな音がするようになった。これが初めての故障。

ディーラーで診てもらったところコンプレッサーごと交換になったが、国内に在庫がなく本国からの取り寄せでざっくり3週間程度はエアコンなしで乗らざるを得なくなった。この修理の費用が大体15万円程度で、出せない額ではないがやはり安くはない。これが国産車であれば在庫もすぐだったろうし、外車でプジョーといえばこんなモンということがよくわかった。

感想

他にもバックカメラの画質がひどいとか、トランクが広くないのでベビーカーを積むと余裕がなくなるとか色々あるのだが、いくら文句をつけても運転体験に関しては気持ちいい車には代わりないので、結局208ってやっぱイイよなという思うことが多い。

しかし、コスパで選ぶなら208よりも取り回しのいい車は山ほどある。

kyrage v1.0.0 をリリースした

前に紹介した TypeScript でスキーマ定義できるマイグレーションツール kyrage の v1.0.0 をリリースした。

izumisy.work

前回の時点ではテーブルのマイグレーションしか対応していなかったが、v1.0.0 ではもうちょい実用的なツールに仕上がったと思う。

以下、追加された主要な機能と変更点。

インデックスと制約のサポート

前回「今後やりたいこと」に挙げていた、index や外部キー制約がついに対応できた。

インデクスや制約を使うスキーマ定義は、defineConfig の第二引数で以下のように書ける:

import { column as c, defineTable as t } from "@izumisy/kyrage";

export const posts = t(
  "posts",
  {
    id: c("uuid"),
    author_id: c("uuid"),
    slug: c("text", { notNull: true }),
    title: c("text"),
    content: c("text", { notNull: true }),
  },
  (t) => [
    // 複合プライマリキー
    t.primaryKey(["id", "author_id"]),
    
    // ユニーク制約(カスタム名付き)
    t.unique(["author_id", "slug"], {
      name: "unique_author_slug",
    }),
    
    // 外部キー制約(CASCADE DELETE 付き)
    t.reference("author_id", members, "id", {
      onDelete: "cascade",
      name: "posts_author_fk"
    }),
    
    // インデックス
    t.index(["slug", "title"], { unique: true })
  ]
);

Dev Database サポート

Atlas の Dev Database という概念に近いものを実装した。

これは、本番データベースに影響を与えずにマイグレーションを生成するための機能。

# 開発用の一時的なデータベースコンテナを起動してマイグレーションを生成
$ kyrage generate --dev
🚀 Starting dev database for migration generation...
✔ Dev database started: postgres
-- create_table: users
   -> column: id ({"type":"uuid","primaryKey":true,"notNull":true})
   -> column: email ({"type":"text","notNull":true,"unique":true})
✔ Migration file generated: migrations/1755525514175.json
✔ Dev database stopped

内部的には以下のような処理が行われる:

  1. 新しい Docker コンテナでクリーンなデータベースを起動
  2. 既存のマイグレーションをすべて適用してベースラインを確立
  3. スキーマ定義とコンテナ上の状態を比較
  4. マイグレーションファイルを生成
  5. コンテナを自動的にクリーンアップ

設定ファイルでは以下のように定義できる:

export default defineConfig({
  database: {
    dialect: "postgres",
    connectionString: "psql://prod:pass@prod-db.com/myapp",
  },
  // 開発用データベース設定
  dev: {
    // Docker コンテナを使う場合
    container: {
      image: "postgres:17"
    },
    // または既存のデータベースを使う場合
    // connectionString: "psql://dev:pass@dev-db.com/myapp_dev"
  },
  tables: [/* ... */],
});

もともと、自前で Docker コンテナを立ち上げて connectionString を設定すれば同じようなことはできたのだが、コンテナの起動し忘れとか、既存マイグレーションのベースライン適用し忘れとか、そういう細かい手間がいちいち発生するのがダルい。作っている間も動作確認でよくあった。

Dev Database ならこれらが全部自動化される。複数の開発者が異なるスキーマ変更を並行して進めている場合でも、各自がクリーンな状態からマイグレーションを生成できる。本番DBの現在の状態に依存しないので、「誰かが先にマイグレーションを適用したから差分がおかしくなった」みたいな問題が起きないだろう。全員が同じ Docker イメージから始めるので、環境差異によるトラブルも起きにくい。

また、開発者に本番データベースへの接続情報を共有する必要がなくなる。これは地味だが重要で、本番環境へのアクセス権限を最小限に保てる。開発者は Dev Database だけで作業を完結できるので、誤って本番データを触ってしまうリスクもない。

ちなみに、内部的には Testcontainers を使って実装している。Testconatinersは超便利で、Github Actionsで動かす際も明示的にサービスの定義など不要で全部いい感じにしてくれるので素晴らしい。

環境別設定との組み合わせ

余談だが kyrage は設定の読み込みに unjs/c12 を採用しているので、NODE_ENV による設定の切り替えも可能。

例えば以下のような設定ができる:

export default defineConfig({
  // 開発環境: 各自のローカル Docker を使用
  $development: {
    database: {
      dialect: "postgres",
      connectionString: "postgres://dev:dev@localhost:5432/myapp_dev"
    },
    dev: {
      container: {
        image: "postgres:17"
      }
    }
  },
  
  // ステージング環境: 共有の Dev Database を使用
  $staging: {
    database: {
      dialect: "postgres",
      connectionString: "postgres://staging:pass@staging-db.internal/myapp_staging"
    },
    dev: {
      connectionString: "postgres://devdb:pass@shared-dev-db.internal/myapp_dev"
    }
  },
  
  // 本番環境: Dev Database なしで直接本番に接続(CI/CD 用)
  $production: {
    database: {
      dialect: "postgres",
      connectionString: process.env.DATABASE_URL!
    }
  },
  
  tables: [/* ... */]
});

これにより、チーム内での役割や環境に応じた柔軟な運用が可能になるだろう。

また、まだ構想段階だが、Dev Database コンテナを永続化する Reuse API という機能の追加も検討している。

現在は --devマイグレーション生成のたびにコンテナが作り直されるが、Reuse API を使えばコンテナを使い回せるようになる。これにより、テストデータを保持したまま開発を進められたり、アプリケーションから同じ Dev Database に接続できたりと、より実践的な開発フローが実現できるはずだ。kyrage dev get-url でコネクション URL を取得して DATABASE_URL=$(kyrage dev get-url) npm run dev のように環境変数に設定する、といった使い方も想定している。

なお、作者である自分はKyselyと組み合わせたくてこのツールを作ったということもあり、スキーマ定義を更新するごとに kyrage generate --dev --apply && DATABASE_URL="$(kysely dev get-url)" kysely-codegen を実行する、みたいなプロセスを妄想している。

まとめ

v1.0.0 では、前回の記事で「今後やりたいこと」として挙げていた主要な機能のうち、特に重要な index と外部キー制約の対応が完了した。さらに Dev Database サポートによって、チーム開発やCI/CDでの利用がかなり実用的になったと思われる。

まだ PostgreSQL 互換以外の DB 対応や down マイグレーションなど、やりたいことは残っているが、ひとまず v1.0.0 として区切りをつけることにした。

興味がある方はぜひ試してみてください。フィードバックや PR も歓迎です。

github.com

TypeScriptでスキーマ定義できるマイグレーションツール kyrage を作った

個人開発で CockroachDB を使いたかったのだが、有名どころの drizzle や Prismaマイグレーションしようとすると、うまくいかなかった。

drizzle-orm はそもそも CockroachDB サポートが計画段階なのだが、PostgreSQL 互換だし動くだろうと思って pg ドライバで動かすとマイグレーションでデータ型関連のエラーが発生してしまう。Prisma も原因は別だが CockroachDB 特有の機能でエラーが起きる。

では、なにかNode.js系のマイグレーションツールを適当に採用しようか... という所だが、よくあるやつはマイグレーションSQLやコードそのものを基本的に手書きする。これがやりたくない。理想的には Ruby 界隈の ridgepole のように宣言的なスタイルでマイグレーションができ、かつ Node.js エコシステムと親和性の高いミニマルなツールが欲しくなる。

Node.js とは関係ないが、似たようなもので Atlas という宣言的なアプローチを採用したデータベースマイグレーション管理ツールがあるのだが、これは HCL でスキーマを書く必要がある。道具としては良いが、個人的な好みとして別に HCL を書きたくないし、補完のために VSCode でも専用の拡張を入れる必要があり微妙だった。あとなんかクラウド版がどうだとか、ツール単体として使うには不要な概念が多くて、ドキュメントがわかりづらかった気がする。

結局、自分の場合は基本的に Next.js + TypeScript という環境でアプリを作ることが多いのでそれに合わせて全部 TS のコードベースに統一したく、そういうやつをバイブコーディングするかーと思って作ることにした。

作ったもの

kyrage (kirāju) という名前のマイグレーションツールを作った。今はテーブルのマイグレーションのみ対応。

github.com

やっていることは以下の通り:

  1. DB に接続して現在のスキーマを取得
  2. 設定のスキーマと現在のスキーマを比較
  3. diff から migration を生成 (JSON形式)
  4. migration を適用

この手法は前述する Atlas が Versioned Migration Authoring と呼んでいるスタイルとのこと。

なお、マイグレーションにおけるSQLの発行だとかバージョン管理などの仕組みは自前では作っていなくて、kyselyのマイグレーション機能をライブラリとして使っている。もちろんCockroachDBのdialectも用意した。

基本的な使い方

グローバルインストールしてもいいが、ここから先はnpxで使う例とする。

1. 設定

kyrage.config.ts を作る

import { defineConfig } from "@izumisy/kyrage";

export default defineConfig({
  database: {
    dialect: "postgres",
    connectionString: "postgres://postgres:password@localhost:5432/mydb",
  },
});

ここで書いたDBに対してイントロスペクションを実行し、スキーマを取得してくる。

2. スキーマ定義

ここでは schema.ts に以下を書く

import { column as c, defineTable as t } from "@izumisy/kyrage";

export const members = t("members", {
  id: c("uuid", { primaryKey: true }),
  email: c("text", { unique: true }),
  name: c("text", { unique: true }),
  age: c("integer", { nullable: true }),
  createdAt: c("timestamptz"),
});

export const posts = t("posts", {
  id: c("uuid", { primaryKey: true }),
  author_id: c("uuid"),
  title: c("text"),
  content: c("text"),
  published: c("boolean", { default: false }),
  published_at: c("timestamptz", { nullable: true }),
});

データ型は kysely から拝借しているので、スキーマ定義ではいい感じに補完が効く。

書けたら設定に追加していく

import { defineConfig } from "@izumisy/kyrage";
+import { members, posts } from "./schema";

export default defineConfig({
  database: {
    dialect: "postgres",
    connectionString: "postgres://postgres:password@localhost:5432/mydb",
  },
+ tables: [members, posts],
});

3. マイグレーション生成

generate コマンドで、テーブルやカラムの作成、削除、変更などの差分を記録した JSON ファイルが作られる

$ npx @izumisy/kyrage generate
-- create_table: members (id, email, name, age, createdAt) 
-- create_table: posts (id, author_id, title, content, published, published_at)
✔ Migration file generated: migrations/1754372124127.json

4. 適用

--plan オプションがあるので、事前にどういうSQLが発行されるのか確認しておく。

$ npx @izumisy/kyrage apply --plan
create table "members" ("id" uuid not null primary key, "email" text not null unique, "name" text not null unique, "age" integer, "createdAt" timestamptz not null)
create table "posts" ("id" uuid not null primary key, "author_id" uuid not null, "title" text not null, "content" text not null, "published" boolean not null, "published_at" timestamptz)

今回は空のデータベースにapplyするので、テーブル作成のクエリしかでていない。

問題なさそうであれば、マイグレーションを実行する。

$ npx @izumisy/kyrage apply
✔ Migration applied: 1754372124127

手でマイグレーションファイルを書く必要がないので便利。

今後やりたいこと

  • もうちょっとまともな diff の生成。
    • 現状は up/down のうち up しか生成できていないので、reversible な変更であれば down も対応したい
  • indexや外部キー制約などの対応
    • かなり重要だけど、まだできてないのでやる
  • PostgreSQL互換以外のDB対応
    • どっかで気合いいれてやる

その他やりたいことはGithub issuesに色々あります

AIで適当なNext.jsアプリをvibe codingした感想と備忘

昔、MoneyForwardにあった「よそQ」という資産推移のシミュレータツールみたいなやつがちょっと便利だったのだが、リニューアルかなんかで今はもうなくなってしまった。というわけで、同じような機能を持つもうちょいリッチなやつが欲しいというモチベーションをベースに Claude (opus-4-20250514) + Cline で作り始めた。

github.com

ざっくりしたアプリの仕様は:

  • 任意のサイクルおよび期間指定で、金融資産や収入、支出を登録できる
  • 登録されたデータを元にバーチャートで任意の期間の支出シミュレーションができる
  • バックエンドやデータベースはなし(全てオンメモリ)

など

以下、作ってみた感想。

設計指示の必要性

作り始めた最初の頃はActのままでずっと作業をさせていたのもあるだろうが、「こういう機能追加して」みたいな言い方だけして作業開始すると、いわゆるDDDでいうところのSmartUI的な実装をどんどん積み上げようとする。

やはり設計の知識を引き出すための指示が必要で、自分の場合には「XXXという機能を作りたいけど、この機能に関わるデータ構造をOOP的に考えるとどういうモデリングがいいと思う?」という質問でPlanして、データ構造や操作のインターフェイスを先に考えさせるといい感じになった。データ構造のことを考える過程で、ちょっと抽象化っぽいことをし始めるのもイイ。

たとえば、当初のアプリのシミュレーション計算部分の設計は非常にナイーブで、その時点で存在していた現金預金・収入・支出の設定をforループの中でそれぞれ参照して、そのままバーチャート用のArrayデータを作るという素人の実装だった。それに対して「今後の新しい収支ソースの追加をしやすいように、OOPの観点で設計を考えて」と指示すると、資産の増減を計算するインターフェイスに対して収入・支出・金融資産の実装を作り、チャート用データの生成ではインターフェイスのみに依存して計算結果をreduceするような、ストラテジーパターンを意識した設計を提案してきた。

「知識はあるが、その使い方が上手くない」みたいなやつがよく分かる。

Planの工夫

Clineを使っているとすぐActモードにしてもらおうとするが、たしかにオーケストレーション的なステップをいくつか踏むほうがいい。

自分のアプリの場合には、データ構造で見ると良さそうでも、それをバーチャートで表示させようとすると情報が落ちたり既存の挙動を破壊するような実装に何度か遭遇したので、"設計考えて"→"設計の懸念点教えて"→"UIレベルで整合性がとれているかコードを確認して" のように順序立てて設計の整合性を確認させるフローをとったら、精度が上がったような気がした。

教科書的には、既存挙動の破壊(デグレ)はテストレベルで検出するべきだと思うが、適当にAIに任せて書かせていたユニットテストの品質がよくなかったというか、そもそもアプリケーションがUIと状態操作を分離した設計になっていなかったせいで既存のテストのカバレッジではデグレを検出できていなかった。ClineはBrowser toolが使えるので、色々試して上手くいかないと最終的にはブラウザ経由で動作確認をしようとするのだが、これがノロくて待っていられないし、この積み重ねが開発速度の低下につながるのであまりやらせたくない。

フロントエンド開発をある程度やっていれば、UIと状態操作を分離して後者のみテストを書くだけでいいような設計にするのが望ましいということは経験上分かっているものだが、やはりAIは知っていても指示しないとやらないので、clinerulesで設計を意識させるよう指示したうえで、テストのカバレッジを上げるのが望ましいと感じた。

ディレクトリ構造やコーディング規約など表面的なもの以前の、データフローや状態設計、UIと状態操作の分離など、根本的にそれが雑に作られていることによって結果的に無駄な作業が毎回発生している、みたいなやつをこちらから指摘せずともAIに最初から意識して改善させる術があまり分かっていない。AIにも作業のたびにKPTとかさせればいいんだろうか?

その他感想

SmartUI的な実装で突っ走ろうとするところや、指示しないと雑なデータ構造やインターフェイスのままで先に進もうとするのを見ていると、大半の人間もこういう仕事の仕方だよなーという気持ちになった。開発に入る前に自分で設計を考えて壁打ちするような人材はソフトウェア・エンジニア全体でも上位数%くらいのレベルだと思うし。

その点、AIだとあれこれ指摘したり無限にやり直しさせても"人間の感情"という最も面倒な状態管理がないぶんかなり気楽。特に、人間相手にやり直しや「なぜその設計にしたのか?」を追及するのは、やる側も疲弊する。こちらも人間なので、作業者の単価を知ってると「その単価でこのレベルのアウトプット?」みたいな気持ちになったりするし... そういうアレコレと比較すれば、従量課金でも超安い。

こき使っても文句言わない、ある程度は正直に仕事をしてくれる、というのはやはり最強。

プログラミングという"作業"に対する個人的なフラストレーション

AIにコーディングをさせるようになったことで、8-9割とは言わずとも、少なくとも半分くらいは自分がこれまでにやっていたコーディングの作業を減らすことができるようになった(気がする)。しかし、いまだに残りの5割くらいは手作業でコードを書いているわけで、ここ最近これにすごくフラストレーションが溜まる。そこまでやれるなら、もう全部やってくれないか?と。

難易度や抽象度の違いはあれど、自分がこれまでやっていた作業が20-30秒かそこらで実現できている中、引き続き自分が手を動かして試行錯誤せざるを得ない状況になると、相対的にとてつもなくスピードが落ちたように感じられる。これは気持ちの問題ではなく、実際めちゃくちゃ遅い。早歩きでオートウォークを通過し終わったあとの、なんとなく体が重くなるあの感じに近い。

もともと遊びで始めたくらいにはコーディングは好きで、そこから関数型プログラミングをやってIOを抽象化した純粋なコードの美しさとか、TypeScriptで型安全性を追求した型パズルの面白さとか、そういったものもわりかし好き寄りであったのだが、自分にとってそういうものは、単にその"難解さ"が心地良かった。

理解することが難しくて、それ故に分かった(解けた)ときに心地いい。岩波文庫で哲学の本を読んでいるような、クイズを解いてるような、そんな感覚。それに、その難解さに根気強く取り組めて、楽しめることが、ソフトウェア・エンジニアとしての資質だと思っていた。実際、それでだいぶ良い評価をされるし、そこそこのお金も貰える。

いまは、そういうものの美しさや面白さは引き続き分かるが、それを自分の仕事にはし続けられないな... という感覚のほうが強い。というか、仕事にしてもいいが、昔ほどは心地よく感じられなくなってきたのと、その心地よさが資質というのも疑わしい。エッジケースはあれど、AIのほうが圧倒的に作業をこなすスピードが速いし、それを自分がいちいち手作業で仕事としてやっているのは、自己満足な職務怠慢に感じられて、自分自身に対して不快な気持ちを催してくる。敢えて遅い道を選んでるんじゃないか?と。

今まで自分がやっていた仕事は全部遊びだったという解釈のほうが、納得できる。


こういう思考に至った背景には、現職のTailorで働いて得られた経験も大きい。

唐突に過去の話をするが、前職では機能開発ではデザイナがPdMを兼任するという開発体制で、ソフトウェア・エンジニアはある程度固められた仕様に対して技術的なレビューを行い、開発に入るという流れで回っていた。当時の自分は、このプロセスが社内受託開発のように見えていて、設計やコーディングだけに集中できるというメリットを感じつつも、結局は単なる作業者以上にはなれないのでは?という行き詰まり感を感じていた。

当時の自分は20代の若者だった故技術的に尖りまくっていることがソフトウェア・エンジニアとしてイケているんだ!という思想があり、コードを書かないロールに入ってしまうと、自分の尖りが失われてキャリアのマイナスになると思っていた。が、Tailorに入りPdMとSWEなどの職能/プロセス分けをせずソフトウェア・エンジニアがワンストップで直接フィーチャーを考えて作り、デリバリするというスタートアップらしいスピード感のある流れを体験すると、プロダクト開発の本筋とはリリースノートや仕様書、ドキュメントなど、最終的に顧客へデリバリーされる理想の像が描かれ、実現されることがメインで、そのうちコーディングというプロセスが占める割合の、躊躇せずに言うならその"無駄さ"はとてつもなく大きく感じられる。極端な言い方だが、無ければ無い方がいい。

今振り返ると、前職でデザイナがPdMを兼任するのはUIプロトタイプ(というかデザイン)と仕様を最も高速に作れるのがFigmaを操れるデザイナだったからで、自分含め開発者が同等かあるいはもっと速いスピードでそれらをカバーするプロトタイプを作れれば、なにかブレイクスルーがあったかもしれない。

しかし、当時の自分にとっては「ソフトウェア・エンジニアはやっぱ技術力鍛えてナンボでしょ」みたいな考え方が支配的で、根本的な開発プロセスの刷新にはモチベーションがあまりなかった。仮にあったとしても、そもそも一人の開発者として分業体制に甘えていたし、PdM≒デザイナという組織の前提を覆すだけの覚悟もなかった。

ブログを書くモチベーションが消失している

ここ最近マジでブログを書くモチベーションが消失しているので、その原因を雑に考察してみる。

yyyank.blogspot.com

上の記事を参考にすると、感動が少ないというのは確かにそうだが、それでも業務ではいまだに試行錯誤の連続で、何も得てない/経験していないわけではない。感動もあるにはある。

じゃあ、そこからくる技術的なアレコレをブログに書きたいが... なにが原因なのか。

ハイコンキストなものばかりで書くのが面倒

実際に業務で解決しているものは、ハイコンテキストなものが多くて書く気がおきない。

たとえば、ググってすぐ解決するような課題は、みんなが遭遇しているものでローコンテキストなもの。これは一般化されたイシューだと思っていて、このレベルはとくに試行錯誤しないので感動ゼロ。書くこともない。

それ以外のもの... 「一般的にはそう解決するよね」を各々個別のコンテキストで実行した際に発生する新たなイシューの解決が実際の仕事の大半なのだが、これをいい感じにボカしたコンテキストにして、いい感じの一部始終としてまとめた記事にするのは非常にダルい。あと、こういう個別具体の内容を変にボカして一般化した雰囲気で語ると、大事なディテールが失われてコレジャナイ感が溢れ出てくる。技術カンファレンスの抽象的なトークがおもんない*1のに近い。

こうなってくると、もうClaudeとかChatGPTと話せば出そうな内容だしいっか、みたいになっちゃう。

あと、基本的にやっていることが試行錯誤の連続なので、そのアウトプットをブログとして残すと、それが「これが俺の解だ!」みたいになり、なんか違うな感もある。Spotifyのスクワッド・モデルが実はもう使われてないのに、変に引用されて「最強の開発組織の構成だ!」みたいに言われていたやつに近い。

対外発信のモチベ減

対外発信に対する自分の解釈は「転職とかでちょっと有利になるやつ」くらいのもので、これもモチベが上がらない理由だと思う。

昔は自分の市場価値を上げる的な目的で対外的な発信力を鍛えていくぞ〜というモチベーションがあったが、外からどう見えるかよりも今いる場所でどれだけ評価を積み上げられるかのほうが結局大事じゃね?という気づきがあり、余計にモチベーションがない。

今思えば、新卒2-3年目とかでやってた対外発信の目的は「いつかは転職してもっと給料上げたいし、そのために使える実績作っとこう」みたいな感じだったわけだが、今の自分の結論は「自分が働き続けたいと思える環境に全力でコミットしよう」になっている。

自分のキャリア的にも市場価値的にも、結果的にはこれが一番最短距離だろうと思っている。あと、外からの見え方だけよくて、一緒に働いてる人からは評価が微妙みたいなのシンプルにダサいよなーと思う気持ちもある。

なにをアウトプットするか

こうなってくると、残るアウトプットはなんか適当なTwitterでのつぶやきとか、雑にQiitaに投稿した備忘用コード片みたいなやつしか残らない。これも別に対外評価されたくてやっているわけじゃないのと、じゃあ自分が見るのかと言うとそんなこともなく... 誰かの役に立てば幸いです、くらいの置き物でしかない。たまにググったら自分の記事が引っかかったりするので、そういうときは助かる。

もっと広い目でみると、人生の中で技術以外のことにも興味が出てきた感はある。車とか猫とか、家族のこととか。最近子供も生まれたし。あと、ここ最近は服に興味が出てきてしょうがない。

ここは技術ブログなのでね、ようわからんアパレルの話を書いたり、うちの猫の甘えてる画像を貼るのも違うよなぁという。

*1:個人的にはカンファレンスはトークがおもろいかよりも、むしろ現場の雰囲気とか熱量とか、技術的に細かい話とは関係ない部分にこそバリューあるよな〜と感じていて、これはブログでも同じなのでは?というざっくりした感覚がある。

2024年を振り返る

あと数日で2024年も終わってしまうので、ここらで今年の振り返りを少し。

本年は、去年末に人生初の車を買ったことにより、ドライブが楽しすぎてプライベートでは全くブログを書く機運が高まらなかった。なんと2024年は4記事しかブログを書いていない。年末振り返りを除けば3記事だけ。これも全部208の運転が楽しすぎるのが悪い!

しかし、車の登場により圧倒的に私生活での移動範囲が大きくなり、房総半島のありとあらゆるところに足を伸ばすことができた。房総半島のおすすめエリアについてもいずれどこかで記事にしたい。夜に気まぐれで九十九里海岸に行って夜の星空を見ることができるのも、レンタカーではなく自分で車を持っているからできることだ。

増えに増えたピンの数 in 房総半島

さて、ここからはいくつか今年のハイライト事項。

fabrix & GraphQL conf 2024登壇

2024年の個人的圧倒的にハイライトは、やはり間違いなくfabrixとGraphQL conf 2024への登壇。

fabrixに関する詳しい内容は自分が書いた弊社のnoteの記事からどうぞ。

note.com

fabrixは、もともと自分がプロトタイプとしてTailor Professional Serviceの顧客向けアプリケーション開発で作ったコードジェネレータから着想を得て作られたものである。

自分がその当時入っていたプロジェクトでは、ある程度パターンの決まったCRUD画面がいくつも存在しており、ソフトウェア・エンジニアとしてそれをひとつづつ手で作っていくのはどうしても無駄な気がしてならなかった。その際に、限られた時間でどうにかならないか… と考えて作ったものがfabrixの前身にあたるもので、Tailor PlatformのDB/Pipelineをデプロイするためのスキーマ定義を読み込んで、静的にReactでテーブルコンポーネントやフォームコンポーネントを全て生成するという素朴な作りであった。

最初は良さそうに見えたものの、時間が経つにつれ突貫で作ったこともあり、スケールしない作りであることが分かってきた。思想は良いがモノが微妙だよね、ということで改めてGraphQLエコシステムに則ったマトモなものを作るプロジェクトがスタートした。これが確か今年の夏頃の話。やっていることはシンプルで、GraphQLからReactアプリケーション向けのコンポーネントを動的に作るための便利ライブラリである。カスタムコンポーネントを作るインターフェイスが提供されているので、基本的にはどんなUIライブラリとも組み合わせて使うことができる。

たとえば、ここ最近自分が関わっている社内のプロジェクトではfabrixを用いてGraphQLのクエリから、自動でEnum型のフィールドからグルーピングをするKanbanや、Date型のデータをマッピングするCalendarなどを動的にレンダリングするコンポーネントを作ったりしている。動的というのがポイントで、notionのようにユーザーがKanban上でグルーピングするフィールドを選択できるような機能も、GraphQLスキーマ上の型情報をfabrixのカスタムコンポーネントからいい感じに参照できるので作りやすい。

とはいえ、fabrixに関する具体的な話はコードがないとわかりづらいと思うので、来年はどこかでブログの記事にしたい。

github.com

チェジュ島でウェディングフォトを撮った

自分らは結婚式をしないという選択をして、その代わりに潤沢にお金を使って人生の記録に残る写真撮影をすることにした。それが今年5月にチェジュ島でのウェディングフォト撮影である。数ヶ月前から現地の撮影スタジオを予約しており、当日は現地の日本人のウェディングフォトの撮影エージェントの人にも同行してもらった。

我々のスケジュールは3泊4日で3日目に1日かけてチェジュ島を縦横無尽に移動して6-7時間の撮影をするというプランで、撮影は海岸、草原、道路など、そしてさらにはドローンを使った空撮が組み合わされており、実際には当日は撮影についていくのが手いっぱいで、緊張している暇すらなかった。撮影された写真は、我々の撮影をしてくれたスタジオがinstagramに上げている写真を上げてくれているので、見るとその雰囲気がわかりやすい。

言語化するのは難しいが、韓国のウェディングフォトというのは撮影技術なのかレタッチの技術なのか、国内で撮影されるウェディングフォトよりも圧倒的にシネマティックな何かがある。チェジュ島というロケーションにも、個人的には北海道と沖縄のミクスチャーのような、幻想的な雰囲気を感じてならなかった。

これだけ素晴らしく記憶に残る作品を作れて、かつ結婚式を開くよりもはるかに金銭的・精神的コストが少なく済んだことには、非常に満足している。もちろん、なんでも安く少なくがいいとは思わない。が、チェジュ島でのウェディングフォトほど満足なお金の使い方はない。それくらいの満足度である。

来年に向けて

まずはfabrixの機能拡充とそれにまつわる発信。これは圧倒的にやらないといけないことだと感じている。

クリティカルなバグの修正や、実際にプロダクトで使っていくにあたって必要な機能が揃ってきているにも関わらず、アップデートや具体的なコードを含めた発信ができていないのが2024年の課題であった。来年はfabrixのアップデートに関するブログでの発信や、コードを交えた具体的なユースケースに関する発信をドンドコやっていく。

その他プライベートでも色々な予感があるが、まずは選択と集中ということで。

寝ることに全集中猫