こんにちは、Appirio に入社して6ヶ月が経ちます、Takahiro です。この6ヶ月の間で色濃く残る思い出といえば、なんといっても楽しいバッチ開発ライフを送れたことです。Java の知識を持つ私がどのようなステップを踏んで、Apex でバッチを書き上げたのかをご紹介します。これから初めて Salesforce で Apex を書き始める方へのエールとなる記事になれたら光栄です。
さあ Apex 書くぞー!と息込んでいる当時の私は、Java での開発経験がある、Salesforce を初めて使う、もちろん Apex も初めてでした。と同時に、新しい世界へ突入することに心が弾む状況でした。
1. 初めての Apex
初めての言語に触れるので、不安と胸の高まりで複雑な気持ちでした。まず、私は気持ちを落ち着かせるために私の好きな午後の紅茶ミルクティーを飲んで糖分摂取をしてみました。
みなさんの学習方法はさまざまかと思いますが、私が初めての言語に触れる時は、まずコードを書かずにドキュメントを読みます。Salesforce では、開発者向けドキュメントがあったり、Trailhead という学習サイトがあったりと、開発時に必要な情報が丁寧にまとめられていますので、それを読み漁るのもおすすめです。下記の項目の最後に Salesforce の開発者向けサイトから参考になるリンクをつけておきますので、ご参考にしてみてはいかがでしょうか。
私はまず最初に、Salesforce の開発者向けのドキュメントを開いて Apex の概要を読み進めていきました。すぐに「強く型付けされたオブジェクト指向のプログラミング言語」「Java に似た」というキーワードを見つけることができ、Apex が書けそう!の気持ちを抱くことができました。
Apex の概要 | Apex 開発者ガイド | Salesforce Developers
2. サンプルプログラムを書いてみる
サンプルプログラムを書きながら、開発ツールの使い方や Apex の書き方を学びました。私は、サンプルプログラムを作りながら学ぶスタイルが好きです。その言語の基礎を固めることができますし、また、実装後に、この機能はデフォルにあったのか、ということを避けるためです。
2.1. 開発環境を整える
最初の段階で開発ツールを決めないと、後で別なツールに乗り換えるタイミングを逃します。それを回避するために、最初にツールを選定してしまいます。開発ツールを調べてみると、開発者コンソール、 Visual Studio Code(VS Code)、Salesforce 上のコードエディタの3種類でコードの記述が可能でした。私は VS Code を選択しました。参照先や参照元を表示できたり、矩形選択できたり、正規表現での置換ができたり、エディタ上からテストクラスを実行できたりと、機能が豊富で気持ちよくプログラムを書けました。
Apex 開発者ガイドおよび開発者ツール | ドキュメント | Salesforce ヘルプ | Trailblazer COMMUNITY
2.2. Apex と Java の違いを見てみる
私のような Java 出身者のために、素敵なドキュメントが用意されていました。上から1つずつ試してみると、難しい箇所はなく安心して書けることがわかります。1つJavaとの違いを上げると、Apex では、static を付けた内部クラスを定義できません。しかし、static を付けなくても static 内部クラスのような動きをして、new SampleClass.InnerClass() とインスタンスを作ることができました。
Apex クラスと Java クラスの違い | Apex 開発者ガイド | Salesforce Developers
また、どんな型が Apex では使えるのか一通り読破してみました。大体の型はJavaでも目にする型なので理解できました。しかし、sObject の型は、Java にはない初めて見る型で読むだけでは理解できませんでした。
型 | Apex 開発者ガイド | Salesforce Developers
プリミティブデータ型 | Apex 開発者ガイド | Salesforce Developers
sObject の操作 | Apex 開発者ガイド | Salesforce Developers
2.3. sObject を学ぶ
sObject を理解するために、Trailhead で sObject について学びました。ポイントとしては、全ての Salesforce の標準オブジェクトとカスタムオブジェクトは sObject を継承している、自作したクラスは sObject を継承していない、メソッドでオブジェクトを引数として汎用的な処理をしたい場合は、引数の型は sObject を指定することがわかりました。
sObject の使用 単元 | Salesforce Trailhead
3. バッチのサンプルプログラムを作る
Apex の基本的な構文は覚えたので、いよいよバッチのサンプルを作成しながら、どうやって実際にバッチを実装していくかイメージしていきました。
Apexでバッチを作成する際は、Database.Batchable をクラスに実装します。Batchable を実装すると、Batchable#start、Batchable#execute、Batchable#finish を実装する必要があります。startとfinish は、それぞれバッチの最初に実行されるメソッド、最後に実行されるメソッドです。execute は、sObject をバッチサイズ毎に処理するメソッドです。
Apex 一括処理の使用 単元 | Salesforce Trailhead
Apex の一括処理の使用 | Apex 開発者ガイド | Salesforce Developers
3.1. CRUD してみる
Create、Read、Update、Delete、Upsert(CRUD) を試してみました。既に用意されているステートメントを使用し、簡単に CRUD することができました。データベースアクセス用の処理や O/R マッパーするための処理等は一切不要です、感動します。
SOQL および SOSL クエリ | Apex 開発者ガイド | Salesforce Developers
DML の操作 | Apex 開発者ガイド | Salesforce Developers
3.2. トランザクションの制御
ポイントとしては、例外を catch しない限り全変更が rollback されること、savepoint を使用してデータベースの状態を記録し復元できること、Batchable#execute は sObject をバッチサイズ毎に処理しますが、それぞれが別のトランザクションに分かれることです。
トランザクションの制御 | Apex 開発者ガイド | Salesforce Developers
3.3. APIコールアウト
バッチ処理から API コールアウトを試しました。試している最中に CalloutException に遭遇し、データベース変更後にコールアウトすると発生することがわかりました。プログラムを組み立てる際に、注意するポイントとなりました。
リモートサイトの設定の追加 | Apex 開発者ガイド | Salesforce Developers
HTTP コールアウトの呼び出し | Apex 開発者ガイド | Salesforce Developers
指定ログイン情報 | ドキュメント | Salesforce ヘルプ | Trailblazer COMMUNITY
3.4. ガバナ制限を知る
サンプルプログラムを作成していく中で、ガバナ制限という言葉が出てきます。Salesforceでは共有リソースを使用するため、ガバナ制限によりリソースを独占させない仕組みが設けられています。ガバナ制限に引っかかると、catchできないLimitExceptionが発生してしまうので、プログラムを組む際は必ず注意する部分となります。
実行ガバナと制限 | Apex 開発者ガイド | Salesforce Developers
Exception クラスおよび組み込み例外 | Apex 開発者ガイド | Salesforce Developers
3.5. テストのサンプルを書いてみる
UnitTest のサンプルを書きました。@isTest を使いテストクラス(テストケース)であることを示し、System#assert をかけるだけです。Java と大きく変わりありませんね。また、テストを行うための初期データ登録もガバナ制限のカウントに入ってしまうため、Test#startTest と Test#stopTest のメソッドを使用してガバナ制限をリセットすることがテストを正しく行うためにヒス長です。mock のためには、Test#setMock の便利なメソッドもあります。
Apex のテスト | Apex 開発者ガイド | Salesforce Developers
Test クラス | Apex 開発者ガイド | Salesforce Developers
HttpCalloutMock インターフェース | Apex 開発者ガイド | Salesforce Developers
4. バッチを実装する
サンプルで作成したものを利用しつつ、バッチを実装していきました。バッチの内容は、API コールアウトで取得したデータを、対象のオブジェクトに記録するようなものでした。予め重要なところは、サンプルとして作成していたので、効率よくプログラムが書けたと思います。
4.1. 例外発生時の処理を入れる
例外を catch しない場合、未対応の例外として開発者にメールが送信されます。対応する必要のある例外は、catch してログに出力するなどの必要な処理をしました。また、上記でも書いた通りガバナ制限で発生する LimitException は "catch(Exception e)" と書いた場合でもcatchできません。
Apex 例外が発生すると何が行われるか | ドキュメント | Salesforce ヘルプ | Trailblazer COMMUNITY
APEX エラーメールの送信先 | 関連情報 | Trailblazer COMMUNITY
4.2. 環境によって変数の値を変える
環境毎に変数の値を変えたい場合は、いろいろ方法はあるようですが、先輩に相談した結果、カスタム設定を利用して実現することになりました。ドキュメントに「すべてのカスタム設定データはアプリケーションキャッシュで公開されます。これにより、データベースへのクエリを繰り返し行うコストをかけずに、効率的なアクセスを実現します。」とあることから環境変数のような使い方に便利なことが分かります。
カスタム設定 | Apex 開発者ガイド | Salesforce Developers
5. Apex スケジューラ
Schedulable を実装したクラスを作成し、 Schedulable#execute 内で対象とするバッチクラスを Database.executeBatch(new SampleBatch()) のようにして実行します。バッチスケジューラクラスには、設定画面からスケジュールを設定します。
Apex スケジューラ | Apex 開発者ガイド | Salesforce Developers
6. 随時
Appirio には、強靭な技術力を持つ先輩がたくさんいます。実装方針が見えなくなったり、技術的に難航した時には、先輩方からアドバイスをいただきながら実装していきました。
7. その他 Tips
- 実現したい方法の探し方
私の場合は、公式ドキュメントや Trailhead をよく読んだりサンプルを地道に書いたりして、実現したい方法を探していきました。例えば、バッチを実装したい時は「apex batch salesforce」と検索して、検索結果に出てきた公式ドキュメントや Trailhead を読んだりサンプルを作成したりしました。 - 地道に Apex を書いて慣れました
私は、Apex初心者なので、コードのコピペはいきなりせずに、まずは読んで理解して、実際に手を動かして書きました。例えば、Apex の static 変数はトランザクション中で値が保持されます。Batchable#start、Batchable#execute、Batchable#finish でどのようにstatic変数の値が保持されるのかを、サンプルを作成して動きを見ました。 - なぜか動かない!その時は Salesforce に issue が報告されている場合もある
プログラムは合っているはずなのに、なぜか期待通りに動かないという場合、Salesforce に issue が報告されている場合があります。私の場合は、List#contains が期待通りに動かず悩んでいましたが、Known Issueとして報告されていました。指示に従い、Set#contains を使用するように書き換えました。(先輩が見つけてくれました。)
まとめ
ワードもわからない、そのような場合でも、上記にまとめたことを1つずつ行うことで、心配なく実装を始められるのではないでしょうか。実装のヒントになる記事になることを願います。
今回、私はバッチ担当でしたので、まだまだ知らない機能がたくさんあります。これから日々勉強してできることを増やしていきたいです。
・・・・・・・・・・・・
一緒に働きませんか?
現在弊社では、プロジェクトマネージャー、シニア・コンサルタント、コンサルタント、ソリューションアーキテクト、アカウントエグゼクティブの5つのポジションの採用を行っております。
アピリオの仕事にご興味のある方は、こちらをご覧ください。
アピリオのリソースハブにもさまざまな資料を掲載しています。
著者について
Takahiro Sato のコンテンツをもっと見る