How do I start to debug my own Apex code?
Sometimes questions are posted here that would best be answered by helping the questioner learn how to do their own debugging. (Remember that proverb?) I'd like to have something to link to on this site for that purpose.
So please provide a step by step recipe for how to output basic debug information from Apex code in triggers or controllers for inexperienced Salesforce developers.
If/when this Force.com IDE Debugger. New feature? appears Apex may/should become as easy to debug as other languages.
PPS Looks like Winter '16 has the interactive debugger for Apex though it is something that has to be opted in to and paid for (and has yet to be widely tried). See Apex debugging in Winter '16 - how well does it work?
This may not be a step-by-step recipe, but the system.debug() method is your best friend. Literally pepper your code with these calls, since when you test your code in a sandbox and have debug logging on (logging level = debug) every message is written into the debug log. I use it to see variable values before and after actions.
@akarnid When I first started working with Salesforce I couldn't find the debug output... its that level of detail I'm trying to capture here.
Let's say you have written a trigger and want to know specific values in the code to find out why it isn't working, and you have set a few debug statements in the trigger code. 1. Save the code. 2. Go to Monitor -> Logs -> Debug Logs 3. Click the New button in Monitored Users. Find your user and select it and save. 4. Trigger the trigger somehow (if it fires on a field update, create a test record and update the field and click Save). 5. Go to Monitor -> Logs -> Debug Logs again. Now you will see a couple of new logs for your user. You can click 'View' and you should see your debug info
@akarnid that information would be more useful (and readable) as an answer rather than a comment.
When using system.debug() to output values from your code, add a prefix that doesn't occur elsewhere in your output. That way, you can filter for just the output of your own system.debug() calls (eg. "MyNewCodeMar2014-" as prefix gives "MyNewCode2014-#of cases: 23" as output)
Here is how I debug my issues. In most cases I would only make it to step 2 before I solve my problem.
Step 1: Explain it to your Rubber Duck
I try explain what my code is doing to my rubber duck. A lot of the time I figure out the problem when I'm explaining the code to someone else. (If exceptions are involved, take a look at your code at the line numbers reported and consider what could have generated the exception.)
Step 2: System Debugs
Debug log recording in Setup is turned on for your User via:
Setup > Monitoring > Debug logs. See here for more information.
I would place temporary debug statements such as
System.Debug('>>>> the value of x is ' + x);within my code to make sure that the code is executing the way I think its working. Individual SObjects, Maps of SObjects and Lists of SObjects can all be appended and that shows you all populated SObject fields.
>>>>is a unique string that usually doesn't appear anywhere else in the log files. This allows me to quickly find my debug output. (Logs are truncated after 2M bytes of output - there are work-arounds for this.)
Step 3: Use the Developer Console
The Developer Console is a great tool for debugging. You do the following things (and more) with the developer console
- View Logs. This is another way of viewing debug output.
- Execute SOQL. This can be used to verify that the SOQL in your code is returning the correct information
- Execute Anonymous. Apex code can be run directly from the dev console
- Checkpoints can be added in the code (maximum of 5 per class), which will allow you to stop the code executing and to see variable information.
See Josh Kaplans YouTube video for more info on the dev console
Step 4: Create a Unit Test
A unit test is a great way to figure out what is going on with a piece of code. It allows you to:
- Execute your code in an environment with no other data
- Create test data that you can use over and over again.
- Use asserts to check your code e.g.
System.assert(contacts.size() > 0);or
Step 5: Take a break
I find myself getting frustrated when I have been looking at the same problem for a long period of time. This does not help solve the problem, it can actually make it harder to clearly see what is going on in the code. Take a break for a while and you may find that when you look at the problem again it makes more sense.
Step 6: Ask for help
If you have done all the steps above and reached this point then you most likely need help. This is where a colleague or stack exchange come in. Make sure when asking a question that you clearly state your problem, provide enough information to make it understandable to others and if you are providing a code sample make sure that it is formatted and easy to read.
Nice. +1 for rubber duck; she never gets enough attention. If you want *nothing* but debug logs, turn all your log settings to the "error" level, then use `System.debug(LoggingLevel.ERROR, someValue)`. You'll get small logs (mere Kb) with just the info you requested.
I try to avoid the use of debug statements like the one mentioned using a unique string like `>>>` unless I plan to remove them when I am done troubleshooting, since they're not helpful to anyone else. Instead, I attempt to create useful, verbose debug statements that can live in the code forever and will probably be beneficial to other devs/admins troubleshooting at a later time. For instance: `system.debug('Found a matching record using the postal code prefix [' + aWrapper.postalCodePrefix + '] but assignee UserId [' + postalCodeOwnerAssigment.Assignee__c + '] is an inactive User.');`
I agree Mark. I have changed my answer to say that it is a temporary debug statement
I usually print apex:pageMessages in Visualforce page or use Trigger.addError in triggers for debugging, they are faster than looking at debug logs sometimes.
people worry about me talking to myself especially when working - actually i talk to rubber duck which can be my other self.