背景と応用シーン
Salesforce 開発者として、私たちは単に特定の組織(Org)のためのカスタム機能を構築するだけでなく、より広範なオーディエンスにソリューションを配布する方法を模索することがよくあります。ここで中心的な役割を果たすのが Managed Packages(管理パッケージ)です。Managed Package は、Apex クラス、Lightning コンポーネント、カスタムオブジェクト、Visualforce ページなど、Salesforce のメタデータを一つのユニットとしてまとめ、他の Salesforce 組織に配布するためのコンテナです。これは AppExchange でアプリケーションを販売する ISV (独立系ソフトウェアベンダー) パートナーにとって不可欠なツールですが、大企業が複数の組織に標準化されたソリューションを展開するためにも利用されます。
Managed Packages は、特に以下のようなシナリオでその真価を発揮します。
AppExchange での商用アプリケーション配布
開発したソリューションを AppExchange を通じて販売する場合、Managed Package は必須です。これにより、知的財産(特に Apex コード)を保護し、顧客に対してシームレスなインストールとアップグレードの体験を提供できます。購読者(Subscriber)はコードの中身を見ることはできませんが、global として定義されたメソッドやコンポーネントを利用して拡張することが可能です。
標準化されたソリューションの複数組織への展開
フランチャイズビジネスや、グローバルに複数の Salesforce 組織を持つ大企業では、各組織で共通のビジネスプロセスやコンポーネントを維持する必要があります。Managed Package を使用することで、本社で開発したコア機能をパッケージ化し、各子会社やフランチャイズの組織に配布・一元管理できます。アップグレードも一括してプッシュできるため、保守性が大幅に向上します。
知的財産の保護
Unmanaged Packages(非管理パッケージ)とは異なり、Managed Package 内の Apex コードは購読者組織からは見えません。これにより、開発者が時間と労力をかけて構築した独自のロジックやアルゴリズムを保護することができます。
原理説明
Managed Package の核心を理解するためには、開発者としていくつかの重要な概念を把握する必要があります。
Namespace(名前空間)
Managed Package を開発する上で最も重要な概念の一つが Namespace(名前空間)です。これは、パッケージ内のすべてのカスタムコンポーネント(カスタムオブジェクト、Apex クラス、Visualforce ページなど)に付与される、組織全体で一意のプレフィックスです。例えば、名前空間が my_app
であれば、Invoice__c
というカスタムオブジェクトは my_app__Invoice__c
となり、Apex クラス MyController
は my_app.MyController
となります。
この Namespace により、パッケージをインストールする購読者組織に既に存在するコンポーネントとの名前の衝突(Naming Conflict)を完全に防ぐことができます。これは、他の開発者が作成したパッケージや、購読者自身のカスタマイズと共存するための不可欠な仕組みです。
開発ライフサイクルと Salesforce DX
現代のパッケージ開発は、Salesforce DX (Developer Experience) と Dev Hub(Dev Hub 組織)を中心に行われます。
- Dev Hub の有効化: 開発の拠点となる本番組織またはトライアル組織で Dev Hub を有効にします。
- Scratch Orgs(スクラッチ組織)の作成: Dev Hub から、開発用の使い捨て環境である Scratch Org を作成します。この際、Namespace を指定して作成することで、パッケージ開発専用の環境を整えます。
- 開発: VS Code などのローカル IDE を使用してソースコードを開発し、Salesforce CLI を通じて Scratch Org にデプロイします。
- パッケージバージョンの作成: 開発が一段落したら、Salesforce CLI を使用してパッケージのバージョンを作成します。これにより、特定の時点でのメタデータのスナップショットが作成されます。
sf package version create --package "My Package" --path force-app --installation-key-bypass
- バージョンの昇格とリリース: テストが完了したバージョンは「Released(リリース済み)」に昇格させることで、本番組織へのインストールが可能になります。
Apex のアクセス修飾子
Managed Package 内の Apex コードでは、アクセス修飾子の意味合いが通常と少し異なります。
- private: 同じクラス内からのみアクセス可能。
- public: 同じ Namespace 内のどの Apex コードからでもアクセス可能。ただし、Namespace の外(購読者組織のコード)からはアクセスできません。
- global: パッケージの Namespace の外、つまり購読者組織の Apex コードや API からもアクセス可能なコンポーネントを定義します。外部に公開する API や拡張ポイントを作成する際に使用します。一度 global としてリリースしたメソッドや変数のシグネチャは、後方互換性を壊すため変更できません。
- protected: 同じ Namespace 内の、クラスを継承したサブクラスからのみアクセス可能。
アップグレードと後方互換性
Managed Package の大きな利点は、アップグレード機能です。新しいバージョンをリリースすると、顧客は AppExchange から、またはプッシュアップグレードによってアプリケーションを更新できます。しかし、これには開発者側に大きな責任が伴います。特に、一度 global として公開したコンポーネント(Apex メソッド、項目など)を削除したり、シグネチャを変更したりすると、それを参照している購読者組織のカスタマイズが壊れてしまう「Breaking Change」となります。このような変更は原則として許されていません。
示例代码
Managed Package の開発においてよくあるシナリオは、パッケージのインストール後に初期設定やサンプルデータを作成する処理です。これを実現するために、Salesforce は InstallHandler
インターフェースを提供しています。
以下のコードは、Salesforce の公式ドキュメントに基づいた InstallHandler
の実装例です。このコードは、パッケージがインストールまたはアップグレードされた後に自動的に実行されます。
PostInstallScript.cls
global class PostInstallScript implements System.InstallHandler { // onInstall メソッドは、パッケージのインストールまたはアップグレードが完了した後に // Salesforce によって自動的に呼び出される。 // context オブジェクトには、インストールに関するコンテキスト情報が含まれる。 global void onInstall(System.InstallContext context) { // context.previousVersion() を使用して、アップグレードかどうかを判定できる。 // 初回インストールの場合は null が返される。 if (context.previousVersion() == null) { // 初回インストール時にのみ実行したい処理をここに記述する。 // 例えば、カスタム設定の初期化やウェルカムメールの送信など。 createSampleData(); } // isUpgrade() メソッドでもアップグレードかどうかを判定可能。 // true の場合はアップグレード、false の場合は新規インストール。 System.debug('Is Upgrade: ' + context.isUpgrade()); System.debug('Previous Version: ' + context.previousVersion()); System.debug('Current Version: ' + context.version()); System.debug('Installer ID: ' + context.installerId()); } // サンプルデータを作成するプライベートメソッド。 // このメソッドは global ではなく、クラス内からのみ呼び出される。 private void createSampleData() { // ここでは、名前空間プレフィックスが 'my_ns' であると仮定する。 // 実際には、動的に名前空間を取得するか、ハードコードする必要がある。 // 例として、'my_ns__Sample_Object__c' というカスタムオブジェクトに // レコードを作成する。 // // 注意:DML 操作はガバナ制限内に収める必要がある。 // 大量のデータを作成する場合は、バッチ Apex などを起動することを検討する。 List<my_ns__Sample_Object__c> samples = new List<my_ns__Sample_Object__c>(); for (Integer i = 0; i < 5; i++) { samples.add(new my_ns__Sample_Object__c(Name = 'Sample Record ' + (i + 1))); } if (!samples.isEmpty()) { try { insert samples; } catch (DmlException e) { // インストールスクリプト内でのエラーハンドリングは非常に重要。 // ここで例外が発生すると、パッケージのインストールが失敗することがある。 System.debug('Sample data creation failed: ' + e.getMessage()); } } } }
このクラスをパッケージに含めると、パッケージ設定で「インストール後スクリプト」として指定できます。これにより、顧客がパッケージをインストールした直後に、アプリケーションが正しく機能するための準備を自動的に整えることができ、ユーザー体験を大幅に向上させることが可能です。
注意事項
Managed Package の開発には、特有の考慮事項が多数存在します。
権限とセキュリティ
パッケージに含めるカスタムオブジェクトや項目、Apex クラスへのアクセス権は、プロファイルではなく Permission Sets(権限セット)を使って管理するのがベストプラクティスです。パッケージに権限セットを含めて配布し、購読者組織の管理者がその権限セットを各ユーザーに割り当てる、という運用が推奨されます。これにより、購読者組織のプロファイル設定を上書きすることなく、柔軟な権限管理が可能になります。
API 制限とガバナ制限
パッケージ内のコードは、購読者組織のガバナ制限と API 制限の下で実行されます。つまり、あなたのコードが非効率で、多くの SOQL クエリや DML ステートメントを発行する場合、購読者組織全体のパフォーマンスに影響を与え、制限超過エラーを引き起こす可能性があります。常に一括処理(Bulkification)を意識し、効率的なコードを記述することが求められます。
コンポーネントの削除と非推奨化(Deprecation)
一度リリースした Managed Package から、公開(global)したコンポーネントを削除することはできません。もし不要になった global メソッドがある場合、それを削除する代わりに @Deprecated
アノテーションを付与して「非推奨」としてマークします。
@Deprecated global static void oldMethod() { // ... }これにより、このメソッドは新規のコードからは参照できなくなりますが、既存の実装は壊れません。将来のメジャーリリースで完全に削除するための移行期間を設けることができます。
AppExchange セキュリティレビュー
AppExchange でアプリケーションを公開するには、Salesforce のセキュリティレビューに合格する必要があります。これには、CRUD/FLS の強制、SOQL インジェクション対策、クロスサイトスクリプティング(XSS)対策など、多くのセキュリティ要件が含まれます。開発の初期段階からこれらの要件を念頭に置いて設計・実装することが不可欠です。
まとめとベストプラクティス
Managed Package は、Salesforce プラットフォーム上で再利用可能かつアップグレード可能なアプリケーションを構築し、配布するための強力なメカニズムです。開発者としてこの仕組みをマスターすることは、スケーラブルなソリューションを提供し、AppExchange エコシステムで成功を収めるための鍵となります。
以下に、Managed Package 開発におけるベストプラクティスをまとめます。
- Salesforce DX を活用する: Dev Hub、Scratch Org、Salesforce CLI を使用したモダンな開発フローを採用し、ソースコードをバージョン管理システム(Gitなど)で管理しましょう。
- API の設計を慎重に行う: 何を
global
として公開するかは、パッケージのアーキテクチャにおける最も重要な決定の一つです。一度公開した API は簡単には変更できないため、将来の拡張性も考慮して慎重に設計してください。 - 後方互換性を常に意識する: アップグレードによって顧客の既存のカスタマイズを破壊しないように、最大限の注意を払いましょう。Breaking Change は絶対に避けるべきです。
- 権限セットを活用する: 権限管理にはプロファイルではなく、パッケージ化可能な権限セットを使用し、購読者組織の管理者に柔軟性を提供します。
- テストを徹底する: Apex の単体テストで高いコードカバレッジ(75%以上)を維持することはもちろん、さまざまなエディションや設定を持つ組織でのインストール・アップグレードテストも重要です。
- 購読者の体験を考える: インストール後の設定を簡単にするための
InstallHandler
スクリプトや、詳細なドキュメント、設定ガイドを提供することで、顧客満足度を高めることができます。
Managed Package 開発は複雑で挑戦的な側面もありますが、その先には広大な AppExchange 市場と、自身のソリューションを世界中の Salesforce ユーザーに届けるという大きな可能性があります。これらの原則とベストプラクティスに従うことで、高品質で堅牢なパッケージを開発することができるでしょう。
コメント
コメントを投稿