Winter '24 で認定 Platform デベロッパー資格を更新する
学習の目的
この単元を完了すると、次のことができるようになります。
- ユーザーモードデータベース操作で Apex コードを保護する。
- レコードトリガーフローでカスタムエラーメッセージを作成する。
- Lightning Web コンポーネントで改良された条件付きディレクティブを使用する。
- Iterable を使用して For ループ内の反復処理を簡単に実行する。
- Comparator インターフェースと Collator クラスを使用して並び替える。
Salesforce 認定資格
認定 Platform デベロッパー資格を保有している場合、その認定資格を維持するためには期日までにこのモジュールを修了する必要があります。資格を維持するためのもう 1 つ重要な点は、Trailhead アカウントと Webassessor アカウントをリンクさせておくことです。
この資格の取得を検討している方は、Salesforce Platform デベロッパーの資格を参照してください。
注意: このバッジは誰でも取得できますが、このモジュールは認定 Platform デベロッパーの有資格者を対象としています。
認定資格の機密を守る
Salesforce は、質の高い認定試験と価値ある資格を提供することを最優先事項としています。業界随一と広く認められている認定資格制度を維持するためには、試験のセキュリティを確保し、その機密を保持することが不可欠です。
Salesforce 認定資格プログラムに参加する場合は、Salesforce Credential and Certification Program Agreement (Salesforce 認定資格プログラム規約) に同意いただく必要があります。詳細は、Salesforce ヘルプ記事「Salesforce 認定資格プログラム同意書および行動規範」に記載の Salesforce 認定資格試験の受験ポリシーを確認してください。
この 1 年間に多数の機能が強化されています。ここでは、特に重要なものについて説明します。
ユーザーモードデータベース操作で Apex コードを保護する
新しい Database
と Search
メソッドは accessLevel
パラメーターをサポートします。このパラメーターを指定すると、デフォルトのシステムモードではなく、ユーザーモードでデータベース操作と検索操作を実行できます。デフォルトで、Apex コードはシステムモードで実行されます。つまり、コードを実行しているユーザーよりも非常に上位の権限で実行されます。Apex のセキュリティコンテキストを強化するために、データベース操作にユーザーモードアクセスを指定できます。ユーザーモードでは、実行ユーザーの項目レベルセキュリティ (FLS) とオブジェクト権限が考慮され、常に共有ルールが適用されます。システムモードでは、クラスの sharing キーワードで共有ルールが管理されます。
対象: この変更は、Enterprise Edition、Performance Edition、Unlimited Edition、および Developer Edition の Lightning Experience および Salesforce Classic に適用されます。
方法: SOQL クエリに WITH USER_MODE
または WITH SYSTEM_MODE
を使用して、操作のモードを指定できます。次の例は、ユーザーモードを指定しています。
List<Account> acc = [SELECT Id FROM Account WITH USER_MODE];
データベース操作で、ユーザーモードまたはシステムモードを指定できます。この例では、ユーザーモードで新しいアカウントを挿入しています。
Account acc = new Account(Name='test');insert as user acc;
新しい AccessLevel
クラスは、Apex がデータベース操作を実行する 2 つのモードを表します。この新しいクラスを使用して、実行モードをユーザーモードまたはシステムモードに定義します。
レコードトリガーフローでカスタムエラーメッセージを作成する
新しいカスタムエラーメッセージ要素を使用して、何が問題であったのか、どのように修正すべきかを説明するエンドユーザーへの的を絞ったエラーメッセージを作成します。このエラーメッセージはレコードページ全体のウィンドウに表示されるか、特定の項目にインラインエラーとして表示されます。関連付けられたレコードの変更はロールバックされます。エラーメッセージは保存前フローと保存後フローに作成できます。この機能は、IdeaExchange のアイデアのおかげで実現しました。
対象: この変更は、Essentials Edition、Professional Edition、Enterprise Edition、Performance Edition、Unlimited Edition、Developer Edition の Lightning Experience と Salesforce Classic に適用されます。
理由: ユーザーがアクション (フローをトリガーするレコードの削除など) を実行すると、フローでエラーが発生することがあります。以前は、フローが失敗したときに、特定のエラーメッセージをユーザーに表示できませんでした。操作が失敗した正確な原因をユーザーに通知できるようになったため、ユーザーが問題を修正して再試行できます。
方法: [Custom Error Message (カスタムエラーメッセージ)] 要素を追加して (1)、エラーメッセージを表示する場所を選択し (2)、エラーメッセージテキストを入力します (3)。
Lightning Web コンポーネントで改良された条件付きディレクティブを使用する
従来の if:true
や if:else
ディレクティブが、lwc:if
、lwc:elseif
、lwc:else
条件付きディレクティブに置き換わりました。
対象: この変更は、Lightning Experience、エクスペリエンスビルダーサイト、およびすべてのバージョンの Salesforce モバイルアプリケーションのカスタム Lightning Web コンポーネントに適用されます。この変更は、オープンソースの Lightning Web コンポーネントにも適用されます。
方法: lwc:if
、lwc:elseif
、lwc:else
条件付きディレクティブを使用すると、プロパティ getter へのアクセスがディレクティブのインスタンスごとに 1 回のみになります。
<!-- conditionalExample.html --> <template> <template lwc:if={isTemplateOne}> This is template one. </template> <template lwc:else> This is template two. </template> </template>
lwc:elseif
と lwc:else
はどちらも、同階層の lwc:if
または lwc:elseif
のすぐ後ろに続ける必要があります。
式は lwc:if
や lwc:elseif
に渡し、lwc:else
には渡しません。
expression1
で truthy が返されると、他のどのプロパティ getter もアクセスされません。
<!-- example.html --> <template> <template lwc:if={expression1}> Statement 1 </template> <template lwc:elseif={expression2}> Statement 2 </template> <template lwc:else> Statement 3 </template> </template>
lwc:if
、lwc:elseif
、lwc:else
条件付きディレクティブを使用するときは、次のガイドラインに留意してください。
- 条件付きディレクティブは、ネストされた
<template>
タグ、<div>
タグ、その他の HTML 要素や、<c-custom-cmp>
のようなカスタムコンポーネントタグで使用します。
-
lwc:elseif
またはlwc:else
の前にテキストや他の要素を配置することはできません。タグ間の空白文字が条件付きディレクティブと同階層である場合、その空白文字は無視されます。たとえば、lwc:if
の後、lwc:else
の前に<div>
タグを含めることはできません。
-
!condition
やobject?.property?.condition
など、複雑な式はサポートされていません。複雑な式を評価するには、JavaScript クラスで getter を使用します。
Iterable を使用して for ループ内の反復処理を簡単に実行する
for
ループに Iterable 変数を使用して、リストまたはセットを簡単に反復処理できるようになりました。
対象: この変更は、Enterprise Edition、Performance Edition、Unlimited Edition、および Developer Edition の Lightning Experience および Salesforce Classic に適用されます。
方法: この例では、文字列のリストを反復処理します。
Iterable<String> stringIterator = new List<String>{'Hello', 'World!'}; for (String str : stringIterator) { System.debug(str); }
この例では、Iterable インターフェースを実装し、返された文字列のセットの文字列を反復処理します。
public class MyIterable implements Iterable<String> { public Iterator<String> iterator() { return new Set<String>{'Hello', 'World!'}.iterator(); } } for (String str : new MyIterable()) { System.debug(str); }
Comparator インターフェースと Collator クラスを使用して並び替える
List
クラスで新しい Comparator
インターフェースがサポートされるようになったため、List.sort()
に Comparator
パラメーターを指定してコードにさまざまな並び替え順を実装できます。ロケールを区別する比較や並び替えを実行するには、新しい Collator
クラスに getInstance
メソッドを使用します。ロケールを区別する並び替えでは、コードを実行するユーザーによって異なる結果が生成される可能性があるため、トリガーや、特定の並び替え順が想定されるコードでは使用しないでください。
対象: この変更は、Enterprise Edition、Performance Edition、Unlimited Edition、および Developer Edition の Lightning Experience および Salesforce Classic に適用されます。
方法: System.Comparator
インターフェースの compare()
メソッドを実装し、Comparator を List.sort()
のパラメーターとして指定します。null ポインター例外を回避するために、実装で compare()
メソッドの null 入力を明示的に処理する必要があります。この例では、従業員の 2 種類の並び替え方法を実装します。
public class Employee { private Long id; private String name; private Integer yearJoined; // Constructor public Employee(Long i, String n, Integer y) { id = i; name = n; yearJoined = y; } public String getName() { return name; } public Integer getYear() { return yearJoined; } } // Class to compare Employees by name public class NameCompare implements Comparator<Employee> { public Integer compare(Employee e1, Employee e2) { if(e1?.getName() == null && e2?.getName() == null) { return 0; } else if(e1?.getName() == null) { return -1; } else if(e2?.getName() == null) { return 1; } return e1.getName().compareTo(e2.getName()); } } // Class to compare Employees by year joined public class YearCompare implements Comparator<Employee> { public Integer compare(Employee e1, Employee e2) { // Guard against null operands for ‘<’ or ‘>’ operators because // they will always return false and produce inconsistent sorting Integer result; if(e1?.getYear() == null && e2?.getYear() == null) { result = 0; } else if(e1?.getYear() == null) { result = -1; } else if(e2?.getYear() == null) { result = 1; } else if (e1.getYear() < e2.getYear()) { result = -1; } else if (e1.getYear() > e2.getYear()) { result = 1; } else { result = 0; } return result; } } @isTest private class EmployeeSortingTest { @isTest static void sortWithComparators() { List<Employee> empList = new List<Employee>(); empList.add(new Employee(101,'Joe Smith', 2020)); empList.add(new Employee(102,'J. Smith', 2020)); empList.add(new Employee(25,'Caragh Smith', 2021)); empList.add(new Employee(105,'Mario Ruiz', 2019)); // Sort by name NameCompare nameCompare = new NameCompare(); empList.sort(nameCompare); // Expected order: Caragh Smith, J. Smith, Joe Smith, Mario Ruiz Assert.areEqual('Caragh Smith', empList.get(0).getName()); // Sort by year joined YearCompare yearCompare = new YearCompare(); empList.sort(yearCompare); // Expected order: Mario Ruiz, J. Smith, Joe Smith, Caragh Smith Assert.areEqual('Mario Ruiz', empList.get(0).getName()); } }
この例では、デフォルトのリストの並び替えを実行してから、Collator を使用してユーザーロケールに基づいて並び替えます。
@IsTest static void userLocaleSort() { string userLocale = 'fr_FR'; User u = new User(Alias = 'standt', Email='standarduser@testorg.com', EmailEncodingKey='UTF-8', LastName='Testing', LanguageLocaleKey='en_US', LocaleSidKey=userLocale, TimeZoneSidKey='America/Los_Angeles', ProfileId = [SELECT Id FROM Profile WHERE Name='Standard User'].Id, UserName='standarduser' + DateTime.now().getTime() + '@testorg.com'); System.runAs(u) { List<String> shoppingList = new List<String> { 'épaule désosé Agneau', 'Juice', 'à la mélasse Galette 5 kg', 'Bread', 'Grocery' }; // Default sort shoppingList.sort(); Assert.areEqual('Bread', shoppingList[0]); // Sort based on user Locale Collator myCollator = Collator.getInstance(); shoppingList.sort(myCollator); Assert.areEqual('à la mélasse Galette 5 kg', shoppingList[0]); Assert.areEqual('Bread', shoppingList[1]); Assert.areEqual('épaule désosé Agneau', shoppingList[2]); Assert.areEqual('Grocery', shoppingList[3]); Assert.areEqual('Juice', shoppingList[4]); } }
リソース
- Salesforce ヘルプ: ユーザーモードデータベース操作による Apex コードの保護
- Apex 開発者ガイド: ユーザーモードでのデータベース操作
- Salesforce ヘルプ: レコードトリガーフローでのカスタムエラーメッセージの作成
- Salesforce ヘルプ: 改良された条件付きディレクティブの使用
- Salesforce ヘルプ: Iterable による For ループ内での反復処理の簡略化
- Apex 開発者ガイド: カスタムイテレーター