1) Let's say a user does not have permission on a child object but has permission on the parent object to read, create, edit, and delete the parent record. If I create a trigger on the parent object to insert a child record after the parent record is created from an Apex class (which does not have any keywords declared, like "with sharing" or "without sharing," nor does it have WITH SECURITY_ENFORCED), will a child record be created after the user inserts the parent record manually?
Yes, a child record will be created. By default, triggers and Apex classes run in system mode, which means they bypass the user's permissions and can insert the child record even if the user does not have access to the child object.
2) If, in the above scenario, from the trigger, I am calling an Apex class that is in "with sharing" mode and inserting a child record after the parent is manually inserted by the user, will a child record be created?
Yes, a child record will be created. The with sharing keyword only enforces the sharing rules for the user, but it does not affect object permissions. Since the trigger runs in system mode and bypasses the user's permissions, it will still create the child record. The with sharing keyword primarily governs the visibility of records based on sharing rules, not user permissions for specific objects.
3) Let’s say an Apex class, which is not declared with any keywords such as "with sharing" or "without sharing," is fetching Opportunity records. The user running under whose context this apex class is invoked does not own any Opportunity records, nor are any Opportunity records shared with them. In this case, will the class be able to fetch Opportunity records?
Yes, the class will be able to fetch Opportunity records. Since the Apex class runs in system mode by default (when neither the
with sharing
nor
without sharing
keywords are specified), it bypasses the user's record-level access and CRUD permissions. As a result, the class can retrieve all Opportunity records, regardless of the user's permissions or whether the records are shared with them.
4) Let’s say an Apex class, which is declared with the "with sharing" keyword, is fetching Opportunity records. The user, under whose context this Apex class is invoked, does not own any Opportunity records, nor are any Opportunity records shared with them. In this case, will the class be able to fetch Opportunity records?
No, the class will not be able to fetch Opportunity records. The with sharing
keyword enforces sharing rules, meaning that only records the user has access to (based on sharing rules, ownership, or explicit sharing) will be retrieved. Since the user does not own any Opportunity records, nor are any records shared with them, the class will not be able to access those records.
5) What is bulkifying code in Salesforce Apex, and why is it important?
Bulkifying code means writing code that can handle multiple records at once instead of processing just one record. It is essential because Salesforce has governor limits on the number of records that can be processed at a time. Bulkifying your code ensures it can efficiently handle large data sets while staying within those limits.
6) Why should you avoid SOQL queries and DML operations inside FOR loops?
Placing SOQL queries or DML operations inside FOR loops can quickly exhaust governor limits, leading to runtime exceptions. To avoid hitting these limits, you should perform queries and DML operations outside of loops, processing records in bulk instead.
7) Why should you avoid SOQL queries and DML operations inside FOR loops?
Placing SOQL queries or DML operations inside FOR loops can quickly exhaust governor limits, leading to runtime exceptions. To avoid hitting these limits, you should perform queries and DML operations outside of loops, processing records in bulk instead.
// Bad practice: SOQL inside FOR loop
for (Contact con : Trigger.new) {
Contact result = [SELECT Id, Name FROM Contact WHERE Id = :con.Id LIMIT 1];
}
// Good practice: Perform SOQL outside the loop
Set<Id> contactIds = new Set<Id>();
for (Contact con : Trigger.new) {
contactIds.add(con.Id);
}
List<Contact> contacts = [SELECT Id, Name FROM Contact WHERE Id IN :contactIds];
8) What is the purpose of using @future
methods in Apex, and what should be considered when using them?
@future
methods are used for asynchronous processing in Apex, allowing operations to be performed in the background. They help offload long-running tasks and improve the user experience. However, @future
methods cannot accept sObjects or objects as parameters and have a limit of 50 invocations per transaction.
trigger accountAsyncTrigger on Account (after insert, after update) {
someClass.processAccount(Trigger.newMap.keySet());
}
global class someClass {
@future
public static void processAccount(Set<Id> accountIds) {
// Code to process accounts asynchronously
}
}
9) Why should you avoid hardcoding IDs in Apex code, and how can you handle record types or other dynamic values instead?
Hardcoding IDs in Apex code makes it less flexible and prone to errors when moving between environments (like from sandbox to production). Instead, use dynamic methods such as querying for IDs based on the label or record type, ensuring the code works across different environments.
List<RecordType> rtypes = [SELECT Name, Id FROM RecordType WHERE sObjectType='Contact' AND IsActive=true];
Map<String, String> contactRecordTypes = new Map<String, String>();
for (RecordType rt : rtypes) {
contactRecordTypes.put(rt.Name, rt.Id);
}
for (Contact a : Trigger.new) {
if (a.RecordTypeId == contactRecordTypes.get('SomeRecordTypeName')) {
// Your logic here
}
}