In my last post, Apex Tips & Tricks, Bobby Watson commented:
For the two solutions for getting SObject record IDs, it would be interesting to see which one is the most efficient given a list of 1,000 or even 10,000, 50,000 records. Using the map is definitely easier, and I would assume is also the most efficient (but I’ve never done a test on this myself).
To answer Bobby’s question, 1,000 accounts were inserted into a Dev org. Next, apex code was run 5 times through execute anonymous to collect the queried accounts’ ids into a set of ids using three methods:
- For Each Loop. The account ids were collected using a For Each loop.
- For Loop. The account ids were collected using a For Loop using the more traditional for(int i = 0; i < numAccts; ++i).
- Map Constructor. The map has a constructor that takes in a list of SObject and automatically creates a Map<Id, SObject> from it. One can then use map.keySet() to get the set of Ids from it.
The For Each Loop takes the longest followed by the For Loop and finally the Map Constructor. The For Each Loop is roughly 8-9 times slower than using a Map Constructor. The For Loop is roughly 4 times slower than using the Map Contructor.
|Test Run #
||For Each Loop
Apex Profiling Code
The following apex code was run in a Developer org on na9 using Execute Anonymous. The 1,000 accounts were already inserted in the org.
Were the results as you expected? Have you done any other apex profiling?
Here are Tips & Tricks that I’ve found useful in Apex.
Get Salesforce Record Ids
There are times when you need to get the set of record ids from a list of SObject records. An easy way to get them is to loop over them and collect them like so:
An easier way using a map:
Request / Response Pattern
The request / response pattern refers to using a “Request” Parameter Object for an apex method’s input and a “Response” Parameter object for what is returned.
- In managed packages, a global method can’t have its signature changed once the package is released. Additional input or output in newer versions is fairly common so adding new request or response fields is how one can get around having to create additional global methods.
- No method overloads are needed.
Apex Can Invoke Salesforce APIs
While counter-intuitive, apex can be used to invoke the Salesforce APIs such as the Metadata, Bulk, Partner or Enterprise APIs. This is helpful when you want to stay on the Salesforce platform without having to manage servers and infrastructure off of it.
See Calling Salesforce Web Services Using Apex as an example.
Interfaces Can Extend Interfaces
While Apex started as a scripting language, it evolved into a feature rich, object-oriented language. While used infrequently, one can have an interface extend another interface. This has been helpful in managed packages where new methods are needed on an existing interface. A new interface is created that extends the old one and then used where needed.
It seems that apex developers often forget that Apex has Enums enumerated values. As a result, it’s fairly common to see code where a string variable is assigned various values and then checked against different values.
Whenever possible, I prefer enums.
What Apex tips and tricks do you have?
A couple years ago I was enhancing an ETL tool at work to add Salesforce Bulk API support so our data migration projects would execute faster. To help others understand how to use the Salesforce Bulk API, the SFBulkAPIStarter open source project was started.
It’s a C# library that has starter code demonstrating how to use the Salesforce Bulk API. The test project has test classes demonstrating how to do various Bulk API tasks such as inserting, upserting, querying, and deleting records.
To take it for a spin, download it from Nuget.
Attachment Support Added
It’s been a while since I had contributed to the SFBulkAPIStarter project so I added support for adding an attachment to a specified record.
Attachment High-Level Steps
The steps to add an attachment to a Salesforce record were easier than expected:
- Create an Insert Attachment Bulk Job.
- Create a request.txt file containing one or more records with the following fields
- Name – Name of the attachment to show in Salesforce.
- Body – The “#” prefixed path of the file in the zip file.
- ParentId – The Id of the Salesforce record to attach the attachment to.
- Create a zip file with the request.txt file and the file(s) to attach.
- Create a batch in the job whose request file is the zip file.
Here’s the attachment method in the BulkAPIClient class that handles the attachment logic. Currently, this method handles attaching one attachment and not multiple.
Here’s the test from the TestBulkApiClient class that attaches a file to a specified Salesforce record.
How often do you use the Bulk API? How about attaching an attachment to a record?
As an architect, you see common recurring needs. One such need is aggregating information from child records onto a parent record. For example, how many closed opportunities does an account have or when was the last opportunity closed on this account.
In Salesforce, aggregating information from child records onto parent records is done in different ways. If the child object has a master-detail to the parent, one or more rollup summary fields can be created on the parent object. A rollup summary could be used to count how many closed opportunities an account has, for example.
An object in Salesforce can also have a lookup field, which is similar to a nullable foreign key in a table in a database. Rollup summary fields can only be created on master-details but not on lookup fields. One solution to aggregate child information linked via a lookup is to create a trigger on the child object that runs whenever a record is inserted, updated, or deleted to aggregate the information onto the parent record(s).
Declarative Lookup Rollup Summary
The better solution is to use the Declarative Lookup Rollup Summary Tool. This tool is an open source project started by Andy Fawcett that allows one to create lookup rollup summaries that run in real-time, on demand, on a schedule, or via custom code. Since it’s configured through declarative, point-n-click means, it’s much easier to manage.
- Free managed package. Andy created this as a managed package on the AppExchange that is installed and upgraded for free.
- Implementation is quicker. Data can now be aggregated in minutes instead of the hours it takes to code, write test code, and deploy.
- More rollup options. One can rollup more than just a count, a min or a max such as the latest or earliest date or a given piece of text.
- Well Supported. With open source software, it’s important to ensure that the project is regularly maintained so bugs and enhancements are implemented. Andy and the other contributors are very responsive to the community and provide regular updates.
- Good Documentation. The documentation allows one to come up to speed quickly with how features work.
Here are the biggest considerations I’ve run into with the tool. For more, see the GitHub project.
- Limits, Limits, Limits. Since this is a native Force.com application, it’s subject to Salesforce limits. For example, be mindful of how many records are being queried. At the time of this writing, 50,000 records can be queried in a given execution context. Also, don’t forget that the records in count() are included in that limit. See SOQL: 50,000 RECORD LIMIT APPLIES WITH COUNT() for more information.
- The tool creates a trigger on objects along with a corresponding test class for the trigger. The test class simply tries to instantiate the record and insert it. Sometimes there are custom validation rules that prevent the insertion and cause the test to fail and ultimately prevents the trigger and test class from being deployed into the org. Sometimes a developer has to create custom test code for the trigger.
What other benefits and consideration do you have? What other open source or free Salesforce tools do you use in your projects?
Salesforce has a feature known as field sets. A field set is a group of fields on an object that is declaratively defined by a user. The field set’s common purpose is to decide which fields to display on a web page for editing on a form or for read only.
Salesforce documentation covers getting started with field sets. We’ll cover the good, the bad, and the ugly of field sets here.
- Ease-of-Use. Salesforce makes it easy to use within VisualForce.
- An object can have multiple field sets that can be used for various purposes.
- Objects can have as many field sets as needed.
- Adding or removing a field to be edited or displayed is as easy as adding or removing it from the field set. This allows easier maintenance of the application as requirements change over time.
- Parent Fields Supported. One can include fields from parent objects. For example, a Contact field set may include fields from the Account.
- Required Fields. Fields can be marked as required so one must fill them out on a form.
- Only One Level of Parent Fields Supported. In SOQL, up to 5 parent levels are supported. It would be nice to have that level of flexibility with field sets. One workaround is to create one or more formula fields on the given object or parent object to grab the additional information and then use the formula field in the field set.
- Easy To Break. Its flexibility is also a weakness. It allows one to remove fields that may be always needed in order for functionality to work. One workaround for this is to have a separate list of always required fields that are merged with the field set’s fields to ensure they aren’t removed.
As an architect, I have to know the capabilities as well as the limitations of the technologies available. Here are the limitations as I see them:
- Read-Only Fields. It’s nice to mark fields as Required. Having the ability to mark a field as read-only would be great so that one can more easily have a mixture of editable and read-only fields on a section of a page. Upvote the Specify a field as readonly in a fieldset idea and hopefully, Salesforce will implement this much needed feature.
- Can’t Add Attributes. One can’t add additional data attributes to the field sets. For example, I may want to add layout information or custom labels that may differ for the same field across field sets. One way to workaround this is to create your own metadata, associate it to a given field in a field set, and have the application combine the metadata at runtime to do the desired behavior.
What’s the good, the bad, and the ugly of field sets for you?