function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Muhariz JabeerMuhariz Jabeer 

Apex @future method - SOQL Query best practice question

Hi

I am doing the 'Asynchronous Apex' module's 2nd part 'Use Future Methods' on Trailheads and had a question regarding SOQL best practice. The directs us to create a method that accepts a list of Account IDs, and update a custom field on the Account called 'number of contacts'. I passed the module but would like to engage in open discourse about SOQL best practices in regards to queries and iteration. The entire code block is as follows:
 
public without sharing class AccountProcessor {
    
    @future
    public static void countContacts(List<Id> accountList){        
        
        // Get all the Contact records with a Parent Account belonging to the above list 'accountList'
        List<Contact> contactsToCount = [ SELECT Id, LastName, AccountId 
                                          FROM CONTACT
                                          WHERE AccountId IN : accountList];
        
        // Create a hashmap of ID to Account so that we can efficiently access them to update their individual contact counts
        Map<Id, Account> accountsToUpdateMap = new Map<Id, Account>([SELECT Id, Name, Number_of_Contacts__c
                                                                    FROM Account
                                                                    WHERE Id IN : accountList]);
        
        // obtain the Accounts from the above into a list for both zeroing existing contact count AND DML update at the end
        List<Account> accountsToUpdateList = (List<Account>) accountsToUpdateMap.values();
        for(Account acc : accountsToUpdateList) {
            acc.Number_of_Contacts__c = 0;
        }
        
        // go through every contact which has a parent account from the list and sequentially increase the parent's contact count
        for(Contact con : contactsToCount) {
            // check to see whether there is a parent to begin with (orhphaned contacts)
            if(con.AccountId != null && accountsToUpdateMap.containsKey(con.AccountId)){ // the last check is not needed
                Account accountToUpdate = accountsToUpdateMap.get(con.AccountId);
                accountToUpdate.Number_of_Contacts__c += 1;
            }
        }
        
        for(Account acc : accountsToUpdateList) {
            System.debug('*** [Output] Account Name: ' + acc.Name + '   Num Contacts: ' + acc.Number_of_Contacts__c);
        }
        
        update accountsToUpdateList;
    }
}

I am looking for feedback on SOQL query usage and possibility of optimisation/scalability pitfalls in the above code block.

Thanks in advance
Muhariz.