■ 1. 定例ミーティングの基本的な捉え方
- 定例ミーティングは「必要悪」であり 同期的に人の予定を拘束するためコストが非常に高い
- 意思決定や合意形成の効果は大きいためゼロにはできないが 少なければ少ないほどパフォーマンスは向上する
- マネージャーはミーティングが増えやすい立場にあり カレンダーが埋まるほど予定調整がパズル化し 定例を増やす方向に自然と働く
■ 2. 定例ミーティングが増える理由
- 予定調整コストの高さ:
- 都度全員の空き時間を探すのが困難なため 「毎週固定」という判断が合理的に選ばれやすい
- 情報共有への不安と同調圧力:
- 主催者側に「呼ばないと後で揉める」「共有漏れを防ぎたい」という心理が働き 議事録共有で十分な人にまで招待が及ぶ
- 参加者側にもFOMO(取り残される不安)や「断ると角が立つ」という同調圧力があり とりあえず出席が増加する
- 参加者が増えると内職する可能性が上がるという研究結果もある
- 意思決定責任の分散と過度な合意形成:
- 「みんなで集まって決めた」という状態を作るために会議が設定される
- 事前根回しや全員の納得を重視しすぎると 「顔合わせ」や「儀式」としての定例が増殖する
■ 3. 定例ミーティングを減らすべき理由
- 合理性を積み重ねた結果カレンダーが定例だらけになり 本来やりたい仕事や集中して考える時間が削られる
- チームの生産性は集中時間の確保に大きく左右されるため 定例は少ないほうが望ましい
■ 4. 定例ミーティングをなくす方法
- 最初から終了日を決める:
- 定例設定時に必ず終了日時を入れ エンドレスや長期間の定例を作らない
- Google CalendarやOutlookでは終了日の設定が容易であるため 新規定例作成時に必ず設定する
- 終了しても誰も困らないまま消える定例はそもそも不要だったと判断できる
- 節目で定例を一度全部消す:
- 年末年始や期の変わり目など区切りの良いタイミングで全定例を削除する
- 必要な定例は結局再設定されるため 再設定されないものはなくても回るということ
- 「一度やめてみる」は継続の惰性を断ち切るのに有効
■ 5. なくしきれない場合のコスト削減策
- 頻度を下げる:
- ミーティング終了時に「本当に毎週必要か」を参加者同士で振り返る
- 毎週から隔週に変えるだけで 5人・1時間の定例なら年間約120時間の集中時間が回収できる
- 参加人数を絞る:
- 参加者を増やすのは容易だが減らすのは心理的に難しい
- SlackやTeamsで次回以降の参加をオプトイン方式にし「参加したい人だけリアクション」とすることで自然に人数を絞り込める
■ 6. まとめ
- 定例が増えるのは予定確保や調整コストだけでなく 情報共有への不安や責任分散の力学も重なるため
- 放置すると集中時間が失われるため 以下の3点を意識することで一定の効果が得られる:
- 定例には終了日時を入れる
- 節目でいったん全部やめる
- 頻度と参加人数を見直す
■ 1. 問題提起と結論
- CQRS/ESで読み書きDBを分けた場合に古いデータを読む可能性があるという疑問が学習者の間で生じやすい
- 結論:整合性はコマンド側モデルで守る
- クエリ側DBは整合性の判断に使用しない
■ 2. よくある誤解と実際の動き
- よくある誤解:
- 書き込みDBは書き込み専用
- 読み取りDBは読み取り専用
- 両者は完全に分離されている
- 実際の構成:
- コマンド側DB(イベントストア):イベントの保存および集約の状態構成
- クエリ側DB(投影済みビュー):検索・一覧・分析用
- コマンド実行時の流れ:
- 対象集約のイベントをイベントストアから読み込む
- イベントをリプレイして現在のステートを構成する
- そのステートに対してビジネスルールを適用する
- 問題なければ新しいイベントを保存する
- 単一集約の詳細表示画面ではコマンド側のステートを直接取得するのが一般的
■ 3. 整合性を守る2つの仕組み
- 楽観的バージョンチェック:
- イベントストアは集約ごとに最新バージョン(イベントの最新ID)を持つ
- コマンドに参照時点のバージョン(ExpectedVersion)を含める
- 保存時にExpectedVersionと実際のバージョンが異なれば競合エラーとする
- ポイント付与のようなケースでは冪等性キー(TransactionId)を使う方法もある
- 型による状態制約:
- 状態を型で表現し不正な操作を型レベルで防ぐ
- 例:AvailableRoomとFullRoomを別の型として定義し満員の部屋には入室メソッド自体が存在しない設計にする
- 削除フラグのような実行時チェックに依存する必要がなくなる
■ 4. アクターモデルによる同時実行制御
- 1つの集約に対して1つの実行単位(アクター)を持つ
- コマンドはメッセージとして順番に処理され1つのコマンドが完了するまで次は実行されない
- 分散環境でもどのサーバーにリソースがあるかを意識せずに適切なサーバーへルーティングされる
■ 5. パフォーマンス対策
- アクターによるステートのメモリ保持:
- コマンド実行後もアクターはしばらくメモリに残る
- 同じ集約への次のコマンド実行時にメモリ上のステートを再利用しイベントストアへの読み込みを省略できる
- スナップショットによる高速化:
- 一定期間アクセスがない場合はアクターをメモリから解放しステートをスナップショットとして保存する
- 次回呼び出し時はスナップショットから復元しその後に追加されたイベントのみリプレイする
- アクターモデルとスナップショットの組み合わせによりパフォーマンスの問題は実用上ほとんど発生しない
■ 6. クエリ側DBの役割と使い分け
- クエリ側DBが使われるケース:
- 複数集約をまたいだ一覧表示
- 検索・並び替え
- 集計・分析
- レポーティング
- 一覧画面と詳細画面の使い分け:
- 一覧画面:クエリ側DB(投影済みビュー)を使用し結果整合性(多少の遅延あり)
- 詳細画面:コマンド側(イベントストア)を使用し強整合性(常に最新)
- 「一覧は古いが詳細は正しい」という現象はCQRS/ESの意図された動作であり不具合ではない
■ 7. 用語の整理
- 「読み込みDB/書き込みDB」という表現は混乱を招きやすい
- より適切な整理:
- コマンド側DB(イベントストア):単一集約の状態構成・整合性チェック・ビジネスルールの適用
- クエリ側DB:複数集約のビュー・検索と一覧と分析・結果整合性を許容する用途
- 「読み書きDBの完全分離」ではなく「コマンド側とクエリ側の役割分担」として捉えるとCQRS/ESの設計が理解しやすくなる
■ 1. Rich Hickeyとその思想的背景
- Clojureの作者でありソフトウェアの複雑性を深く洞察する思想家
- 音楽活動の経験から時間・構造・制約の概念をソフトウェアに応用
- コンサルタントとして多数の複雑なシステムを観察し「人間は自分が作る複雑性に対して非常に限られた存在だ」という確信を得た
- 主張の重心は言語仕様よりも「ものの見方」にある
- Simple Made Easy (2011)はその集大成であり他の講演(Are We There Yet? / Hammock-Driven Development / The Language of the System)にも共通テーマが現れる
■ 2. SimpleとEasyの違い
- SimpleとEasyは全く別の軸にある概念:
- Simple: 構造的に「絡んでいない」状態であり分離・一方向・明確な境界・独立した要素を持つ客観的な概念
- Easy: 慣れている・すぐ理解できる・すぐ使えるといった人間の主観による心理的・技能的な距離の概念
- ソフトウェアでこの2つが混同されることが複雑性の主な原因
- Simpleは「構造の状態」でありEasyは「人間の経験」である
■ 3. 複雑性の正体:Entanglement(絡み合い)
- Complexityは多機能や難易度ではなく構造的なEntanglement(絡み合い)を指す
- Hickeyは"complect"という古語を復活させ複雑性の正体を定義:
- 本来分離されるべき責務が混ざる
- データとロジックが密につながる
- 依存が循環し片方を変えるともう片方が壊れる
- Entanglementは指数関数的に増大し気づいた頃には解けなくなる
■ 4. Simple優先の設計原則
- 核心は「Simple first then easy」(Simpleを優先しEasyを後から足す)
- Easyを先に選ぶと短期的には速いが構造的コストが蓄積する
- Simple優先の設計は変化に強く長期的な開発速度を維持できる
- Simpleを基準にしておけばEasyのツールやフレームワークを後から安全に追加できる
- Simpleの条件:
- 分離されていること
- 依存が単純であること
- 一方向であること
- 解釈の余地が少ないこと
■ 5. 事例によるSimpleとEasyの比較
- レゴブロック(Simpleの象徴):
- ピースが明確に分離されている
- 接続ルールが単純で例外がほとんどない
- 構造そのものがSimpleであるため壊れにくく変更しやすい
- UNIX(Simpleの好例):
- 各コマンドが単機能で責務が明確
- 小さく副作用が少なく結合が一方向で組み合わせに強い
- Simpleを積み上げることで高い生産性を実現
- Spring Boot(EasyだがSimpleではない例):
- アノテーションで暗黙的に依存が増える
- 自動設定が巨大で見通しにくい
- Easyが強いがゆえに構造が把握しづらくEntanglementを招きやすい
- GraphQL(Easyが強いと境界が曖昧になる例):
- 巨大クエリが複数のドメインを横断する
- スキーマの結合関係がフロント都合で増えていく
- 型や責務の境界が曖昧になりやすくSimpleから遠ざかる
- AIコード生成(「Easyの暴走」の例):
- 局所的に賢い抽象化を入れ責務境界を曖昧にする
- 仕様の曖昧さを埋めるために余計な意味付けや判断を自動追加する
- 動くコードを優先し構造の純度(Simple)より即時性(Easy)を強化する傾向がある
- Easyの暴走を止める役割は依然として人間が担う必要がある
■ 6. AI時代におけるSimple Made Easyの読み直し
- AIはEasyを極端に強化したがEntanglementも同じ速度で増殖させる
- AI時代においてもSimpleのステップを意識的に先に挟む順番は変わらない:
- まず境界を決める
- 責務を分離する
- 依存の方向を整える
- その上でAIに実装を任せる
- AIはSimpleに書く作業自体も得意であり人間がSimpleの基準を示せばそれに従って実装できる
- AIは自発的にSimpleを選ばないが指示すればその通りに動く
- AI時代に人間の価値となる「Simpleを選ぶ能力」:
- 何をどこで分けるべきか
- 境界をどこに置くべきか
- 結合をどこまで許容するか
- どうすれば絡まりを避けられるか
- AIの性能が上がるほどSimpleを軸にできる開発者・チームが強くなる
- Simpleはただの美学ではなくプロダクトの持続性を決定する基盤そのもの
■ 7. Simpleを守るための9つの問い
- Complectを見抜く問い:
- 「この2つは本当に一緒にすべきか」(関連と結合は違い一緒にしなくても動くなら分けたままにする)
- 「この変更の影響範囲を即答できるか」(即答できないならどこかで絡まっているEntanglementの兆候)
- 「片方を変えたらもう片方は壊れるか」(壊れるなら絡んでおり将来の変更コストが積み上がっている)
- Easyの誘惑に気づく問い:
- 「これは慣れているから選んでいないか」(慣れや経験で選んでいるなら一度立ち止まって構造を見る)
- 「1週間後の自分はこれを理解できるか」(今だけのEasyに最適化していないかを問う)
- 「短期の速さと長期の速さどちらを取っているか」(Easyは短期で速くSimpleは長期で速い)
- Simpleに立ち返る問い:
- 「これを分けたら何が楽になるか」(分割の目的を言語化できないなら分けない)
- 「この抽象化がなくても動くか」(なくても動くなら今は不要であり3箇所以上で使うまで抽象化を遅らせる)
- 「この賢さは本当に必要か」(愚直でも読める方が長期的には強くAIが生成する賢いコードほど将来の自分を苦しめる)
■ 1. 概要
- シニアエンジニアが実践するトラブルシューティング・切り分けの思考パターンを9つに整理したもの
- 調査力の差は経験や知識量だけでなく「不確実性を1つずつ削り落とすプロセスの徹底」にある
■ 2. 調査・切り分けの思考パターン
- まず全体を見る:
- いきなり一点を疑わず全体像を把握する
- 局所ではなく構造を見る
- 見る前に予測する:
- ログやコードを開く前に「おそらくここだろう」を言語化する
- 仮説なしに掘り始めると異常を見逃しやすいため観測は仮説とセットで行う
- 外から内へ絞る:
- 全体→サービス境界→コンポーネント→コードの順に見る
- いきなりコードを読み始めずスコープを段階的に狭める
- 計測してから動く:
- 「遅そう」「怪しそう」という体感で修正しない
- APMやダッシュボードで実測してから手を動かし数値で判断する
- 変化点を探す:
- 「昨日まで正常だった」場合はデプロイ・設定変更・トラフィック・依存サービス更新などの変化を探す
- 状態ではなく変化を見る
- 1つずつ変える:
- 複数の改善を同時に入れない
- 影響を限定し即時に戻せる形で小さく変更して検証する
- 調査ログを残す:
- 何を見て・何を考え・なぜそう判断したかを記録する
- 仮説と結果をセットで残し思考の履歴を共有資産にする
- 境界条件を叩く:
- 「正常か異常か」だけでなく「どこまでなら正常か」を探る
- 前提が破綻する条件を意図的に試し暗黙の前提をあぶり出す
- 再現手順を最小化する:
- 複雑な手順のまま調査せず「これさえあれば再現する」最小構成を見つける
- 不要なコードや依存関係を削ぎ落としノイズを排除する
■ 1. 問題提起:技術ヒエラルキーという構造的偏見
- 著者はC#・Python・クラウドAPI・AIエージェントといったモダン技術とExcel/VBAによる現場改善の両方を実践している
- 技術の内容(何を実現したか)ではなく技術の種類(何を使ったか)でエンジニアの価値が判断されるという不合理なヒエラルキーが存在する
- 現場の改善が「属人化」と一蹴される問題と管理側に善意の改善が「負債」として降りかかる問題という非対称な衝突が生じている
■ 2. 目に見えない技術ヒエラルキーの実態
- クラウド・分散DB・Rustは「高尚」とされ使用者が高度なエンジニアとみなされる一方でExcelやVBAは「古臭い非エンジニアの道具」として軽視される
- バージョン管理や課題管理システムで適切に管理されたExcel/VBAの運用体制でさえ管理部門やベンダーから「管理できていない」と決めつけられる事例がある
- VBAコードのみのgit管理提案のようにドメイン知識を欠いた実情から乖離した提案がなされることがある
- ChatGPTやGeminiなどのAIも技術コミュニティの学習データに反映された偏見を回答に含む場合がある
- 評価対象の内容を詳細に吟味する時間・労力が不足するため外形的情報のみで判断される偏見は人間社会の一般的な現象でもある
■ 3. 偏見の心理的背景:ドメイン恐怖症
- 医療や法律と異なり情報処理技術には名称独占も業務独占も存在せず誰でもエンジニアを名乗れる
- ドメイン知識と技術力を併せ持つ現場の人材はDX推進において情報処理専門家より圧倒的に有利な立場にある
- 情報システムの提供・管理側はトラブル時に現場固有のドメイン知識の理解を要求されがちであり強い心理的負荷(ドメイン恐怖症)を抱えやすい
- この構造が「専門性の境界を明確にしたい」「自分たちだけが使う技術を高く位置づけたい」という防衛的動機を生み技術コミュニティへの発信内容にも反映される
■ 4. 管理部門の立場:統制と持続可能性の確保
- 管理部門の役割はシステム提供による業務向上だけでなくセキュリティとガバナンスの維持にも及ぶ
- 特定部門にのみ技術的特権を与えることは組織全体の統制上不可能であり現場の不満を抑えざるを得ない構造がある
- 技術力の高い現場人材への業務依存が生じた場合その人材の離脱後に業務継続が困難になり管理部門への要求が高まる
- 現場改善による要求水準の引き上げは管理部門のドメイン知識不足とリソース制約から対応が極めて困難である
- 上記の理由により現場の業務改善は「属人化リスク」または「シャドーIT」として捉えられ部門間関係が悪化する
■ 5. 現場部門の立場:業務改善と属人化解消の実態
- 現場がExcelなど利用可能な技術を選ぶのは管理部門に禁止されにくく持続可能性が最も高いためである
- 現場開発が発生する根本原因は公式システムが業務要件を満たさず改修要求が費用対効果を理由に却下されてきたことにある
- 業務課題の解決リソースを現場が自発的に投入するのは未解決の被害が自部門に直接降りかかるからであり合理的な判断である
- 自部門内でPDCAサイクルが回り始めると部門間・組織間の交渉調整プロセスが不要になり改善速度が桁違いに向上する
- 管理部門が「属人化」と一言で片付けることで現場には不満と管理部門への不信感が蓄積する
- 皮肉にも現場の技術活用の目的は「業務の属人化解消」であることが多く管理側の言う「技術の属人化」とは指す意味が異なる
■ 6. 技術の種類を決めるのは技術力ではなく立ち位置
- Excel/VBAは現場部門で使える技術の代表格であり管理部門から統制リスクとして扱われやすい
- クラウドや分散DBやRustは情報処理専門家のみが扱う技術であるため習得が望ましいものとして高尚に映る
- FileMaker・Kintone・Google SpreadsheetとGASなども現場技術の選択肢となりうる
- 技術の種類が偏るのは現場で使える技術がそもそも限定されているためであり技術力とは無関係である
- 著者は両方の技術領域を経験したことで技術間の壁が技術力ではなく立場の違いに起因すると結論づけている
■ 7. 部門間の反発を協力に変えるための提言
- ハイブリッドな立ち位置の公認:
- 現場の技術人材に管理部門への兼務や技術アドバイザーとしての公的役割を付与する
- これにより現場は管理側の統制意図を理解し管理側は現場のドメイン知識へのアクセス経路を得る
- 技術の種類ではなく解決の質で評価する:
- 「Excelだからダメだ」という技術種別によるマウントを廃し業務継続性への貢献度を共通評価基準とする
- 管理部門はExcelの「禁止」ではなく安全かつ非属人化された運用方法(コード共有・ドキュメント化支援)を提示すべきである
- 技術はドメイン(業務)を救うために存在し管理はその救済を持続させるために存在するという共通目的を出発点とする
- 各立場が抱える「理不尽」を相互に認め合うことが技術ヒエラルキーという虚構を崩す第一歩となる
■ 1. 問題提起
- ソフトウェア設計論(SOLID原則・DRY・YAGNI・OOP/FP・TDD/DDDなど)が絶対的な真理として語られる光景に違和感を覚える
- これらを「コンピュータサイエンス」「アルゴリズム」として権威付けし批判を封じる風潮が存在する
- 「事実」と「規範」という性質の異なる知識に同じ「科学」のラベルを貼ることに対してエンジニアとしての危機感を持つ
- この混同は現場から考える力を奪い設計論を批判不可能な信仰へと変質させる
■ 2. 事実と規範の二領域
- 従うしかない事実の領域:
- 停止性問題の決定不能性(任意のプログラムの停止判定は不可能という証明済みの事実)
- CAP定理・FLP不可能性といった分散システムの制約
- クイックソートの計算量オーダー(平均O(n log n)・最悪O(n²))
- 光速を超えた情報伝達の不可能性やネットワーク帯域の物理的上限
- これらはエンジニアの努力や美しいコードでは覆せない制約である
- 取捨選択して調整すべき規範の領域:
- SOLID原則・デザインパターン・RESTfulといった設計思想が該当する
- 自然法則でも数学的定理でもなく観測された事実ですらない
- 人間にとって扱いやすいシステムを作るために先人が編み出した知恵・ベストプラクティスである
- 採用すべきか否かはチームのスキルセットやシステムの寿命など文脈によって常に正解が変わる
■ 3. カリキュラムへの包含は分類の根拠にならない
- 「CS学部のカリキュラムに含まれるからCS」という反論への反駁:
- 問題にすべきは「基礎か実用か」ではなく「事実か規範か」という分類である
- 実用的な分野の中にもこの二層は存在する
- OSを例にした分類:
- スケジューリングアルゴリズムの数理や待ち行列の理論はサイエンスの側面が強い
- UNIXのファイルシステム設計思想やモノリシック/マイクロカーネルの議論はトレードオフの中で最適解を探るエンジニアリングである
- 倫理の例示による論証:
- 理学・工学カリキュラムには「科学技術者の倫理」が必修として含まれる
- しかし倫理はカリキュラムに含まれても「科学」とは呼ばれない
- 同様に教科書に掲載されるという理由だけで性質の異なるものを「サイエンス」と呼ぶのは乱暴である
- ソフトウェア工学の実証的アプローチ(開発プロセスのデータ収集と統計的傾向の把握)は科学的と言えるが現場で語られるSOLIDなどの原則は統計的事実ですらなく経験則に基づく規範に過ぎない
■ 4. 物理法則と設計戦略の混同
- 「DRYやSOLIDはメモリ領域の管理破綻を防ぐための工学原則であり絶縁原則と同様」という主張への反駁:
- 電子回路の絶縁破壊は観測された物理法則であり人間の意図と無関係に発生する自然現象である
- DRY原則の違反はメモリ領域の管理を常に破綻させるわけではない
- コンパイラの最適化を用いた反証:
- 近代的なコンパイラはインライン展開(DRYの逆であるコード複製)を最適化として頻繁に行う
- もしDRY違反がメモリ破壊をもたらすならコンパイラの最適化時点でバイナリがクラッシュするはずだが現実にはそうならない
- DRYやSOLIDはコードの管理・構造理解を容易にするための人間のための規範である
- メモリ安全性を担保するのはGCやRustの借用チェッカーといった言語処理系の仕組みであってソースコード設計の美しさではない
- 物理的破壊は壊れるか否かの二元論であるのに対しDRY違反による認知負荷は保守しやすいか否かというグラデーションの議論であり混同はエンジニアリング的解像度の低さの表れである
■ 5. 権威付けによる指導は怠慢である
- 「初心者に作法を守らせるために科学的権威で指導することは教育的配慮」という意見への反対:
- 設計が必要な理由・適用しない場合の実害(保守コスト増大・認知負荷上昇)を説明せず権威を借りて従わせるのは指導側の「説明の怠慢」である
- 権威付けによる指導の結果:
- 目的が蔑ろにされ「従うこと自体」が目的化する
- 文脈が変わっても思考停止して万能薬のようにルール遵守を強制するカーゴカルトが生まれる
- 「DRYの違反は物理的な破壊と等しい」と本気で信じるエンジニアが実際に存在することは教育的方便として行われた偽りの権威付けが現場で絶対的信仰として定着した実例である
- 初学者が型を身につける「守」の段階を否定するわけではないが指導者が理由を説明せず虚偽の権威でマウントを取ることは教育ではなくただの怠慢である
■ 6. 工学の本質としての抽象化
- 設計原則や規範を重視する理由はエンジニアリングの本質が「よい抽象化を模索すること」にあるからである
- 共通化と抽象化の違い:
- 共通化: 「AとBは似ているからまとめる」というボトムアップな整理整頓に過ぎない
- 共通化の問題: 文脈が異なるものを無理やりまとめると片方の仕様変更にもう片方が引きずられる密結合なシステムが生まれる
- 抽象化: 複雑な事実の上に人間が扱いやすい「都合のよいモデル」の層をトップダウンに設計すること
- TCPプロトコルを用いた抽象化の例示:
- ネットワーク上のパケットは消失し順序も入れ替わるという逆らいようのない事実がある
- TCPを被せることでデータが信頼性をもって順序通りに届くという抽象化されたモデルをアプリケーション層に提供する
- パケットロスという事実の上にストリームという扱いやすいモデルを提供することがエンジニアリングである
- SOLIDやDRYはこのような抽象化を成立させるための発見的な道具であり観測された事実そのものではない
- どの詳細を隠蔽してどの自由度を残すかという境界線の引き方は科学的裏付けだけでなくエンジニアの意思決定とトレードオフに委ねられる
- 絶対的な唯一の正解はなく人間の美意識やチームの文化に依存するアートやデザインに近い側面があるため自然科学と同列に扱うことには無理がある
■ 7. まとめ
- 「サイエンス」のラベルを貼ることで主張を客観的事実に見せかけ反論を封じることは誠実ではない
- 科学者の仕事が「変えられない事実」を解き明かすことであるのに対しエンジニアの仕事は「変えられる設計」を調整して現実の問題を解決することである
- 規範や原則を科学と偽ることはエンジニアリングの本分を放棄することに等しい
- CSの原則として正しいからと思考停止するのではなくサイエンスという制約条件のもとで設計原則の物差しをどう使いこなすかその文脈とトレードオフを語ることがプロフェッショナルとしての工学的な態度である
■ 1. 論旨の核心
- 記事の中心主張は「事実(is)と規範(ought)を同じ『科学』というラベルで括ることは誤りであり危険である」という点にある
- 哲学におけるヒュームの「is-ought問題」(自然主義的誤謬)に対応する知識論として正当な問題提起である
■ 2. 論理的に強い部分
- 事実と規範の二分法:
- 停止性問題・CAP定理・計算量オーダーといった「証明または観測された制約」と SOLID・DRYのような「人間の認知都合から導かれたベストプラクティス」を区別する視点は哲学的に堅実である
- 前者は反証不可能な定理であり後者は文脈依存の経験則であるという分類は概ね正確である
- コンパイラのインライン展開による反証:
- 「DRY違反はメモリを破壊する」という主張に対しコンパイラが最適化としてコード複製(DRYの逆)を行っても問題が起きないという具体的な反例を提示している
- 論理的に有効な反証であり論証の精度が高い
- 倫理のアナロジー:
- 「カリキュラムに含まれるから科学」という反論に対し「倫理も必修カリキュラムに含まれるが科学とは呼ばない」という例示は端的かつ有効である
■ 3. 論理的に弱い部分・留意点
- ストローマン論法の傾向:
- 「DRY違反は絶縁破壊と等しい」という主張を議論の代表例として使用することで反論者全体を極端な立場として描いてしまっている
- 「SOLIDは経験的に有効性が示されている」といったより一般的な反論には十分に答えていない
- 二分法の過剰な単純化:
- 「事実 vs 規範」の境界は実際には曖昧なグラデーションである
- サイクロマティック複雑度とバグ率の相関(実証的研究あり)・テストカバレッジと保守コストの関係(統計データが存在する)・チーム規模とモジュール境界の関係(Conwayの法則など)といった「観測から導かれた傾向」は記事の二分法に収まりきらない
- 「規範は人間の都合に過ぎない」の過剰な相対化:
- 設計原則を「人間側の都合に過ぎない」と述べることは認知科学的知見に基づいた設計論の妥当性を軽視するリスクがある
- 「都合」であっても人間の認知特性や計算機の動作原理に根ざした合理性を持つものは多い
- 教育的権威付けへの批判の一面性:
- 初心者への指導で「まず型を守らせる」アプローチを全面的に「怠慢」と断じているが学習理論上は「先に規則を内面化し後で理由を学ぶ」プロセスが有効な場面も存在する
- この批判は正当な側面を持つものの教育的文脈の複雑さを十分に扱えていない
■ 4. 総合評価
- 核心論旨の妥当性: 高い(is-ought問題として正当)
- 具体的反証の精度: 高い(コンパイラ例は有効)
- 反論への対応の網羅性: 中程度(極端例への反証に偏る)
- 二分法の精度: やや粗い(グレーゾーンを扱えていない)
- 結論の一貫性: 高い
■ 5. 結論
- 記事の主張する「規範を科学と偽ることの危険性」は知識論として正当であり実務的にも重要な問題提起である
- 事実と規範の二分法を過度に単純化している点および最も極端な反論を論駁の対象としている点で論証の網羅性に限界がある
- 主張の方向性は妥当だが設計原則の実証的根拠に関する議論を避けていることが論証の弱点となっている
時間t=1/48000×1200(s)
距離d=4×a(mm)
速度v=4×a×48000/1200(mm/s)
…が、4×a×48000は非常に大きな数になる可能性がある。コンピュータが扱える数は65535までなので、まぁ無理だ。
だから48000/1200×4×aにしてやる必要がある。
やってられない。
■ 1. EAVとは何か
- EAV(Entity-Attribute-Value)はデータを「何が(Entity)」「どんな属性を持ち(Attribute)」「その値は何か(Value)」の3要素で表現するデータモデル
- 通常のRDB設計では属性をカラムとして定義するが、EAVでは属性を「行」として表現する
- 属性の追加はattributesテーブルへのINSERT1件で完結し、DDL変更が不要
■ 2. EAVがアンチパターンとされる理由
- SQLの複雑化:
- 通常なら単純なSELECTで済むクエリが、属性ごとにJOINを要する複雑なものになる
- データ型制約の欠如:
- value列がTEXTやVARCHARになりがちで、RDBMSの型安全性が失われる
- 外部キー制約の使用不可:
- 汎用的なvalue列ではFOREIGN KEYによる参照整合性の維持が困難
- パフォーマンス劣化:
- エンティティ1件あたり属性の数だけ行が生まれ、行数が爆発的に増加する
■ 3. EAV採用の判断基準
- 採用を検討すべき条件:
- 属性の数が数千〜数十万規模で、事前に確定できない場合
- 属性の追加・変更がビジネス要件として頻繁に発生する場合
- ほとんどのエンティティが属性の一部しか持たないスパースなデータの場合
- 避けるべきケース:
- 属性が数十個以下で固定されている場合
- 複雑な集計やレポーティングが主要なユースケースの場合
- チームにEAVの運用経験がない場合
- 代替案として検討すべき技術:
- JSONBカラム(PostgreSQL)
- ドキュメントDB(MongoDB等)
- ワイドテーブル+パーティショニング
■ 4. 事例1: 財務諸表プロジェクト(Speeda)
- 背景:
- 複数企業グループ・複数会計基準・複数国をまたぐ数十万件の勘定科目を管理
- 勘定科目をカラムとして設計するとRDBMSのカラム上限に抵触し、かつALTER TABLE運用が非現実的
- EAVの適用:
- 勘定科目そのものをAttribute、企業をEntityとして扱い、金額をValueで表現
- 新規勘定科目の追加はINSERT1件で完結し、DDL変更・アプリ改修が不要
- スパースなデータに対してNULLを持たずに必要な行だけを格納できる
- 時間軸の組み込み(period_id):
- EAVテーブルにperiod_idカラムを追加し、主キーを(entity_id, attribute_id, period_id)の3カラム構成に変更
- 財務諸表データを「誰の・何が・いつの・いくら」という4次元のデータキューブとして表現
- 期間はすべてのデータに共通する固定軸として扱い、EAVの動的な属性部分と分離
- インデックス設計:
- アクセスパターンを事前に洗い出し、逆算した複合インデックスを設計
- 数十億件規模でも実用的なレスポンスタイムを実現
- パフォーマンス問題の本質は行数ではなくアクセスパターンを無視したインデックス設計にある
- 考慮点:
- マイグレーション管理: 属性マスタの変更もシードデータとしてバージョン管理に含め環境間の一貫性を維持
- ORM非対応: EAVの読み書きを抽象化するリポジトリ層を独自実装し、アプリ側のコードからEAVの存在を隠蔽
■ 5. 事例2: ID管理プロジェクト(YESOD)
- 背景:
- 人・組織・会社・オフィス・プロジェクトという複数種類のEntityとその関係性を管理
- Entity間の関係性(所属・アサイン・勤務地等)を通常設計で表現すると中間テーブルが増殖し、要件変化のたびにDDL変更が発生
- ReferenceIdの導入:
- EAVテーブルにreference_idカラムを追加し、entitiesテーブルへの外部キーとして定義
- プリミティブな値はvalue列、Entity間の関係性はreference_id列で使い分け
- 外部キー制約によりRDBMSの仕組みの中で参照整合性を保証
- 新たな関係性の追加はattributesテーブルへのINSERT1件で完結
- Entityの拡張性:
- entitiesテーブルにentity_typeカラムを持たせるだけでEntity種類を追加可能
- 要件が流動的なプロジェクトでのテーブル構造変更なしの拡張が実現
- バイナリ格納と型安全なシリアライズ(Kotlin):
- value列をBYTEA型として定義し、すべての値をシリアライズしたバイナリで格納
- Kotlinのsealed interfaceでAttributeValueの型を定義し、data_typeに基づくシリアライザを一箇所に集約
- コンパイル時にwhen式の網羅性チェックで型の不整合を検出
- TEXT型と比べて数値精度の劣化がなく、「とりあえず文字列で入れておく」運用上の怠慢を設計で防止
■ 6. まとめ
- EAVがアンチパターンとされる主因は、不適切な条件下での採用の歴史にある
- 属性が動的で大量・データがスパース・スキーマ変更を最小化したい条件が揃う場合はEAVが合理的な設計選択になる
- EAVの弱点(型安全性・参照整合性・パフォーマンス)はそれぞれ実践的な工夫で対処可能
- 型安全性: バイナリ格納+言語側のシリアライズ機構
- 参照整合性: reference_idによる外部キー制約
- パフォーマンス: アクセスパターンを逆算した複合インデックス設計
- EAVの弱点を正しく理解した上で補完策とセットで採用することが重要
■ 1. 職務経歴書における課題とSTAR法の限界
- エンジニアは自分以外の職務経歴書を見る機会がなく自分の経歴書の品質を評価しにくい
- エージェントはエンジニアの技術の詳細を把握しにくいため一人ひとりの強みに合わせたアドバイスが困難
- STAR法は出来事の報告には有効だが周囲の状況と自分の役割が分けられておらず能力の証明には不十分
- ミドルエンジニア以上では意思決定の思考プロセスが重要だがSTAR法はやった事実を記載しやすいフォーマットになっている
- 思考がブラックボックス化し候補者が「運が良かっただけの人」や「指示待ちの優秀な作業者」に映るリスクがある
■ 2. シーキューブモデルの構造
- エンジニアの経験を客観的な責任と主観的な判断の構造として整理するフレームワーク
- 3つの視点(縦軸)と3つの項目(横軸)からなる3×3の表で経験を捉える
- 横軸の構成:
- 課題 → 役割・行動 → 結果(原因から結果への時間の流れ)
- 縦軸の構成:
- 上段: 周囲の客観(Context)
- 中段: 自分の客観(Capacity)
- 下段: 自分の主観(Choice)
- 「シーキューブ」の名称は3つのCと3×3の表に由来する
■ 3. 各観点の定義と記載ルール
- 周囲の客観(Context):
- 自分が関与する前から存在していた課題や状況
- 解釈を含めず事実のみを記載
- 自分がいなくても成立する組織・プロダクト全体の前提環境
- 自分の客観(Capacity):
- 全体の中で自分に割り当てられた役割・責務・公式な立ち位置と権限
- 周囲からのミッションや役割を記載し周囲と自分の関係を明確化
- 自分の主観(Choice):
- 課題をどう捉え何を本質と判断しどこに介入したかという意思決定の領域
- 時間や思考が存在する唯一の層
- 行動の理由となった事象や判断を記載
- 記載ルール:
- 周囲の客観には解釈を書かない
- 自分の客観には判断を書かない
- 自分の主観にのみ自分の考えを書く
■ 4. 職務経歴書への活用効果
- 3×3の表は重要な要素を漏らさないための分析・整理ツールであり全内容を文章に詰め込む必要はない
- シーキューブモデルを使うことで以下の3点を混同せずに説明可能:
- 周囲の課題と期待・状況(どこまでが前提条件だったか)
- その中で自分が担っていた役割(どこからが本人の裁量だったか)
- そこで下した判断とその判断が作った状態(判断が結果にどう結びついているか)
- 「言われたことを実装した人」と「構造に責任を持って判断した人」の違いが自然に表現される
- 特にシニアエンジニア以上が自分の価値を誤解なく伝えるためのツールとなる
■ 5. STAR法との関係
- シーキューブモデルはSTAR法を否定するものではなく経験を手早く共有するためのプラクティスとして有効
- STAR法は判断や責任の構造を評価する場面では客観的情報と主観的情報の整理が困難で表現が不足することがある
- シーキューブモデルは前提となる状況・客観的な自分への期待・主観的な意思決定をもれなく整理するフレームワーク
- 元々の期待よりどれだけ大きいことができたかの比較表現が可能になる
■ 1. GitHubをメモ帳として活用するアウトプット観
- GitHubはポートフォリオではなく「巨大なメモ帳」として捉える
- 未完成・中途半端なコードでも公開する理由:
- 後で自分が検索できるようにするため
- 過去の活動の記録として残すため
- 自分の本棚を公開する感覚に近い
- 「人に見せる」ではなく「自分のために置く」という認識がアウトプットのハードルを下げる
- OSSを完成品ではなく「対話のきっかけ」として捉える:
- 公開することでプルリクエストなどのフィードバックが得られる
- 完璧にしてから出すのではなく出すからこそ完成に近づく
■ 2. 「便利なものを作ったら負け」という哲学
- アウトプットの原動力は実用性ではなく「驚き」と知的好奇心
- Vimスクリプトでの機械学習・動画再生など一見無意味な活動を好む
- 代表作emmet-vimも「Vimでもできるぞという見せびらかし」から生まれた遊び心が起点
- 役に立たねばという先入観を捨て興味本位の遊びを許容することがユニークなプロダクトを生む土壌となる
■ 3. 遊びを通じた技術的成長
- 「遊びこそが最高の学習法」をサッカーのリフティングに例える:
- リフティングはサッカーの上手さを保証しないがボールタッチの基礎能力を高める
- 遊びの中での実践が基礎能力を確実に向上させる
- 非効率な「縛りプレイ」を自分に課す学習法:
- Pythonで済む機械学習モデルをC言語やVim scriptで書き直す
- わざと負担をかけることでブラックボックスの仕組みを理解する
- 仕事上あり得ない技術的挑戦が未知のトラブル解決の地力となる
- 成長を目的にせず面白がって遊んでいたら勝手に成長していたというアプローチが第一線に立ち続ける理由
■ 4. AI時代における人間のアウトプットの価値
- AIはすでに「簡単なWebサービスを数日で作れる」レベルの実力を持つ
- AIへの過度な依存への懸念:
- AIばかり使うとプログラミングが下手になる可能性
- リハビリとして四則演算のアセンブラコンパイラを自作するなど基礎力の維持を重視
- 効率・実用性ではAIに勝てないが「面白そうだから作る」「仕組みを知りたいから書く」という人間の根源的欲求はAIに代替不可
- AI時代の人間のスタンス:
- 仕事ではAIを使って効率化する
- 余暇・OSS活動では義務感なく「みんなが驚きそうなもの」を自分のために作る
- 便利なものはAIが量産するからこそ人間は堂々と「無駄に見える遊びや驚き」を追求すべき
Bun v1.3.8の大きな新機能が、Markdownパーサーの搭載です。
BunはZig言語で開発されており、このMarkdownパーサーはC言語で実装された高速なMarkdownパーサー「MD4C」をZig言語に移植したものだと説明されています。
BunのMarkdownパーサーは、主に以下の3つの機能を備えています。
MarkdownからHTMLへのレンダリング
[...]
GitHub Flavored Markdonwの対応
GitHubがMarkdownを拡張した「GitHub Flavored Markdonw拡張」にもデフォルトで対応。テーブル、取り消し線(~~deleted~~)、タスクリスト( - [x] done)、自動リンク(Permissive autolinks)が利用可能です。また、wikilinks、latexMath、headingIds、autolinkHeadingsも利用可能となっています。
Reactコンポーネントとして利用可能なフラグメントの生成
MarkdownからReactコンポーネントとして利用可能なReactフラグメントを生成。
■ 1. オンボーディング高速化の概要
- 転職・異動のたびに「立ち上がりが早い」と評価される筆者が自身の取り組みを言語化したもの
- オンボーディングの速さはエンジニアとしての評価・チームからの信頼に直結する
- 「情報」「人」「組織」「自分」の4軸を意識して行動する
■ 2. 情報収集の仕組みを作る
- ドキュメントのAI活用:
- 専用GitHubリポジトリを作成し社内ドキュメントをまとめてAI(ClaudeまたはCursor)から参照できる環境を構築する
- リポジトリはアーキテクチャ設計書・API仕様書・運用手順書・議事録などの分類で管理する
- 会社のポリシーや組織規約の範囲内で実施する
- 過去ログの精読:
- GoogleドライブやSlackの過去ログをすべて読む
- Slackの過去ログにはドキュメント化されていない暗黙知(設計の背景・過去の障害・各メンバーの専門領域)が含まれる
- システム全体像の把握:
- 最初の1週間でシステム全体の構造を頭に入れる(細部は後回しでよい)
- 自分で図を描き先輩に確認することで理解の正確性を担保する
■ 3. 人との関係を築く
- 積極的な質問:
- 質問しない新人は「何を考えているかわからない」存在と映る
- 質問により自分の理解度の提示・相手への教える機会の提供・コミュニケーションの創出が可能になる
- AIやGoogleでは得られない社内知識は人に聞くことでのみINPUT可能
- キーパーソンマップの作成:
- 最初の2週間でインフラ・ドメイン知識・フロントエンド・過去の経緯など分野ごとのキーパーソンを把握する
- マップがあることで問題解決のスピードが向上する
- 助けを求める姿勢:
- 経験10年のベテランでも新環境では新人であり変なプライドを持たない
- 「助けてもらう」ことを前提に動くことで周囲も協力しやすくなる
■ 4. 組織を理解する
- 業務フローの把握:
- PRのレビューフロー・デプロイの頻度とタイミング・会議体の種類と目的・承認権限の所在を理解する
- 技術的に正しくても進め方が合っていなければ指摘される
- マネージャーの視点の理解:
- 今期のチーム目標・チームが抱える課題・上層部からの要求を把握する
- 1on1の機会があれば直接確認することも有効
- 組織課題の早期把握:
- 組織が困っている点・改善したい点を早めに把握することで自分の貢献領域が見えてくる
■ 5. 自分の立ち位置を見つける
- 足りていない領域の探索:
- チームを観察し「誰もやりたがらない仕事」「手が回っていない領域」を見つける
- 貢献領域の見極め:
- 自分の強みとチームのニーズが重なる部分を探す
- 最初の1ヶ月を観察期間とし2ヶ月目から貢献できる領域で成果を出しにいく
自前のPCサーバーやVPSなど、OSだけが用意されているような環境でインターネットアプリケーションを構築する場合、webサーバーやデータベースサーバーなど1つ1つインストールし管理するのは手間がかかります。そこでDockerを利用してアプリケーションと必要な構成を全て自動的に構築できるDokployが公開されています。
語弊があるタイトルだけど、外資系どころか海外でIT企業で働く場合でもそう、俺大学出てからずっとITエンジニア一本でジョブホッパーやってるけど。
ここ3~4年でどこも外資系ITで「日本人のエンジニアで35才以上って時点でちょっと難色を示すね」っていう通念みたいなものがどの会社でもあって、一種「あるあるネタ」になっててちょっと興味深かったので、
この辺の事情、何故かXやはてなで書いてるやつごく少数しかいなかったので、今後若い日本人ITエンジニアとかの参考になるんじゃないかなと思って書き残しておきたい。
先に言っておくとだけど必ずしも35歳以上は絶対取らん、というわけではない。実際俺も35歳以上なわけだし。外資系で活躍してる日本人エンジニアは海千山千のツワモノが多いから35以上~50代当たり前ではあるし
ただある種の偏見(まあ一面真実なわけなんだが)というか、法則の様なものがやっぱり体感的に俺も、外資系で通用してる日本人エンジニア達や外人や経営層にもみんなあるみたいで、一種の「マーフィーの法則」みたいになってる。
■ ① 海外から見た日本の35歳以上のエンジニアを採用しづらい理由「技術的バックボーンの文化からして他責思想が染みついてるから」
これが一番の理由で、一番面白かったところ。
俺は口にはしないくらいの分別はあるとはいえ、気持ちの理解はできるけども、欧米中はもちろん、イスラエル、韓国、インド、東南アジアのIT新興国のエンジニアも皆本気で不思議がっている
「彼らはなんで、いつまでも金子勇とTRONは無理解な政府と、外国に潰されたって言い続けてるんですか?」って、確かにね、Winnyなんか出てた頃なんかまだブラウン管のPC残ってたような時代の事だから、今の若いエンジニアからすればもう理解不能の領域だよね、あの他責思想は。
前の外資ITにいたとき、そこの上司がアメリカの人だったんだけど、「TRONって世界中で使われて普及国産OSだから、端的に言って成功してると思うし、潰されたとか全然そんなことないのに、何であんなに他責思想なんだろうね、日本人エンジニアって」と酒の席で不思議がってたのをよく覚えてる。
「Winnyって、もう20年前の技術でしょ?20年前のパソコンなんて、僕は"シュタインズゲート"でしか見たことないよ」、「そんな昔の事いつまでも引きずってるから世界観からして技術のキャッチアップが偏っちゃってるところあるよね」って後輩の中国人・韓国人エンジニアが突っ込んでたのとも、ちょっと苦笑してしまった。
上司だったアメリカ人も「例えば、イギリス人のITエンジニアがアラン・チューリングは政府に潰されたせいでIT技術はアメリカに奪われたのだ!なんて言ってる人、いる?いないでしょ?いたら頭がおかしい人としか思われないよ」と滅茶苦茶辛辣なツッコミをしていた。
言われてみれば確かにそうだな、と思う。外資で働いてる日本人エンジニアって、俺含めてそういう部分は内心思うところはあるんだけど、口に出したりいつまでも気にしてる人全くいないんだよね。俺お金が稼げるからって理由で特に愛着とかないし。
でも、そういう「こだわりが強い(他責思想の)日本人エンジニア」は外資に挑戦してくることは腐るほど見て来たけど、みんな物にならずに去っていってるから(後述すると一部はハマって活躍できる人たちもいる)、採用コストも含めてその時点で難色を示すっていう「マーフィーの法則の亜種」みたいなのができちゃってて、
しかもこれ、例に挙げたのが前の会社ってだけで、ここ3~4年でどこもみんな似たような認識の話が出てるっていう話。
■ ② 特定のアニメ・サブカル分野が好きな奴は要注意
これも採用・人事考査に響くほどの謎の法則性があるんだよね。具体的な作品名は上げないけど、まぁ所謂「異世界で転生してやり直すとか、悪い女貴族に生まれ変わって…みたいなのがいっぱい書かれてるジャンルの某web小説系」が好きって日本人エンジニア、伏字にすると「●●●系」って奴。
コミュニケーション取ってる中でこの話題が出た時点で、周りの空気がピキって緊張感で凍り付く程割とみんな「あっ…(察し」ってなってしまうくらい、「使えない」というよりコンプライアンス・コミュニケーション的に問題ある「問題児」的な日本人エンジニアは圧倒的にこれが多かった。圧倒的というより、100%そうだった。
というか①に該当しなくとも「②」が発覚した段階で、空を見上げて「Oh…my god…」とみんななってしまうくらいのレベルだった。
正直「①」で上げた様な他責思想気味の人たちでも、もうテック大好き!ってくらいな人たちはこだわりが強いだけで、スキルセットがハマったらかなりうまく外資でも活躍できる可能性があるし、実際そういう人も結構いるんだよね、特にAI系とビッグデータ操れる人材は重宝されてるし。
でもこの「某アニメ分野が好きな」エンジニアって時点で、今までそんな奴一人もいなかった。マジで鍛えれば使えるとかマネジメントでどうこうなるって領域超えたレベルの、酷い奴は対人トラブルまで起こすレベルで、まぁ言葉悪いが「外れガチャ」しかいない。
これ、前の会社どころか、前々、今の会社でも同じような法則性で見てる外人や経営層が多くて、ちょっと笑っちゃった。外資で働いてる人らはてな含めて多いはずなのに、この辺のあるあるネタ出ないの割と不思議だと常々思う。
①と②がそろってるやつの率が圧倒的に35才から上で比率が異常に高かったから、なんか外資系でもそういう法則性みたいなのが流れちゃってるんだろうな、と個人的には思ってる。
まぁ逆に言えば、①と②の傾向がないエンジニアがそれだけ日本でも若手では増えてるから、「日本人のエンジニアだから」って取らないなんてことは全くないんだけども、
これから外資で働いてみたいっていう日本人エンジニアがいたら、①と②には注意してマインドセット変えた方がいいと思うよね、っていう老婆心ながら言いたいかな。
個人的な観測範囲でと前提するが特に②はヤバい、酒でべろんべろんになってたって絶対口が裂けてもいっちゃいけないレベル
しかしまぁどうしてもアニメ以外にコミュニケーションが取れないなら、外人ウケする奴がいい、結構外資は経験値高いんで外人も日本人も上司は40~50代プレイヤー多いから、鉄板は80~90年代のOVA系とか(攻殻とか銀英伝とか、あとGIジョーとかG1トランスフォーマーとか)はまぁ無難かな、って感じ。
■ 1. 記事の概要
- バグ修正のプロセスをReact/React Routerのスクロールバグを実例として体系的に解説した記事
- AIも人間のエンジニアも再現手順なしで修正を試みるという同様の誤りを犯す傾向がある
■ 2. Step 0: 再現手順なしでの修正の失敗
- ClaudeにスクロールバグのFix指示を出したが繰り返し誤った修正を提案した
- useEffectの条件変更やスムーススクロールからインスタントスクロールへの変更などを試みたが効果はなかった
- バグが修正されたかを検証する手段がないことが根本的な失敗の原因
■ 3. Step 1: 再現手順(Repro)の確立
- Reproとはバグが確実に再現できる操作手順であり「何をするか」「期待動作」「実際の動作」の3要素で構成される
- 毎回確実にバグが再現できるReproは信頼性の高い検証を可能にする
- 再現率が低い場合はネットワークのモック化など不確実性の排除が必要
- Claudeはスクリーンを視覚的に確認できないため視覚的なRepro(スクロールのジッター)は有効に機能しない
- 元のReproが使用できない場合は別の形式のReproへの変換で対処可能
■ 4. Step 2: 再現手順の絞り込み
- 別のReproへの変換には新しいReproが元のバグと無関係である可能性というリスクが伴う
- 視覚的なジッターの代わりにスクロール位置の数値変化を測定するReproに変換した
- ボタンクリック前後のdocumentのスクロール位置を計測
- 位置に変化がない状態を「バグあり」として定義
- 新しいReproの有効性を「バグが解消した状態でも正しく機能するか」で必ず検証する
- ネットワークコールをコメントアウトするとスクロール位置に変化が生じることで確認
- コメントイン・コメントアウトを繰り返して因果関係を検証することが望ましい
- 新しいReproが元の問題と完全に一致しなくても関連性が認められれば継続する価値がある
■ 5. Step 3: コードの段階的削除による問題の絞り込み
- 新ブランチを作成し以下のワークフローを繰り返す
- Reproを実行してバグの存在を確認
- 関連コードから何か一部を削除(コンポーネント・イベントハンドラ・条件・スタイル・importなど)
- Reproを再実行してバグの継続を確認
- バグが継続する場合はその変更をコミット
- バグが消えた場合は解消要因の仮説を記録しリセット後により小さな単位で再試行
- Claudeは途中から独自仮説を立ててその検証に特化したテストケースを作成し始めた
- 仮説を立てて検証すること自体は問題ない
- 仮説検証が失敗した場合はバグが再現するチェックポイントに戻り削除を継続することが不可欠
- 「整礎再帰(well-founded recursion)」の概念と同様に常に確実な前進が保証される必要がある
- Fibonacci関数のバグ例(fib(n)がfib(n)を呼び出す無限再帰)を整礎でない再帰の例として示す
- Lean言語ではnが小さくならない再帰をコンパイル時に型エラーとして検出できる
- Reproの削減も同様に常にReproが「小さくなっている」ことを確認しながら進める必要がある
- このプロセスを繰り返すことで最終的には削除できるものがなくなり根本原因が浮かび上がる
■ 6. Step 4: 根本原因の特定
- Step 3のプロセスにより問題が単一ファイルに絞り込まれた
- ファイルをルーターの外に移動すると正常に動作しルーター内に戻すと再び破損した
- トップレベルルートでは動作しルートレイアウト内のネストで破損することが判明した
- 根本原因はReact RouterのScrollRestorationコンポーネントのバグ
- 本来はルート変更時のみ起動すべきところ全てのrevalidation時に起動するバグが存在していた
- アクション経由のネットワークコールがrevalidationを発生させScrollRestorationが起動した
- ScrollRestorationがscrollIntoView実行中に干渉しジッターを引き起こしていた
- 古いバージョンのReact Routerを使用していたことが問題の前提条件
- この手法はFacebookのReactツリーの半分を削除してバグを50行のコードまで絞り込んだ事例でも有効だった
■ 1. 背景と課題
- 組織拡大に伴う意思決定のボトルネック:
- 開発タスクは回るが予算や採用などの経営判断はCTOに集中
- 承認待ちの発生により組織運営の停滞が発生
- 2019年頃のプロダクトチーム拡大期に課題が顕在化
■ 2. 経営チームという解決策
- 仕組みの概要:
- CTOが担っていた責務を複数チームに分割
- 各チームへ意思決定に必要な裁量を委譲
- 特定個人の承認待ちを回避し素早い意思決定を実現
- リーダー職と経営タスクの分離:
- リーダーにならずとも経営タスクへの参加を可能に
- 柔軟な参加と離脱を実現
- 個人の状況に応じた関わり方を許容
■ 3. 権限委譲の方法
- 全権委譲の方針:
- 段階的ではなく担当領域全てを委譲
- 採用チームなら採用領域全て、コンピテンシーチームなら評価基準全てを担当
- サポート体制:
- 初期は領域を知る人物が伴走
- 一定期間後にチームへ完全移行
- 迷った際の相談体制を維持
- 全権委譲の意図:
- 部分的委譲では全体感の把握が困難
- ボトルネック解消の実効性確保
■ 4. 経営チームの構成と運営
- 経営と運営の分離:
- 経営チームは「何をやるか」の設計と意思決定を担当
- 日々の実務オペレーションは担当外
- 本業である開発への影響を最小化
- チーム構成:
- 現在13チームが存在(承認、採用、新卒採用、ブランディング、コンピテンシー、kickoff-techforum、メンタルヘルス、360FB & 個人OKR、オンボーディング、構造化面接、原則、ブルー、戦略担当)
- 各チーム2〜4人のメンバーで構成
- 状況に応じて新設や統廃合を実施
- メンバーの流動性:
- 6〜12カ月に平均1〜2回のシャッフル
- 別チームへの移動や開発集中のための離脱が可能
- 掛け持ちやスカウトも許容
- 経営チーム活動は週2時間までを目安に設定
■ 5. エンジニアが兼任する理由
- 組織文化との整合性:
- ユーザベースの「34の約束」における「自己規律」の重視
- 自分たちで考え判断し行動する文化
- XPの価値観:
- 現場に近い人間による意思決定
- 小さく試してフィードバックを素早く回す考え方
- 実態に即した判断:
- 開発現場のコンテキストを深く理解した上での判断が可能
- エンジニアの実情に即した無理のない意思決定を実現
■ 6. エンジニア個人へのメリット
- 小さく始めるトレーニング:
- 正解不明な状況での意思決定力を養成
- フィードバックサイクルを速く回す考え方は開発と共通
- より高い不確実性下での判断訓練の機会
- 視座と意識の変化:
- 組織全体を考える時間の確保
- 違和感への対処意識の向上
- チームや組織全体にプラスとなる振る舞いへの意識醸成
■ 7. 事例1: 採用チーム
- 課題:
- 指名受託率の低下
- 採用基準のメンバー間でのブレ
- 解決策としてのドラフトコーチ導入:
- 組織理解が深く経験豊富なメンバーがコーチ役を担当
- 指名判断前の必須相談プロセスを追加
- 成果:
- 判断基準の学習機会の提供
- 言語化プロセスによる情報整理と判断の明確化
- メンバーの心理的負担軽減と質の向上
- 当事者としての関与:
- 課題発見から改善実施までを自ら担当
- 仕組みとしての課題解決によるやりがい
■ 8. 事例2: 構造化面接チーム
- 目的:
- 面接評価のブレ軽減
- 構造化面接アプローチの導入
- 段階的導入戦略:
- 正社員面接への導入決定
- 一次面接のみでの実施
- ひとつの設問に限定
- スピード重視の意思決定:
- 小さくリリースして早期フィードバック取得
- 定例ミーティングでの背景説明と質疑応答
- 意思決定の透明性確保:
- 背景共有による納得感の醸成
- 建設的な提案を引き出す効果
■ 9. カオスCTOによる実証
- 取り組み内容:
- 2025年1〜3月の3カ月間CTOが経営業務から離脱
- CTO業務は原則として他メンバーへ委譲
- 必須業務のみCTOが対応
- 結果:
- メンバーの反応は落ち着いており大きな問題なく進行
- 採用活動や評価基準改定などが自律的に実施
- 組織のボトルネック可視化の負荷テストとして機能
- 組織強度の実証:
- 経営チームによる自律的な経営タスク遂行を確認
■ 10. 自己組織化の追求
- 自由と責任の考え方:
- 技術選定やプロジェクト進め方への大きな裁量(自由)の付与
- 成果創出と組織健全性維持という責任とセット
- 経営チーム参加の位置付け:
- やらされる仕事ではなく自由を守るための活動
- エンジニアとしての責任を果たす重要な取り組み
- 自己組織化の定義:
- 自らの手で組織ボトルネックを解消
- 最高のパフォーマンスを発揮できる環境の自律的構築
■ 1. 背景と概要
- PostgreSQLはChatGPTやOpenAIのAPIなどの中核製品を支える最も重要な基盤データシステムの一つである
- ユーザーベースが急速に拡大するにつれてデータベースへの要求も指数関数的に増加している
- この1年でPostgreSQLの負荷は10倍以上増加しており現在も急速に増え続けている
- PostgreSQLはこれまで考えられていたよりもはるかに大きな読み取り中心のワークロードを確実にサポートできるように拡張できる
- 単一のプライマリAzure PostgreSQLフレキシブルサーバーインスタンスと世界中の複数のリージョンに分散された約50のリードレプリカを使用して大規模なグローバルトラフィックをサポートしている
- 厳密な最適化と確固たるエンジニアリングを通じて8億人のユーザー向けに毎秒数百万件のクエリをサポートするに至った
■ 2. 当初の設計の欠陥と課題
- ChatGPTの公開後トラフィックはこれまでにない速度で増加した
- アプリケーション層とPostgreSQLデータベース層の両方で広範な最適化を迅速に実装した
- インスタンスサイズを増やしてスケールアップしさらにリードレプリカを追加してスケールアウトした
- 単一のプライマリアーキテクチャがOpenAIの規模の要求を満たすことができるというのは驚くべきことである
- 実際にこれを実現するのは簡単ではない
- Postgresの過負荷によるSEVを複数確認しておりその多くは同じパターンに従っている:
- 上流の問題がデータベース負荷の急激な増加を引き起こす
- キャッシュ層の障害による広範なキャッシュミス
- CPUを飽和させる高コストなマルチウェイ結合の急増
- 新機能リリースに伴う書き込み集中
- リソース使用率が上昇するとクエリの遅延が増加しリクエストがタイムアウトし始める
- 再試行によって負荷がさらに増大し悪循環を引き起こす
- ChatGPTとAPIサービス全体の性能を低下させる可能性がある
- PostgreSQLは読み込みが多いワークロードに対してはスケーラビリティが高い
- 書き込みトラフィックが多い時期には依然として課題がある:
- PostgreSQLのマルチバージョン同時実行制御(MVCC)の実装によるもので書き込みが多いワークロードに対しては効率が低下する
- クエリがタプルや単一のフィールドを更新する際には新しいバージョンを作成するために行全体がコピーされる
- 書き込み負荷が高い状況下では深刻な書き込み増幅を引き起こす
- クエリが最新のデータを取得するために複数のタプルバージョンをスキャンしなければならないため読み取り増幅も増大する
- MVCCはさらにテーブルやインデックスの肥大化インデックスメンテナンスのオーバーヘッド増加複雑なautovacuumのチューニングといった課題をもたらす
■ 3. 全体的な戦略
- 書き込み負荷を軽減するためシャード化可能な書き込み集約型ワークロードをAzure Cosmos DBなどのシャード化システムへ移行し続けている
- アプリケーションロジックを最適化し不要な書き込みを最小限に抑えている
- 現行のPostgreSQLデプロイメントへの新規テーブル追加は許可していない
- 新しいワークロードはデフォルトでシャードシステムに設定される
- インフラが進化してきたにもかかわらずPostgreSQLはシャーディングされず単一のプライマリインスタンスがすべての書き込みを処理している
- 主な理由:
- 既存のアプリケーションのワークロードをシャーディングすることは非常に複雑で時間がかかる
- 数百のアプリケーションエンドポイントの変更が必要となる
- 数か月場合によっては数年かかる可能性がある
- ワークロードは主に読み取り中心であり広範な最適化を実装している
- 現在のアーキテクチャでも継続的なトラフィック増加を支えるのに十分な余力がある
- 将来的にPostgreSQLのシャーディングを行う可能性を排除しているわけではない
- 現在および今後の成長に対して十分な余裕があるため短期的な優先事項ではない
■ 4. プライマリの負荷軽減
- 課題:
- ライターが1つのみのため単一プライマリ構成では書き込みを拡張できない
- 書き込みの急増が発生するとプライマリノードが瞬時に過負荷状態となる
- ChatGPTやAPIなどのサービスに影響を及ぼす
- 解決策:
- 書き込みの急増に対応できる十分な容量を確保するためプライマリノードへの負荷を可能な限り最小化する
- 読み取りトラフィックは可能な限りレプリカにオフロードする
- 一部の読み取りクエリは書き込みトランザクションの一部であるためプライマリに残す必要がある
- それらについては効率性を確保し低速のクエリを回避することに注力する
- 書き込みトラフィックに関してはシャード化可能で書き込み負荷の高いワークロードをAzure CosmosDBなどのシャード化されたシステムに移行した
- シャーディングが難しいのに書き込み量が多いワークロードは移行に時間がかかりそのプロセスは現在も進行中である
- 書き込み負荷を減らすためにアプリケーションを積極的に最適化した
- 冗長な書き込みを引き起こしていたアプリケーションのバグを修正した
- 適切な場合には遅延書き込みを導入してトラフィックの急増を緩和した
- テーブルフィールドをバックフィルする際には過剰な書き込み負荷を防ぐために厳格なレート制限を設けている
■ 5. クエリの最適化
- 課題:
- PostgreSQLでコストのかかるクエリをいくつか特定した
- 過去にはこれらのクエリの処理量が急増すると大量のCPUリソースを消費した
- ChatGPTとAPIリクエストの両方の速度が低下していた
- 解決策:
- 多くのテーブルを結合するような高コストなクエリが少数存在するだけでサービス全体のパフォーマンスが著しく低下したり最悪の場合は停止することがある
- PostgreSQLクエリを継続的に最適化し効率を確保して一般的なオンライントランザクション処理(OLTP)のアンチパターンを回避する必要がある
- 12個のテーブルを結合する非常にコストのかかるクエリを特定した
- このクエリの急増が過去に重大度の高いSEVの原因となっていた
- 可能な限り複雑なマルチテーブル結合は避けるべきである
- 結合が必要な場合はクエリを分解することを検討し複雑な結合ロジックは代わりにアプリケーション層へ移すようにした
- これらの問題のあるクエリの多くはオブジェクトリレーショナルマッピング(ORM)フレームワークによって生成される
- 生成されたSQLを注意深く確認し期待通りに動作することを確認することが重要である
- PostgreSQLでは長時間アイドル状態のクエリが見つかることも一般的である
- idle_in_transaction_session_timeoutのようなタイムアウトを設定することはautovacuumのブロックを防ぐために不可欠である
■ 6. 単一障害点の軽減
- 課題:
- 読み取りレプリカがダウンした場合でもトラフィックは他のレプリカにルーティングされる
- 単一のライターに依存するということは単一障害点が存在することを意味する
- そのライターがダウンするとサービス全体が影響を受ける
- 解決策:
- 最も重要なリクエストには読み取りクエリのみが関係する
- プライマリにおける単一障害点を軽減するためにこれらの読み取りをライターからレプリカにオフロードした
- プライマリがダウンした場合でもこれらのリクエストが引き続き処理されるようにした
- 書き込み操作は引き続き失敗するが影響は軽減されている
- 読み取りは利用可能なままのためSEV0ではなくなる
- プライマリの障害を軽減するためにプライマリは高可用性(HA)モードでホットスタンバイと共に運用している
- ホットスタンバイは常に同期されているレプリカでいつでもトラフィックの処理を引き継ぐ準備ができている
- プライマリがダウンしたりメンテナンスのためにオフラインにする必要がある場合はスタンバイをすぐに昇格させてダウンタイムを最小限に抑えることができる
- Azure PostgreSQLチームは非常に高い負荷がかかってもこれらのフェイルオーバーの安全性と信頼性を確保するために多大な努力を払ってきた
- リードレプリカの障害に対処するため各リージョンに十分な余裕を持たせて複数のレプリカを配置している
- 単一のレプリカ障害がリージョン全体の障害につながらないようにしている
■ 7. ワークロードの分離
- 課題:
- PostgreSQLインスタンスにおいて特定のリクエストがリソースを過剰に消費する状況が頻繁に発生する
- 同じインスタンス上で実行されている他のワークロードのパフォーマンスが低下する可能性がある
- 新しい機能の導入によりPostgreSQLのCPUを多く消費する非効率なクエリが発生し他の重要な機能のリクエストが遅くなることがある
- 解決策:
- ノイジーネイバー問題を緩和するためワークロードを専有インスタンスに分離する
- リソース集約的なリクエストの急増が他のトラフィックに影響しないようにする
- リクエストを低優先度と高優先度の層に分けそれぞれを別のインスタンスに振り分ける
- 優先度の低いワークロードがリソースを大量に消費する状態になっても優先度の高いリクエストのパフォーマンスが低下することはない
- 異なる製品やサービス間でも同様の戦略を適用する
- ある製品での活動が別の製品のパフォーマンスや信頼性に影響を与えないようにしている
■ 8. 接続プール
- 課題:
- 各インスタンスには最大接続数制限(Azure PostgreSQLでは5000)がある
- 接続が不足したりアイドル状態の接続が過剰に蓄積したりしやすい状況である
- 過去には接続ストームにより利用可能な接続が全て枯渇する事象が発生した
- 解決策:
- データベース接続をプールするためにプロキシレイヤーとしてPgBouncerを導入した
- ステートメントまたはトランザクションプールモードで実行することで接続を効率的に再利用できアクティブなクライアント接続数を大幅に削減できる
- 接続設定の遅延も短縮されベンチマークでは平均接続時間が50ミリ秒から5ミリ秒に低下した
- リージョン間の接続やリクエストはコストがかかるためプロキシクライアントレプリカを同一リージョンに配置している
- ネットワークオーバーヘッドと接続使用時間を最小限に抑えている
- PgBouncerは慎重に設定する必要がある
- アイドルタイムアウトのような設定は接続の枯渇を防ぐために非常に重要である
- 各リードレプリカは複数のPgBouncerポッドを実行する独自のKubernetesデプロイメントを保持している
- 同じKubernetesサービスの背後で複数のKubernetesデプロイメントを実行しポッド間でトラフィックの負荷を分散する
■ 9. キャッシュ
- 課題:
- キャッシュミスの急増によりPostgreSQLデータベースの読み取りが急増しCPUが飽和状態になりユーザーリクエストが遅くなる可能性がある
- 解決策:
- PostgreSQLへの読み込み負荷を軽減するためにキャッシュ層を使用して大部分の読み込みトラフィックを処理する
- キャッシュヒット率が予期せず低下した場合キャッシュミスが急増することで大量のリクエストがPostgreSQLに直接押し寄せることがある
- データベースの読み取りが急増するとかなりのリソースを消費しサービスの速度が低下する
- キャッシュミス集中時の過負荷を防ぐため特定のキーでミスした読み取りプロセスがPostgreSQLからデータを取得するのは1つだけとなるようキャッシュロック(およびリース)機構を実装している
- 複数のリクエストが同一キャッシュキーでミスした場合1つのリクエストのみがロックを取得しデータ取得とキャッシュ再構築を実行する
- 他のすべてのリクエストはPostgreSQLに一斉にアクセスするのではなくキャッシュが更新されるのを待つ
- これにより冗長なデータベースの読み取りが大幅に減少し連鎖的な負荷の急増からシステムを保護する
■ 10. リードレプリカの拡張
- 課題:
- プライマリはすべてのリードレプリカにログ先行書き込み(WAL)データを書き込む
- レプリカ数が増加するにつれてプライマリはより多くのインスタンスにWALを送信する必要がある
- ネットワーク帯域幅とCPUの両方に負荷がかかる
- これによりレプリカの遅延がより高く不安定になりシステムを信頼性高く拡張することが難しくなる
- 解決策:
- 遅延を最小限に抑えるため複数の地理的リージョンにわたり約50のリードレプリカを運用している
- 現在のアーキテクチャではプライマリはすべてのレプリカにWALをストリーミングする必要がある
- 現時点では非常に大規模なインスタンスタイプと高ネットワーク帯域幅で適切に拡張できる
- プライマリに過負荷をかけずにレプリカを無期限に追加し続けることはできない
- この問題を解決するためにAzure PostgreSQLチームと協力して中間レプリカがWALを下流レプリカに中継するカスケードレプリケーションを導入している
- このアプローチによりプライマリに負担をかけずに潜在的に100以上のレプリカに拡張できる
- しかしこれにより運用上の複雑さが増し特にフェイルオーバー管理において顕著になる
- この機能はまだテスト中である
- 本番環境に展開する前に堅牢性と安全なフェイルオーバーが可能であることを確認予定である
■ 11. レート制限
- 課題:
- 特定のエンドポイントでの突然のトラフィック急増高コストなクエリの急増またはリトライストームにより重要なリソースが急速に枯渇する
- CPU、I/O、接続などのリソースが枯渇し広範囲にわたるサービスの劣化を引き起こすことがある
- 解決策:
- 突然のトラフィックの急増によってデータベースインスタンスが過負荷になり連鎖的な障害が発生するのを防ぐためアプリケーションコネクションプーラープロキシクエリの複数のレイヤーにわたってレート制限を実装した
- リトライ間隔が短すぎるとリトライストームを引き起こす可能性があるためこれを避けることも極めて重要である
- レート制限をサポートし必要に応じて特定のクエリダイジェストを完全にブロックできるようORMレイヤーを強化した
- この的を絞った負荷遮断により高コストなクエリの急増から迅速に復旧することができる
■ 12. スキーマ管理
- 課題:
- 列の型変更といった小さなスキーマ変更でもテーブル全体の書き換えを引き起こす可能性がある
- スキーマ変更は慎重に適用し軽量な操作に限定するとともにテーブル全体を書き換える変更は避ける必要がある
- 解決策:
- 特定の列の追加や削除などテーブル全体の書き換えを引き起こさない軽量なスキーマ変更のみを許可する
- スキーマ変更には厳格に5秒のタイムアウトを設けている
- インデックスの作成と削除は同時に行うことができる
- スキーマの変更は既存のテーブルに限定されている
- 新機能に追加のテーブルが必要な場合それらはPostgreSQLではなくAzure CosmosDBなどの代替シャーディングシステムに配置する必要がある
- テーブルフィールドをバックフィルする際には書き込みの急増を防ぐために厳格なレート制限を適用する
- このプロセスは時には1週間以上かかることがあるが安定性を確保し本番環境への影響を避けることができる
■ 13. 結果と今後の道筋
- 達成した成果:
- 適切な設計と最適化によりAzure PostgreSQLが最大規模の本番ワークロードに対応できるよう拡張できることを実証した
- PostgreSQLは読み込み中心のワークロードで数百万QPSを処理している
- ChatGPTやAPIプラットフォームなどOpenAIの最も重要な製品を支えている
- レプリケーション遅延をほぼゼロに保ちながら約50のリードレプリカを追加した
- 地理的に分散したリージョン間で低遅延の読み取りを維持している
- 将来の成長を支える十分なキャパシティの余裕を確保した
- 遅延を最小限に抑えながら信頼性を向上させる形で機能している
- 本番環境ではクライアント側のレイテンシの99パーセンタイルを常に2桁ミリ秒台前半で維持している
- 99.999%の可用性を実現している
- 過去12か月間で発生したPostgreSQLの重大障害(SEV-0)は1件のみであった(ChatGPT ImageGenのバイラルローンチ時に発生し1週間で1億人以上の新規ユーザーが登録し書き込みトラフィックが10倍以上に急増した)
- 今後の取り組み:
- PostgreSQLがこれまで当社を支えてくれたことには満足している
- 将来の成長に向けて十分な運営余力を確保できるよう引き続きその限界に挑戦していく
- 既にシャード可能な書き込み集約型ワークロードはCosmosDBなどのシャード化されたシステムへ移行済みである
- 残っている書き込み負荷の高いワークロードはシャーディングがより難しいためPostgreSQLのプライマリからの書き込みをさらに軽減すべくそれらについても積極的に移行を進めている
- Azureと協力してカスケードレプリケーションを有効化しより多くのリードレプリカを安全に拡張できるようにしている
- インフラストラクチャの需要が拡大し続けるにつれてシャード化されたPostgreSQLや代替の分散システムなどさらなる拡張のための追加のアプローチを模索し続けていく
SSL/TLSプロトコルを実装したオープンソースライブラリ「OpenSSL」が、1月27日にアップデートされた。複数の脆弱性が修正されているので注意が必要だ。
今回のリリースで修正された脆弱性は、以下の12件(括弧内は深刻度の評価)。
- CVE-2025-11187:PBMAC1パラメーターの不適切な検証が原因でコードが実行される。v3.6 / v3.5 / v3.4系統のみに影響(Moderate)
- CVE-2025-15467:CMS AuthEnvelopedDataメッセージの解析でスタックバッファオーバーフローが発生し、DoSやリモートコード実行が引き起こされる。v3.6 / v3.5 / v3.4 / v3.3 / v3.0系統のみに影響(High)
- CVE-2025-15468:不明な暗号スイートを受信するとDoSが発生する。v3.6 / v3.5 / v3.4 / v3.3系統のみに影響(Low)
- CVE-2025-15469:ワンショット署名アルゴリズムを使用する際の整合性ギャップ。v3.6系統のみに影響。v3.6 / v3.5系統のみに影響(Low)
- CVE-2025-66199:証明書の圧縮を使用するTLS 1.3接続でサービスの低下やリソース枯渇(DoS)が引き起こされる。v3.6 / v3.5 / v3.4 / v3.3系統のみに影響(Low)
- CVE-2025-68160:BIO_f_linebufferの範囲外書き込みによるDoS(Low)
- CVE-2025-69418:低レベルの OCB 関数呼び出しによるデータの読み取りや改竄。v3.6 / v3.5 / v3.4 / v3.3 / v3.0 / v1.1系統のみに影響(Low)
- CVE-2025-69419:PKCS12_get_friendlyname()におけるUTF-8変換の範囲外書き込みによりDoSなどが発生する。v3.6 / v3.5 / v3.4 / v3.3 / v3.0 / v1.1系統のみに影響(Low)
- CVE-2025-69420:TimeStamp Response検証コードの型混乱によるDoS。v3.6 / v3.5 / v3.4 / v3.3 / v3.0 / v1.1系統のみに影響(Low)
- CVE-2025-69421:PKCS12_item_decrypt_d2i_ex関数におけるNULLポインター参照によるDoS(Low)
- CVE-2026-22795:PKCS#12ファイルの処理で発生するNULLポインター参照によるDoS。v3.6 / v3.5 / v3.4 / v3.3 / v3.0 / v1.1系統のみに影響(Low)
- CVE-2026-22796:PKCS7_digest_from_attributes()関数における型混乱によるDoS(Low)
開発チームは、以下のバージョンへのアップデートを推奨している。
- 3.6.1
- 3.5.5
- 3.4.4
- 3.3.6
- 3.0.19
■ 1. Faciloの事業とプロダクトの現状
- Faciloは不動産仲介における煩雑な業務や顧客とのコミュニケーションを一元化可視化するSaaSを提供している
- 不動産仲介というマーケットは非常に複雑である:
- 複数の関係者が絡む
- 取引が同時並行で進む
- 営業担当者は物件情報をPDF化してメールやLINEで送り内見調整の電話をする
- プロダクト導入により業務が改善され仲介営業としての自信がついたという声がある
- 毎朝仕事を始めるときにOutlookと一緒にFaciloを立ち上げる光景が当たり前になりつつある
- 業務に深く根付いてきている手応えを感じている
■ 2. マルチプロダクト戦略への転換
- 資金調達の際に思い描いていたプロダクトは二つのみであった:
- Facilo物件購入クラウド(祖業で一番最初に作ったプロダクト)
- Facilo物件売却クラウド(購入と表裏一体の売却を支援)
- 当初は長らく一点突破型で走ってきた
- 現在はFacilo賃貸仲介クラウドとFacilo事業用クラウドが加わり4つのプロダクトを擁するマルチプロダクトなプラットフォームビジネスになっている
- マルチプロダクト戦略を最初から戦略として目的化したことは一度もない
- スタートアップとしてはやるべきことを絞るべきだという考え方がありマルチプロダクトに対してはアンチパターンという捉え方であった
- 現在はマルチプロダクト化に振り切っている:
- 物件購入クラウドの導入が進み顧客との接点が増えた
- このペインも解けるかもしれないという課題の解像度が一気に上がってきた
- 顧客課題の詳細:
- 不動産仲介の会社は売買と賃貸の両方を手がけているケースが多い
- 売買の二つのプロダクトのコンセプトや技術力を評価されながらもドメインがずれている賃貸には対応できなかった
- 賃貸でも使いたいという声をたくさんいただき賃貸仲介クラウドをリリースした
- 店舗やビルやオフィスといった事業用の不動産でもプロダクトを使いたいという声をいただき事業用クラウドが生まれた
- 現場の声に対応していった結果である
- フェーズの推移:
- フェーズ1:物件購入クラウドに集中する一点突破の期間
- フェーズ2:顧客の声に沿ってマルチプロダクト化していった期間
- フェーズ3:より戦略的にプロダクト間をつなげて複合的な課題を解決していく構想
- 段階を経てマルチプロダクト戦略になっていったがそれはあくまでも手段である
■ 3. マルチプロダクト化を支える技術的準備
- CTOの梅林はいつかはマルチプロダクトになっていくんだろうなという思いが創業時からあった:
- バーティカルSaaSにとってマルチプロダクト戦略でいろいろなプロダクトを作っていくことはベストプラクティスである
- プロダクトが増えるタイミングで人構成運用が一気に複雑化しがちである
- そこに耐えられる共通の型を先につくっておく必要がある
- もしそうなったときに開発スピードが落ちる構成だけは絶対に避けたいとずっと考えてきた
- Ruby on Railsというフレームワークを選んだ理由:
- 誰が触っても同じ構造ですぐに次を作れることを重視した
- 創業時としては最適な技術選定であった
- Railsのメリット:
- 普通の会社ではオンボーディングした新しいエンジニアが最初にリリースをするまでには早くても1週間程度かかる
- Faciloではライトなチケットであればオンボーディング初日にリリースができるくらい手軽である
- ローカル開発環境のセットアップが非常に単純化されている
- インフラもシンプルに保たれている
■ 4. シングルデータベース設計
- 教科書的な設計であればプロダクトごとにデータベースを構築するのが当たり前である
- Faciloではデータベースは一つである:
- 物理的にはシングルデータベースクラスタで複数のプロダクトを運用している
- 論理的にネームスペースをプロダクトごとに分けている
- スケーリング戦略:
- データベースはまず縦にスケールさせる戦略を取っている
- 10年前20年前のインフラであれば一つのサイズを大きくするにも一定の限界があったため横にスケールさせる戦略しか取れなかった
- 現在のデータベースの性能は昔に比べてはるかにアップしている
- サイズ自体を限界まで大きくしたいと考えている
- BtoBのサービスがメインで数千万ユーザーを相手にするような大規模なBtoCサービスとは前提が異なる
- 保守運用体制:
- この人じゃないと管理できないというような属人化しやすい専門の人を作らないようにしたい
- FaciloにはSREもいない
- エンジニア全員にインフラやCI/CDパイプラインの流れを理解してほしいと考えている
- ソフトウェア開発とSREというように組織を分けてインフラ側がバックエンドエンジニアがインフラのことを何も気にせずに触れるような環境を作ったよとやってしまうとブラックボックス化してしまう
- バックエンドエンジニアがインフラのことを常に理解しその上でいかに監視コストを減らしていくかを考えるべきである
■ 5. 外部キー制約と削除フラグを設けない設計
- Faciloでは外部キー制約を設けていない
- 重視しているのは認知コストを下げることとスケールしにくい書き込み処理をできるだけ早くすることである
- 銀行のシステムのように整合性が非常に大切なドメインであればトランザクションをしっかり組みデータベースの整合性を厳密に管理すべきである
- 削除フラグの問題:
- とりあえず入れてしまうとこのテーブルには削除フラグがあるかこのクエリでは考慮が必要かといった判断があらゆる場所で発生する
- 開発時の認知コストがどんどん上がってしまう
- Faciloの場合はそもそもなぜ削除フラグが必要なのかから考える:
- 誤操作から復元したいのであればまず誤操作が起きにくいUXにする
- それでも誤操作が起きるとしたら年に何件なのかその確率と設計の複雑さのトレードオフで考える
- 実は削除フラグではなく更新履歴として違うものをつくるべきかもしれない
- 問題の本質を常に考えながら設計が開発効率に与える影響を吟味している
- 復元が必要なケースについても今のAI時代はCloudWatchのログをAIエージェントにgrepさせることで人力でも十分対応できる
■ 6. ベストプラクティスを前提にしない設計思想
- 組織設計にしろデータベース設計にしろ教科書的にはアンチパターンとされる手法を選択している
- ベストプラクティス自体は過去の経験や教科書を通して一通り学んできた
- Faciloのビジネスや規模を前提に考えると本当にそこまで必要なのかを毎回問い直している
- 教科書的には正しいとされる構成でも運用や組織まで含めて見るとかえって複雑さを招くこともある
- 過去の大きな組織での経験:
- インフラが強く抽象化され過ぎていて裏側で何が起きているのか分からないことに強い違和感を持った
- 本来は開発しやすくなるはずの仕組みなのに実際にはインフラエンジニアへの問い合わせが増え承認フローもどんどん複雑になっていく
- 開発側も運用側も幸せになっていないのではないかと思った
- インフラとアプリケーションは密接に結びついている:
- バックエンドエンジニア自身がインフラを理解し自分の操作とシステムの挙動が結びつく手触り感を持った方が自然である
- 技術選定の判断:
- 一見すると何も知らないエンジニアが作った構成に見えるかもしれない
- ベストプラクティスとしてある分散構成やハイパフォーマンスなシステム構築をすぐに候補から外したわけではない
- Redisを使えばキャッシュやセッション管理やキューなどを高い性能で処理できる
- その性能がオーバーエンジニアリングではないのかと期待されるスループット量から逆算しどの程度ちゃんと作るべきなのかを常に見極めている
- そうした判断の積み重ねがシステムと組織のスケーラビリティを支えるシンプルさにつながっている
- 組織設計への適用:
- エンジニア職種が20人程度という今の規模であれば横断組織を作るよりもチームを小さく保ち全員が同じ設計思想を共有している方がスピードを落とさずに済む
- エンジニアだけで100人200人を超えたり世界中で分散して開発を進めているような組織であれば縦割りにしたり横断組織を作ったりする必要がある
- 組織構造のベストプラクティスも理解しているがそれがどんな規模の企業での前提で語られているのかを見た上で現在のFaciloにとって本当に必要かどうかを見ている
■ 7. カルチャーとしての手触り感
- 会社として大事にしていることとエンジニア組織の考え方がきれいにリンクしている
- 二つの重要な要素:
- 手段と目的を逆転させないこと:
- 目的はクライアント企業の課題解決や事業成長である
- そのためにプロダクトがあり技術がある
- この順番を組織全体で共有している
- モノ作りが好きでそのプロダクトを通してお客さまやその接点となるカスタマーサクセスやセールスにありがとうと言ってもらえる手触り感が好きというカルチャーが会社全体に共通している
- 定石を理解した上であえて型を外すという姿勢:
- 一見するとセオリーから外れているように見える部分も基礎を押さえた上で事業や組織にとって最適だと考えて選んでいる
- エンジニアに限らずセールスやカスタマーサクセスなど全職種に共通する考え方である
- 型を破る判断基準:
- 常に型を破ることが目的ではない
- アプリケーションのコード自体はRailsのレールに乗って定石通りに作る
- インフラやDB設計はビジネスの速度を優先してあえて定石を外す
- どこは定石通りに作りどこであえて外すかを常に見極めている
- Railsの良さを生かせる場面ではあえてサーバサイドレンダリングを採用しフレームワークの王道から外れない使い方をしている
- よりインタラクティブな体験が求められる部分ではReactを使ったSPA構成を選ぶこともある
- 全てを最新技術で固めるのではなく標準的な作りで十分なところはシンプルにという方針で敬遠されがちなStimulusも普通に使っている
- 型から外れること自体を目的にしてしまうとそれもまた手段の目的化になる
- 急成長を支える開発スピード:
- セールスやCSが現場接点の中でいただいた要望やフィードバックは1営業日以内にSlackのフォームから投稿するルールにしている
- プロダクトマネージャーがチケット化してエンジニアにつなぐサイクルを通して週に10件から20件の機能をリリースしてきた
- お客さまから見たことのないスピードで対応してもらえていると高く評価されている
■ 8. 全社的なAI活用の展開
- 2024年12月にChatGPT Proを全エンジニアに配布した:
- 当時シリコンバレーに住んでいた梅林が生成AIに対応しないといけないと危機感を抱いた
- 梅林がコードを書いたら負けと宣言し生成AIだけで開発する期間を2カ月ほど設けた
- エンジニアにAIはまだ微妙でしょという意識があるとAIの能力を過小評価したままコードを書き続けてしまいAIフレンドリーになれない
- AIをしっかり信頼し一度エディタを捨ててみようと提案して開発してもらった
- AI自体の進化もあるがみんながAIをどう活用すべきかを真剣に考えるようになり開発組織においてはAIが相棒のようになってきた
- 2025年2月に標準ツールとして全エンジニアにDevinアカウントを作成し段階的に全社員へ活用範囲を広げた
- 最初は試行錯誤であったがこの数カ月で実運用に耐えるレベルまで安定してきた
- 組織としてのAI活用の3段階:
- 第1段階:エンジニアの開発での活用:
- 各自が最適な使い方を見出した
- 開発生産性は体感で3倍ほどに向上した
- 第2段階:PdM業務への展開:
- エンジニアがPdMでも自然言語で安全に開発できる環境を整えた
- PdM自身が自分でできるかどうかを判断し軽微な修正であれば自ら実装からデプロイまで行うようになっている
- 第3段階:セールスやCSへの展開:
- 仕様確認や簡単な分析をSlack上で自然言語で尋ねると即座に返ってくる仕組みを整えた
- エンジニアへの問い合わせが減り現場のスピードが大きく向上している
- 単なる効率化ではなく業務の進め方や役割そのものが変わる変革レベルの変化を感じている
■ 9. AI時代のエンジニアの価値
- ゼロからこういうものを作りたいという程度ならばDevinに依頼すれば作れる
- 要求を満たす複数の解法の中からそれぞれの善し悪しについても何度も尋ねて往復を重ねればたどり着けるがこうしたプロセス自体が大きなロスになる
- エンジニア相手であれば往復の回数は絶対に減る
- 今までの技術の蓄積や知識を使っていかに最少のラリーで最適なものを導けるかがエンジニアに求められていく
- CEO市川自身もDevinを使ってハンズオンで開発するようになっている:
- エンジニアがどれだけ複雑で高度なことをさまざまなプレッシャーの中でやってくれているのかよく分かるようになった
- 広い視野を持って依存関係なども意識しながら課題を解いてくれている
- PdMがハンズオンで開発できるようになってエンジニア不要論者になっているかというとむしろ逆でエンジニアの価値を再認識した感覚がある
■ 10. Faciloのエンジニアにとっての魅力
- 不動産仲介という分野が扱う住まいはあらゆる人の人生の根幹である
- 人口減少で多くの市場が縮小する中でも中古不動産流通など成長分野があり、なおかつデジタル化の余地が大きい希有なマーケットである
- そんな市場に向かい合いながらプロダクトを通してやりがいや手触り感を得られるのはエンジニアにとっても大きな魅力である
- CTOとしていかにエンジニアが快適にプロダクトの開発にコミットできるかということだけを常に考えている
- その考え方は無駄なコミュニケーションを省き必要なコミュニケーションをしっかり取るという組織のあり方やインフラの思想にも表れている
- AI時代になり技術選定そのものの重要性は相対的に下がってきている
- Faciloではその前提に立った上でAIの活用にフルベットしている
- 他社と比べても非常に高い割合で活用しており今後はエンジニアの人材戦略においてもAIを使いこなせるかどうかが重要な指標になると考えている
- Faciloではより先進的なAIの活用方法を学べる
Mermaid Rendering, made beautiful.
An open source library for rendering diagrams, designed for the age of AI: beautiful-mermaid. Ultra-fast, fully themeable, and outputs to both SVG and ASCII.
Built by the team at Craft — because diagrams deserve great design too.
マーメイドレンダリングを美しく。
AI時代のために設計された、図表レンダリング用のオープンソースライブラリ、beautiful-mermaid。超高速で、テーマ設定も自由自在、SVGとASCIIの両方で出力できます。
Craftチームによって開発されました。図表にも素晴らしいデザインがふさわしいからです。
天才数学者「私たちの『知能』に対する考えは正確ではない。」テレンス・タオは、「LLMは次の単語を予測してるだけで知的ではない」に対して、「実は人間もほぼ同じことをしているだけでは」と言う。数学を極めたタオ氏の口からこの言葉が出てくると重みがある。我々が「トリックにすぎない」と思っていたものが、実は我々自身の知能の本体で、「本物の知能」などないのかもしれない。
例えば、AIにとって完全に初見の推理小説があって、物語が進行した上で最後に探偵が「犯人の名前は...」と言う。もしAIがその次の名前を正しく言い当てられたら、それでもそれは単なるトリックだろうか。これはイリヤ・サツケバーの投げかけた問いだが、単なる「統計的オウム」としてのAIには、いささか振る舞いが知的すぎる。
現実はそれよりも奇妙なことが起きていて、「次単語予測」マシーンであるはずのAIが、推理小説どころか数学の未解決問題を解けてしまったりしている。「パターンマッチ」の極致がここまできたら、「パターンマッチだから知能ではない」ではなく、もはや我々人間の考える「知能」も結局パターンマッチと同じようなものと考える方が良いのではないか。
この部分の全訳「AI全体の領域が教えてくれているのは、私たちの「知能」についての考えが実は正確ではないということです。
AIの歴史は「これは人間にしかできないタスクだ」というものでした。自然言語を読む、チェスに勝つ、数学の問題を解く、など。そして一つずつ、AIアルゴリズムがそれを達成していきました。顔認識も、音声理解もできるようになった。
でも、その仕組みを見ると「知能」には感じない。「トリックだ」と思う。ニューラルネットワークを組み合わせてアルゴリズムを動かしただけ、と。私たちは何か「本物の知的な思考」を探しているのに、実際に目標を達成するツールにはそれが見えない。
でも、それは「知能」が私たちの思っているものと違うからかもしれない。
LLM(大規模言語モデル)は特に成功していますが、やっていることの多くは「次のトークン(単語)を予測する」だけ。これは知的に聞こえない。誰かに準備なしでスピーチを即興でさせて、毎瞬間ただ頭に浮かぶ次の言葉を言うだけ、意識の流れのまま...これがうまくいくとは思えない。
でもLLMではうまくいく。そして、実は人間もかなりそうしているのかもしれない。」
エンジニア誰もWordPress 運用したくなくて、Web系の会社なのに WordPress の運用は外注みたいな状態結構見る
Manning刊『Architecture Modernization』の邦訳版。
本書は、技術・組織・戦略を統合し、システムの価値を最大化する実践ガイドです。
長年運用され中身がブラックボックス化したシステムや、ドキュメントが機能せず改修のたびにリスクが伴う設計。こうした技術的負債は、現代のビジネスにおいて成長を阻む大きな壁となっています。
本書は単なるコードのリファクタリング手法ではなく、ドメイン駆動設計(DDD)やチームトポロジー、ワードレイマッピングといった定評ある手法を組み合わせ、技術・組織・戦略という3つの視点からシステムを現代的な姿へと刷新するための包括的なアプローチを解説します。
■ 1. 一般的なイベント期間のテーブル設計
- アプリケーション開発で期間を表すデータを扱うことは珍しくない
- イベントの開催時間やタスクの予定時間などが該当する
- 一般的なテーブル設計は開始時間と終了時間をそれぞれstart_atとend_atカラムで保存する
- この設計はAIが一発で提案するほど一般的である
■ 2. 一つのテーブルに期間を持つ場合の適用範囲
- 一つのテーブルに開始時間と終了時間の両方を持つ設計は期間が明確に定義されている場合には有効である
- 開始時間と終了時間がともに必ず存在し必ず終了することが保証されている場合に適している
- イベントの開催時間は必ず開始時間と終了時間が存在しイベントが終了することが保証されている
- イベントの属性として期間を持つことは自然である
■ 3. 終了時間が不明確な場合の問題
- 終了時間が開始時に決まっていない場合や終了しない場合もある:
- タスクの予定時間はタスクが完了するまでの時間が開始時に決まっていないことが多い
- 有効期間のようなもので終了時間を決めずに無期限にする場合もある
- このような場合はend_atをNULLとして登録する設計になる:
- taskにデータを登録するタイミングではend_atにはNULLが登録される
- 終了時間が確定したタイミングでend_atにUPDATEで値を設定する
- 無期限の場合はNULLをそのまま設定する
- この設計は一見問題なさそうに見えるが実際にはいくつかの問題がある
■ 4. キャンセル仕様追加時の設計問題
- タスクのキャンセルを表現させたい場合の課題:
- end_atにキャンセル日時を設定すると理由がわからない
- キャンセルを表現するためにstatusカラムを追加することが考えられる
- status='canceled'のときはキャンセルでありstatus='closed'のときは正常終了である
- 最もやってはいけない設計:
- canceled_atカラムを追加すること
- end_atとcanceled_atの両方に値が入る可能性がある
- 逆にどちらかにしかデータが無い場合が発生する
- 集計クエリが破綻しどちらが正しい終了時間なのかがわからなくなる
■ 5. statusカラムの制限事項
- statusカラムは最新のデータしか持てない
- 失敗から学ぶRDBの正しい歩き方の「失われた事実」で説明されている
- キャンセル後の再オープンの問題:
- キャンセルしたがリオープンしたい場合はステータスをcanceledからopenにUPDATEしend_atをNULLに戻す
- 過去にキャンセルされた事実が失われてしまう
- statusカラムがなくても一回クローズしたタスクを再度オープンする場合も同様である
- このユースケースはGithubのIssueやPull Requestでもよくあり想定する必要がある
- 解決策:
- ステータスのhistoryテーブルを別に持つ必要がある
- statusカラムは履歴の最新の状態を非正規化で持っていることと同義になる
- 更新漏れや不整合が起きるリスクを常に抱える
- historyテーブルの最新行を現在のステータスとして参照する設計に変えることもできる
- status_historyテーブルにステータス変更の日時をもたせた方が良い
■ 6. イベントテーブル分割による設計改善
- start_atとend_atを持たせて期間として扱うという前提自体を疑う必要がある
- テーブルのステータスに依存関係がある場合:
- 下書き→承認→公開のようなワークフローがある場合
- ステータスの順番に制約を持たせたい場合もある
- イベントごとのテーブル分割設計:
- tasksテーブル(基本情報)
- task_draft_eventsテーブル(下書きイベント)
- task_approve_eventsテーブル(承認イベント。draft_event_idを参照しtask_idで必ずユニークになるように制約)
- task_close_eventsテーブル(クローズイベント。statusでclosedまたはcanceledを区別)
- この設計の利点:
- 特定のステータスの順番に制約を持たせることができる
- taskテーブルにstart_atとend_atを持たせる設計だとステータスの順番に制約を持たせることが出来ない
- データの整合性が保てなくなる
■ 7. 設計の推奨アプローチ
- 期間を表すデータをテーブルに持たせる場合の注意点:
- 開始時間と終了時間の両方を持たせる設計は一般的である
- 終了時間が不明確な場合や状態遷移がある場合には注意が必要である
- 終了時間カラムや範囲をもたせるときにNULLを許容する場合:
- まず一度立ち止まる
- そもそも期間として設計することが適切かどうかを検討する
- 多くの場合の最適解:
- 深ぼるとテーブルを分割した方が良いケースが多い
- 結果としてデータの整合性が保たれる
- クエリもシンプルになることが多い
- テーブル分割の検討方法:
- 期間の対象となるイベントやリソースに対してどのような状態があるのかを洗い出す
- 状態ごとにイベントテーブルを分割することを検討する
- まずは細かく分けて設計する
- その後に必要に応じて物理設計の際にパフォーマンスなどと比較しながら統合を検討する
■ 8. 時間枠の集計の難しさ
- テーブルを分割してもしなくても時間枠の集計は難しい
- ある期間に重複しないタスクを登録したい場合の課題:
- 時間枠の扱いはSQLに限らずプログラミングの題材として難易度が高い
- 特に重複と含有が複数のパターンの場合ロジックが複雑になりバグの温床になりやすい
- リーダブルコードでも「8.5 例:複雑なロジックと格闘する」でこの問題が取り上げられている
- end_atにNULLがある場合の処理:
- NULLは無期限のタスクとして扱う
- NULLは比較演算子で扱えないためWHEREの範囲で絞ることはできない
- NULLを特定の未来日時に変換する必要がある(例:9999-12-31 23:59:59)
- MySQLではIFNULL関数を使用しPostgreSQLではCOALESCE関数を使用する
- 実務での複雑性:
- アサインされた担当別やプロジェクト別やステータス別など条件が増える
- より難易度が高くなる
- PostgreSQLの範囲型:
- この問題を解決してくれるため強力な選択肢である
- 全てのDBMSでサポートされているわけではない
- 別の考え方が必要になる
■ 9. start/endの命名に関する考察
- ClaudeもChatGPTも全てstart_atとend_atで設計することを提案する
- 本来の適切な命名:
- 期間を表す場合はfromとtoの方が適切である
- beginとendの方が自然である
- startならstopの方が対になる
- 期間を表すならfrom-toやbegin-endの方が意味が通りやすい
- 著者は毎回レビューなどで指摘しがちである
- あまりにもstartとendが浸透している
- 本来は誤用だったが慣用化したと言えるかもしれない
ソフトウェアがいずれ「使い捨てすら可能になる」は自分も賛成だけど、ここで反対論を出してる人の多くは例によって「今の性能の生成AIが続いたら」という仮定で話してるので議論として噛み合っていない。
この話いっつも同じパターンになるんですよね。横軸が時間で縦軸が性能だとして(ざっくり近似)、遠くない内に使い捨て可能なソフトウェアが作れるくらいAIの性能が上がるんじゃないの、てのが元の問題提起であって、それに反論するなら「そこまで生成AIの性能は到底上がりそうにない」を持ってこないといけないわけだ。
もっとざっくり言えば「そのうち~なる」という主張に対して「今は~でない」は反論になってないって話。時相論理的な主張なんだけど、反論者がそこを読み取れていない。この話なら元の話題は数年~10年スパンくらいの話に見えるので、反論として性能がサチりそうな気配とかそういうの出せばいいんじゃないかな。
■ 1. 調査の背景と動機
- WordPressエコシステムで20年以上活動してきた著者が代替案を探索した
- 7歳の息子がウェブサイトを作りたいという要望がきっかけとなった
- 2025年のAutomatticとWP Engine間のガバナンス問題が緊急性を高めた:
- Matt MullenwegがAutomatticとWordPress.org基盤の両方をコントロールしている
- WP Engineのプラグインアップデートアクセスをブロックした
- WordPressエコシステムには単一障害点が存在することが明らかになった
- 一人の決定が数百万のサイトが依存するプラグインアップデートメカニズムを混乱させ得る
- WordPressは全ウェブサイトの約43%を占める
■ 2. 静的サイトジェネレーター(Astro、Hugo、Eleventy)
- 開発者コミュニティで人気がある
- Astroは特に勢いがありCloudflareが2026年1月にチームを買収した
- MarkdownまたはHTMLでコンテンツを作成し静的ファイルを生成する
- Cloudflare Pages、Netlify、Vercelに無料でデプロイ可能である
- 利点:
- 出力が非常に高速である
- データベース不要である
- PHP不要である
- セキュリティパッチ不要である
- 問題点:
- 管理パネルがない
- ビジュアルエディタがない
- コードエディタでファイルを編集しGitにプッシュする必要がある
- クライアントがコンテンツを更新する場合は不適切である
- トレーニング時間がサイト構築時間を超える
- WordPress代替ではなくウェブサイトを生成する開発者ツールである
■ 3. モダンPHP CMS(Statamic、Craft、October)
- Statamic:
- Laravelで構築されている
- クリーンなコードベースである
- 美しいコントロールパネルを持つ
- フラットファイルストレージオプションでGitでバージョン管理可能である
- ソロおよびホビープロジェクトは無料である
- 商用利用にはライセンスが必要である(サイトあたり275ドル以上)
- モダンなアーキテクチャでWordPressを再構築したものである
- 商業的に売り込みが難しい
- Craft CMS:
- 優れた開発者体験を持つ
- 優れたコンテンツモデリング機能を持つ
- エコシステムが小さい
- October CMS:
- Laravel-WordPressハイブリッドを目指したが牽引力を得られなかった
- ClassicPress:
- Gutenbergを削除したWordPressのフォークである
- より伝統的で安定したWordPress体験の維持を目指す
- ブロックエディタの方向性が主な不満である場合に対処する
- より小さなエコシステムという同じ根本的な制限を持つ
- Gutenberg専用に構築されたプラグインは動作しない
- 開発者コミュニティはWordPressのごく一部である
- いずれもニッチを超えて成長しない
- ネットワーク効果が存在せず今後も存在しない可能性が高い
- LaravelはAI駆動のルネサンスを経験している:
- AIアシスタンスでプラグインや拡張機能を構築することが容易になっている
- Laravel ベースのCMS代替案が増加すると予想される
- マーケットプレイスが急速に充実すると予想される
- 堀が1年前の予測よりも早く崩壊する可能性がある
■ 4. ヘッドレスCMSオプション(Strapi、Directus、Sanity、Contentful)
- コンテンツ管理とフロントエンドを分離するアプローチである
- CMSにAPIでコンテンツを保存しフロントエンドを自由に構築する(React、Vue、静的HTMLなど)
- エンタープライズおよび複雑なアプリケーション構築開発者に人気がある
- 典型的なウェブサイトやブログには過剰設計である
- 2つのものを構築および維持する必要がある
- 使用量ベースの価格設定(ContentfulやSanity)またはセルフホスティングに大きな技術的オーバーヘッド(StrapiやDirectus)が必要である
- WordPress代替ではなく異なる問題のための異なるツールである
■ 5. ホスティングウェブサイトビルダー(Squarespace、Wix、Webflow)
- シンプルなウェブサイトを求める層をWordPressから奪った
- WordPressで苦労したであろう人々にとっては良い選択肢である
- サブスクリプションサービスであり柔軟性が制限されている
- 所有ではなくレンタルである
- プラットフォームがサポートしないことを実行したい場合に行き詰まる
- 月額料金を永久に支払う必要がある
- 異なる市場であり代替ではない
■ 6. 唯一の例外:Shopify
- WordPressから大きな領域を奪った唯一の例である
- 特にWooCommerceから領域を奪った
- 主張的でホスティングされているという特徴で成功した
- サーバー、アップデート、セキュリティ、プラグインの競合について考える必要がない
- 単に商品を販売できる
- テクノロジースタックよりも製品に集中したい商人にとって利便性プレミアムが価値があることが判明した
- 開発者でない場合はeコマースサイトにShopifyが正しい答えであることが多い
- 10年前は真実ではなかった
■ 7. WordPressが勝つ理由
- WordPressの堀はテクノロジーではない
- テクノロジーは最も弱い点である:
- レガシーコードベース
- 時として不器用なプラグインアーキテクチャ
- コミュニティを分断したGutenbergの方向性
- 堀はエコシステムでありその中心はプラグインディレクトリである
- 公式WordPressリポジトリには60000以上のプラグインがある
- 商業的に販売されているプラグインが数千追加で存在する
- SEOツール、eコマース(WooCommerceとその数百の拡張機能)、Instagram表示(Spotlight)、RSSフィード集約(WP RSS Aggregator)、メンバーシップ機能、予約システム、フォームビルダー、多言語サポート、バックアップソリューション、セキュリティ強化、パフォーマンス最適化、アフィリエイト管理、メールマーケティング統合などあらゆる機能のプラグインが存在する
- この部分は新しいプラットフォームが近道できない
- 技術的に優れたCMSは1〜2年で構築できるが20年以上かけて開発された数万のプラグインのエコシステムは構築できない
- WordPressの代替案を評価する際に必要な機能が新しいプラットフォームに存在しないかカスタム開発が必要になる瞬間が訪れる
- その瞬間に戻ってくる
- プラグイン以外の要素:
- WordPressを知っている数百万の開発者
- ワンクリックインストールを提供するホスティング会社
- 20年分のStack Overflowの回答
- 非技術者が実際に理解できるメンタルモデル
- 教育エコシステム(WP Mayor、WPBeginnerなどの数百のブログ、YouTubeチャンネル、コミュニティが無料でWordPressを教えている)
- チュートリアル、レビュー、ガイドの深さが代替案には存在しない
- 午前2時にサイトが壊れた理由を解明しようとする時ほぼ確実にどこかに答えが既に書かれている
- プラグインエコシステムがキラー機能である
- 非開発者がコードを書かずに真に複雑なサイトを構築できる
- WordPressを置き換えるにはすべてを複製する必要がある
- より良いCMSを構築するだけでなくその周りに完全なエコシステムを構築する必要がある
- それには10年と多くの運が必要である
■ 8. AIの影響
- プラグインエコシステムの利点はカスタム開発が高価で遅いために部分的に存在する
- プラグインとして存在しない機能が必要な場合は開発者に支払うか自分でコーディングを学ぶ必要がある
- その摩擦が既存のソリューションを持つプラットフォームに人々を押しやる
- AIがカスタム開発をより速くより安価にしている
- ClaudeやCursorのようなツールで開発者は数日かかっていた機能を数時間で構築できる
- 非開発者がAIアシスタンスで簡単なツールを自分で構築し始めている
- この傾向が続けば「プラグインを使うだけ」という利点は侵食される可能性がある
- WordPressが負けるとは限らない:
- WordPressのオープンで拡張可能なアーキテクチャはAIがオンデマンドでカスタムプラグインを生成できる時にさらに価値が高まる可能性がある
- より新しくクリーンなプラットフォームが不足機能を構築するコストが劇的に低下するためより実行可能になる可能性がある
- 境界線はすでに曖昧になっている
- 確立されたWordPressプラグイン(WP RSS Aggregatorなど)は既存の製品にAI機能を大幅に実装している
- 問題は「WordPressか他のものか」だけでなく「AIを備えたWordPress、カスタムAI駆動アプリ、またはまだ完全に定義されていないハイブリッド」になっている
- 著者はAgentVaniaを通じて中小企業のAIソリューション実装を積極的に支援している:
- 最終的にスタンドアロンアプリになる可能性のあるカスタム統合
- AIをコアに持つWordPressプラグイン
- その他完全に異なるもの
- 今後10年間の技術選択を考える際に完全に予測できない方法で計算が変わる可能性があることを考慮する価値がある
- WordPressとAIの両方に近い位置にいることは合理的なヘッジである
■ 9. 用途別の推奨
- SaaSマーケティングサイト(ランディングページ、価格設定、ドキュメント):
- WordPressは機能するが過剰である
- AstroまたはHugo等の静的ジェネレーターが理想的である(高速、安全、ホスティングが安価、開発チームが製品コードと一緒にGitで管理可能)
- 多くのSaaS企業がこの方向に移行している
- 非技術的なマーケティング担当者が定期的にコンテンツを編集する必要がある場合はWordPressまたはWebflowが適切である
- SaaSアプリケーション自体(顧客がログインする実際の製品):
- カスタムアプリケーション領域である
- WordPressでもCMSでもない
- Laravel、Next.js、Railsなどチームに合うもので構築する
- ダッシュボード、ユーザー管理、コア機能はすべてカスタムコードである
- ブログ(個人または企業):
- WordPressが合理的なデフォルトである
- 使いやすい
- SEOプラグインエコシステム(Yoast、Rank Mathなど)が他の場所で複製するには大きな努力が必要な機能を提供する
- 技術的でミニマルなものが必要な場合はAstroが適している
- メンバーシップとニュースレターが組み込まれている場合はGhostが検討に値する(ただしホスティングはサブスクリプション価格に戻る)
- パンフレットサイト(5〜10ページの典型的な中小企業):
- クライアントが自分で編集する必要がある場合はWordPress
- 真に静的でクライアントが触れない場合はCloudflare PagesまたはNetlifyにデプロイされた静的ジェネレーターがシンプルでホスティングコストがかからない
- 継続的なメンテナンス責任を負いたくない場合はSquarespaceも良い
- アグリゲーターサイト(ディレクトリ、リスティング、求人掲示板、コンテンツキュレーション):
- WordPressのプラグインエコシステムが真に輝く場所である
- カスタム投稿タイプ、Advanced Custom Fields、WP RSS Aggregatorのようなプラグインでゼロから構築せずに複雑なコンテンツ関係をモデル化し外部フィードを取り込むことができる
- 新しいプラットフォームでそれを行おうとするとカスタムコードを書くか機能が単に存在しないことを発見する
- プラグインが提供する以上の重いカスタム機能が必要な場合はLaravelがより良い基盤になるがすべてを自分で構築および維持することにコミットする
- ダッシュボードまたは内部管理パネル:
- 決してWordPressではない
- カスタムアプリケーション領域である
- FilamentまたはLivewireを使用したLaravelが適している
- APIと通信するReact/Vueフロントエンドも適している
- ローコードアプローチが必要な場合はRetoolまたはBudibaseのようなツールが存在する
- eコマース:
- 特定の理由(複雑なカスタマイズ要件、月額料金回避、Shopifyのモデルに合わないB2B使用例)がない限りShopify
- WooCommerceは完全な制御が必要で継続的なメンテナンス負担を処理できる場合に実行可能である
- WooCommerce拡張エコシステムは巨大である
- これが他のWordPressベースのソリューションよりもShopifyに対して優位性を保っている理由の一部である
- メンバーシップまたはオンラインコースサイト:
- LearnDash、MemberPress、Restrict Content ProなどのプラグインとWordPressが確立されたルートである
- 代替案(Teachable、Kajabi、Thinkific)は適しているがサブスクリプションベースでプラットフォームにロックインされる
- 所有権、柔軟性、他のプラグインで機能を拡張する能力が必要な場合はWordPressが勝つ
- メンバーシッププラグインとWordPressエコシステムの残りの部分との統合によりすべてがサイロ化されることなくコースをWooCommerce、メールマーケティングプラグイン、アフィリエイト追跡などと組み合わせることができる
- フォーラムまたはコミュニティサイト:
- BuddyPressまたはbbPressとWordPressは機能するが専用ソリューションと比較して不器用に感じる可能性がある
- Discourseは伝統的なフォーラムに真に優れているが別のホスティングと管理が必要である
- CircleやBBPressおよび同様のプラットフォームはサブスクリプションベースである
- ほとんどの使用例ではプライベートSlack、Discord、TelegramグループがWPでの伝統的なフォーラムの必要性に取って代わった
- フォーマットが流行遅れになった
- ポートフォリオサイト(写真家、デザイナー、作品を紹介するクリエイティブ):
- WordPressまたはSquarespaceの両方が適している
- Squarespaceテンプレートはビジュアルポートフォリオ用に箱から出してより良くデザインされていることが多い
- ポイント全体が美学である場合に重要である
- 技術的な人の場合は優れたギャラリー設定を持つ静的サイトがよりクリーンで高速である
- Instagram中心のポートフォリオの場合はSpotlightのようなプラグインで手動更新なしにフィードを美しく表示することが容易である
- ニュースまたはメディアサイト:
- WordPressが支配的であり僅差ではない
- 公開ワークフロー、編集役割、リビジョン履歴、スケジューリング、広告、分析、ペイウォール、ニュースレター統合用のプラグインエコシステムは一致させるのが難しい
- ほとんどの主要なオンライン出版物はWordPressまたははるかに大きな予算で構築されたカスタムのものを実行している
- 今日メディア会社を始める場合はWordPressを使用しない説得力のある理由が必要である
- 多言語サイト:
- WPMLまたはPolylangとWordPress
- プラグインエコシステムが明確な利点を持つ分野の1つである
- 多言語コンテンツ管理は真に複雑である
- これらの専用プラグインは予想もしないエッジケースを解決するために何年も費やしてきた
- カスタムサイトに多言語サポートを構築するか成熟した多言語プラグインのないプラットフォームを使用することはこれらすべてのエッジケースを自分で再発見することを意味する
- ランディングページまたは単一キャンペーンページ:
- CMSがまったく必要ない場合がある
- Cloudflare PagesまたはNetlifyにデプロイされた単一のHTMLファイルまたはWebflowやCarrdで迅速に構築されたものが正しい答えであることが多い
- AIツールが今や数分で完全なランディングページを生成できる
- 結果は真に良好である
- 3か月間実行されてからアーカイブされるワンページキャンペーンにはWordPressは過剰である
- パターンの出現:
- 非技術者が編集するコンテンツ管理ウェブサイトが必要な場合特に基本的なコンテンツ管理を超える機能が必要な場合にWordPressが勝つ
- プラグインエコシステムによりゼロから始めることはほとんどない
- 独自の要件を持つアプリケーションを構築する場合はカスタムコードが勝つ
- 開発者が管理しパフォーマンスが最重要である場合は静的ジェネレーターが勝つ
- 消費者にオンラインで製品を販売する場合はShopifyが勝つ
■ 10. 著者の息子への選択
- 純粋主義者としては静的サイトジェネレーターを検討した:
- 最初から本物のHTML、CSS、JavaScriptを教える
- 抽象化なし管理パネルなしコードとテキストエディタだけ
- 他のすべての基礎となる基礎を学ぶ
- しかしサッカーについて書いたり旅行の写真を共有したりしたい子供には現実的ではない
- アイデアからインターネット上での公開までの摩擦をできるだけ小さくする必要がある
- そうでなければ最初の投稿を公開する前に興奮が死ぬ
- ホスティングビルダー(Squarespace、Wixなど)も検討した:
- 真に簡単である
- しかしサブスクリプションサービスであり移転可能なものを何も教えない
- それらを超えて成長した場合は最初からやり直す
- 初日からコンテンツを所有してほしい
- より技術的なアプローチも検討に値する:
- Localを使用してWordPressをローカルで実行し静的HTMLに変換しGitHub経由でCloudflare Pagesに公開する
- 利点は年間10ドルのドメイン更新料を支払い続ける限り数十年後もブログが存在する
- 継続的なホスティング料金なしサーバーメンテナンスなしセキュリティ更新なし
- AI生成も現在最速の方法である:
- Claudeのアーティファクトのようなツールが数分で完全で洗練されたウェブサイトを生成できる
- GitHubに保存しCloudflare PagesまたはNetlifyで公開して完了
- 結果は正直素晴らしい
- 両方のアプローチへの躊躇:
- あまり学ばない
- Local-to-staticワークフローはエレガントだが不透明である
- 何が起こっているか理解せずにボタンを押すことになる
- AI生成サイトは自分で何かを構築するプロセス全体をスキップする
- 正直な答えが「AIがこれを作り私はデプロイをクリックした」である場合「私がこれを作った」という魔法が失われる
- 著者はWordPressを選択した:
- 完璧だからではなく若い初心者に適切なバランスを取っているから
- すぐに書いて公開できる
- 何か言いたいことがあることと公に言うことの間のギャップはわずか数クリックである
- その即座の満足感は7歳の時に非常に重要である
- 準備ができたら深さがある
- 投稿を書くことから始めてテーマに興味を持ちその下のコードを覗くことができる
- 天井は何年も超えないほど十分に高い
- スキルが移転可能である
- WordPressの仕組みを理解することはどこでも適用される概念(コンテンツ管理、データベース、ホスティング、ドメイン)を教える
- 最終的に何か他のものに移行してもメンタルモデルは引き継がれる
- 著者がそれを知っている
- 行き詰まったときに助けることができトリックを見せることができなぜ物事がそのように機能するかを説明できる
- 親が教えることができるものを学ぶことには技術的知識を超えた価値がある
- 20年後著者が学んだのと同じプラットフォームを教えている
- それはWordPressの持続力または代替案の欠如またはその両方について何かを語っている
■ 11. 結論と提言
- 開発者またはエージェンシーが移行を検討している場合の正直な答えは移行先がまだ存在しないということである
- WordPressガバナンスについて不安がある場合(合理的である)の実用的な対応はスキルを移植可能に保つことである:
- モダンなPHPとJavaScriptを学ぶ
- WordPress固有の実装だけでなく原則を理解する
- 何かが最終的に出現した場合に準備ができている
- 今日新しいサイトを構築し非技術者が使用できる管理パネルを持つCMSが必要な場合はWordPressが依然として答えである
- もっとエキサイティングなことを伝えたいができない
- 市場のギャップは現実である
- WordPressレベルの使いやすさと成長するエコシステムを持つモダンなオープンソースCMSは真に価値がある
- しかし誰もまだそれを構築していない
- それが機会かもしれない
■ 1. なぜなぜ分析がソフトウェア開発に不適切な理由
- なぜなぜ分析(根本原因分析・RCA・5 Why手法)はソフトウェア開発においてアンチパターンである
- ソフトウェアは平均的に複雑系である
- 複雑系は複雑な方法で故障する
- インシデントや問題に対する単一の因果関係を持つ単一の根本原因はそもそも存在しない
- なぜなぜ分析は単一な根本原因に焦点を当てるために過度または誤った抽象化を行いやすい
- 適用すべきではないというより有害である
- なぜなぜ分析はその特性上人的ミスに帰結しやすい点も問題である
- 超シンプルで小さなソフトウェアには有効かもしれないが現代ではそのようなソフトウェアは存在しない
■ 2. なぜなぜ分析がなくならない理由
- 会社のルールだから:
- 古い会社のルールを見直さず放置している
- 偉い人が言うから:
- 偉い人が学習を怠り過去の自分の成功体験を繰り返している
- 他の方法を勉強していない
- なぜなぜ分析の結果は対外的に説明しやすい:
- シンプルな因果関係やストーリーはわかりやすい
- しかし選択したシンプルな因果関係やストーリーはすぐに破綻する
- また別の理由で次のインシデントが発生する
- 再発防止策がさらに増える
- チェックリストが拡充される
- 無駄な作業ばかりが増え生産性は落ちていく
■ 3. なぜなぜ分析のダメな例(SREをはじめようより)
- システムダウンの事例:
- システムがダウンした
- →サーバーが停止した
- →ディスクがいっぱいになった
- →ログが肥大した
- →ログローテしてなかった
- →設定ファイルが漏れていた(根本原因)→すべての設定ファイルにログローテーションの設定があることを確認という分析
- 問題点:
- 観察した1つの事柄を深く掘り下げる際に他の要因を無視している
- なぜを繰り返す前に何が起こったのかの質問にすべて答える必要がある
- 単一の根本原因に焦点を当てることが失敗から学ぶ上で不利になる
- 明確な因果の連鎖を1つ特定できたと思った時点でインシデントを深く観察することをやめてしまう
■ 4. 根本原因という正解の不在
- インシデントの原因は無数にある
- 複合要因をちゃんと分析すべきである
- 根本原因という用語はすべての背後に1つの真の原因があるように見えてしまう点でダメである
- 現代は唯一解のない正解がいくつもある時代である
- 問題を分析しその問題の正解を外から持ってくるという思考法だけでは通用しない
- 少し前の教育を受けていた世代は優等生主義や正解主義のきらいがある
■ 1. 記事の概要
- SmartHRのプロダクトエンジニアが実装した巨大なSQLにおいて活用したPostgreSQLの機能を紹介
- 一般的な構文の影に隠れがちだが非常に助けになった機能をピックアップ
- ORMだけでは解決できない課題やパフォーマンスチューニングをする際の一助となることを目的とする
■ 2. 複雑なクエリを保守しやすくするための基本
- WITH句とウィンドウ関数の知識:
- CTEとウィンドウ関数は現代的なSQLを書く上で必須
- SQLの自由度は理解度で劇的に変わる
- WITH句CTE:
- SQL内で一時的なテーブルに名前をつけて定義できる機能
- 古いスタイルのSQLではサブクエリをネストして書くことが一般的だったがネストが深くなると内側から外側へ読み解く必要があり脳のメモリを消費する
- WITH句を使うと処理を上から下へ流れるように記述できる
- アプリケーションコードでいう変数や関数に切り出して名前をつける感覚に近い
- ロジックをステップごとに分解して記述できる
- ウィンドウ関数:
- SUMやRANKなどの関数にOVER句を組み合わせることで実現する機能の総称
- 通常のGROUP BYとともに集約関数を使うと行がグループごとに1行に圧縮される
- 個別の明細行は残したいが全体の集計値も横に添えたい場合にウィンドウ関数を使用
- OVER句が出てきたらその手前にある関数がウィンドウ関数というグループに属していると理解すればよい
- 明細行を残したまま集計結果をすべての行に持たせることができる
- SUMは通常は集約関数だがOVERをつけるとウィンドウ関数として振る舞う
- DENSE_RANKなどウィンドウ関数としてのみ振る舞う関数も存在
- 行を集約しない特性がアプリケーションが必要とする複雑なデータ構造を1回のクエリで作る上で非常に重要
■ 3. 任意のIDリスト順にソートする方法
- unnest関数とARRAYとWITH ORDINALITYとCTEのWITH句を組み合わせて使用
- WITH ORDINALITYのWITHはCTEのWITH句とは全く別物
- すでにあるIDのリスト順の通りに検索結果を返したい要件が発生することがある
- WHERE id INのように検索すると返却されるレコードの順序はバラバラになる
- リストが並び替えでしか使われていない場合はarray_position関数を使う選択肢がある:
- array_positionは並び替え済みの値の配列と今の行の値という形式でその値が配列の何番目にあるかを返す関数
- ORDER BYを書くことが可能
- シンプルだがクエリの複数箇所でそのIDリストを使いたい場合は共通化した方が良い
- IDリストが数百から数千件と長大な場合:
- 配列リテラルをクエリのあちこちに埋め込むとSQL全体のサイズが肥大化
- 人間にとって読みにくいだけでなくDBのパーサーに無駄な負荷をかけ通信量も増大
- パフォーマンスの観点でも好ましくない
- unnest関数とARRAYとWITH ORDINALITYを使うとCTEのWITHと組み合わせて記述可能:
- 長大なリストの登場は一回だけで済む
- 長いリストはCTEで一度だけ定義しテーブルとして使い回す
- WITH ORDINALITYを使うと元のデータの横に連番が自動的に付与される
- AS t関数とカラム名でテーブルの別名とカラムの別名を同時に定義する構文を使用
■ 4. JOINで増えた行へマークするDENSE_RANK
- ランキング関数は売上ランキングのような用途が真っ先に思い浮かぶが実務特に履歴管理を含む複雑なデータを扱う場面では違った用途で活躍
- 1対多の1:NのJOINを含む履歴データから最新の1件N行すべてを取得したいケースで使用
- DENSE_RANKは同率順位があった場合番号を飛ばさずに詰めて採番
- 評価完了日が同じであればJOINによって行が増えていてもそれらは全て同率1位として扱われる
- 自分で名付けたrank_numで絞り込みをすれば各社員の最新のプロジェクトを取得可能
- 絞り込みはウィンドウ関数と同じ階層ではWHEREに書けず別のCTEなどで書かなくてはいけない
- DENSE_RANKに類似した関数としてROW_NUMBERやRANKがあるがいずれも採番のルールが違うため今回のケースでは適さない
■ 5. BOOL_ORウィンドウ関数
- グループ内のデータ全体を見渡してどれか一つでも条件を満たせばフラグを立てたい場合やどれか一つでも条件を満たしているグループのみ絞り込みたいケースでよく使用
- PostgreSQLならBOOL_ORをウィンドウ関数として使うことで自然言語に近い形で記述可能
- BOOL_OR論理和という名前の通りパーティション内のどれか一つでもtrueであれば結果はtrueになる
- グループ内のすべてがtrueのときだけtrueを返したい場合はBOOL_AND標準SQLだとEVERYが使用可能
■ 6. ウィンドウ関数に空のOVER関数を使って全体集計
- 通常ウィンドウ関数といえばPARTITION BYで区切って使うものだが何も指定しないことで実現できる便利な挙動がある
- 空のOVER関数とその使い道:
- Webアプリケーションで一覧画面を作る際に必ずと言っていいほど実装するのがページネーション
- 現在のページの20件と全ヒット件数1530件などの両方が必要
- 通常これを実装するには2回のクエリを発行するのが定石
- ウィンドウ関数を使えば1回のクエリで完結可能
- OVERの中にPARTITION BYを書かずに空っぽにすると検索結果全体を一つの大きなグループとして扱える
- パフォーマンス上の注意点:
- クエリの回数を減らせるというメリットがあるが常に最適解とは限らず最適解となることは少ない
- 単純なCOUNTであればインデックススキャンのみで高速に完了するケースでもウィンドウ関数COUNT OVERを使うとテーブル本体へのアクセスが必要になりパフォーマンスが落ちる可能性
- インデックスが効く単純な検索の場合はクエリを2回に分けたほうが速い場合が多い
- 複雑な検索でフルスキャンが避けられない場合は1回で済ませるこのテクニックが有効なことがある
- COUNT OVERはJOINで膨れ上がった重複レコードもすべてカウントしてしまう
- JOINで生まれた重複を除いた純粋な母数が知りたい場合には次に紹介する方法が有効
- ページネーション用にDENSE_RANKの値を使っていたときついでにJOINで膨れる前の件数を出す応用:
- ページネーションの判断基準を作るために既にDENSE_RANKの数値を利用していた場合その数値から全体の件数も出す
- 1人のユーザーが複数の行履歴を持っているデータにおいて全行数ではなく全ユーザー数をベースに1ページあたり10ユーザーのページネーションを実装したい場合
- 単にCOUNT OVERをすると行数分が返ってきてしまう
- LIMIT 10をかけると10行おそらくユーザーが重複し10ユーザー未満の数しか含まれないしか取れない
- DENSE_RANKで振った番号を活用しMAXを使うことでJOIN済みの結果セットが返ってくる状態でも実質のページネーションとともにその母数がいくつかを導出可能
- COUNT DISTINCT user_id OVERでも全ユーザー数は出せるがページネーションの絞り込み用として既にDENSE_RANKを計算していたためその計算結果を再利用するほうがクエリとして無駄がないと判断
■ 7. JOIN済みの結果をJSONにするjsonb_agg
- やむをえずアプリケーション層でほぼ生SQLを書く時にあるあるなのが1対多のテーブルをJOINしてデータを取得した結果行の増幅が発生してアプリ側での再整形が必要になること
- アプリケーション層で必要になる処理:
- DBから大量の行を取得
- forやeachでループを回す
- 1つ前のIDと今のIDをチェックし値が違ったら新しいユーザーオブジェクトを作る
- 値が同じならタグ配列に値をpushする
- IDが変わったかチェックして何かしらを行う処理はコードが複雑になりがち
- 素朴な一対多が一つだけあるならまだ大丈夫だが二重三重に一対多の関係がありJOINされたレコードを頭に入れて再構築するのは大変
- アプリケーションサーバーよりもDBサーバーの方がスケールしにくいためこの手法を嫌う人もいるがDB側でJSONに集約してから値を返してもらうのも一つの手
- json型とjsonb型:
- PostgreSQLにはJSONを扱うためのデータ型としてjson型とjsonb型の2種類が存在
- json型は入力されたテキストをそのまま文字列として扱う型で書き込みは速いが検索や加工のたびに構文解析が必要なため参照は遅い
- jsonb型は入力されたテキストをバイナリ形式に分解変換した型でjsonbのbはbinaryのb
- jsonb型は書き込みは少し遅いが参照や検索が非常に高速でカラムとして追加する場合はインデックスGINを貼ることも可能
- json型を使うのはレアなケースで基本的にはjsonb型を使うと覚えておけば大丈夫
- jsonb_agg集約関数で行を配列に畳み込む:
- 増幅された行を畳み込むのにはjsonb_aggを利用
- GROUP BYで集約された複数の行を一つのjsonb型の配列の値に変換する集約関数
- 集約関数内のORDER BYが重要なテクニック
- これを書かないと生成されるjsonb型の配列の値の中身の順序はランダムになる
- 配列内の順序を保証したい場合関数の中でソート指定を行う必要がある
- アプリケーション側でIDが変わったかどうかを判定するループ処理を書く必要はなくなる
- DBから返ってきたJSONをそのまま利用するだけになりロジックが劇的にシンプルになる
- jsonb_aggは集約結果をすべてメモリ上で構築してから返却するため数万から数十万行といった大量データを1つの値にまとめようとするとDBサーバーのメモリを急激に圧迫する恐れがある
- jsonb_build_arrayでjsonbの配列を作る:
- jsonb_aggが複数行をまとめてjsonb型の配列の値にするのに対しjsonb_build_arrayは指定したカラムや値をその場でjsonb型の配列の値にする関数
- 型合わせのために利用
- ある配列jsonb型と別のID単一の数値をUNION ALLで結合したかったが型が違うとエラーになる
- 単一のIDもjsonb_build_arrayで配列に変換することで強引に型を揃えてUNION ALLした
- データの形式を揃えたい時などに利用可能
- 生成したjsonb型の値に対する検索:
- 生成したjsonb型の値に対して後から検索をかけることも可能
- PostgreSQLのjsonb型は非常に優秀で包含演算子などを使用することで生成後の値に対しても検索可能
- パフォーマンスには注意が必要
- UNIONされた結果やCTEで動的に生成されたJSONデータに対してはインデックスを効かせることができない
- すでに対象件数が十分絞り込まれているコンテキストだったため許容したが大量データに対して無邪気にインデックスの効かない検索処理を行うと事故につながるリスクがある
■ 8. おわりに
- 紹介したテクニックはすべて実際のプロダクト開発におけるとある1つの巨大クエリに詰め込まれたエッセンス
- 無闇に複雑で巨大なSQLを書くことが正義ではない
- ミッションクリティカルな機能や多くの人が頻繁に触れる箇所であれば要件の再検討テーブルの非正規化アプリ側での処理分割などを選んでいた
- プロダクトの開発背景パフォーマンス要件開発速度それらを天秤にかけあえてDB側で完結させることが最適解となる瞬間は存在
- PostgreSQLには強力な機能が備わっていることを知っていただければ幸い
- 最終的に9つのCTEが連なることとなった
■ 1. MySQLのオープンソース性の問題
- 2026年においてMySQLを使用している場合はMariaDBへの移行を検討すべき
- github.com/mysql/mysql-serverへのgitコミット数が2025年に大幅に減少
- MySQLはライセンス上はオープンソースだがプロジェクトとしてはオープンソースではない
■ 2. Oracleによる管理の問題点
- 2009年にOracleがSun MicrosystemsとともにMySQLを買収
- 欧州委員会は競争を抑制する目的があると懸念し買収を阻止しようとした
- OracleはMySQLを維持する約束をしたが良いオープンソースプロジェクトの管理者ではなかった
- コミュニティは長年にわたり衰退
- 開発の問題点:
- すべての開発は非公開で行われる
- 公開されているバグトラッカーはOracle担当者が実際にMySQL開発に使用している本物ではない
- MySQLへの貢献を試みる人々のプルリクエストやパッチ提出は受領としてマークされるがフィードバックはほとんどない
- 変更が次のMySQLリリースに含まれるかどうかは不明で多くの場合書き直される
- gitのauthor/committerフィールドにはOracle担当者のみが記載される
- 実際の著者はブログ投稿で小さく言及されるのみ
- Amazon Web ServicesのRDS MySQLとRDS MariaDBのコアチームのエンジニアリングマネージャーだった際にエンジニアの両方への貢献を監督したがOracleによる貢献の受け入れが悪いためMySQL側への提出を嫌がった
■ 3. MariaDBとの比較
- MariaDBはMySQLの元の作者Michael Wideniusによるフォーク
- すべての開発がgithub.com/mariadb/serverでリアルタイムに行われる
- 誰でもプルリクエストを提出しレビューを受けることができる
- すべてのバグがjira.mariadb.orgで公開討論される
- 真のオープンソースプロジェクトに期待される通りの運営
■ 4. MySQLの技術的衰退
- Oracleは買収後10年以上にわたりMySQL組織を存続させ比較的独立して新バージョンを開発リリースすることを許可した
- MySQL事業は財務的に有用だったと推測されるが少なくともOracleの主要データベース事業を脅かすほど多くの機能を獲得しない限り
- 2022年以降技術的観点から明らかに劣化し始めた
- MySQL 8.0.29の問題:
- デフォルトのALTER TABLEメソッドがin-placeに切り替えられた
- 多くのコーナーケースが機能せずデータベースがクラッシュしデータが破損
- 問題は1年後のMySQL 8.0.32まで完全には修正されなかった
- Oracleが8.0シリーズをevergreenと発表しマイナーリリースで機能と変更を導入した
- ユーザーは歴史的にx.y.Zメンテナンスリリースからバグ修正とセキュリティ修正のみを期待していたため不満
- 新しいメジャーバージョンのリリースが6年間なかった:
- 2018年のMySQL 8.0の後2023年にMySQL 8.1がリリースされたが短期プレビューリリースのみ
- 最初の実際の新しいメジャーリリースMySQL 8.4 LTSは2024年にリリース
- 新しいメジャーリリースにもかかわらずほとんど新機能がなく多くのユーザーが失望
- パフォーマンスの低下:
- 新しいMySQLバージョンでパフォーマンスが低下したという報告が多数
- MySQL性能専門家Mark Callaghanのベンチマークによると書き込み重視のワークロードでMySQL 9.5のスループットは通常8.0より15%少ない
- アップグレードの問題:
- 新しいMySQLバージョンが多くの機能を非推奨にしたため多くのユーザーがMySQL 5.7から8.0および8.0から8.4へのアップグレードで大きな苦労を報告
- 新機能がほとんどなくコードベースのクリーンアップと機能の非推奨に重点が置かれたためOracleがMySQLをかろうじて生かしておくだけと決定したことが明らかになった
- すべての新しい関連機能はOracleのクローズドソースでクラウド専用のMySQL顧客向けサービスHeatwaveに投入
- OracleがMySQLに投資していないことが明らかになりPerconaのPeter Zaitsevが2024年6月にIs Oracle Finally Killing MySQLと執筆
- DB-Enginesによるランク付けでMySQLの人気が急落し始め2026年にはその傾向が加速する可能性
- 2025年9月にOracleが労働力を削減しMySQL担当者が大幅に削減されたとニュースで報道
- MySQLの将来に良い兆候ではなくPeter Zaitsevが11月に最新のMySQLメンテナンスリリースに含まれるバグ修正が以前より少ないことを示す統計を投稿
■ 5. オープンソースの重要性
- オープンソースはイデオロギー以上のものでありソフトウェアのセキュリティと主権に実際の影響を与える
- MySQLが真にオープンソースであるかどうか気にしない人や今後数年間の将来があるかどうか気にしない人がいるが大きなリスクを取っている
- データベースはソフトウェアアプリケーションスタックの最も重要な部分であり運用上の欠陥や問題特にセキュリティ問題は即座に結果をもたらす
- オープンソースでは問題が公開討論され問題が大きいほど多くの人々や企業が修正に貢献する
- オープンソース開発手法は科学的方法に似ており自由なアイデアの流れが常に争われ最も説得力のある証拠を持つものだけが勝つ
- オープンではないことはより多くの不透明性より多くのリスクより多くの信頼してくれという態度を意味する
■ 6. セキュリティ問題の取り扱い
- 2025年だけでMySQLは123件のセキュリティ問題に関するCVEを公開しMariaDBは8件
- 2025年にMySQLのみに影響しMariaDBには影響しなかったCVEは117件
- CVEにはほとんど実際の詳細が含まれていない
- 最新のCVE-2025-53067の例:
- 容易に悪用可能な脆弱性により高権限の攻撃者が複数のプロトコルを介したネットワークアクセスでMySQL Serverを侵害できると記載
- セキュリティ研究者や監査人が元の問題が実際に存在したか修正されたか修正が十分で問題を完全に軽減したかどうかを検証するために使用できる情報がない
- MySQLユーザーはOracleの言葉を信じるしかない
- このようなセキュリティ問題の取り扱いは他のオープンソースプロジェクトとは対照的
- 他のオープンソースプロジェクトでは最初のエンバーゴが終了しCVEが公開された後すべてのセキュリティ問題とそのコード修正が完全な精査のために公開される
■ 7. エンシッティフィケーション
- 真のオープンソースプロジェクトでは見られない様々な形態のエンシッティフィケーションが進行中
- MySQLのソフトウェアドキュメントウェブサイトのすべてがユーザーにオープンソース版の使用を停止しクローズドMySQLバージョン特にHeatwaveへの移行を促している
- Heatwaveはクローズドソースであるだけでなく顧客のデータベースコンテンツをOracleが完全に管理する結果となる
- Redditなどでの話によるとOracleは残りのMySQL顧客から搾り取っており顧客はますます少ないものに対してますます多く支払うことを余儀なくされている
■ 8. 移行の選択肢
- MySQLユーザーの大部分は2010年代半ばに既にMariaDBに切り替えた
- データベースソフトウェアが真にオープンソースであり続けることを深く気にかけた人々が含まれる
- 大規模インストールの例:
- Wikipedia
- FedoraやDebianなどのLinuxディストリビューション
- オープンソースであり統計を収集する中央集権的な機械がないため正確な市場シェアは不明
- アプリケーション固有の統計:
- 世界中のWordPressサイトの57%がMariaDBを実行
- MySQLのシェアは42%
■ 9. 移行方法
- WordPressDrupalMediawikiNextcloudMagentoなどの古典的なLAMPスタックアプリケーションを実行している場合:
- 古いMySQLデータベースをMariaDBに切り替えるのは簡単
- MariaDBはMySQLのフォークでありほとんど後方互換性がある
- MySQLをMariaDBに交換しても既存のコネクタやデータベースクライアントを変更する必要がない
- それらはMariaDBがMySQLであるかのように動作し続ける
- カスタムアプリケーションを実行しデータベースの使用方法と内容を変更する自由がある場合:
- 成熟した十分に機能するオープンソースデータベースが数十ある
- PostgreSQLが最も人気のある一般的なデータベース
- アプリケーションが最初からMySQL用に構築されている場合PostgreSQLへの切り替えには多くの作業が必要な可能性
- MySQL/MariaDBアーキテクチャとストレージエンジンInnoDBは高性能スケーラビリティ堅実なレプリケーション機能が最優先であるオンラインサービスなどで優位性を提供する可能性
- 迅速で簡単な移行にはMariaDBがおそらく最良の選択肢
- Percona Serverへの切り替えも非常に簡単:
- MySQLのすべての変更を密接に追跡しPerconaによる少数の改善によってのみ逸脱
- 基本的にMySQLサーバーのカスタマイズバージョンであるためOracleへの依存を完全に捨てようとする人々にとっては長期的に実行可能なソリューションではない
- MySQLと共通の祖先を持たないがMySQL互換を目指すオープンソースデータベースも複数存在:
- MySQL用に構築されたほとんどのアプリはSQL文を書き直す必要なく単純に切り替え可能
- TiDBの例:
- 非常にスケーラブルで大規模なシステム専用にゼロから設計
- Amazonの最新データベースソリューションDSQLはTiDBから多くのアイデアを借りて構築されるほど優れている
- TiDBは大規模な分散セットアップで真価を発揮するため現在MySQLを使用している大多数の通常の小中規模アプリケーションにとって最も実用的なソリューションはMariaDBへの切り替え
- ほとんどのLinuxディストリビューションでapt/dnf/brew install mariadb-serverを実行するだけでインストール可能
- Oracle以外を選択すれば何を選んでもより良い状況になる
■ 1. Ryan Dahlの発言と背景
- 2026年1月20日にNode.js作者Ryan Dahlが「人間がコードを書く時代は終わった」とXに投稿
- ソフトウェアエンジニアの仕事がなくなるという意味ではなくプログラムのシンタックスを直接書くことがエンジニアの仕事ではなくなったという主張
- Ryan DahlはDeno Land Inc.の共同創業者でありNode.jsに代わる新しいJavaScript/TypeScriptランタイムDenoを開発中
- 投稿は24時間で約300万ビュー2300以上のリポスト11000以上のいいねを獲得
■ 2. 筆者の働き方の変化
- 数ヶ月前まで:
- 自分がコードを書きAIはたまに相談する相手
- 現在:
- AIが運転席に座り自分は助手席でナビゲーションする感覚
- AIは「分身」に近い存在として機能
- 適切な頼み方で十分なコンテキストを与えることで疲労知らずで作業を実行
- 時間をかけてもたどり着けなさそうなバグの原因を一撃で発見することもある
- Opus 4.5の登場が転機となり頼れる相棒分身となった
■ 3. プログラミングのシンタックスを書く必要性の減少
- AIがコードを書くため自分でコードを打ち込む機会が明らかに減少
- 実装プロセス:
- 実装したい機能や修正したいバグについてプランを練らせる
- レビューする
- 実装する
- レビューする
- 同僚の書いたコードをレビューする程度の感覚で信頼できるレベルに到達
■ 4. ソフトウェアエンジニアの役割の変化
- 比重が下がった要素:
- コードを書く部分
- 比重が強まった要素:
- あるべきアーキテクチャの指針を決める
- コードベースからは読み取れないコンテキストを整理し与える
- 期待する挙動を自動的継続的に検証できる枠組みを整える
■ 5. 現在のプログラミングスタイル
- ある機能を実装したい場合の初手で自分からコードを書くことはほぼなくなった
- 作業フロー:
- まずAIにやってもらう
- 自分で手直ししたほうが速いと思ったらエディタを開いて自分で直す
- 変更量が多そうだったらAIにまたお願いして直してもらう
- エディタを開いて自分で直す作業もAIにお願いすることに置き換え可能
- 置き換えた場合人間はもはやコードを書いていないことになる
■ 6. 筆者の認識の変化
- 半年前なら反発したかもしれない発言だが現在の働き方を照らし合わせるとその通りだと認識
- 頭の中にある漠然としたアイデアを信頼できて疲れ知らずの相棒と相談して形にできる状況を楽しんでいる
- 本記事もAIに書いてもらったドラフトを修正加筆して完成
■ 1. Nadella CEOの基本的主張
- 世界経済フォーラムでMicrosoft CEOサティア・ナデラがAIの社会的許可について警告
- AIが人々やコミュニティや国や産業の成果を変える有用なことに使われなければ公共の支持を失うと発言
- エネルギーは希少資源であり健康や教育や公共部門の効率や民間部門の競争力を改善しなければトークン生成にエネルギーを使う社会的許可を失うと指摘
■ 2. 供給側と需要側の課題
- 供給側の課題:
- AI企業と政策立案者はエネルギーとトークンの遍在的グリッドを構築する必要がある
- この作業が現在RAM価格の高騰を引き起こしている
- 需要側の課題:
- 全ての企業がAIを使い始める必要がある
- ナデラはAIを「認知増幅器」や「無限の知性へのアクセス」と表現
- 求職者はExcelのスキル習得と同様にAIスキルを習得する必要がある
- 人々がAIスキルを習得することで実体経済における製品やサービスの提供者として向上すべき
■ 3. 具体例と医療分野での応用
- 医師が患者との時間を増やせる例:
- AIが文字起こしを実行
- 電子医療記録システムへの記録入力を担当
- 適切な請求コードを入力し医療業界全体(支払者と提供者と患者)により良いサービスを提供
- 医療専門家による研究ではAIスクライブ使用で「多大な利益」が報告されているがさらなる研究が必要
■ 4. 懸念と批判的視点
- AIによる盗聴の懸念:
- 予防的ケア訪問をより高価な診断訪問に再分類する理由を探すAI盗聴者の存在
- 米国医療システムの再設計の必要性
- LLMの限定的な応用:
- 汎用LLMがパソコンやインターネットと同程度に革命的であると期待する場合多くのアプリケーションが音声文字起こしやテキスト要約やコードスニペット取得に集約されることは懸念材料
- LLMのエラー傾向:
- 英国警察署長がMicrosoft Copilotのエラーで辞任
- これらの機能を中心に社会を再編成するという考えに懐疑的な理由が存在
- MIT Media Lab研究者による報告:
- 数十億ドルの投資にもかかわらず組織の95%がAI採用からゼロリターンを得ている
■ 5. バブル論への反論と将来展望
- ナデラのバブル論への見解:
- テクノロジー企業のパートナーシップとインフラ支出だけならバブル
- AIが生産性曲線を曲げ資本支出だけでなく世界中で経済成長をもたらすと確信
- 筆者の皮肉的コメント:
- RAM価格が正常化する時期を知りたいという指摘
■ 1. プロジェクト概要
- astroz は最速の汎用SGP4実装でネイティブZigで1秒あたり1100万〜1300万回の伝播計算を実現
- Python経由では約700万回毎秒でpip install astrozのみで利用可能
- GPUを使用せずCPUのSIMD命令のみで高速化を達成
- 汎用実装の定義:
- heyoka.pyは複数衛星の同時バッチ処理で高速だが一般的なODE積分器でLLVMのJITコンパイルとC++依存関係が必要
- astrozは時間バッチ伝播で2倍高速で単一衛星の複数時刻計算に特化
- GPU加速SGP4実装は大規模バッチワークロードで高速だがCUDA/OpenCLセットアップが必要で汎用的ではない
■ 2. SGP4最適化の動機
- SGP4は1980年代からTLEデータから衛星位置を予測する標準アルゴリズム
- 既存実装は元のリファレンスコードの移植版で機能するが高密度時間解像度では遅い
- 実用的な課題:
- 1ヶ月のエフェメリスデータを1秒間隔で生成すると衛星1個あたり260万回の伝播計算が必要
- 地上局ネットワークでの通過予測は数週間にわたりサブ秒精度が必要
- 接近スクリーニングの軌道解析は近接アプローチを捕捉するため細かい時間ステップが必要
- 典型的な良い実装で200万〜300万回毎秒だと衛星1個あたり数秒かかり反復解析やインタラクティブツール構築では遅い
■ 3. 初期最適化とスカラー実装
- SIMD導入前のスカラー実装で既にRust sgp4クレート(最速のオープンソース実装)と同等以上の性能
- 主要な設計選択:
- 分岐のないホットパス:
- SGP4アルゴリズムには多数の条件分岐が存在
- 深宇宙対近地球や異なる摂動モデルやケプラーソルバーの収束チェックなど
- 可能な限り分岐なし表現として記述
- 当初はパフォーマンス目的ではなくコードの理解しやすさのため
- 偶然にも現代CPUが予測可能な命令ストリームを好むため高速化
- コンパイル時事前計算:
- Zigのcomptimeで任意のコードをコンパイル時に実行可能
- SGP4のセットアップ作業の多く(重力定数や多項式係数や派生パラメータ)を一度計算してバイナリに焼き込む
- ランタイム初期化や繰り返し計算が不要
- constでマークした変数は自動的にcomptimeとして扱われる
- スカラー実装で520万回毎秒を達成しRustの500万回毎秒を若干上回る
■ 4. SIMD実装の発見と基礎
- SGP4は状態に依存せず各衛星と各時点が独立しているためSIMDに適している
- ZigがSIMDを第一級市民として扱う設計:
- シンプルな型宣言のみで開始可能
- const Vec4 = @Vector(4, f64)で4つの64ビット浮動小数点数のベクトルを定義
- イントリンシクスやプラットフォーム検出や条件付きコンパイルが不要
- LLVMバックエンドがコード実行環境に適した命令セットを自動的にターゲット
- 組み込み演算:
- スカラーを全レーンにブロードキャストする@splat
- LLVMイントリンシクスを通じた自動ベクトル化された超越関数
- @sinと@cosはLinux x86_64でのlibmvecなどプラットフォーム最適実装を使用
- レーン単位の思考への転換:
- スカラーコードではif文で一方のパスを実行
- SIMDでは全4レーンが同時に実行されるため両方の結果を計算してレーン毎に選択
- 両方のパスを計算することは無駄に見えるが分岐予測ミスより高速な場合が多い
- SGP4では大半の衛星が同じパスを取るため無駄な計算は少ない
- 収束ループの処理:
- SGP4のケプラーソルバーは各結果が収束するまで反復
- スカラーでは許容誤差以下になるまでループ
- SIMDでは異なるレーンが異なる速度で収束
- 解決策はレーン毎に収束をマスクで追跡し@reduceで全員完了を確認
- パターン理解後はスカラー実装を一行ずつ変換し元のコードをテストスイートで比較できるよう保持
■ 5. 3つの伝播モード
- 時間バッチ propagateV4:
- 最も一般的なワークロードに対応
- 単一衛星の複数時点を同時に4時点処理
- エフェメリスデータ生成や通過予測や軌道解析や接近スクリーニングに使用
- 衛星の軌道要素がレジスタに留まり4つの出力を計算するため最もキャッシュフレンドリー
- 最大の初期高速化を実現
- 衛星バッチ propagateSatellitesV4:
- 多数の衛星を1つの特定時点で処理
- 衝突スクリーニングスナップショットやカタログ全体の可視性チェックに使用
- 4つの異なる衛星を同一時点で同時処理
- ElementsV4という異なるデータレイアウトが必要
- 各フィールドがVec4で4つの異なる衛星の値を保持
- コンステレーションモード propagateConstellationV4:
- 多数の衛星を多数の時点で伝播
- ライブデモでは13000個の衛星を1440時点で処理
- キャッシュを意識したタイリング戦略:
- 各衛星の全時点を計算する素朴なアプローチはキャッシュをスラッシング
- 64時点を全衛星で処理してから次の64時点を処理
- 時間値がL1キャッシュにホットな状態で衛星バッチをスイープ
- タイルサイズ64はL1サイズを作業データサイズで割りSIMDフレンドリーな数に丸めたもの
- 大規模カタログでは素朴なループより15〜20%高速
■ 6. atan2問題と解決策
- SGP4のケプラーソルバーはatan2を必要とするがLLVMはベクトル化されたビルトインを提供していない
- スカラー関数を呼び出すとSIMD実装が壊れる
- 多項式近似による解決:
- SGP4の精度要件(モデルに固有の制限がある)では完全な精度は不要
- 引数を[0,1]の範囲に保ち多項式精度を向上
- ホーナー法で計算
- @selectを使用した分岐なしの象限補正
- 多項式近似は約1e-7ラジアンの精度でLEO距離で約10mmの位置誤差に相当
- これはSGP4の固有精度限界内で数日間の伝播では数キロメートルの不確実性がある
- この数学は複雑でAIの支援を受けて実装
■ 7. Struct of Arraysデータ構造
- 複数衛星処理のためStruct of Arraysレイアウトを使用
- ElementsV4構造体:
- 各フィールドがVec4で4つの衛星の値を保持
- 重力モデルや離心率や傾斜角や昇交点赤経などの軌道要素
- 事前スプラット済み定数をinit時に一度計算
- 事前スプラット最適化:
- ホットパスでの繰り返し@splat呼び出しを排除
- 毎秒数百万回実行されるコードでは小さな最適化も重要
■ 8. ベンチマーク結果
- ネイティブ実装比較(Zig vs Rust):
- 1日(分間隔)でastroz 0.27ms対Rust 0.31msで1.16倍高速
- 1週間(分間隔)でastroz 1.99ms対Rust 2.04msで1.03倍高速
- 2週間(分間隔)でastroz 3.87ms対Rust 4.03msで1.04倍高速
- 2週間(秒間隔)でastroz 222ms対Rust 234msで1.05倍高速
- 1ヶ月(分間隔)でastroz 8.37ms対Rust 8.94msで1.07倍高速
- 両実装ともスカラー処理で約500万回毎秒を達成
- Zig実装がRustを若干上回るのはホットパス最適化とcomptimeの積極的な事前計算による
- ネイティブSIMDスループット:
- astroz Zig SIMD実装で1200万回毎秒
- astroz Zigスカラー実装で520万回毎秒
- Rust sgp4で510万回毎秒
- @Vector(4, f64)を使用した複数衛星または時点の並列処理でスループットがスカラー実装の2倍以上に向上
- Pythonバインディング性能:
- 2週間(秒間隔)でastroz 160ms対python-sgp4 464msで2.9倍高速
- 1ヶ月(分間隔)でastroz 5.9ms対python-sgp4 16.1msで2.7倍高速
- Pythonバインディングスループット:
- astroz Python 700万回毎秒
- satkit(Rust)370万回毎秒
- python-sgp4 220万回毎秒
- heyoka.pyとの比較:
- 8衛星×1440時点でheyoka.py 1620万回毎秒対astroz 750万回毎秒
- 1衛星×1440時点でheyoka.py 380万回毎秒対astroz 850万回毎秒
- 100衛星×100時点でheyoka.py 1550万回毎秒対astroz 840万回毎秒
- heyoka.pyは複数衛星バッチで勝利しastrozは時間バッチワークロードで勝利
- ユースケースによる選択:
- 数百の衛星を同時に同一時点で伝播する場合はheyoka.pyが有利
- 個別衛星のエフェメリス生成や通過予測や軌道解析の場合はastrozが2倍高速
- 簡単なデプロイメントが必要な場合はastrozがpip installのみでNumPyのみ依存しheyoka.pyはLLVMとC++スタックが必要
■ 9. 実用的なデモ
- インタラクティブCesiumビジュアライゼーション:
- CelesTrakの全アクティブカタログ約13000個の衛星を処理
- 1440時点(1日を分解像度)で約1900万回の伝播計算
- Pythonバインディング経由で約2.7秒で完了(約700万回毎秒)
- TEME→ECEF座標変換に約0.6秒追加で合計約3.3秒
- ネイティブZigでは1100万〜1300万回毎秒に到達
- 高速化により計算のバッチ処理やスケジューリングを考える必要がなくなり必要な時に必要な計算を実行可能
■ 10. 今後の展望と利用方法
- 今後の開発:
- SDP4実装で深宇宙天体に対応(現在は軌道周期225分未満の近地球衛星のみ)
- マルチスレッド化でコア全体にスケール
- SIMD作業は単一スレッドで実行されており別の倍率が待機中
- 利用方法:
- PyPIで利用可能でpip install astroz
- Zigプロジェクトへの追加はzig fetch --save
- GitHubでオープンソースとして公開
- examplesを参照して統合可能
- ライブデモで動作確認可能
■ 1. 結論と前提
- フリーランスは社員ほどではないが取り組み方次第で今後生き残るためのスキルを獲得するチャンスはある
- 早いうちにフリーランスとして色んな現場に参画することは長期的な視点でメリットがある
- 筆者の報酬は年齢と過去の経歴を加味すると同年代より高くエージェント紹介の単価水準でも高単価の部類
- 9年ほどフリーランスエンジニアとして培った案件選びや面談のスタンスやチームコミュニケーション改善のナレッジを共有
■ 2. チャンスをもらえない構造の否定
- チャンスをもらえないのは選んだ現場とあなたの評価の問題
- 筆者は技術力が高いわけではなく30代に入ってアルゴリズムを勉強し直している最中
- 独立当時はウォーターフォール開発で詳細設計から実装を半年ほどのベビーエンジニアステータス
- しかし現在や前の会社で多数のチャレンジ機会を獲得:
- ゼロイチのプロダクトの初期メンバーに抜擢
- 未経験言語の実装を任される
- エンジニアの採用面談に同席し合否に関わる立場
- 完全未経験なrustの開発に単価を下げず参画
- プロダクトの要になるデータパイプラインの新規構築
- 顧客管理システムリプレイスの技術選定からリリース前までの実装をリードエンジニアとして推進
- 「経験が積みづらくなる構造的な力学」があるなら9年間業務委託のエンジニアOnlyな筆者はもっと厳しいスキルで今を迎えているはず
- フリーランスなら先に鍛えるべき力が不足していたために「チャンスを与えてくれる現場に出会う能力や見せ方ができなかった」
- 「フリーランスとして魅力的なマインドを持っていたわけではない」
■ 3. エージェントの存在が将来を不安にさせる
- ITエージェントという存在のせいでその力を培わずともなんちゃってフリーランスになれてしまう
- 「あなたの年齢とスキルで紹介できる案件がない」と言われた瞬間に自分で案件を開拓することをしなかったエンジニアは窮地に追い込まれる
- 動物園で飼育員がご飯を挙げなかったらどんなに屈強なライオンだって餓死する
- Findy関係者の意見:
- 売り手市場ではなくなってきている状況
- エンジニアが企業のニーズを汲み取りアピールできるかが鍵
- エージェント視点でも売り手市場の陰りとエンジニアが受け身で居続けることの懸念
■ 4. 正社員とフリーランスの比較
- 正社員は待ってても来る可能性があるが望んでなくても来る
- フリーランスは手を上げ続けなきゃ来ないが望んでないなら来ない
- フリーランスが正社員より優れているという主張ではない
- 100%の責任を追う経験や意思決定の場に参列するのは多くは正社員
- 賃貸やローン等の社会的信用は企業のエンジニアには到底叶わない
- 生存戦略的視点で言えば正社員の70から80%程度の役割や権限ならフリーランスにもチャンスはある
- 案件探しや業務への向き合い方次第
- 正社員だろうともあっさり辞める時代
- チームメンバーだし業務委託だろうともっと良いコード書けるようになってほしいなとコストをかけてもいいと思わせる当時のパーソナリティと案件の目利き力がなかっただけ
- 業務委託だって強くなって良いコードが書ければそれがコードとして資産になる
- ノウハウがそのままプロダクションコードとして残るのがエンジニアという職業の良いところ
■ 5. フリーランスにおける成長の定義
- 成長の3要素:
- 案件レベルに直結する技術的成長
- 案件の獲得率につながる営業的成長
- 案件の継続に関わるコミュニケーション的成長
- 営業的なコミュニケーション力とチーム開発で必要とされるコミュニケーション力は別
- ロースキルでまず一番先に身につけるべき優先順位:
- 1: 営業的成長
- 2: コミュニケーション的成長
- 3: 技術的成長
- 営業力の定義:
- お客さんに押し売るゴリゴリなパワーではない
- 日常生活においても役立つコミュニケーションのテクニック的な部分
- 繰り返し実践することで徐々に自分の身体に染み付く
■ 6. 営業力が大事な理由
- 理由1:質の高い案件に入り込めれば他の成長は付随する
- 営業力が上がると高単価の案件に参画できる
- 期待値と能力があっていないので自己研鑽せざるを得ない
- シニアエンジニアの端的なコミュニケーションを理解するために言葉の言い回しや質問の質を上げざるを得ない
- 質の高い案件獲得を目指すことが一番連動して効率よく成長できる環境を手に入れられる
- 理由2:面談が「加点評価の場」になるか「減点評価の場」になるかは営業力次第
- 面談は文字列でわからない人格や雰囲気やコミュニケーションスタイルを把握する大事な場
- 正社員だろうがフリーランスだろうが対面の会話は最も重視すべき
- 技術力が突出していないエンジニアが1時間の面談の中でまず探るべきはセールスでいうところの潜在的ニーズ
- 自分の経歴を語る前にこれを引き出せるかが特に大事
- 採用の目的(求人票)だけでなくブラインドされたチームの課題を引き出せるかで「相手の事を考える回数」がかなり増える
- 限られた数十分のあなたのターンで引き出す必要がある
- 面談が面倒な見極めの場ではなく相手の欠けたピース探しと気持ちよくそのパズルをはめるゲーム感覚で臨める
■ 7. スキルの切り売り問題への反論
- スキルの切り売りになる原因:
- 自分がある意味一番技術力あるチームにいる
- 新しい知識を入れるチーム文化がない
- 背伸びして入った現場じゃない
- 営業行為とは「付加価値」をつける行為
- 営業力がない人は自分を時給4000円で案件を探し実力に見合う仕事しか紹介されず出会えない
- 営業に自信があれば時給5000円や6000円で案件を探すまたは決裁前に値上げ交渉をする
- 今の実力に見合わない仕事を手に入れるチャンスが出てくる
- 上振れであなたに見合わない仕事はつまり伸びしろを与えてくれる仕事
- ダイナミックなスキルチェンジに関わる案件以外は最低時給500円以上は単価アップするような案件を選び続ければ単価が成長の具体値として示してくれる
■ 8. 権限とマネジメント
- 権限について:
- 一部の企業は与えないが意欲のある人でも絶対与えられないなんて事はない
- 高い単価をもらっているとやれるかは別として依頼される確率は高い
- 高い金払ってるんだからやってよ的な思想
- マネジメントについて:
- 別に関われるし人次第
- まとめるのが上手な人なら業務委託がサブリーダー的に使えない正社員の代わりにマネジメントすることはよくある
- 相性悪い人のマネジメントをしたくない
- 「マネジメント経験しました」と語れる実績より優秀な人と働ければその人をマネジメントする必要がない
- 最も良いマネジメントはマネジメントしないこと
- いかに仲間を上手に指揮して動かすかではなくいかにマネジメントしなくていい環境を作るかに注力すべき
■ 9. 意思決定と契約継続
- 意思決定について:
- 関わりにくく社員の人ほど重要な人が集まるMTGには突っ込まれない
- 心血注ぎたいプロダクトに出会ったときに社員になればいい
- 意思決定に関わりたいなら個人開発すればいい
- 個人開発をした経験は案件で関わったプロダクトより自身を持って技術選定やこだわりポイントを語れる
- ある種の営業力強化になる
- 契約継続について:
- すぐ切られるかは人による
- 6年以上同じ現場にいる人もいれば1ヶ月持たず即契約終了される人もいる
- 雇用形態的に切りやすいのは事実だが働きやすくチームにプラスになるメンバーを予算の都合がない限り簡単には切らない
- 切られてしまうならそれはあなたの目利きが悪かった
- この世は等価交換でギブとテイクがマッチする会社を探すべき
■ 10. フリーランスの推奨と戦略
- 20代から30代前半にこそフリーランスを一度くらいは経験するべき
- 早期に複数社の現場経験ができることで多種多様な現場のコードを見ることができる
- コードリーディングがエンジニアにとって一番大事で自分のコードや設計の多様性を広げることに繋がる
- 「3年で1社」と「3社を1年ずつ」では後者の方がエンジニアとしての成長を実感するという経験則
- 労働基準法に守られない立場で数年ワーカホリックに働くという経験をしたからこそ同年代よりは少しいい生活ができている
- スキルフルになってからでないとフリーランスになるのは怖いでは既に今のAIトレンドの時代では遅いこともある
- 雇用形態にかかわらず自分のやりたいプロダクト単位で仕事を選べる力をつければ雇用形態は二の次
- フリーランスになったらできればエージェントを使わずに直契約できる会社を探すという経験もしたほうがいい
- エージェントの問題点:
- 企業の手数料が35%からと高額
- フロントの営業マンの技術理解力はエンジニアほど高くない
- 要望を言ってもマッチする案件が来る可能性は自分で探すより低い
- エージェントガチャもある
- エージェントのフォローがなくても案件を獲得できるという成功体験はAIによるジュニアからミドルエンジニア供給過多問題を乗り越えるために必要かもしれない
- 中間マージンも減ってお互いWin-Win
■ 11. まとめ
- チャンスはあり参画する案件とあなたの能力次第
- フリーランスは本来先行して身につけるべき能力は営業力
- あなたの単価は任されるチャンスの範囲
- 雇用形態関係なく「人としての相性」がまず大事
- エージェント使わずに直契約取れるかチャレンジ
■ 1. 議論の構造
- IT業界においてWeb系とSIerを比較する議論は長年繰り返されている
- 多くは技術的優劣という形で語られている
- 議論の中心は技術そのものではなく認知の歪み
- ITのにわか層においてWeb系は技術的に優位でSIerは劣位であるという単純化された幻想が強固に信じられている
- 議論の対象は技術文化ではなく人事文化とマネジメント構造そしてそれを誤認する人間側の認知メカニズム
■ 2. 技術は個人にしか宿らないという前提の欠落
- 技術は組織や業界に自動的に蓄積されるものではない
- 個人の思考と試行錯誤の結果として身につくもの
- この前提が抜け落ちた瞬間「場所に行けば技術が身につく」という誤解が発生
- Web系というラベルがあたかも技術力を付与する魔法の環境であるかのように語られる
- 実際には考え続けた人だけが技術を獲得し考えない人はどこにいても何も残らない
- 技術は人に宿る
- 環境は確率を変えるだけ
- 自動付与は存在しない
- この三点を無視した議論はすべて幻想
■ 3. 人事文化やマネジメント文化との混同
- Web系とSIerの違いは技術文化ではなく人事評価の軸とマネジメントの設計思想
- Web系の特徴:
- アウトプットが短い周期で可視化される
- 個人の成果が評価に直結しやすい構造
- SIerの特徴:
- 分業と調整が前提
- 説明責任や役割遂行が評価の中心
- にわか層の誤認:
- 評価軸の違いをそのまま技術力の差と誤認
- 評価構造、役割設計、責任分散というマネジメント上の差異が技術文化の差として誤変換されている
■ 4. 可視性バイアスと生存バイアス
- Web系の可視性:
- 成果物が外部に公開されやすい
- GitHubや技術ブログなどを通じて技術的アウトプットが目に入りやすい環境
- 可視性の高さが「Web系には優秀な技術者が多い」という印象を強化
- 実態との乖離:
- 単なる観測可能性の問題であり実態の分布とは一致しない
- 技術的に尖った人が目立ちやすくそうでない人が視界から消えやすいという偏り
- 認知バイアスの構造:
- 可視性、選択的観測、生存者偏重という認知バイアスが幻想を補強
■ 5. 経済合理性と人材分布の現実
- 人材分布の決定要因:
- 人材の分布は理想論ではなく経済条件によって決定
- 高い給与、安定した雇用、大規模な採用母集団を維持できるのは大企業
- 日本の現実:
- 大企業の多くがSIer側に存在
- 優秀な人材の絶対数はSIerに多く集まる
- Web系の限界:
- 密度では優れて見えても人数と資金力の差を覆すことはできない
- 現実要因:
- 給料水準、会社規模、知名度、母集団サイズが最終的な人材分布を規定
■ 6. SIerが人をだめにする構造とその誤解
- SIerの構造的問題:
- SIerという組織が多くの人をだめにしてしまうのは事実
- 技術文化が劣っているからではない
- 技術を深く考えなくても生存できるレーンを大量に用意しているから
- 構造の特徴:
- 人を選別しない代わりに人を鍛えもしない
- 成長しない人が大量に残る
- 外部からは「技術的に弱い集団」に見える
- 誤解の構造:
- 構造的温存、非選別性、成長不要ルートという特徴が文化論として誤って語られている
■ 7. にわか層が幻想を欲しがる心理
- 心理的動機:
- 裏技への期待と自己正当化の欲求
- 努力や思考を積み重ねるよりも正しい場所に行けば解決するという物語は非常に魅力的
- 自身の立場を誇るあるいは嘆くためのポジショントークとして文化論は便利
- 議論の性質:
- 真偽は重要ではなく感情の整合性が優先される
- 幻想を必要とする動機:
- 裏技願望、責任転嫁、自己物語化
■ 8. 「技術文化」という幻想上の言葉
- 本来の意味:
- 技術文化という言葉は本来思考の深さや問題解決姿勢を指すはず
- 現実の使われ方:
- 単なる業界ラベルや雰囲気の話に矮小化されている
- Web系という言葉に付与される先進性のイメージが技術文化と短絡的に結びつけられる
- 問題点:
- 概念の乱用であり議論の精度を著しく下げる
- 概念混同、ラベル依存、定義不在が誤った理解を固定化させている
■ 9. まとめ
- ITのにわか者がWeb系をSIerより技術的に優位だと信じる理由は技術の問題ではない
- 原因の構造:
- 個人要因を無視
- 評価構造を誤認
- 認知バイアスに流される
- 経済合理性を見落とした結果
- SIerの実態:
- 多くの人をだめにする構造を持っている
- それは所属する人間の技術の低さを意味しない
- Web系の実態:
- 強く見えるのは密度と可視性の問題
- 分布全体を見ればどっこいどっこいに収束
- 根本的な真実:
- 技術は個人に宿る
- 人は金と規模に集まる
- この二点を直視しない限りこの幻想は繰り返され続ける
■ 1. 根本的な自己矛盾
- セクション2では「技術は個人にしか宿らない」「環境は確率を変えるだけ」と主張
- セクション6では「SIerという組織が多くの人をだめにしてしまうのは事実」と主張
- 環境が人をだめにするほどの決定的影響力を持つなら技術は個人に宿るという主張は崩壊する
- 著者は自分で設定した前提を自分で否定している
■ 2. 証拠の完全な欠如
- 記事全体が著者の印象と推測のみで構成されている
- 証拠が欠如している要素:
- にわか層が実在するという証拠
- その幻想が広く存在するという調査データ
- Web系とSIerの技術力分布に関する実証的データ
- すべてが断定形で書かれているが根拠は示されていない
■ 3. 藁人形論法
- にわか層という架空の敵を設定しその愚かさを論じる構造
- 問題点:
- 誰が実際にそのような主張をしているのか不明
- その主張がどの程度広まっているのか不明
- 批判対象が具体性を欠き著者の想像上の存在である可能性が高い
■ 4. 論理的飛躍
- セクション5の論理は大企業はSIer側に多いため優秀な人材の絶対数はSIerに多いというもの
- 成立しない理由:
- GoogleやMetaやAmazonなどの巨大Web系企業の存在を無視
- 給与だけで人材分布が決まるという単純化
- 優秀の定義が不明確
- 大企業の数と採用規模の関係が検証されていない
■ 5. 定義の曖昧さ
- 批判的検討に耐える定義が一切存在しない
- 曖昧な用語:
- にわか層とは誰か
- Web系とSIerの境界はどこか
- 技術力をどう測定するのか
- 優秀な人材の基準は何か
■ 6. 可視性バイアスの誤用
- 著者自身が可視性バイアスを指摘しながら自分の主張も可視性バイアスに基づいている
- SIerが人をだめにするという認識自体が問題のある事例が目立ちやすいという可視性バイアスの産物である可能性
- 自分が批判する認知の歪みを自分自身が犯している
■ 7. 結論の不在
- タイトルはなぜ幻想を抱くのかだが記事は以下に答えていない:
- その幻想が本当に存在するのか
- 存在するとしてそれが問題なのか
- 著者の主張であるどっこいどっこいが正しいという根拠
- 技術は個人に宿るや人は金と規模に集まるという結論は最初の問いとは無関係
■ 8. 総評
- 記事は議論の体をなしていない
- 著者はにわか層を批判しているが自身の主張こそが根拠のない思い込み論理的矛盾藁人形論法に満ちている
- 真剣に論じるために必要な要素:
- 実証的データの提示
- 用語の厳密な定義
- 論理的一貫性の確保
- 自己矛盾の解消
- 現状では主張したいことを先に決めてそれらしい理屈を後付けした印象論に過ぎない
I/Oの負荷分散の話。
書き込み側の負荷分散。
DB1台のノードで書き込みがサチるなら、2台→4台→8台とノードを増やしてデータを書き分ける(シャーディング)。
読み込み側の負荷分散。
同じデータを読みたいクライアントが多いなら、そのデータを別のDBノードにコピーして配って読ませる(リプリケーション)。
RDBでやるなら、Writer : Read Replica = 1 : N のクラスタを複数台用意する構成になる。ただし、データのヒントに基づいてどの Writer を選ぶかは開発者の責任。当然、クラスタをまたいだ SELECT JOIN もできない。ソシャゲは基本これ。
クラスタが増えたときのリハッシュも「気合いで頑張れ」になる。運用負荷はかなり高い。体制があれば別にこれでもいいけどね。
まぁ、これはスタートアップではマジで無理っす、って話になることが多いので…… 書き込みも読み込みもそれなりあるなら、前段に DynamoDBなどを置いてCDCを介して、後段の DB クラスタにゆっくり書く構成にすることが多い。
そう、これはほぼ CQRS / Event Sourcing のことなんだよな。書き込みのシャーディングは DynamoDB が自動でやってくれるし、めちゃくちゃ安定的に捌ける。
jQuery開発チームは、10年振りのメジャーバージョンアップとなる「JQuery 4.0」正式版のリリースを発表しました。
ちなみに2026年1月は、最初のバージョンのjQueryが2006年1月にはじめて公開されてからちょうど20周年に当たります。
OOP はくそ,DDD はムズい,GoF は古い,Next.js はでかい,React は難しい,仮想 DOM はクソ,静的型付けじゃない言語はクソ,TS の型は弱い,SPA が良い,every/some の単位元,IEEE 754 の不可解な計算に驚き,OSS は儲からない,ならお前がやれは意味無い,はてブコメントはクソ,休日に勉強は必要か,などずっと同じ話しかしてない
■ 1. AIがプロダクトに与える変化の認識
- AIがプロダクトを大きく変えると感じ従来と何が違うのかが気になってきた
- 投資家として海外を含むスタートアップやプロダクトを見る機会が増える中でAIを前提に設計されたプロダクトには従来とは明らかに異なる成功パターンがあるように感じている
- AIが中心となるプロダクトの設計には完璧な仕様を追い求める従来の手法とは異なる新しい姿勢が求められている
- プロダクトを完成させるのではなく変化し続ける前提で設計するという姿勢が必要である
■ 2. Cursorの事例とAIネイティブ設計
- AIコードエディタとして登場したCursorはVS Codeという巨大な既存プロダクトが存在する市場においてまたたく間に支持を集めた
- VS CodeにもGitHub CopilotをはじめとするAIサービスのアドオンを追加することはできAI機能そのものは利用可能だったにもかかわらずである
- Cursor以前のアプローチ:
- 既存のエディタにAIアシスタントを追加するというものだった
- これは従来のプロダクト開発の延長線上にある発想である
- すでに完成されたプロダクトが存在しそこに新しい機能を付け加えるという考え方である
- Cursorのアプローチ:
- AIがコアにあることを前提としてゼロからエディタを再設計した
- AIは追加された機能ではなくプロダクトの中心的な存在である
- リポジトリ全体をセマンティックにインデックス化し複数ファイルにまたがる変更を生成し開発者の意図を理解して自律的に行動する
- これはAIが完璧に機能するという前提に立ちワークフロー全体を再構築した結果である
- このCursorのアプローチが有効であることはその後GoogleがAntigravityという形で追従したことからも明らかである
■ 3. 決定論から確率論への転換
- AIネイティブプロダクトでは従来の仕様設計が限界を迎える理由の整理が必要である
- AIを機能として追加するのではなくプロダクトの中心に据えるという設計への転換が起きている
- この変化を一言で言えば設計対象が変わったということである
- ソフトウェアが決定論的な存在から確率論的な存在へと変わったことによって起きている
- 従来のプロダクト設計:
- 振る舞いを固定した完成物を設計する仕事だった
- 入力と出力の関係を定義し想定される状態やユーザーフローを網羅し意図した通りに動作することを保証する
- その前提にあるのはソフトウェアは設計者の意図通りに振る舞うべきだという考え方である
- 生成AIを中核に据えたプロダクト:
- 設計する対象は完成物ではなく学習し続ける存在になる
- プロダクトはリリースされた時点で完成するのではなく利用される中で振る舞いを変え進化し続けることが前提となる
- 学習し続ける存在とはどのデータを集めどの文脈でAIに渡しどのフィードバックを次の振る舞いに反映させるかという一連の仕組みを指す
- 設計対象の変化は単なる機能や実装の差ではない
- Cursorが示したのはプロダクト設計における根本的なパラダイムシフトである
- 従来のプロダクトは完成させて出荷するものだった
- 生成AIを組み込んだプロダクトはリリース後に学習し続ける生態系として設計される
■ 4. 変わる人間の役割
- テックリードやプロダクトマネージャーが何をすればよいのかという問いがある
- 答えは完璧な仕様を書くことではない
- 良い方向に学習する構造を設計することそしてプロダクトを進化させる仕組みを整えることである
- プロダクトはもはや完成させて出荷するものではない
- プロダクトはリリース後に学習し続ける存在である
- 人間の仕事はこの生態系が健全に進化するための構造を設計することである
- プロダクトマネージャーの役割の変化:
- 従来のプロダクトマネージャーは機能の門番だった
- どの機能を作るかどの順番で作るかどのように作るかを決める存在だった
- AIネイティブプロダクトを担当するプロダクトマネージャーは学習システムの設計運用責任者である
- 具体的にはAIモデルそのものを鍛えるのではなくどのデータや文脈を与えるかどのフィードバックを取り込みどの振る舞いを強化抑制するかといった学習が回る構造そのものを設計運用する役割を担う
- ここでの学習はモデルの再学習を意味しない
- 多くのAIネイティブプロダクトは自らモデルを開発していない
- モデルを持っている場合でも有料プランの利用ユーザーデータを直接モデル学習に使わないことがほとんどである
- それでもプロダクトは使われるほどに振る舞いを変えていく
- その違いを生むのはモデルの外側に設計されたデータ文脈履歴フィードバックの構造である
- つまりプロンプトなどのAIへの指示方法でありAIに参照させるデータとしてのコンテキストである
- 技術的にはRAGであったりMCPであったりする
- AIネイティブプロダクトでは前提条件が変わる
- 振る舞いを完全に制御できない以上問われるのは個々の機能ではなく学習がどう回りどう修正されるかという構造そのものである
- 人間に求められるのは何を作るかを細かく決めることではない
- AIがどのように振る舞いを変えていくのかその前提となる構造を設計し方向を調整し続けることである
■ 5. AIネイティブプロダクトにおける学習
- 人間が設計すべき構造が実際のプロダクトの中でどのように形になっているのかを見る必要がある
- AIネイティブなプロダクトにおいて人間がどこに介在し何を設計しているのかという問いがある
- AIネイティブエディタの例:
- リポジトリ全体がセマンティックにインデックス化されコードは単なるテキストの集合ではなく意味を持つ構造として扱われる
- 開発者がどのような編集を行ったかどの提案を受け入れどの提案を拒否したかといった利用の痕跡が継続的に蓄積される
- 重要なのはこれらが単なるログではなく次にAIを使う際の入力文脈として再利用される点である
- どの情報を参照させるかどの履歴を重ねるかといった判断は人間が設計した前提に基づいて行われる
- ここで起きているのはAIの中身が変わることではない
- 固定されたモデルはそのままにどの情報を参照させどの履歴を重ねどのフィードバックを次に活かすか
- その積み重ねによってプロダクト全体の振る舞いが変わっていく
- AIネイティブプロダクトは学習し続ける存在として設計されている
- 利用のたびに得られるデータが次の振る舞いに影響を与える
- モデルを自ら開発しないプロダクトであっても学習する構造を内包することは可能である
- この構造をどう設計しどう運用するかこそが人間に委ねられた最も重要な仕事である
- 超ざっくりとした設計イメージの例:
- AIが出した修正提案に対して開発者が採用したか拒否したかをログとして残す
- そのログを用いて次回以降の提案時に採用されやすい修正パターンを優先的に提示する
- 繰り返し拒否される提案パターンについてはルールやプロンプトを調整し出力されにくくする
- 重要なのは精度の高いアルゴリズムではない
- 提案から選択から次の提案に反映という学習のループが意図した方向に回るよう設計されているかどうかである
■ 6. データ設計における蓄積から循環への転換
- 学習し続ける存在をどのように作り上げていけばよいのかという問いがある
- 鍵となるのはデータである
- ただし生成AI時代において問われているのはデータの量ではない
- 従来のデータの価値:
- 蓄積にあった
- どれだけ多くのデータを集めたかどれだけ詳細な情報を記録したか
- データウェアハウスに大量のデータを保存し分析ツールで可視化する
- これがいわゆるデータ駆動型の意思決定だった
- 生成AI時代におけるデータの価値:
- 循環にある
- データは集めただけでは価値を生まない
- 利用され学習に回されAIの振る舞いを変えその結果として新たなデータが生まれる
- この循環が回って初めてデータは資産になる
- フィードバックループの設計こそがAIネイティブプロダクトの成否を分ける
- AIを導入してもフィードバックを回収せず学習に活かさなければプロダクトは賢くならない
- その結果プロダクトは学習する生態系ではなく固定されたツールのままにとどまる
- この循環が回り始めたときそれは強力な競争優位性となる
- 他社が容易に模倣できない独自のデータと学習ループがいわばデータモートとして機能する
- 生成AI時代においてはソフトウェアそのものの差別化は急速に難しくなっている
- AIがコードを書き機能実装の大部分を肩代わりしてくれるようになったことでソフトウェア開発の再現性は飛躍的に高まった
- オープンソースモデルや汎用APIの普及も相まって技術的な障壁は大きく下がっている
- 誰でも一定水準のAI機能を備えたプロダクトを作ることができるようになった
- だからこそ差別化の源泉はデータに移る
- ただし重要なのは独自のデータを持っているかではない
- そのデータを学習に回し改善のループを回し続けられているかどうかである
- 多くの企業はすでに独自のドメイン知識とデータを持っている
- 日本企業も例外ではない
- 問題はそれらが十分に循環していないことである
- 生成AIを既存業務に部分的に導入するだけではこの循環は生まれない
- プロダクトそのものをAIネイティブな前提で再設計する必要がある
- 新興企業の戦略:
- フィードバックループをできるだけ早く回すことである
- データの量が少なくても利用と改善の循環を高速に回すことができればAIは急速に賢くなる
- AIが賢くなればユーザー体験が向上しユーザーが増える
- ユーザーが増えればデータが増える
- この好循環がやがてデータモートを形成する
- Cursorの成長はそのことを端的に示している
- 独自データをすでに持っている企業にとってもフィードバックループを早く回すという考え方は同様に重要である
- 派手な先行事例が出そろうのを待っていては競争優位性は築けない
- 自社の事業にAIを組み込みAIネイティブなプロダクトへと転換していく
- そのための第一歩がデータを蓄積ではなく循環として設計し直すことである
- 重要なのはフィードバックの量ではなく向きである
- 誤ったシグナルを回せばプロダクトは高速に劣化する
- 人間は学習が向かう方向に最低限のガードレールを引く必要がある
- フィードバック設計の例:
- どの提案を評価対象とするのかどの操作を良いシグナルと見なすのかを最初からすべて自動化しようとしない
- 初期段階では人間が明示的にこれは良いこれは悪いと判断するポイントを絞り込む
- 学習が誤った方向に進まないよう制御する
- フィードバック設計とはそのための最小限の安全装置である
■ 7. AIネイティブプロダクトはAIネイティブな組織でしか作れない
- この話は技術の話だけではない
- 学習システムは個人の工夫や一部のチームの努力だけでは成立しない
- AIネイティブなプロダクトはAIネイティブな人と組織でなければ作れない
- 見た聞いた調べた範囲ではプロダクトに関わる人間がAIを理解していない組織でAIネイティブなプロダクトがうまくいった例はない
- AIネイティブ組織の特徴:
- 会議の中でこの挙動はモデルの限界なのかそれともコンテキストやデータ設計の問題なのかを議論できるかどうか
- KPIについても機能が予定通り完成したかではなく学習のループが回り振る舞いが改善したかを問う指標に置き換えられているか
- こうした具体的な問いが日常的に交わされているかどうかがAIネイティブ組織かどうかの分かれ目になる
- 論文を読めという話ではない
- 実際に使い自分の手で試し失敗し挙動の癖を体感しているかどうかが重要である
- AIをブラックボックスとして扱ったままでは学習する構造を設計することはできない
- 作る経験も欠かせない
- モデルを自作する必要はないがプロンプトやコンテキストデータの与え方ひとつで振る舞いが大きく変わることを身体感覚として理解している必要がある
- AIネイティブプロダクトとはAIを前提に思考し設計し試行錯誤できる人間によってのみ生み出される
- 意思決定の速さが何より重要である:
- 生成AIの進化は極めて速い
- 半年待てば状況は一変する
- このスピードに追いつくためには完璧な検討や合意形成を待っている余裕はない
- 試し学び修正するそのサイクルを回し続けられるアジリティの高い人と組織でなければAIネイティブな競争には参加できない
- これは組織の規模の問題ではない
- 大企業であろうとスタートアップであろうと条件は同じである
- AIネイティブプロダクトを作れるかどうかはAIネイティブな人と組織になれているかどうかで決まる
■ 8. 結論
- プロダクト設計とはもはや機能や画面を設計する仕事ではない
- 変化し続ける前提に立ち学習が回り続ける構造とそれを回し続けられる人と組織を設計する仕事である
- あなたのチームはどこまで機能の設計から学習する構造と組織の設計へと軸足を移せているだろうかという問いかけがある
誰も思い出さないが、東大入試を解くAIの研究開発に失敗した挙げ句、適当に哲学的にでっちあげた人間の教育論を振りかざして研究失敗を煙に巻いて、「私は研究に失敗しないんですよ」とうそぶいていた例のあの研究者、元気かな。
しかし、Geminiが共テを制覇するレベルになると、果たしてこの共テとかいう「茶番」はいつまで続けられるのか。生徒側の方がモチベがなくなるだろうに
世界のすごいプログラマは個人ホームページでロングテールに発信をしていることが多い。これはユーザー投稿タイプのサービスの寿命よりも自分のキャリアの方が確実に長くなるためです。(世界的にdevtoやmediamの没落が例)
個人的にはこのトレンドをめちゃくちゃ支持しています。
うほうほ!(鳴き声)
■ 1. 問題提起と背景
- コードレビューにおいて素通しでApproveしてしまう状況が多く発生している
- 思考停止でのApprove実施はレビュープロセスの形骸化を招く
- 主な要因として理解不足・権威への盲従・時間不足の3つが存在する
■ 2. ケース別対処法
- 正直理解できない場合:
- スキルセット不足による理解不能:
- 素直に質問コメントを残す
- 勉強不足を恥じる必要はない
- 質問により自身の知識増加と実装者の見直し機会創出という2つのメリットが得られる
- シニアエンジニアのコメントを観察し新たな視点を取り入れる
- PRの目的理解不能:
- 実装者の説明不足である可能性が高い
- チケットリンクや背景説明の追記を依頼し差し戻す
- 変更量過多による本質的変更の理解不能:
- PR分割を指摘することで適切なレビューを実現する
- 無理に全部読まずPR粒度の改善を求める
- 自分より知識がある人が実装している場合:
- 権威バイアスは即座に捨てるべきである
- 凄腕エンジニアでもタイポや削除漏れは発生する
- 高度すぎる複雑さは運用負債となる可能性がある
- 難しいと感じた場合は可読性向上を提案する
- レビュー時間を取ることができない場合:
- コードレビューは品質担保のための正式な業務である
- コンテキストスイッチコスト削減のためレビュー時間を固定化する
- 急ぎでなければ朝一番での実施が効果的である
■ 3. レビュー依頼側の心がけ
- タスク・実装の細分化:
- PR変更行数の最小化がレビュアーの心理的ハードル低下につながる
- 小さなPR複数回の方がトータルマージ時間は短縮される
- 機能追加とリファクタリングの分離など工夫が重要である
- 自己レビューの徹底:
- Files changedタブでの変更内容確認によりデバッグコード残存等を発見できる
- 実装時の判断理由をコメントとして事前記載する
- レビュアーの納得感向上と前提勘違いの早期発見につながる
- Descriptionに背景・目的・テスト結果等の証跡を明記する
- 実装者としての責任意識:
- 一番理解しているのは実装している自分であるという矜持を持つ
- レビュアー頼みではなく自信を持ってPRを出す
- 実装の端々に責任感の有無が現れる
■ 4. 現代のレビュー環境
- ツール活用による負担軽減:
- LinterのCI実行による文法チェック自動化
- PolicyAgentによる組織ルール遵守の自動化
- AIレビュー導入によるコスト削減
- ツールでコスト低減可能だが人間レビューで担保できる品質は必ず存在する
- AI進歩に伴う課題:
- 大規模PR増加による確認負荷上昇
- 意図不明のままPR提出されるケース発生
- AI盲信による品質低下リスク
- 人間レビュー対象と自動チェック対象の分離が必要
- 実装前の設計・方針レビューの重要性増大
- 思考履歴の言語化と記録が重要
■ 5. 結論
- わからないことを質問するのは恥ではない
- 間違いを指摘するのは失礼ではない
- 思考停止Approveを止め一言でもコメントを入れることから開始する
- 小さな一歩が自身とチームの成長につながる
■ 1. マスタ管理の拡張性
- 疑問の提起:
- シングルテーブル設計はスケールが容易なDynamoDBなどのNoSQLで定番な方法でRDBであるPostgreSQLで耐えられるのだろうか
- マスタが巨大化すると詰むのではという疑問
- 結論:
- 特に問題はない
- 理由:
- RDBはスケールしないと言っても数十万件くらいなら余裕で捌ける
- 前編で説明した全マスタをまとめて取得するのはどこかで限界が来るけど取得時にMetadataによるフィルタリングをすれば適切に絞り込みが可能
- 運用が続いて規模が大きくなったら無理が出るのは仕方がない問題が出たときにリファクタすれば良い
- そもそも肥大化するデータはもはやマスタとして扱うのは正しくなくトランザクションとして扱うべき
- 大抵なんとかなるしなんとかならなかったらトランザクションに寄せればいいよね
■ 2. 普通のリレーションの問題点
- 通常のアプローチ:
- トランザクション用のテーブルを作る
- マスタのcodeを外部キーに持たせる
- JOINしてトランザクションと紐づくマスタをセットで取得する
- 問題点:
- マスタがトランザクションに拘束されることになる
- 前編で実現した柔軟なマスタの変更が封印されてしまう
- 考え直す必要がある
■ 3. トランザクションをマスタから自律させる
- 問題の本質:
- マスタが変更されると古いマスタ情報が消えてしまうのが問題
- 解決策:
- トランザクションの中に必要なマスタの情報をコピーしてまとめて保存する
- この単純で分かりやすい力技はとても効果的
- マスタがどれだけ破壊的に変更や削除されてもトランザクションデータは当時の姿のままで生き残り続ける
- 手法の名称:
- こういった手法は一般的にスナップショット・パターンと呼ばれている
■ 4. DynamoDBの採用理由
- PostgreSQLでの限界:
- PoCなどの大きくスケールしないケースであればトランザクションもマスタと同じようにJSONBでPostgreSQLの1つのテーブルに保存しても問題ないかもしれない
- 仮にもトランザクションなので一般的なアプリであれば使っているうちにデータは増え続ける
- しかもマスタのデータをトランザクションにコピーするのでデータ量も増える
- スケールできるように考えるべき
- DynamoDB採用の利点:
- スケーラビリティ: トランザクションデータは増え続けPostgreSQLでも数十万件程度なら問題ないが数百万件や数千万件となるとシンプルに扱うことが困難でDynamoDBなら自動的にスケールするためこの心配がない
- 書き込みパフォーマンス: トランザクションは頻繁に書き込まれDynamoDBであればキーバリューストアとして高速な書き込みに最適化されている
- アクセスパターンが明確: トランザクションは通常特定のキーで検索されDynamoDBはアクセスパターンが事前に定義できる場合に最高のパフォーマンスを発揮しマスタのような自由な検索は不要
- 使い分け:
- 検索性が必要なマスタ管理ではPostgreSQLを採用
- スケーラビリティが重要なトランザクションではDynamoDBがよさそう
■ 5. ルーズなSQLと厳格なNoSQL
- PostgreSQLでのマスタ:
- スキーマレスなJSONBで何でも受け入れる
- 構造の変更が自由
- 整合性チェックはアプリ側に任せる
- ルーズで柔軟
- DynamoDBでのトランザクション:
- スナップショット・パターンで当時の状態を厳格に保存
- 一度書き込んだら変更しないでイミュータブル
- データの整合性は書き込み時点で確定
- 厳格で不変
- 設計思想:
- マスタは変わるものだから変更に強い柔軟な設計にする
- トランザクションは変わらないものだから厳格に保存して整合性を保つ
- 一見しただけだとRDBとNoSQLに求めるものが逆転しているように見えるかもしれないがデータの性質に合わせてDBの使い方を考えればこの設計も自然に見えてくる
■ 6. 正規化についての考察
- 正規化を避けてきた理由:
- 正規化や非正規化に囚われずにゼロベースで考えデータをありのままに扱いたかった為
- 正規化の目的の歴史:
- 正規化理論が確立された50年前の状況を振り返る
- ストレージが高価だったためコストの観点からデータの冗長性排除が必須だった
- 更新処理が重かったため更新回数を最小限にする設計が必須だった
- トランザクション処理が複雑だったため更新箇所を1箇所に集約する必要があった
- つまり正規化の目的はデータの冗長性排除や不整合の防止というよりも限られたリソースの中で更新処理を効率的に行うことにあった
- 現代の環境:
- ストレージコストが劇的に低下したためコスト観点では冗長性はある程度許容できる
- 読み取り速度が物理的に向上したためJOINによる複雑な結合よりも冗長でもシンプルな構造の方が速い
- クラウドを活用すればスケールアウトも容易になったため正規化による更新箇所の集約よりもスケーラビリティで対応できる
- ビジネスのスピードが加速したため厳密性よりも柔軟性が重要
- 制約の変化:
- 2026年現在のDB設計は50年前と比べて制約の性質が根本的に変わった
- 正規化が前提としていた1970年代の制約から解放され新たな制約である開発スピードが支配的になった現代ではデータの性質に応じて正規化しない選択肢も合理的
- 重要な考え方:
- 新規システム開発では正規化しないほうがいいという単純な話ではない
- RDBだから正規化でもモダンだから正規しないでもなくデータの性質や規模や更新頻度や一貫性の要件や変更速度の要求やチームの状況を考えたとき何が最適かを考えることがモダンな設計の本質
■ 7. まとめ
- エクセルでマスタ管理をできる程度のアプリのDB設計のポイント:
- マスタ管理はPostgreSQLとシングルテーブルとJSONBで小規模で変更が多いデータで検索の柔軟性が必要でスキーマレスで構造の変更に強い
- トランザクションはDynamoDBとスナップショット・パターンで大規模で書き込みが多いデータでアクセスパターンが明確でマスタのデータを含めることで整合性を保証
- 設計の特徴:
- DBが原因でアプリの拡張性が損なわれるということを避けるDB設計をGeminiくんに考えてもらった
- その結果マスタは柔軟に作る為にPostgreSQLを使いトランザクションは整合性を確保する為にDynamoDBを使うという直感とは異なる考え方でありながらマスタはPostgresqlでトランザクションはDynamoDBというとても普通なDB使い分けというちょっと面白い設計になった
■ 1. はじめにと背景
- DB設計への姿勢:
- 個人的にDBというものに対してあまり興味がない
- 基本的にDB設計は詳しい人に任せたいと思っている
- PoCやスモールスタートでの課題:
- ある程度以上の大きめのシステムならそれで良いがPoCやスモールスタートの場合だとDBだけを切り離せるほど人的リソースを割けないことも多い
- 外部にDBを丸投げしたことにより知見がなくなりDB起因でアプリの機能追加や変更が困難になるといった事態も避けたい
- 記事の目的:
- なるべくアプリ開発の邪魔にならないDB設計を考えておきたいとGeminiくん相手に壁打ちしてみた
- 硬い設計をするのが一般的なマスタ管理に柔軟性の高いシングルテーブル設計を採用しNoSQLの定石であるシングルテーブル設計をPostgreSQLのJSONB機能で実現するアプローチが登場した
■ 2. モダンなアプリ開発に求められるDB設計
- 対象システムの特徴:
- 柔軟でモダンなシステムで規模は大きくないがモダンなシステムをなるべく柔軟に作ることを考える
- 取り敢えずマスタを対象に考えDB設計ではよくマスタとトランザクションに分けて考えるのでまずはマスタについて考える
- シンプルな構造を扱うユーザーの意見を素早く取り入れたいのでエクセルで作ったマスタ管理台帳を簡単に取り込めることを前提にする
- 人間が全体を管理できる程度にシンプルなマスタということ
- 自由度は高く項目の増減や変更の自由度は高くしたいモダンなアプリは変更に強いことが求められる
- 従来のDB設計との違い:
- 従来は多くのシステムのデータベースには巨大なデータを扱える堅牢な設計を求められること多かった
- 今は誰にでも気軽にアプリを開発してデプロイして公開できる時代
- モダンな開発では規模は小さいけど柔軟性が求められる事が多く従来のDB設計では上手くいかない事もある
- アプローチ:
- 従来のDB設計は一旦横においてエクセルで実施したマスタ定義をなるべくそのままシステム化することを考えた
■ 3. GeminiくんのDB設計提案
- 設計の概要:
- マスタの定義をすべて一つのテーブルに集約する
- 1つのテーブルに全ての項目を放り込むという大胆な設計を提案してきた
- よく考えると実際にこれが理にかなっている
- テーブル構成:
- master_type: カテゴリやステータスなどの区分でエクセルのシート名に相当
- code: 一意のキー
- name: 表示名で実質的なValue
- category_path: 文字列による階層表現で例は/家電/冷蔵庫
- metadata: エクセルの残りの列をすべてここに放り込む
■ 4. シンプル構成の利点
- 従来設計の問題点:
- PoCやスモールスタートにおいて従来の1エンティティ=1テーブルという硬い設計は柔軟な開発の足枷になる
- エクセルの管理台帳に1つ列を足したいだけなのにDBのマイグレーションに怯え影響調査に時間を費やすことになる
- シングルテーブル設計の利点:
- テーブルを細かく分けずあらゆるマスタを一つの大きな器に放り込むシングルテーブル設計を選択肢に加える
- これにより構造を固定せずビジネスの変化をそのまま受け止める構成を考えることが出来る
- 比喩:
- 正規化重視の設計は川の流れをガチガチに固める堤防を作るのに対してシングルテーブル設計は広い遊水地を用意するといったところ
■ 5. PostgreSQLでの実装
- NoSQLとの比較:
- シングルテーブルと聞くとDynamoDBのようなNoSQLを連想する方が多い
- 実際クエリの効率化のためにデータを1つのテーブルに集約する手法はNoSQLの定石
- DynamoDBではパーティションキーやソートキーを抽象的に定義することで後からアプリ側でデータを解釈する柔軟性を持たせることが一般的
- DynamoDBの課題:
- 直面するのは検索の壁
- DynamoDBは一部の項目にしかインデックスを作れないしそれを補うGSIなどの機能はとても複雑
- 今回は対象がマスタ管理なので検索の柔軟性はとても重要
- PostgreSQL採用の理由:
- シングルテーブル設計によるマスタ管理を検索能力が高いPostgreSQLで実施することを考える
- PostgreSQLの優位性:
- アドホックな検索への対応力: NoSQLは事前に定義したアクセスパターンには強いが想定外の条件での検索や集計は苦手でPostgreSQLはSQLの強力な表現力でいつでも自由な切り口でデータを抽出できる
- JSONBと高度なインデックス: PostgreSQLのJSONB型はスキーマレスな柔軟性を提供し内部フィールドに対してGINやB-Treeインデックスを後から自由に追加可能
- 複雑な階層やパス検索: /食品/生鮮/野菜のようなパスに基づく検索はPostgreSQLのLIKE検索やltree型を使えばインデックスを効かせつつ爆速実行可能でNoSQLのキー設計で解決するよりも遥かに直感的で強力
- PostgreSQLの位置づけ:
- PostgreSQLをただのRDBではなく強力な検索エンジンを備えたドキュメント・ストアとして使うことでスマートなマスタ定義の管理が実現できる
■ 6. マスタのデータ取得方法
- 懸念への対応:
- テーブルが1つでリレーションもないならアプリ側で扱うときに不便じゃないかという懸念がある
- 実はそんなことはない
- アプローチ:
- DB側でJOINして整えるのではなくDB側で構造化して1発で返すというアプローチを取る
- PostgreSQLの関数活用:
- PostgreSQLにはjson_aggやjsonb_build_objectといった抽出結果をまるごと構造化する強力な関数がある
- これらを使えば複数テーブルを何度も叩く代わりに必要なマスタを1つのJSONオブジェクトとしてアプリに返すことができる
- アプリ側はそれを受け取り起動時や定期的なリフレッシュのタイミングでメモリ上に展開してしまえばいい
- メリット:
- アプリ起動時に全ロード
- メモリ上で高速検索
- DB通信のオーバーヘッドなし
- データ量への懸念の解消:
- マスターのデータを全て渡すのは無駄じゃないのかという懸念がある
- しかし今回はあくまでエクセルで人間が管理できるマスタであることが前提
- 今時のコンピューターやネットワークなら数千件や数万件程度のデータは一瞬で処理出来る
- むしろ通信が1回で完結するので効率よくデータを処理することが可能
- 設計思想:
- DBに知能を持たせるのをやめアプリが使いやすい塊としてデータを扱う
- こうすることでリレーションに頼らないスマートなマスタ取得が実現できる
■ 7. モダン開発との関係
- 従来のアプリ開発の問題:
- 特にマスタに関しては整合性を徹底するためにDBの型や制約をガチガチに固めることが多い
- しかし素早い開発や柔軟な仕様変更を求められるモダンな開発ではこの設計が足枷になってしまうことが多々ある
- DBの位置づけの変更:
- DBは器であってフィルターではない
- JSONBで何でも受け入れる柔軟な土台に徹しデータの解釈や不整合の吸収は変更が容易なアプリ側で対応することも考えるべき
- 健全な関係性:
- アプリが賢く立ち回ることで土台であるDBを自由にする
- この関係性こそがモダンな開発における健全なアプリとDBの関係
■ 8. おわりと次回予告
- 提案の効果:
- PostgreSQLを使ってマスタ定義を自由にすることで柔軟なアプリ開発を爆速で実現出来る
- 残された課題:
- そんなルーズなマスタではトランザクションの整合性が取れないのではという疑問が出るのは当然
- 小規模アプリと言っているけど将来的にマスタが巨大化すると詰むよねという懸念がある
- 次回予告:
- 後編ではこのルーズなPostgresqlを支える整合性を担保するDynamoDBについて語る
Dockhand は、リアルタイムコンテナ管理、Docker Compose スタックのオーケストレーション、そしてマルチ環境サポートを提供する、最新の効率的な Docker 管理アプリケーションです。これらすべてを軽量で安全、そしてプライバシーを重視したパッケージにまとめています。
機能:
- コンテナ管理:コンテナをリアルタイムで起動、停止、再起動、監視
- Compose スタック:Docker Compose デプロイメント用のビジュアルエディター
- Git 統合:Webhook と自動同期を使用して、Git リポジトリからスタックをデプロイ
- マルチ環境:ローカルおよびリモートの Docker ホストを管理
- ターミナルとログ:インタラクティブなシェルアクセスとリアルタイムのログストリーミング
- ファイルブラウザ:コンテナからのファイルの参照、アップロード、ダウンロード
- 認証:OIDC 経由の SSO、ローカルユーザー、およびオプションの RBAC(エンタープライズ)
■ 1. IT業界における生成AI登場前の状況
- コミュニケーションが苦手な人材にとっての楽園的環境:
- 論理的に仕様を詰め正確なコードを書けば多少無愛想でも職人として尊重された
- 饒舌さや気の利いたお世辞は不要であった
- 技術力だけで周囲を驚かせることが可能であった
- プログラミング愛好家のアイデンティティ:
- 自分の指先から生まれるロジックで問題を解決することが誇りであった
- 得意なことで収入を得られる環境が存在していた
■ 2. 生成AIによる業務内容の変化
- コーディング作業の減少:
- エディタに向かってコードを書く時間が激減した
- AIが生成した80点のコードの検品係が主な役割となった
- 創造する喜びが失われた
- プログラミング能力の価値暴落:
- プログラミング未経験の業務担当者がChatGPTを使い簡単なツールを自作できるようになった
- 現場のドメイン知識を持つ人材がAIを手足として使えるようになった
- プログラマーという通訳の役割が不要となった
■ 3. 求められるスキルの変化
- コーディングからコミュニケーションへの転換:
- 要件定義や業務整理やステークホルダーとの調整が増加した
- 何を作るべきかやなぜ作るのかを言語化し整理する能力が求められるようになった
- 評価軸の変化:
- 美しいコードを書く能力から生成AIを使いこなし素早くアウトプットを出す能力へ変化した
- 技術力一本での評価という爽快感が消失した
■ 4. IT業界を目指す人へのメッセージ
- 推奨しない動機:
- プログラミングが好きで人と話すのが苦手という理由だけでは生き残れない
- プログラミングそのものはAIがより上手に実行するようになる
- 推奨する動機:
- 作りたいサービスがある人材
- 解決したい社会課題がある人材
- アイデアで世界を良くしたい人材
- 技術の民主化:
- 高度なコーディングスキルという壁が消失した
- 情熱とアイデアとAIへの指示力があれば誰でもクリエイターになれる
- 静寂とコードの職人芸の世界から誰もがアイデアを形にできる創造的な世界への移行
■ 1. DDDにおける集約とファットリポジトリ化の問題
- 集約の重要性:
- 関連するエンティティと値オブジェクトを1つの単位として扱う概念
- ビジネスルールの整合性を保つための境界を定義する
- データの一貫性を保証する役割を果たす
- ファットリポジトリ化の問題:
- 1つのリポジトリに多くのメソッドが集約される
- 変更影響範囲の拡大により他メソッドへの影響考慮が必要になる
- テストの複雑化が発生する
- 責務の曖昧化が生じる
- チーム開発での競合が増加する
- アクション単位設計の設計思想:
- 各アクションに対して専用のプレゼンターとユースケースとリポジトリを用意する
- 各アクションが独立し変更影響が局所化される
- DDDの層構造とADRパターンを組み合わせる
■ 2. ADRパターンの概要
- ADRパターンの定義:
- Paul M. Jonesによって提唱されたMVCパターンの代替アーキテクチャ
- HTTPリクエストの処理を3つの明確なコンポーネントに分離する
- 3つのコンポーネント:
- Action: HTTPリクエストを処理するエントリーポイント
- Domain: ビジネスロジックとドメインモデル
- Responder: レスポンスデータの構築とHTTPレスポンスの生成
- MVCパターンとの違い:
- MVCではControllerがModelとViewの両方に依存し責務が曖昧になる
- ADRではActionとDomainとResponderの役割が明確に分離される
- メリット:
- 各コンポーネントの責務が明確になる
- 各コンポーネントを独立してテストできる
- ビジネスロジックがフレームワークから独立する
- Domain層がプレゼンテーション層に依存しない
- DDDとの組み合わせ:
- ActionをPresentation層のControllerにマッピングする
- DomainをDomain層にマッピングする
- ResponderをPresentation層のPresenterにマッピングする
■ 3. 従来の設計パターンの問題点
- 集約にこだわった設計の特徴:
- 1つのリポジトリに複数の操作を集約する
- OrderRepositoryにcreateやupdateやcancelなど多数のメソッドが存在する
- 問題点の詳細:
- 変更影響範囲の拡大: 1つのメソッド変更時に他メソッドへの影響考慮が必要
- テストの複雑化: 各メソッドのテスト時に他メソッドとの相互作用を考慮する必要がある
- 責務の曖昧化: データアクセスだけでなくビジネスロジックも含まれる可能性がある
- チーム開発での競合: Gitのマージコンフリクトが発生しやすくなる
■ 4. 提案する設計パターン
- アクション単位設計の構成:
- 1プレゼンター: 各アクション専用のプレゼンター
- 1ユースケース: 各アクション専用のユースケース
- 1リポジトリ: 各アクション専用のリポジトリ
- 各アクションをパーティションで区切るイメージ
- 依存性逆転の法則:
- Application層にインターフェース定義を配置する
- Presentation層とInfrastructure層はApplication層のインターフェースに依存する
- Application層が外部層に依存しない構造を実現する
- ADRパターンとの対応:
- Action: OrderControllerとしてHTTPリクエストの受付とルーティングを担当
- Domain: Domain/Entities/Orderとしてビジネスルールとエンティティを担当
- Responder: CreateOrderPresenterとしてレスポンスデータの構築を担当
- ARC パターン:
- DDDの構造設計とADRパターンを融合させた設計
- Action-Responder Cleanパターンと呼称する
■ 5. Laravel実装例
- ディレクトリ構造:
- Application層: インターフェース定義とユースケース
- Domain層: エンティティ
- Infrastructure層: リポジトリ実装
- Presentation層: プレゼンターとリクエストとレスポンス
- Http層: コントローラー
- 各レイヤーの役割:
- リクエストDTO: リクエストデータを保持する
- レスポンスDTO: レスポンスデータを保持する
- プレゼンターインターフェース: アクション単位で独立したインターフェースを定義
- プレゼンター実装: リクエストとレスポンスの保持と取得
- リポジトリインターフェース: データアクセスの抽象化
- リポジトリ実装: Eloquentを使用したデータアクセス
- ユースケース: ビジネスロジックの実装
- コントローラー: HTTPリクエストの受付とバリデーション
- 依存性逆転の法則のメリット:
- ビジネスロジックの独立性により外部の実装詳細に依存しない
- 実装の交換が容易でインターフェースが変わらない限り影響がない
- モックやスタブを使ったテストが可能
- フレームワークからの独立性により移行時もビジネスロジックを再利用可能
- Responderの責務に関する設計選択:
- 現在のアプローチ: PresenterがCreateOrderResponseを返しコントローラーがJsonResponseを構築する
- 代替アプローチ: Presenterが直接JsonResponseを返す
- 現在のアプローチはフレームワークからの独立性を重視する
- 代替アプローチはADRパターンの徹底を重視する
■ 6. アクション単位設計のメリット
- 独立性:
- 各アクションが独立し変更影響が局所化される
- 注文作成のロジック変更時に注文キャンセルのロジックに影響を与えない
- テスタビリティ:
- モックが容易で単体テストが書きやすい
- 各コンポーネントを独立してテストできる
- 保守性:
- 機能追加や変更時の影響範囲が明確になる
- 新機能追加時に既存コードへの影響を最小限に抑える
- 可読性:
- 各クラスの責務が明確でコードの理解が容易
- 1クラスのステップ数が200から300程度に収まる
- 新しいメンバーのプロジェクト理解が速やかに進む
- スケーラビリティ:
- チーム開発での競合が減り並行開発が容易になる
- 複数の開発者が異なるアクションを並行して開発できる
- 依存性の明確化:
- 依存関係が明確で変更に強い設計になる
- インターフェースを変更しない限り実装変更が他層に影響を与えない
- ADRパターンの利点:
- ActionとDomainとResponderの分離により責務が明確になる
- ビジネスロジックがフレームワークから独立しフレームワーク変更への耐性が向上する
■ 7. 実践的なTips
- Laravelサービスコンテナ活用のベストプラクティス:
- 各機能ごとにサービスプロバイダーを作成し依存関係を明確に管理する
- インターフェースに依存することでモック化が容易になる
- プレゼンターは都度生成しリポジトリはシングルトンなど適切なライフサイクルを選択する
- テストコードの書き方:
- 依存関係が明確で必要なモックを特定しやすい
- 1つのアクションに焦点を当てたテストが書きやすい
- インターフェースに依存しているためモックの作成が簡単
- データベースや外部APIに依存せず単体テストが高速に実行できる
- ユースケースのテスト例:
- リポジトリをモック化してテストする
- 在庫不足時の例外スローを確認する
- コントローラーのテスト例:
- プレゼンターとユースケースをモック化する
- レスポンスのステータスコードとデータを確認する
- リポジトリのユニットテスト:
- DBファサードとEloquentモデルをモック化する
- データベースに依存せずテストが高速に実行される
- エッジケースのテストが容易になる
- 拡張時の注意点:
- 新しいアクションには新しいコンポーネントを作成する
- 既存コンポーネントの変更を避け影響範囲を最小化する
- 共通処理はドメインサービスやアプリケーションサービスとして抽出する
- 共通処理の抽出例:
- ドメインサービス: 価格計算や配送料計算などビジネスロジック
- アプリケーションサービス: 在庫チェックなど複数アクションで共通する処理
- パフォーマンス対策:
- リポジトリの最適化により必要なデータのみを取得する
- 頻繁にアクセスされるデータはキャッシュを実装する
- Eloquentのwithメソッドを活用しN+1問題を回避する
- ADRパターンとDDDの組み合わせガイドライン:
- Action層の薄さを保ちビジネスロジックを含めない
- Domain層の純粋性を保ち外部層に依存しない
- Responder層の独立性を保ちビジネスロジックを含めない
■ 8. まとめ
- 設計の重要性:
- 集約にこだわりすぎることでファットリポジトリ化し保守性が低下する
- アクション単位設計により各アクションが独立し変更影響が局所化される
- DDDとADRパターンの組み合わせによりクリーンアーキテクチャの原則を実現する
- 依存性逆転の法則により外部層がApplication層に依存する構造を実現する
- 長期的なサービスへの適用:
- 数年から数十年と長く運用し続けるサービスにこそ価値がある
- 機能の追加や変更が頻繁に発生する環境に適している
- チームメンバーの入れ替わりに対応しやすい
- 技術スタックの進化に柔軟に対応できる
- 複数の開発者の並行作業で競合が発生しにくい
- 長期運用における優位性:
- 機能追加時の影響範囲が明確で既存コードへの影響が最小限
- コードの理解が容易で新メンバーも特定機能に焦点を当てて理解できる
- フレームワークからの独立性により技術スタック変更に柔軟に対応できる
- 並行開発の促進により複数開発者が同時開発しても競合が発生しにくい
- 実践的な設計指針:
- アクション単位設計に従い各アクションに専用コンポーネントを作成する
- 依存性逆転の法則に従いApplication層にインターフェースを配置する
- ADRパターンとDDDの層構造を組み合わせる
- テスト容易性と保守性を重視する
僕の観測範囲で喋ってしまうけど、AI コーディングエージェントが登場してきて、プログラマがやってた事を AI が肩代わりするだろう、そして人間に時間の余裕ができるだろう、と思われていたにも関わらず、多くのプログラマはそれどころか 2 倍や3倍の作業量になってしまっており「おいおい君ら倒れるで」という状況をチラホラ目にしている。
■ 1. Raspberry Pi AI HAT+ 2の概要
- Hailo-10H AIアクセラレータを搭載
- 8GBのオンボードRAMを搭載
- Raspberry Pi 5に生成AI機能を追加するHAT
- 価格は130ドル
- 現在販売中
■ 2. オンボードRAMの利点
- 8GBの専用オンボードRAMを搭載
- 大規模言語モデル(LLM)やビジョン言語モデル(VLM)をローカルかつセキュアに実行可能
- ホストのRaspberry Pi 5を他のタスク処理に解放できる
- AIモデルのスムーズな動作を保証
■ 3. プライバシーとセキュリティ
- エッジでの信頼性が高く低遅延なAI処理を実現
- ネットワーク接続なしで動作可能
- データセキュリティを簡素化
- インフラ要件を最小化
- クラウドAPIコストを削減
■ 4. モデルの提供
- Hailoがサンプルモデルを提供
- ユーザーによるカスタマイズ:
- カスタムビジョンモデルのトレーニング
- 生成AIモデルのファインチューニング
- 対応アプリケーションの例:
- 音声からテキストへの変換
- 翻訳
- 視覚シーン分析
- 互換性のある生成AIモデル用ソフトウェアはHailoのGitHubリポジトリで入手可能
■ 5. 主な仕様
- Hailo-10H AIアクセラレータ搭載
- 40 TOPS(INT4)の推論性能
- コンピュータビジョンモデルの性能はRaspberry Pi AI HAT+(26 TOPS)と同等
- 8GBオンボードRAMにより生成AIモデルを効率的に実行
- Raspberry Piのカメラソフトウェアスタックに完全統合
- Raspberry Pi HAT+仕様に準拠
■ 6. 付属品
- オプションのヒートシンク付属
- 16mmスタッキングヘッダー付属
- スペーサーとネジ付属
- Raspberry Pi Active Cooler装着済みのRaspberry Pi 5への取り付けが可能
■ 1. loss32プロジェクトの概要
- コンセプト:
- デスクトップ環境全体がWINE上で動作するWin32ソフトウェアで構成されるLinuxディストリビューション
- 完全にフリーかつオープンソースのOS
- exeファイルをダウンロードしてそのまま実行できる
- 想定ユーザー:
- 必ずしもUnix愛好家ではないパワーユーザー
- このコンセプトを面白いと思う人
■ 2. ReactOSとの違い
- ReactOSの問題点:
- Windows NTカーネルの再実装を試みている
- これがアキレス腱となりハードウェア互換性と安定性の面で足を引っ張っている
- loss32のアプローチ:
- ReactOSと似た最終結果を目指す
- より使いやすい基盤の上に構築
- 動作実績のあるコンポーネントを使用:
- Linuxカーネル
- WINE
- それらを結合する各種ツール
- ReactOSユーザーランドの便利な機能
- loss32の利点:
- 技術的にはLinuxディストリビューションのため必要に応じてLinuxソフトウェアも実行可能
- ReactOSではLinuxソフトウェアを実行できない
■ 3. プロジェクトの目標
- ユーザーランド全体を可能な限りWINEで置き換える
■ 4. プロジェクトを構築する理由
- 90年代後半から2010年代初頭のPCデスクトップ体験はパワーユーザー特にクリエイティブユーザーにとって素晴らしかった
- その夢を維持したい
- WINEには残念な荒削りな部分が多くユーザーは最後の手段としてのみWINEを使用するため許容している
- 全てがWINE上で動作するデスクトップ環境はWINEの改善を促進する
- このプロジェクトを使うかどうかに関わらず全員にとって有益
- Win32は安定したLinux ABIである
- 技術的に可能だから
■ 5. Win32が安定したLinux ABIである理由
- exeファイルをダウンロードしてWINEで実行できることで何度も助けられた経験がある
- クリエイティブプロジェクトでは以下のようなソフトウェアが必要になることが多い:
- 自分で再ビルドするのが不可能または非現実的
- LinuxやmacOS版が動作しないまたは存在しない
- Win32ソフトウェアには30年以上の歴史がある
- WINEまたはWindows上で実行可能
- 他のABIにはこれほどの互換性実績がない
- WINEはWin16のソフトウェアも実行可能
- Win32は世界の安定したABIでもある:
- GNU/LinuxやPOSIX系の選択肢が限られており品質が低い分野が多い
- 例としてクリエイティブソフトウェアやゲーム
- Win32により人類の文化遺産のより大きな部分にアクセス可能
■ 6. 現在の状態
- スクリーンショットは実際のもの
- Debian 13上で安定版WINEを実行している状態
- スクリーンショットには映らない多くの荒削りな部分があり現時点では使用が快適ではない
- プロジェクトの目標:
- 多くの荒削りな部分を修正
- この環境を簡単にインストールできる形でパッケージ化
■ 7. 協力者の募集
- 特に求めている知識や協力:
- デスクトップ環境を強制しないWaylandコンポジター
- 現在はスタンドアロン版のmutterを使用
- WINEとの連携改善
- WINE関連:
- explorer.exe
- shell32.dll関連
- HiDPIスケーリング
- パッケージング
- ReactOS関連:
- explorer.exe
- shell32.dll関連
- ReactOSユーザーランドとWINEの非互換性
- GNU/Linuxデスクトップスタックの複雑な詳細全般
■ 8. リリース予定
- ビジョンの完全な実現時期:
- 不明
- 2026年1月中に初期の概念実証版をリリース予定:
- /etc/apt/sources.listに追加してsudo apt installで導入可能
- 欠落や不具合の長いリストが付属
- そこから反復的に改善していく
■ 1. フリーランス・小規模ソフトハウスが直面する構図
- 元請けが穴だらけの立派な工程表を出してくる
- 大半の人はその穴を見抜けるレベルのレビュー実戦経験がない
- プライムにケチを付けられない立場のため従うしかない
- 末端側はウォーターフォール型工程に従い各工程のみを担当する
- 作るものの全体像が曖昧なまま設計が進む
- 実際に環境を組み上げたタイミングでようやく現実が見える
- 結果として発生する問題:
- 仕様漏れ
- 追加作業と追加料金交渉
- 納期ギリギリ
- ユーザー満足度の低下
■ 2. プロジェクト計画の理想と現実
- 理想:
- プロジェクト計画書がパートナーにも展開される
- 双方でコンセンサスを取りながら進める
- リスク想定とヘッジ案の説明や議論がある
- 現実:
- 小さな会社の社長やフリーランスはプロジェクトキックオフの儀式としてしか見ていない
- 様々な事情からリスク議論が実践できない
■ 3. 元請けの工程表の実態
- PMの願望が強く出たドキュメントと認識すべき
- 通常書かれていないもの:
- 商用環境の構成が固まるタイミング
- 試験環境でどこまで再現するか
- どの段階で何を試すか
- 現場の安全マージンやリスクヘッジ
- 極端な工程表の例:
- 要件定義工程がない
- 各工程での成果物が決まっていない
- 設計工程なしにいきなりパラメータ設計書
- PoCでやったから設計なしでいけるという幻想でいきなり環境構築
- ステージングをそのまま本番にするノリで商用後の保守イメージがない
- 実装期間が妙に短く3週間に環境構築から報告書作成まで全部入り
- セキュリティ設計やセキュアコーディングガイドラインがなく脆弱性試験で炎上
- このまま乗ると後半で燃える
- 外向け工程表とは別に内部で裏プロジェクト計画を持つ発想が重要
■ 4. 技①:基本設計段階でプロト環境を先に作る
- 基本設計フェーズの早い段階で本番と同じ構成イメージの影のプロト環境を自分たち側でこっそり作る
- プロト環境の内容:
- 土台となるOS
- 想定しているミドルウェア(アプリケーションサーバやレポーティング基盤など)
- 知る限り本番構成に近い形で一度組んでみる箱
- あらかじめ作っておくべきもの:
- GitLabなどのソースコード管理とCI/CD基盤
- メリット:
- 早い段階でリバースプロキシ不足や追加DB必要などの設計上の大穴に気づける
- 元請けの基本設計がふわっとしていても動くものの全体像を先に掴める
- 構築メモや設定手順と要件定義があれば基本設計書は後から2〜3日で一気に書ける
- 体裁や細かい部分はLLMを使えば2〜3日で形にできる
- ポイント:
- 工程表通りにドキュメントだけ書くのではなく基本設計の最初にプロト環境をこっそり動かす
- 内部工程を勝手に入れ替える
- 外には言わず自分たちが燃えないための保険として自社努力で行う
- コスト面:
- 自社で新たに大きなコストを捻出する必要はない
- プロジェクト開始早々は要件定義未提出や基本方針未確定などの待ち時間が多い
- 自分に関係ない打ち合わせ中にこっそり進める
- 待ち時間を活用して動くものの断片でも作っておく
- 勝手アジャイルを回す勢い
■ 5. 技②:バージョン釘打ちミーティングをねじ込む
- プロト環境を先に作る際の落とし穴:
- バージョンが後から変わって全部作り直しになる
- 対策として基本設計の初期にバージョン釘打ちミーティングをねじ込む
- 最低限合意しておくべき項目:
- 土台となるOSのバージョン(メジャーとマイナーまで決まれば上出来)
- 主要なミドルウェアとそのバージョン(アプリケーションサーバやレポーティングやバッチ基盤など)
- それぞれのサポート状況(EoL時期やメーカーサポート有無やOSSコミュニティ活動状況)
- 釘打ちは完璧でなくてよい:
- 一生変えないという固定ではない
- ひとまずこの前提で設計見積もりを進めるレベルの合意
- 後から変更が出ても柔軟に対応できるようにしておく
■ 6. 技③:プロト環境の存在は言わず経験値として出す
- 影のプロト環境で性能やリソースを見ておくと後のフェーズで楽になる
- 聞かれる質問の例:
- この構成でCPU何コアぐらい必要か
- 何ユーザーぐらいまで余裕があるか
- どのくらいのマシンサイズを見込めばいいか
- 裏ではプロト環境でちゃんと数字を取っているが自前環境で負荷かけたとストレートに言う必要はない
- 期待値コントロールの領域
- 外向きの言い方サンプル:
- 同等規模の構成での過去案件の経験値ではこのくらいのアクセス数ならCPU使用率は何%前後
- 近い構成のプロジェクト実績をベースにすると初期はこのマシンサイズから始めるのが妥当
- 似たような業務負荷の案件で取った数値を参考にするとこのくらいのスペックで当面余裕がある
- 実際にはその過去案件の1つが今回の影のプロト環境だが外から見れば経験値として扱える
- バランス感覚のポイント:
- 裏側ではしっかり測っている
- 過度に全部やってあげてますと期待値を上げすぎない
- 過去の知見として妥当な範囲を出していますというトーンを守る
■ 7. 技④:LLMに食わせる前提で手順書だけちゃんと残す
- 影のプロト環境を作るときは基本設計書そのものより手順書とメモの残し方をちゃんとしておく
- 理由:
- LLMに食わせるとかなり精度の高い基本設計書ドラフトが一瞬で出てくる
- 流れ:
- 影のプロト環境を作る
- その過程でインストール手順やミドルウェア設定や詰まったポイントと解決策をざっくりテキストで残す
- LLMに渡して基本設計書の構成案出しや顧客向け表現整理や試験項目洗い出しやパラメータシートたたき作成を依頼
- 2〜3日かけて書くレベルの文書が数時間で形になる
- この組み合わせの効果:
- 実装リスクを下げる
- ドキュメント工数も削る
- かなり相性の良い戦略
■ 8. ウォーターフォールを表で守りつつ裏でアジャイルを回す
- 表向きの対応:
- 元請けが出してきた大きな工程表(ウォーターフォール)に従っているように見せる
- マイルストーンや成果物の名称も基本設計や機能設計や結合テストを崩さない
- 裏側での対応:
- 基本設計フェーズのうちにプロト環境を作って動かす
- バージョンを釘打ちする
- 実際に動かしながらこれで行ける構成を先に固めてしまう
- そこで得た知見をもとに性能見積もりやリソース見積もりやリスク洗い出しをスッと出せるようにしておく
- 効果:
- 表面上はウォーターフォールでも内側では小さなアジャイルサイクルをぐるぐる回して後続工程をどんどん楽にできる
- 大線表の納期を遅らせるという話ではない
- 最初に影のプロト環境を作っておくことで大線表を遅らせずに済む確率がかなり上がる
- その構成で実際に動いている環境がすでにあるため
■ 9. 環境をプロジェクトごとに準備する効率化
- ネック:
- 案件ごとにOSやミドルウェアや認証まわりやテスト用クライアントを毎回ゼロから用意するのはフリーランスや小規模ソフトハウスにはheavy
- 対策:
- 案件ごとの箱庭環境を簡単に量産できるテンプレートやツールを少しずつ自分の側に用意しておく
- 具体例:
- 手元のマシン1台に仮想化環境と案件ごとの箱庭を自動で作るスクリプトを置いておく
- 新しい案件が始まったらまず影のプロト環境を30分くらいで立ち上げてから設計に入る
- 使うツールや技術スタックは何でも構わない
- 大事な発想:
- 毎回手作業で環境を組むのではなく案件ごとの箱庭をほぼテンプレートから起こす
- リモートからVPN経由で簡単に入れるようにしてパートナーがすぐに参加できる環境を作っておく
- となりの案件のVMが見えてしまわないようなセキュリティに十分配慮した分離開発環境を構築する
- パブリッククラウドで回してもよいが採算度外視で使うのはかなり危険
■ 10. まとめ
- 元請けの工程表だけを信じて燃えないための要点:
- 外向け工程表とは別に自分たちの内部工程計画を持つ
- 基本設計の初期にプロト環境をこっそり作ってしまう
- OSとミドルウェアのバージョンを早めに釘打ちしておく
- プロト環境で得た数字は自前ラボで測りましたではなく他プロジェクトでの経験値ですとして出す
- 手順書をちゃんと残しておけばLLMに食わせて基本設計書を一気に仕上げることもできる
- 表向きはウォーターフォールでも裏で小さなアジャイルを回して先回りしておくといろんな工程が楽になる
- 正論のセキュリティ記事というより現場で生き残るためのテクニック集
- これらの工夫が積み上がると変わること:
- プロジェクトの燃え具合
- ユーザーの満足度
- 自分たちの消耗度合い
■ 1. プログラミングにおける2つの本質的な力
- 冗長性の最小化:
- 全ての知識を一度だけ定義することが理想
- 依存関係の最小化:
- AがBに依存するのは絶対に必要な場合のみに限定すべき
- 優れたプログラマの特徴:
- 冗長性と依存関係を嫌悪する
- 劣ったプログラマはこれらを気にしない
■ 2. 冗長性と依存関係の衝突
- モジュール境界を越えたコード再利用の問題:
- モジュールAとBが共通モジュールCを使うか各自で実装するかの選択
- モジュール内部での再利用:
- 議論の余地なく再利用すべき
- モジュール間での再利用:
- 第三のモジュールを作成するか「ユーティリティ」モジュールに追加する必要がある
- ユーティリティモジュールの問題点:
- 外部ライブラリへの依存
- 設定の誤り
- 初期化タイミングの問題
■ 3. 経験がもたらすもの
- 経験は知識の蓄積より性格の形成または破壊に寄与する
- 若いプログラマ:
- インフラ構築に積極的
- 第三のモジュール作成を喜ぶ
- ベテランプログラマ:
- インフラ活動に対して否定的反応を示す傾向
■ 4. コマンドライン解析の例
- 機能拡張の誘惑:
- オプション構文の統一
- 値の型対応(文字列/真偽値/整数/16進数/ユーザー定義型)
- ヘルプ文字列
- ヘルプ画面の自動生成
- GUIプロパティページ
- 設定ファイルからの読み込み
- フラグの妥当性チェック
- 過剰設計の実例:
- XParam: 1万行以上のコードと独自シリアライゼーションフレームワーク
- ホストプロジェクトでは機能の5%未満しか使用されない
- 著者自身もXLogという1万行以上のログライブラリを作成し機能の0%しか使用されなかった経験を持つ
- 著者の現在のアプローチ:
- 5行のCコードで単純に解析
- ヘルプ画面やバリデーションは不要と割り切る
- 1万行のパッケージへの依存を回避
■ 5. モジュールの定義と要件
- コンパクトで安定したインターフェース:
- OOの訓練がコンパクトさの軽視を招いている
- 数十のクラスや複雑なデータ構造を公開することが許容されている
- ドキュメント:
- セマンティクスの記述
- サンプルコードの提供が理想
- テスト:
- 各クラスや関数の単体テストではなく公式インターフェースのテストが重要
- 適切なサイズ:
- 1K〜30K LOC(C++換算)が目安
- 大きすぎても小さすぎても泥の塊になる
- オーナー:
- 変更はオーナーを説得して行う
- 一貫したメンタルモデルを維持できる人数は1人
- ライフサイクル:
- 変更はバージョンにまとめて頻繁すぎないリリース
■ 6. 他者のモジュールへの依存の問題
- オーナーシップの問題:
- 作成者が継続的なサポートを認識していない
- 他者による不適切な変更が発生
- 循環依存の発生
- コマンドラインパーサーの潜在的依存先:
- シリアライゼーションパッケージ
- パースパッケージ
- カラーターミナルI/Oパッケージ
- プラットフォーム固有パッケージ
- シングルトン初期化管理パッケージ
- ライフサイクルの問題:
- バージョン互換性の確認
- テストのコンパイルに他者のコードが必要
- 新バージョンが追加の依存関係を引き込む
- インターフェース安定性の問題:
- 破壊的変更によるテストスクリプトの破損
- 予期しない動作変更
■ 7. 生物学的アナロジー
- 生物における冗長性の例:
- 人間とタコは盲目の祖先から独立して類似の眼を進化させた
- 眼全体という複雑な器官が独立して開発される
- 冗長性は進化において機能している:
- 全員の努力を調整するより効果的
■ 8. 結論
- 冗長性の欠点:
- 努力の重複
- 相互運用性の問題
- 依存関係はより深刻:
- 依存すべきは本格的なモジュールのみ
- 無定形なコードの塊には依存すべきでない
- モジュール化の成功可能性の評価基準:
- 実際のオーナーの存在
- 安定したインターフェース
- 全ユーザーを満足させる見込み
- 著者の主張:
- 成功の見込みが低ければ冗長性を選択すべき
- 見積もりは保守的に行うべき
- 冗長性は悪だが依存関係は麻痺を引き起こす
- 依存関係を先に排除すべき
■ 1. RLMの定義と本質
- 再帰的言語モデルの位置づけ:
- 最も注目を集めている大規模言語モデルエージェント・アルゴリズム
- 実際のモデルはOpenAIのChatGPTやgpt-ossやDeepSeekなど既存のLLMを使用する
- 再帰とはLLMの呼び出し方を指す
- RLMの本質:
- LLMを一発回答の生成器として使うのではなく複数の推論ステップを持つ手続きとして編成する
- 自己修正しながら目的の成果物へ収束させる
- 重要なのは再帰という言葉の響きよりも実装上の設計原則
■ 2. RLMの3つの構成要素
- オーケストレーターLLMとワーカーLLMの役割分担:
- オーケストレーター: 大局的な戦略を立てる役割でどの資料を読むべきかや抽出すべきスキーマは何かや矛盾が出たらどの観点で再検証するかを担う
- ワーカー: 局所的な作業を担当しこの段落から顧客要望を候補抽出するやこの候補の根拠となる引用箇所を特定するなど粒度の小さいタスクを大量に捌く
- 同じLLMで役割を分担することが可能でgpt-ossは非常によく働く
- 分業が効く理由:
- LLMの失敗が往々にして大局と細部の混線で起きる
- 戦略を考えながら同時に細部を埋めるともっともらしい整合を優先し検証が甘くなる
- 戦略と実務を分けることで作業の責務が明確になり失敗の検知と修正がしやすくなる
- 非自然言語的な中間表現:
- Pythonコードなど機械的に検査可能な表現を途中に置く
- 抽出結果をJSONにしPythonでスキーマ検証を行う
- 重複や欠落や型不一致や相互参照の矛盾をコードで弾く
- 候補の根拠引用が本当に原文に存在するかを文字列一致や範囲照合で検証する
- 中間表現の効果:
- モデルが賢くなったから精度が上がるのではない
- LLMが苦手な厳密さをコードと型と制約で肩代わりしLLMには意味の解釈を担当させる
- LLMを推論エンジンとして使いつつ検証と制約は計算機の得意技に寄せるアーキテクチャ
- 検証から差分修正から再実行のループ:
- 最初の抽出はあくまで暫定解にすぎない
- Pythonで検査してエラーが出たらそのエラーを次の入力条件としてオーケストレーターに返し再度ワーカーにタスクを割り当てる
- やり直しを精神論ではなくプロトコルとして設計する
- プロトコル設計の例:
- フィールドが埋まらない場合は未確定を許す
- 未確定のまま残した理由を分類して残す
- 矛盾が出たら根拠引用を必須にして再抽出する
- モデルがそれっぽい完成品を捏造する余地が減りシステム全体として信頼性が上がる
■ 3. RLMの全体像と従来手法との比較
- RLMの定義:
- 戦略立案担当と局所作業担当に分解する
- Python等で検証可能な中間表現を挟む
- 誤りを差分として回収し再帰ループで収束させる方式
- 従来手法の問題点:
- LLMに抽出させて人間が目視で直す運用がスケールしなかった
- 失敗が最後に露呈し修正が属人的だった
- RLMの優位性:
- 失敗を途中で機械的に検出し修正を自動で次工程に流す
- 非構造化から構造化のような業務で予想以上に効く
- コアの考え方:
- 賢い一発回答ではなく検証可能な中間表現と再実行プロトコルによって正しさへ収束する工程を作る
■ 4. KnowledgeSTATIONでの実装例
- 実装結果:
- RLMによる非構造化データから構造化されたデータを取り出す機能を追加した
- 予想外にうまくいった
- 機能の詳細:
- 過去の著作や議事録や講義録など雑多な情報を貯めた知識ベースに注目するデータと出力して欲しいデータを渡す
- 技術的な話題に注目し技術と発明者とその効果と関連する技術を指定すると自動的にデータを検索して構造化する
- RLMがどのように動作して情報をかき集めまとめているのかという過程も可視化されている
- 間違ったデータが出てきてもどこで間違ったのか理解しやすいメリットがある
- 出力例:
- GPUやELIZAやAlexNetやニューラル機械翻訳やChatGPTなど技術に関する構造化データが抽出された
- トークン上限8000など純粋に技術そのものとは言えないものも出てくるが索引などに引用する場合は納得できる
- 構造化されたデータはExcel形式でダウンロードできる
■ 5. RLMの特徴的なメリット
- 非構造化データのノイズの活用:
- RLMがうまく回り始めると非構造化データのノイズがむしろ追加情報源になる
- 議事録の脱線や雑談や言い淀みや感情的な言葉が優先度の根拠やリスクシグナルとして意味を持つ
- それ今日中にやらないとまずいという一言が期限の強制力を示す
- 顧客が同じ要望を三度言うならそれは単なる繰り返しではなく強い痛みの表現
- RLMは再帰の過程でこうした文脈特徴を拾い上げ構造化スキーマに落とし込める
■ 6. 課題
- 計算コストの増加:
- 再帰はループを回すほどトークンも増え遅延も増える
- 検証関数の設計依存:
- 再帰の品質は何を矛盾とみなすかや根拠は十分かやスキーマ制約を満たすかの設計に依存する
- 情報の欠落:
- ドメインによってはそもそも根拠がテキストに存在しないことがある
- 会議で決まったはずなのに議事録に書かれていない場合などが該当する
- 未確定を無理に埋めず追加の情報取得フローに接続する必要がある
- エージェントは万能の魔法使いではなく情報の欠落を検知して次の行動へつなげる工程管理でもある
■ 7. 今後の展望
- LLM活用の主戦場の変化:
- 文章生成ではなく非構造化データを意思決定可能な構造へ変換することになる
- 人間の組織が抱えるボトルネックは情報の不足ではなく情報の形式
- 見つけられないや比較できないや集計できないや追跡できないという問題がある
- RLMはここに正面から切り込むための基本部品になり得る
- ローカル動作の利点:
- 完全にローカルで動作するという点も見逃せない
- クラウドAIのAPI利用料金や制限に悩まされることなく黙々とデータを構造化していく
- エージェンティックAIの新局面:
- RLMによってエージェンティックAIは新しい局面に到達できる可能性がある
■ 1. OpenSSLの品質問題
- OpenSSLの品質や状況に懸念があるという指摘は専門家やエンジニアの間で事実として存在
- 特にOpenSSL 3.0(2021年リリース)以降パフォーマンスの低下やアーキテクチャの複雑化をめぐって厳しい批判
- 主な指摘内容:
- パフォーマンスの大幅な劣化:
- 新しい「プロバイダー・アーキテクチャ」が原因で特定の処理が旧バージョン(1.1.1系)より著しく遅くなった
- マルチスレッド環境でのロック競合によりスループットが劇的に低下
- APIのオーバーヘッドにより証明書の検証や鍵の生成といった基本的な操作のステップ数が増加
- コードの複雑化とテストの不備:
- テストを通過していないコードがマージされる事象が2025年時点でも指摘
- 修正によって別のバグ(デグレード)が発生
- メモリ安全性の欠如(C言語で書かれているためバッファオーバーフローなどの脆弱性が継続的に発見)
- QUICへの対応遅延:
- 次世代通信規格QUIC(HTTP/3)への対応が非常に遅れた
- 多くのプロジェクトがBoringSSLやquictlsなどの別ライブラリへ流出
- 業界の反応(OpenSSL離れの加速):
- BoringSSL: GoogleがOpenSSLをフォーク/不要な機能を削ぎ落としセキュリティとパフォーマンスに特化
- rustls: Rust言語で書かれたTLSライブラリ/メモリ安全性が保証されパフォーマンスも高い
- Goの標準ライブラリ: 独自実装を選択しOpenSSLの混乱の影響を受けない
■ 2. OpenSSLの資金面と組織面の変遷
- Heartbleed以前(2014年以前):
- 世界中のインフラを支えていながら正社員はほぼゼロ
- 寄付金は年間わずか2,000ドル程度という極めて劣悪な環境
- Heartbleed後:
- Linux Foundationの「Core Infrastructure Initiative」などを通じて数億円規模の資金援助
- 組織は急拡大
- 資金拡大の副作用:
- 「商用化」へのシフト: 安定した運営のためサポート契約を販売する法人化を推進/大口顧客が求める「FIPS認証」などの要件が優先
- 官僚化と構造の複雑化: 少数の凄腕エンジニアによる属人的な開発から委員会による合議制へ移行/意思決定の鈍化
- OpenSSL 3.0の問題:
- 過度な抽象化: 将来的な拡張性を求めて内部構造をゼロから作り直す「プロバイダー・アーキテクチャ」を導入/極めて複雑で旧バージョンの数百倍遅い処理が発生
- QUIC対応の失敗: 内部の設計方針が二転三転した結果開発が大幅に遅れた
- 「レガシー」と「新設計」の板挟み:
- 世界中で動いているという責任があるため古いC言語のコード(30年前のものも含む)を維持しながら最新の安全な設計を取り入れる必要
- テストの不足: 膨大なコードベースをカバーする自動テスト体制が追いついていない
- 技術的負債: Rustなどのメモリ安全な言語への移行を求める声もあるがC言語に固執せざるを得ない現状
■ 3. OpenSSLの組織改革(2024年〜)
- 二頭体制への分離(2024年3月〜):
- OpenSSL Corporation(事業会社): 商用ユーザーや大口顧客を対象/サポート契約の販売/FIPS 140認証の取得など
- OpenSSL Foundation(財団): 非営利コミュニティや個人開発者を対象/オープンソースとしての理念を守る
- 旧体制(OMC/OTC)の解散:
- OMC(管理委員会)の解散(2024年3月): 代わりに10名の取締役会が意思決定
- OTC(技術委員会)の解散(2025年4月予定): 代わりにTAC(技術諮問委員会)が新設され技術ロードマップの決定に透明性
- リリースサイクルの「予測可能性」の重視:
- タイムベースのリリース(毎年4月と10月)に移行
- 組織改革の背景にある反省点:
- 「身内感」の払拭: 閉鎖的な構造が外部からの批判を招いていた/新体制では選挙制を導入
- 「商用優先」への批判回避: 組織を分けることでバランスを取る
■ 4. OpenSSL 4.0の野心的変更(2026年4月リリース予定)
- 過去10年以上の負債を一掃するための「大掃除」のリリース
- ENGINE APIの完全削除:
- ハードウェアアクセラレータや独自の暗号モジュールを利用するための仕組み
- 設計が古くメンテナンスの大きな負担
- 「Provider(プロバイダー)」アーキテクチャに一本化
- 独自のハードウェア支援を利用している古いシステムはProvider形式に書き換えない限り4.0に移行不可
- SSLv3のサポート完全終了:
- 2015年に脆弱性(POODLE)によって完全に否定されたがコードとしては残されていた
- 4.0ではSSLv3に関連するコードがライブラリから物理的に削除
- C99標準への移行とツールチェーンの刷新:
- 非常に古いC言語規格(ANSI C/C89)をベースに書かれてきた
- 4.0からはC99以降のコンパイラが必須
- コンパイラの最適化が効きやすくなりパフォーマンス劣化を解消するためのコード整理が進めやすくなる
- スケジュール:
- 2026年2月: コードフリーズ
- 2026年3月: ベータ版リリース
- 2026年4月7日: 正式リリース(予定)
- 4.0でのリセットはOpenSSLが「枯れたが重いライブラリ」から「現代的で筋肉質なライブラリ」へと再生できるかどうかの分水嶺
■ 1. 記事の概要
- pyca/cryptography(Pythonの暗号化ライブラリ)のメンテナーであるPaul KehrerとAlex Gaynorによる2026年1月14日の記事
- 12年間OpenSSLに依存してきたが成長する問題について2025年10月のOpenSSL Conferenceで発表
- OpenSSLの開発における過ちが重大になったため実質的な変更が必要(OpenSSLに対して、または依存関係に対して)
■ 2. OpenSSLの軌跡(3幕構成)
- 第1幕: Heartbleed以前(2014年以前):
- OpenSSLはメンテナンスが不十分で停滞していた
- 期待を大幅に下回っていた
- 第2幕: Heartbleed直後:
- OpenSSLのメンテナンスが再活性化され大幅な進歩と改善
- 実際のコードレビュープロセスの導入
- CIでのテスト実行開始
- ファジングテストの採用
- リリースプロセスの成熟
- 第3幕: 2021年のOpenSSL 3リリース:
- 新しいAPIを導入し大規模な内部リファクタリング
- パフォーマンス/複雑性/APIの使いやすさにおいて大幅な後退
- テスト/検証/メモリ安全性の面で必要な改善がなかった
- 同時期にOpenSSLのフォーク(LibreSSL/BoringSSL/AWS-LC)はこれらの分野で進歩
■ 3. パフォーマンスの問題
- OpenSSL 1.1.1と比較してOpenSSL 3はパース処理やキー読み込みなどで大幅なパフォーマンス後退
- 楕円曲線公開鍵の読み込みがOpenSSL 1.1.1と3.0.7の間で5〜8倍遅くなった
- 改善後も以前より3倍遅い
- OpenSSLの対応は「OpenSSL 3では後退が予想されており最適化の余地はあるが1.1.1レベルに戻ることは期待すべきではない」
- pyca/cryptographyがX.509証明書パースをOpenSSLから独自のRustコードに移行した結果OpenSSL 3と比較して10倍のパフォーマンス向上
- 公開鍵パースを独自のRustコードに移行したことでエンドツーエンドのX.509パス検証が60%高速化
- 独自パースでより良いパフォーマンスを達成できることは実践的に可能であることを示している
- 彼らのパフォーマンスは巧妙なSIMDマイクロ最適化の結果ではなくコピー/アロケーション/ハッシュテーブル/間接呼び出し/ロックを避けるというシンプルな方法の結果
■ 4. 複雑性とAPIの問題
- OpenSSL 3はAPIを大幅に変更し始めた
- OSSL_PARAMを導入しすべての新しいAPIサーフェスに使用(ポスト量子暗号アルゴリズムを含む)
- OSSL_PARAMは通常の引数渡しの代わりにキー値ペアの配列を関数に渡す
- OSSL_PARAMの問題点:
- パフォーマンス低下
- コンパイル時検証の減少
- 冗長性の増加
- コードの可読性低下
- 具体的な比較:
- OpenSSLでML-KEMカプセル化を行うには37行と6つのフェイラブル関数呼び出しが必要
- BoringSSLでは19行と3つのフェイラブル関数呼び出し
- OpenSSL内部も複雑化:
- OSSL_PARAMの配列管理を容易にするために多くのソースファイルがCファイルではなくCコード用のカスタムPerlプリプロセッサを持つ
- OpenSSL 3は「providers」の概念を導入:
- アルゴリズムの外部実装を許可
- プログラム実行の任意の時点で任意のアルゴリズムを置き換えることを許可
- ほぼすべての操作に無数のアロケーションとロックを追加する必要があった
- パフォーマンス後退の原因
- 悪い決定の連鎖:
- providersAPIの設計ミス → パフォーマンス後退 → キャッシングとRCUによる追加の複雑性 → さらなるバグ → それでもパフォーマンスは最初より悪い
- OpenSSLのソースコードを読むことが苦痛になった:
- 間接呼び出し/オプションパス/#ifdef/その他の理解への障害の数が驚くべきもの
- 以前はそうではなかったしLibreSSL/BoringSSL/AWS-LCでもそうではない
■ 5. テストと検証の問題
- OpenSSLプロジェクトはテストを十分に優先していない
- OpenSSL 3.0開発サイクル中にテストカバレッジのギャップが顕著に見えた:
- 16ヶ月にわたる19のプレリリースの拡張アルファ/ベータ期間中にコミュニティからの後退報告に大きく依存
- 自社テストでは意図しない実世界の破損をキャッチするには不十分だった
- バグ修正が付随する回帰テストなしでランドされることがまだ一般的
- OpenSSLのCIは非常にフレーキー(不安定)でプロジェクトはこのフレーキーさを許容するようになった
- OpenSSL 3.0.4の重大なバグの例:
- AVX-512対応CPUでのRSA実装に重大なバッファオーバーフロー
- CIで実際にキャッチされていたがCIランナーがたまたまAVX-512 CPUを持っている場合にのみクラッシュが発生したため障害はフレーキーさとして却下された
- 3年後もテストが失敗するコードをマージ:
- カンファレンススライド準備日には最近の10コミット中5つがCIチェック失敗
- トーク前日にはすべてのコミットがクロスコンパイルビルド失敗
- Intel SDEなどのツール採用の価値:
- x86-64拡張命令の異なるサブセットを持つCPUに対する制御されたテストが可能
- AVX-512の有無での専用テストジョブを持つことで障害の性質がすぐに読みやすく再現可能になる
- OpenSSLは形式検証の最先端に追いついていない:
- 形式的手法は学術的な新奇さから暗号コードの意味のある部分に対する実用的な現実になった
- BoringSSLとAWS-LCは形式的に検証された実装を組み込み自動推論を使用して保証を高めている
■ 6. メモリ安全性の問題
- OpenSSL作成時にはパフォーマンス/埋め込み可能性/メモリ安全性を意味のある形で提供するプログラミング言語はなかった
- 世界は変わった:
- 約5年前にpyca/cryptographyはRustコードを組み込んだ最初のリリースを発行
- それ以来ほぼすべての機能をRustに移行
- 純粋なRustですべてのパースとX.509操作を行い暗号アルゴリズムにはOpenSSLを使用
- パフォーマンス向上と複数のOpenSSL CVEの回避を達成
- これらの移行が可能であることを彼らは知っている
- セキュリティにコミットしたライブラリはメモリ安全なプログラミング言語への長期的な移行にコミットする必要がある
- OpenSSLはこの問題に全くイニシアチブを示していない
■ 7. 原因の考察
- これは資金不足やコモンズの悲劇の問題ではない
- Heartbleed以降の10年間でOpenSSLはかなりの資金を受け取っている
- 現時点でOpenSSL CorporationとFoundationはBoringSSLまたはLibreSSLでフルタイムで働く人数より多くのソフトウェアエンジニアを雇用
- 他のOpenSSLフォークがこれらの同じ設計選択をしていないという事実は「これが必要だったか」という質問に対して有益な情報
■ 8. 今後の方向性
- ポリシー変更1:
- 新機能にOpenSSL実装を要求しない
- LibreSSL/BoringSSL/AWS-LCでのみ利用可能な新しいAPIを追加
- 具体的にはML-KEMとML-DSA APIをLibreSSL/BoringSSL/AWS-LCでのみ利用可能にしOpenSSLでは利用不可
- ポリシー変更2:
- 現在wheelsにOpenSSLのコピーを静的リンクしている
- wheelsをOpenSSLフォークの1つにリンクするために何が必要かを調査開始
- ポリシー変更3:
- バイナリwheelsをOpenSSLフォークの1つに切り替えることに成功した場合OpenSSLのサポートを完全に廃止する状況の検討を開始
- 長期的方向性:
- GraviolaなどのOpenSSL派生でない暗号ライブラリを潜在的な代替として積極的に追跡
- 暗号実装を提供するために使用するライブラリの変更はユーザー(特に再配布者)に大きな影響を与えることを認識
- これらのステップを軽々しく考えておらず急いで行うことも予想していない
- 懸念の重大さから行動せざるを得ない
- pyca/cryptographyのOpenSSLサポートに依存している場合はOpenSSLプロジェクトに関与しこれらの軸での改善に貢献することが最も抜本的なステップを避ける最良の方法
■ 1. 記事の概要
- Crank.jsの開発者Brian Kim氏による2025年8月20日の記事
- リアクティブフレームワークは自動的なUI更新を約束するが微妙なバグやパフォーマンスの罠を生み出す
- Crankの明示的なrefresh()呼び出しは制限ではなく野心的なWebアプリケーションを構築するためのスーパーパワー
- リアクティブ抽象化の一般的な落とし穴を検証しCrankがリアクティブ抽象化を持たない哲学的根拠を提供
■ 2. Crank.jsの特徴
- 「非リアクティブ」フレームワーク
- コンポーネントは関数(async関数やジェネレータ関数を含む)
- Promiseを直接コンポーネント内でawaitできる
- 状態をローカル変数として定義できる
- 状態が変更されたときにrefresh()を明示的に呼び出してビューを更新する
- refresh()コールバックAPIの導入:
- 状態変更をrefresh()コールバック内に置くことでrefresh()の呼び忘れが不可能になる
- コールバック内のコードが再レンダリングを意図していることを宣言的に特定できる
■ 3. バグの重大度分析
- バグのクラスの「重大度」を評価する2つの質問:
- これらのバグは見つけやすいか?
- これらのバグは修正しやすいか?
- Crankの場合:
- refresh()の呼び忘れバグはアプリが更新されていないことにすぐ気づくため見つけやすい
- refresh()呼び出しを追加するだけで修正しやすい
- リアクティブ抽象化は古いレンダリングを排除すると主張するが独自の落とし穴を生む
■ 4. Solid.jsの問題: リアクティビティの喪失
- Solid.jsではpropsはリアクティブストア
- propsをデストラクチャリングしたり派生値をJSX式の外で計算しようとすると失敗する
- 壊れたコンポーネントはpropsが変更されても更新されない(値を抽出してpropsからJSXへのリアクティブ接続を壊すため)
- バグの重大度:
- 単純なケースはリンタールールで見つけやすいが複雑なアプリケーションにはリンターの隙間をすり抜けるエッジケースがある
- 修正が難しい(フレームワークのリアクティブルールを理解する必要がある)
- SolidはsplitPropsやmergePropsなどのユーティリティを提供する必要がある
- Crankの明示的なrefreshモデルではこのクラスのバグは存在しない
■ 5. Vue.jsの問題: ディープリアクティビティのパフォーマンストラップ
- Vueはプロキシを使用してリアクティブオブジェクトのプロパティと子を再帰的にリアクティブ抽象化でラップする
- 深くネストされた状態が変更されたときにDOM更新を実行するのに便利
- 問題点:
- プロキシはプライベートクラスメンバーでは機能しない
- プロキシはプリミティブには使用できない(VueがreactiveとrefのAPIを両方提供する理由)
- 大きなオブジェクトや配列を深くプロキシするとパフォーマンスのボトルネックになる
- Vueはパフォーマンス問題を回避するためにshallowRef()やmarkRaw()などのエスケープハッチを提供
- 深くネストされた更新が再レンダリングを引き起こす便利さから追跡が必要な状態に移行
- VueはisReactive()などのユーティリティを提供して開発者にデータのどの部分がリアクティブかを伝える必要がある
- バグの重大度:
- リアクティビティはデータ構造に不可視に追加されパフォーマンスのために選択的に削除されるため見つけにくい
- 修正が難しい(状態が作成された場所まで遡ってなぜリアクティブかどうかを把握する必要がある)
■ 6. Svelteの問題: エフェクトと無限ループ
- Svelte v4以前は代入がコンパイラによって計装されて再レンダリングをトリガー
- Svelte v5では「runes」という特別な構文を導入($state()/$derived()/$effect()など)
- エフェクトを使用するリアクティブ抽象化は無限ループに陥りやすい:
- 同じ$state()ルーンを$effect()ルーンコールバック内で読み書きするとコールバックが発火し続ける
- リアクティビティ支持者は「スプレッドシートのようなプログラミング」と称えるが多くの計算セルを持つスプレッドシートは遅い読み込みや開けない問題を抱える
- 解決策はSvelteのuntrack()関数でルーンの読み取りを非リアクティブとしてマーク
- バグの重大度:
- 通常はすぐにスタックを吹き飛ばすが複雑なコンポーネントでは無限ループがすぐにトリガーされないエッジケースがある
- $effect()ルーンはその中で実行されるすべてのコードを着色するためエフェクトコールバック内のコードだけでなくすべてのネストされた関数呼び出しもルーンに書き込まないようにする必要がある
- 修正が困難(デバッグ時に状態をログに記録するだけで無限ループがトリガーされる可能性がある)
- CrankにはエフェクトAPIがないため無限ループを引き起こさない
■ 7. 各フレームワークのエスケープハッチ
- リアクティブ抽象化は手動更新管理を排除すると約束するがそれぞれ独自のエスケープハッチと回避策が必要:
- Solid: splitPropsとmergeProps(propsを安全に操作するため)
- Vue: shallowRefとmarkRaw(パフォーマンスの崖を避けるため)
- Svelte: untrack()(無限ループを防ぐため)
- これらのAPIはリアクティビティが更新の懸念から完全に隔離してくれないことを示している
■ 8. 実行透明性(Executional Transparency)
- 参照透明性(Referential Transparency)はデータがどのように変換されるかを「見る」ことを容易にする
- 実行透明性はコードがいつ実行されるかを「見る」ことに関する
- Crankコードは明示性により実行透明性が高い:
- コンポーネントは親によって更新されるかrefresh()が呼び出された場合にのみ実行される
- Reactは最もリアクティブ抽象化が少ないにもかかわらず最も実行不透明:
- 開発時にコンポーネントを二重レンダリング
- useEffect()/useSyncExternalStore()/useTransition()などの混乱するAPI
- コールバックがコールバックを返し任意のスケジューリングアルゴリズムの気まぐれで呼び出される
- Reactエコシステムには「Why Did You Render」などのツールや過剰レンダリングのデバッグに関する無数の誤解とブログ記事がある
■ 9. 非リアクティビティはスーパーパワー
- Webの最前線はTODOアプリではない
- 難しいもの:
- アニメーション
- 仮想リスト
- スクロールテリング
- コンテンツ編集可能なコードエディタ
- WebGLレンダラー
- ゲーム
- WebSocketストリームを使用したリアルタイムアプリケーション
- 大規模データビジュアライゼーション
- オーディオ/ビデオエディタ
- 地図
- リアクティブ抽象化はこれらの難しい問題に役立たない
- コンポーネントがいつレンダリングされるかを明示的に制御することはスーパーパワー:
- コードが実行される理由のコンテキストを維持できる
- 必要なときに正確にレンダリングできる
- これらの重要な決定を仲介するリーキーなリアクティブ抽象化がない
■ 1. Constelaの概要
- 江口優一(yuu1ch13)氏によって開発されているオープンソースのUI言語およびフレームワーク
- 「UIをJavaScriptではなくJSON(DSL)で記述する」という非常にユニークなコンセプトを持つ
- 2026年1月時点で活発にアップデートが行われている(直近ではv0.8.0など)
■ 2. コンセプト: Compiler-First UI言語
- 従来のWeb開発(ReactやVueなど)ではJavaScriptのコードとしてUIを記述し実行時にそのロジックを動かす
- ConstelaはUIを「プログラム(命令)」ではなく「検証可能なデータ(JSON)」として扱うことを重視
- コンパイル時検証:
- 未定義の状態(state)の参照や不正なアクション/構造の不整合などを実行前に検出できる
- 静的解析の容易さ:
- 任意のJavaScript実行を排除し制約されたJSON形式にすることでUIの振る舞いが決定論的(予測可能)になる
■ 3. AIとの高い親和性
- 開発者が明示している大きな目的の一つが「AIによるUI生成・修正」への最適化
- 自然言語で書かれたコード(JSXなど)はAIにとって自由度が高すぎバグを含みやすいという課題がある
- Constelaは構造化されたJSONであるためAIが「どのボタンがどの状態を更新するか」を正確に把握しやすい
- 機械的な自動生成や修正のワークフローに適している
■ 4. 主な機能と技術的特徴
- State & Action:
- UIの状態管理や副作用もJSON内で宣言的に定義
- Style System:
- Tailwind CSSのようなクラスベースのスタイリングが可能
- CVA(Class Variance Authority)ライクなバリアント管理が可能(v0.8.0以降)
- Builder API:
- AIツールなどがプログラムからUIを構築するためのTypeScript APIを提供
- コンポーネント化:
- PropsやSlotといった概念も備えており再利用可能なUIパーツを定義できる
■ 5. 役立つ場面
- AI生成UI:
- ユーザーの指示からAIが即座に管理画面やダッシュボードを生成するようなアプリケーション
- UIの安全な自動更新:
- 人間がコードを書かずにシステムのメタデータからUIを動的に構成したい場合
- ノーコード/ローコードツールの基盤:
- 構造化データとしてUIを保持する必要があるサービスのバックエンド
■ 6. まとめ
- 単なる新しいUIライブラリではない
- 「人間が手でコードを書く時代から機械(AI)がUIを構成・検証する時代」を見据えた次世代のフロントエンド基盤を目指しているプロジェクト
- 特にAIとの連携機能や開発体験の向上が図られている
■ 1. 問題提起と背景
- レイヤリングへの疑問:
- Controller -> UseCase -> Domainsというドメイン駆動なレイヤリングに対して本当にUseCaseは必要なのかという問いに向き合う
- どちらもロジックを持ち得るレイヤーでどう棲み分けするのが良いのか
- 以前のアーキテクチャ:
- MVCというレイヤー分けをしてそれ以外にレイヤーを増やさないという誤ったRails Wayへの則り方だった
- 前任者の当時の判断は環境や状況にあったものだったかもしれないので悪いことだとは思っていない
- アーキテクチャの修正:
- CQRSの考え方を導入しレイヤーを一枚増やした
- controllerがdomainsに依存する構成に修正した
■ 2. 新たな課題の発生
- domainsの依存問題:
- domainsがdomainsに依存してしまう状況が発生した
- 複雑なロジックを共通化するにあたりdomainsがdomainsを呼び出す箇所が生まれた
- ロジックを書く場所がdomainsもしくはmodelsしか現状無いため
- 依存させたくないdomainsが依存を持ってしまうことになりアーキテクチャの破綻になってしまう
- UseCaseの必要性への疑問:
- UseCaseはやはり必要なのではないかという考えが生まれた
- しかしUseCaseを挟んだところで今Controller -> Domainsでうまくいっている箇所においてはただdomainsを呼ぶだけのUseCaseができる
- あまりにそういうのが増えて冗長なのではないかという疑問が生まれた
■ 3. DomainsとUseCaseの役割
- Domainsの役割:
- 主な役割はビジネスロジックの実装
- 操作するものはDomainsオブジェクト
- ビジネスルールはドメイン固有のルールを実装する
- UseCaseの役割:
- 主な役割はユースケースの実装
- 操作するものはDomainsクラス
- ビジネスルールはユースケースに沿った手順を実装する
- 本質的な違い:
- DomainsとUseCaseは全く異なるもの
- Domainsはサービスを展開するビジネス上におけるドメイン知識を含む
- Domainsがアプリケーションの知識を持つ必要は全く無い
- Domainsのコードそのものがドメイン知識を持つドキュメントとしても在るべき
- UseCaseはドメイン知識を纏ったDomainsをユーザーストーリーにあったユースケースの手順に合わせて実装されるもの
- UseCaseがドメイン知識を知る必要はなくユースケースにあったDomainsを利用するだけで良い
- だいぶ抽象化されたドメインという概念を扱うだけの裏の苦労を知らないお客さん的なイメージ
■ 4. UseCaseの必要性の検討
- 現状の構成:
- ControllerがDomainsに直接依存しているアプリケーションという状況
- UseCaseの導入による弊害もある
- UseCaseの弊害:
- Controller -> Domainsでうまくいっている箇所においてはただdomainsを呼ぶだけのUseCaseができてしまう
- 呼ばれたらdomainsを呼び出すだけという冗長なクラスが増えていってしまう
- 段階的導入の困難さ:
- 全体にUseCaseを挟むというルールにするにはエンドポイント数的にも不可能なので段階的にはなる
- そもそもUseCaseはoptionでいいんじゃないかという疑問が生まれた
- 相談結果:
- 冗長なUseCaseは増やさずとも良い
- Controllerから直接Domainsに依存したところで問題はない気がする
- もし他の手続きが必要になったならUseCaseを挟むのはそこまで大変な作業ではない
■ 5. まとめ
- UseCaseの必要性:
- UseCaseがなくても問題はない
- 役割の明確化の重要性:
- Domainsにはドメインとなるロジックを抽出する
- UseCaseはユースケースを実現するためのドメインを利用した手続きを書く
- それぞれの役割を明確に意識することが重要
- これはもちろんアプリケーションの実装ルール次第
- それぞれの役割を明確に意識することでUseCaseにドメインロジックが生まれるなどの破綻を回避することができる
■ 1. 記事の概要
- 2018年から2019年夏頃までの1年半フリーランスエンジニアとして活動した経験に基づく
- フリーランスになってどこかの会社で業務委託として働くスタイルは長期的にはオススメできない
- フリーランスとして業務委託で働く形態には経験が積みづらくなる構造的な力学が働いている
- 個人の努力や能力とは関係なくその構造の中にいると自然とそういう方向に引っ張られる
■ 2. フリーランス時代の振り返り
- 「経験を切り売りしていた」という感覚が強い
- お金は得られたが新しい経験はほとんど積めなかった
- 社会的な価値も全然つかなかった
- 市場価値としてはほとんど上がっていなかった
- 危機感を覚えたのでフリーランスを辞めCTOになった
■ 3. 構造的な問題1: 挑戦させてもらいづらい
- 業務委託に入ると基本的に「成功しそうなことしか任せてもらえない」状況になる
- クライアントからすれば外部の人間に失敗のリスクがある仕事を任せるのは怖い
- 正社員なら失敗しても一緒に成長していける
- 業務委託は失敗したら契約を切れば良いので確実にできることしか任せない
- 正社員は育成投資の対象になれるが業務委託はならない
- 得られにくい機会:
- 新しい技術に挑戦する機会
- 難易度の高いプロジェクトをリードする機会
- 事業の意思決定に関わる機会
- フリーランスエンジニアが「得意なことをやり続ける」状態に陥る
- 効率は良いが成長はない
■ 4. 構造的な問題2: 社会的な評価が蓄積されにくい
- 「業務委託として開発」と書いても何をどこまで任されていたのかが見えない
- 「リードエンジニアとして事業を推進」と書けばオーナーシップを持って取り組んでいたことが伝わる
- 実際にやっていた仕事の内容が同じでも肩書きと立場で見え方が変わる
- フリーランスとして働いている間その経験がどんどん「消費」されていく
- 正社員として働くとその会社での実績が積み上がり次第により大きな責任を持つポジションに就く
- フリーランスの場合いくら長く働いても「外部の人」のまま
■ 5. 構造的な問題3: マネジメントや組織の意思決定に関われない
- エンジニアとして成長するには技術力だけでは足りない
- ある程度のキャリアを積んだ後は技術以外の能力が重要となる場合が多い
- 組織としての意思決定/マネジメント経験は組織の中で責任あるポジションに就かないと身につかない
- 外部の人間に組織のコアな部分を任せることはほとんどの会社がしない
- 採用の判断/チーム編成/評価制度/組織文化の形成は全て「中の人」だけで行われる
■ 6. この構造が生まれる根本的な原因
- 企業が「企業内人的資本の最大化」を目指すから
- 企業内人的資本 = 社員のスキル・知識・経験・ノウハウの総和
- 企業内人的資本が企業の競争力の源泉になる
- 正社員に投資すればその成長は企業内に蓄積される
- 業務委託に投資しても契約が終われば企業外に流出してしまう
- 正社員を雇う場合は長期的な視点で投資する
- 業務委託を使う場合は短期的な視点で考える
- 「投資対象かどうか」の違いが全ての構造的な問題の根源
■ 7. 例外: 労働市場の需給で変わるケース
- 「需要が供給を大きく上回るスキル」を持っている場合は状況が変わる
- 希少人材の例:
- 特定の領域で日本に数人しかいない専門家
- 世界的に見ても希少な技術スタックの経験者
- 業界で名前が知られているレベルの実績がある人
- オープンソースのメインコミッターなど代替不可能な立場の人
- こういった人はフリーランスであっても立場が強い
- これは例外中の例外
- ほとんどのエンジニアは「できる人が他にもいる」領域で仕事をしている
- 「自分は希少人材だ」と思い込んでフリーランスになるが実際にはそこまで希少ではなかったケースをよく見る
- 希少人材で居続けることができるかについてもよく考えるべき
■ 8. 「即戦力」という罠
- フリーランスが求められるのは即戦力
- 即戦力として評価されるのは「今持っているスキル」
- 新しいスキルを身につける機会ではなく既存のスキルを使う機会を与えられる
- 最初は問題ないが数年経つと技術は進化する
- フリーランスは「今持っているスキル」で契約しているから新しいことを学ぶ機会が少ない
- 正社員なら会社が新しい技術の研修を受けさせてくれることもある
- 業務委託は新しいことに挑戦するコストは自分で負担するしかない
- 「即戦力」として求められ続けることで皮肉にも「戦力としての価値」が下がっていく
■ 9. 社会資本という見えない資産
- 社会資本とは人間関係や信頼関係を通じて得られる価値
- 人脈/信用/評判/実績
- 正社員として働くと社会資本は自然と蓄積される:
- 同僚との信頼関係
- 上司からの評価
- 社内での実績
- 業界内での評判
- 昇進による肩書き
- フリーランスの場合社会資本が蓄積されにくい
- 業務委託として入った会社の人との関係は契約が終われば薄れていく
- 毎回ゼロから信頼を築き直さないといけない
■ 10. 「自由」の代償
- フリーランスになる理由として多くの人が「自由」を挙げる
- 働く時間を自分で決められる/嫌な仕事を断れる/場所を選ばずに働ける
- しかしその自由には代償がある:
- 挑戦の機会を得る自由は失われる
- 成長する機会を得る自由も失われる
- 責任あるポジションに就く自由も失われる
- 表面的な自由と引き換えにキャリアの自由度を失っている
■ 11. 構造から抜け出す選択肢
- 選択肢1: 正社員に戻る
- 組織の中で責任あるポジションに就き挑戦の機会を得て社会資本を蓄積する
- フリーランスの構造的な問題を根本的に解決する方法
- 選択肢2: 自分で事業を作る
- 業務委託ではなく自分のプロダクトを持つ
- 自分が意思決定者になりリスクも責任も自分が負う
- 構造的な問題を「逆転」させる方法
- 選択肢3: 戦略的にフリーランスを使う
- 長期間続けるのではなく特定の目的のために一時的に使う
- キャリアの転換期に複数の会社を経験するため/特定のスキルを集中的に使って実績を作るため/正社員のオファーを見極めるため
- 強い意志が必要
■ 12. キャリア早期にフリーランスになる人に向けて
- 20代から30代前半はキャリアの中で最も成長が期待できる時期
- この時期に「確実にできることしか任せてもらえない」環境に身を置くのはもったいない
- 経験の価値は「複利」で効く
- 20代で得た経験は30代のキャリアに効き30代で得た経験は40代のキャリアに効く
- フリーランスで「経験の切り売り」を続けるとこの複利が効かなくなる
- 10年後/20年後のキャリアを考えた時今どんな経験を積むかは決定的に重要
■ 13. まとめ
- フリーランスエンジニアが経験を積みづらくなるのは個人の問題ではなく構造の問題
- この構造は「投資対象かどうか」という違いから生まれている
- フリーランスになること自体が悪いわけではなく目的を持って期間を区切って戦略的に使うなら問題ない
- 問題はこの構造を理解せずにフリーランスを続けること
- フリーランスを選ぶならこの構造を理解した上で選ぶこと
- 定期的に「今の自分は成長できているか」「社会資本は蓄積されているか」を問い直すこと
- 表面的な自由や短期的な収入より長期的な成長とキャリアの自由度の方が結局は大きな価値を生み出す