Apex Stem をはじめる

Apex Stem ドキュメント
Apex StemGet StartedIntroduction
Apex Stem の短い導入。書き直しは不要、最小の一歩から始められます。

Apex Stem は、Handler-Usecase アーキテクチャと、それを支える OSS 群でできています。何かを書き直す必要はありません。今日のコードを少しでも良くする最小の一歩から始めて、そこから育てていけます。

このページは短い導入です。本格的な移行手順が必要になったら、ページ下部のリンクから 4 ステップの完全ガイドに進めます。

コード例は ApexEloquent v2 以降で動きます。v3 では SOQL/DML の既定がユーザーモード (FLS を尊重) になっているため、実行ユーザーの項目権限にご注意ください。

得られること

  • テストが本番より甘くならない。実 SOQL で取ったレコードは、SELECT していない項目に触ると例外になります。ところが、テスト用に自分で組み立てた SObject にはその検査がありません。テストのときだけ緩くなり、本番で初めて落ちます。ApexEloquent のモックは本番のクエリが何を SELECT しているかを知っているので、テストの段階で落ちます。
  • 単体テストが数 ms で回る。DB に触らないので、org に Flow やトリガーが増えても速度が変わりません。速いから気軽に実行でき、フィードバックのループが回り続けます。
  • 構造がそのまま見える。親子関係はインデントで書けます。クエリの組み立ても、テストデータの生成も、コードの形がデータの形になります。
  • AI に渡す規約が軽い。アーキテクチャの宣言は 30 行ほどで書けます (実物は Handler-Usecase Architecture に掲載)。CLAUDE.md に常駐させても、他に読ませたいコンテキストを圧迫しません。
  • 大規模な書き直しは不要。Usecase 1 つ、モック可能なクエリ 1 本ずつ進められます。

最初の一歩

今日ひとつだけやるなら、これです。いまインラインで書いている SOQL を 1 本、ApexEloquent の型付きビルダー Scribe 経由に通します。

Before

APEX
List<Account> accounts = [
  SELECT Id, Name FROM Account WHERE Industry = :industry
];

After

APEX
Scribe accountScribe = Scribe.of(Account.class)
  .field('Id')
  .field('Name')
  .whereEqual('Industry', industry);
 
List<IEntry> accountEntries = new Eloquent().get(accountScribe);

挙動は変わりません。変わるのは、テストから見たときのこの 1 本です。

  • 差し替えられるようになる。テストでは Eloquent の代わりに MockEloquent を注入すれば、DB に触らずにこのクエリの結果を決められます。
  • SELECT 漏れが、テストで落ちるようになる。上の例は IdName しか SELECT していません。もし後続のコードが Industry を読んだら、その場で例外になります。素の SObject なら null が返って静かに通り、本番で初めて気づくところでした。

これだけです。1 本ずつ進めれば十分。Usecase の切り出しやテスト層の追加は、準備ができてからで構いません。

補足: フィールドは SObjectField ではなく文字列 ('Id''Industry') で渡します。これにより、ビルダーは動的に組み立てられます。

さらに先へ進む準備ができたら

フルガイドでは、実際に動くコードとともに 4 つの段階的なステップを解説します。

  1. Scribe で SOQL を置き換える (上記をさらに展開)
  2. 結果を IEntry のまま扱う。早すぎる SObject 変換が罠になる理由
  3. Usecase を切り出す。Layered Constructor Pattern
  4. 適切な層でテストする。Usecase は MockEloquent、Handler は ApexBlueprint

フルガイドを読む

フレームワークを組織に入れる準備ができたら → Installing Apex Stem へ。コマンド1つの Unlocked Package と git submodule、2つの導入経路を解説しています。