+ Start a Discussion
EmForce AdministratorEmForce Administrator 

Looping all object field: Best practices (Class/Trigger)

Hey all, I'm a pretty inexperienced Apex dev and was wondering about some best practices for looping through all object fields for their helptext metadata.

Our business case requires us to have more than 20 Lookups on a record.  Each of these lookups has their own set of fields on the record that pull in data from the lookup (Can't use formulas, otherwise cross object reference limit gets too high).  To mark which fields to put data in from the lookup, I added a search string in the help text "<<CODR" (I would put it in the description but you can't access description metadata?).  My apex class currently loops through all the object's fields and searches for the ones with the code string.  Once it grabs all of the strings, it performs the necessary steps to put in the data from the respective lookup into the field.

My biggest issue is scaling.  Our object has ~600 fields and this process takes a lot of CPU time (On average, around 75% before CPU Limit!).  I have this class activated on a before update trigger, which fires off anytime a user saves a record.  It's very slow and highly inefficient.

The data needs to be filled in only when
A. A specified Lookup is changed
B. A specified field is changed

Below is the method that is called when trigger is fired.  Every time the record is updated, this method loops through the entire object's field list.  I feel that if there was a way to only search on the criteria above, I would be able to cut down the CPU time by a large factor.  I don't know enough about Apex to figure it out though. 
-Search only lookups first, see if they're changed?
-Search only fields w/ <<CODR in helptext, see if they're changed?

Any advice?  If you need any additional information, please ask!  Thanks a ton!
 
/**
	*To be used with trigger
	*
	*/
	public void populateFieldsTrigger(Proposal__c p) {
		/*This loop goes through all fields and sees if the field is a CODR field 
		If the field is a CODR field, it gets sent to the fieldDataSorting method
		*/
		/*
		Sample search string format
		<<CODR,LookupSource,FieldSource,FieldTarget>>
		*/
		
		//Loop through all fields
		for(String key : fieldsMap.keySet()){
			String fieldName = fieldsMap.get(key).getDescribe().getLabel();
			//See if field has inlinehelptext to pull
			try{
				String fieldHelpText = fieldsMap.get(key).getDescribe().getInlineHelpText();
				//If field inlinehelptext has "CODR" in string, get substr numbers to split string
				if (fieldHelpText.contains(codeName)){
					Integer codeIndexStart = fieldHelpText.indexOf(codeName)+2;
					Integer codeIndexEnd = fieldHelpText.indexOf('>>');
					String codeStrOnly = fieldHelpText.substring(codeIndexStart,codeIndexEnd);
					//isProperCode checks string to make sure it's a valid format
					if(isProperCode(codeStrOnly)){
						fieldDataSorting(codeStrOnly, p);
					}
				}
			}
			catch (Exception e){
				//System.debug(e);
			}
		}
		//Once all fields are set up, call SOQL query to retrieve data and place it in targetFields
		queryLU(p);	
	}

 
Guilherme OliveiraGuilherme Oliveira
Here's a suggestion: create a Fieldset on your child object (the one the trigger runs on) with all the lookup fields (maybe another with the "CODR" fields? Didn't really understand what those fields are meant to do), and use Fieldsets on each parent objects with the list of fields you're populating on the child. With clever naming conventions, you can iterate on these fieldsets of  the  parent object to populate your queries and fields on child object without losing on scalability or ease of maintenance, and you don't need to rely on Help Text (which might be useful for other scenarios).

Here's the  official documentation on Fieldsets, to get you started:
https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_dynamic_vf_field_sets.htm