Upgrade to Pro — share decks privately, control downloads, hide ads and more …

痛みからOSSを作った話

Avatar for krile krile
August 16, 2026

 痛みからOSSを作った話

Avatar for krile

krile

August 16, 2026

Other Decks in Programming

Transcript

  1. 自己紹介 名前: 松岡宏行 年齢: 38歳 所属: 株式会社unitedworks 飼料会社で営業と仕入部門 受託開発会社でPM 自社開発企業でLaravelエンジニア

    → 担当者退職に伴いsalesforceを触り始める 株式会社unitedworks にて salesforce エンジニアしてます
  2. OSS作成のきっかけ 5年運用した組織で、請求情報生成の仕様変更が発生! • 複雑な請求情報生成処理が 1 つの神クラスに全部入っている • テストはリリース要件の75%を満たすものだけ。Assertはされていない • 依存するオブジェクト多い。1

    本テストを書くのに全部用意する • 取引先→商談→見積→見積明細→請求情報 • 他にも商品や請求先部署とかもある TestDataFactoryがあるが、動かすだけで落ちる バグを起こさずにリリースは不可能な状態
  3. OSS作成のきっかけ Laravelでやってたアーキテクチャを輸入だ! controller data-access object-oriented 1 method 1 usecase DBへの依存の

    抽象化 usecaseを責務毎 に作る デグレゼロ、仕様変更分の不具合ゼロ 特殊ケースで不具合1件、責務を分けて作っていたので速攻で修正完了
  4. 組織の成長に伴う影響 Tame the Deployment Tax: Faster, Smarter Test Runs Salesforce

    architect blog 2026/6/8 最初はとても機敏に動く環境 成長するに従い段々と重くなる 全てのテストの実行が辛くなる 開発速度の維持ができなくなる これは導入に成功した組織のほとんどが辿る道
  5. そして Headless 360 エージェントが org を触る前提となった 書く デプロイ テストを回す エージェントはこの輪を1日に何周も回す

    エージェントが書く量が増えるほど、輪を回す回数が増える 回転数を決めるのは、テストの実行時間 だから Mock がいる この後の検証も Claude CodeがDeveloper組織に直接デプロイして回しています 直す
  6. 速さの比較 テストメソッド一つあたりの平均実行時間 15 ms Mockを使ったクラス VS 272〜1,062 ms 2組織における実DMLのクラス 1つ目:まだ若い組織

    2つ目:そこそこ成長した組織 組織 が育つほど差が開く。組織が成長しても Mock の速度は変わらない。
  7. バグの検出力 ミューテーションテストによる「変異の検出率」 Mock 83.4% 実 DML vs 79.3% 同じ仕様を Claude

    Code に渡して、Mock 版と実 DML 版のコードを生成 334体の変異体で「変異の検出率」を計測(=バグを捕まえる力) 実装様式が変わっても、検出力は落ちない
  8. コード生成の時間と消費トークン量の増加 Mock版、DML版のコード生成をClaudeCode2体に対して依頼、計測 手 性質 トークン 時間 Phase1: 請求情報作成 ゼロから 3.8倍

    3.1倍 Phase2: 仕様変更 既存に積む・5オブジェクト 横断 1.66倍 1.75倍 Phase3: フェーズ対応とロック 再入・固定点・拒否ロジック 1.15倍 0.99倍 装備の税は前払いで、複雑さが増すと回収される さらにPhase2実装中に、Mock版が「SOQL 101個 発行してガバナ制限エラー」にぶつかった → 単体テストはクエリを実際に発行しないので結合テストで初めてN+1に遭遇。 → Mockはガバナ制限に盲目なので、「結合テストが絶対に必要」な根拠の一つ
  9. デプロイのブロック フレームワーク自体がデプロイをブロックすることがある ApexEloquentのテストが Account > Contact > Opportunity の入れ子クエリを組んでいる。 ある顧客組織では

    Opportunity に Contact への Lookup が追加されていたため Contactから見たOpportunityの子リレーションが2本になり 「どちらか判断できない」という例外で落ちた。 フレームワークの動作としては正しい(曖昧なら黙って選ばず落ちる)。 壊れていたのはテストがorgスキーマに依存していたこと Account Contact Opportunity Opportunity2 子供のうち、オブジェクトが 「Opportunity」のものを連結 → 1つならOK → 2つ以上なら落とす (リレーション名指定必須)
  10. ApexEloquent特有の問題ではない 株式会社ユーザベースさんの事例。Apex Fluently(企業がメンテしている別のOSS)を導入し た際の記事より 当初、Apex Fluently の各ライブラリをすべて Git サブモジュールでソース管理しようとしたところ 本番デプロイ時にOSS

    側のテストクラスが環境差分で落ちるという問題に当たりました。 独立した別の会社が、別のOSSで、まったく同じ問題を踏んでいる → 原因はOSSの品質ではなく、OSSのテストクラスが組織のスキーマに晒されるという構造にある → したがって対策も一般解がある。アンロックパッケージで入れられるものはパッケージで入れる (パッケージ内のテストは自組織のテスト実行対象に入らない) 私のOSS群はまだアンロックパッケージを用意していない・・・が、考えています
  11. 付録 参考資料名 URL Tame the Deployment Tax: Faster, Smarter Test

    Runs https://www.salesforce.com/blog/faster-deploymenttest-runs/ 遅い・重い・書きづらい Apex テストを「モック 化」で作り変えた話 https://tech.uzabase.com/entry/2026/07/07/171729 The Joys Of Apex https://www.jamessimone.net/blog/joys-of-apex/ おすすめ! OSSリンク URL ApexEloquent https://krileworks.com/ja/apexeloquent ApexBlueprint(結合テスト用データファクトリ OSS) https://krileworks.com/ja/apexblueprint Claude Code用 SKILL置き場 https://krileworks.com/ja/agent-skills
  12. 資料:コード生成の時間と消費トークン量の増加試験内容 Phase1: 請求情報生成グリーンフィールド Phase2: 請求情報の仕様変更 請求 insert → 親見積の予定売上を delete、請求ごとに確定売上を

    create 税抜=請求の税抜合計 / 税額=税込−税抜 / 計上日=支払期限 同時に 親見積.Confirmed__c = true → 見積.RevenueAmount__c = Σ(予定売上.税抜 × 商談.Probability) + Σ(確定売上.税抜) → 商談.RevenueTotal__c = Σ(確定見積.RevenueAmount__c) → 収束まで再評価(IsChanged で固定点) Phase3: フェーズ判定とロック追加 フェーズ判定(単調・後戻りしない / 累積的) 確定見積あり → 見積確定 納品あり → 納品書提出 請求あり・支払期限 >= 今日 → 請求中 請求あり・支払期限 < 今日 → 完了 ロック 確定見積の配下に 納品 / 見積明細 を insert しようとしたら before-insert で拒否