With more that 100,000 companies around the world using Salesforce, there is a good chance that you will come into contact with it at some point in your career. As a primarily .NET developer I’ve started my foray into this environment over the past month. These are my thoughts and experiences so far.
Things you’ll miss from C#
The more functional style programming I do the less I find myself reaching for a ‘for-loop’ in favour of C#’s more terse lambda expression syntax. As Apex does not support lambda expressions or delegates, Linq is out of the question. So get ready to write loops… lots of them.
Working in the .NET world it’s easy to forget how much pain we can avoid by using Visual Studio’s debugger. Being able to pause program execution at any point can often highlight the root of a problem within minutes, if not seconds. The only Apex debugging method I’ve discovered so far is to use print-line statements. With this technique it can take a long time to filter through all of the debug information to get the information you need to fix the problem. This chrome extension helps somewhat with the problem.
This makes the practice of TDD all the more important. Developing the Apex test suite, then building code to make each of these tests pass is a great way to narrow down the potential surface area for bugs. You will find the bugs faster, and have a higher degree of confidence that your code is correct. Finally, as Salesforce requires a certain degree of test coverage for a change set to be pushed to production you will have to write the tests at some point anyway.
Traps to look out for
After a while you start to become comfortable with the ‘not quite Java’ syntax. Salesforce is a valuable tool, and the built in functionality is extensive. This means that you can deliver some amazing business value with very little code. As you get further along the path you will likely run into some of the Apex traps. These are things you want to be wary of, lest you disappear down the rabbit hole for days whilst your product owner wonders what is going on (ask me how I know).
Trap #1 – Trigger Recursion
The Apex programming model leans heavily on the concept of triggers. Database operations on entities within Salesforce cause triggers and workflow events to fire. Anybody new to Apex development should read the trigger life-cycle guide to get an understanding of how this all fits together Triggers and Order of Execution.
For example: When I convert a lead to a contact a ‘before update‘, and ‘after update‘ trigger will fire on the the lead object, and a ‘before insert‘ and ‘after insert‘ trigger will fire on the contact object.
This allows one to manipulate entity states as events occur within the system, and these state changes are decoupled from the classes that caused them. Continuing with the above example, I could hook into the ‘after update‘ trigger on the contact object and attach some meta-data to track where the contact came from (in this case an auto-converted lead).
Sounds simple enough right? So imagine this scenario:
Before insert trigger on Contact -> Find and Convert a Lead matching on email address (Which causes a Contact to be created for the Lead) -> Triggers before insert on Contact -> .. and around we go.
There are some techniques for breaking out of these kind of loops, but the most important thing is to be aware that they can happen. This allows you to decide up front whether there are any technical limitations of the user story you are trying to implement, and also allows you to provide a more accurate estimate for the given story.
Trap #2 – Collaborating on Code
Salesforce entities are an interconnected web of Triggers and Workflow Events. Because of this it is very easy to step on another developer’s toes if you are both developing features that impact related Salesforce entities. When this happens you can potentially break each others unit tests, and confuse the debugging process.
The only solutions that I’ve found so far for this are:
- Introduce a different Sandbox per developer
- Try to make sure you don’t have multiple developers working on the same area of the codebase simultaneously.
Trap #3 – Database call limits
Salesforce Object Query Language (SOQL) is a SQL like syntax used to query entities in a Salesforce environment. It’s a powerful tool but should be used with caution. Salesforce impose limits on API calls. When running SOQL or entity update/insert statements within a loop it can be quite easy to run into these limits. It is best to perform these kinds of queries/upserts outside of a loop wherever possible to avoid hitting these limitations.
Salesforce Apex development can allow developers to quickly deliver great business value. Apex is familiar enough to C# that .NET developers should be able to pick it up fairly quickly, so long as we TDD our code, and watch out for Apex traps.