Salesforce Advanced Developer DEV 501 Course Notes

I recently attended the Advanced Developer DEV 501 course in Staines.

The course was taken with Winter '15 and was delivered by the excellent MVP Simon Goodyear.

I've just finished tidying up my course notes and just wanted to share them for anyone out there starting on their Dev 501 journey.

I hope you find them useful:

Day 1

Introduced and discuss development tools such as Sublime Text EditorMaven’s Mate, and the
ANT Migration Tool.


You cannot use a Validation rule to prevent deleting a record in Salesforce

It is possible to pass a list of IDs through to a custom VF page so that you can act upon them. I.e. select 3 orders to be processed.

Many limitations of current workflow are changing in new process builder (Spring 15) i.e. you currently cannot update related records in Workflow and would have to use Trigger – this will not be the case soon

If you ever have a question Twitter Salesforce group #askforce and someone will come back to you.

Trigger after UnDelete. Fire this trigger if you are trying to restore a record

Apex is a programming language in the cloud and is a multi-tenant sensitive language. It is also metadata-aware, i.e. you create an object and can immediately reference that.

You can edit Apex in production ORGs via Eclipse or the Developer Console.

You can deploy Apex in production if it has min 75% test coverage. You should always aim for 100% coverage, though.

You can run Apex in any production ORG except Enterprise/Unlimited (Trial Only edition) and Other.

How to Invoke Apex * this is useful to know for your DEV 501 exam
  1. Save a record in SF UI
  2. Saving records via API
  3. Via Triggers
  4. Interacting with a VF page
  5. Sending an email
  6. Submitting an anonymous block via API
  7. Creating a job via Apex Scheduler
  8. Invoking an Apex Web Service
  9. Web Service Client makes a call
Action Types available in the new Process Builder include:
  • Create a record
  • Update fields on any related record—not just the record or its parent
  • Launch a trigger-ready flow—as an immediate or a scheduled action
  • Send an email
  • Post to Chatter
  • Submit for approval.


SOQL is a query only language. Therefore if you are doing Select statements you are doing SOQL but if you’re trying to edit/insert records you’re actually performing DML – Data Manipulation Language

No such thing as a case statement in Salesforce – it is not known why this is not supported

Record IDs in Salesforce are not replicated across any ORG – ever. They were initially 15 digits long and were case sensitive. When people started exporting to Access/Excel and other tools that were case insensitive then people had issues when they re-imported data as suddenly duplicates emerged.

sObject just means Salesforce Object

sObject lets you gather together common fields used in several objects and pass them to a method in one go

So, if I wanted to do an update with Accounts and Contacts I could create both as sObjects and then do a single update. So, there is an sObject of all objects in Salesforce.

Collections – There are 3 types –
  • Lists
  • Sets
  • Maps
If you call a keyset command from a map you’ll get the values of the Keys contained in the array/collection

Execute anonymous allows you to execute Apex direct in a production environment but the anonymous part of it is a misnomer – Salesforce does know who is executing the code.

Date.Parse is bad practice – use instead because Date.Parse takes the locale of the current SF ORG. If you applied the code to a different locale ORG the code would fail.

Primitive data types =
  • String
  • Integer
  • Boolean
IDs can be treated like Strings in many respects – always use the 18 digit version

What is a Transaction? 

A single Synchronous operation – Entry point – user clicking saves, going to DML operation and completing.

Governor limits are runtime limits enforced by the Apex runtime engine. They ensure that coders don’t get sloppy and use up more memory than needed for their code. As SF is multi-tenant we need to be efficient.

Putting too many SOQL statements through SF does cause an exception but it’s not “catchable” – the data just stops. There are classes on Get Limits and Get SOQL statements so that you could deal with these, though.

If you do an SOQL statement and limit it to 1 result then the result can be set straight to a variable.

All Apex should have an Exception statement in it. This allows your Code to Try and then Catch various problems. There is an overall Exception E element that you can add – or there are specific exceptions that you think will come along you can target them.

Record Access: 

“With sharing” command restricts record access to that of the user. So if the user only has access to 50 out of 100 records in a table then With Sharing will bring back 50 and Without Sharing will bring back all 100.

Most Class Declarations run in System Context – which equals Without Sharing.

So, Triggers run in a System Context as do most other Apex scripts.

  • You can average and summarise data within a SOQL statement.
  • You don’t need to add ID to a SOQL query but its good practice to include it.
  • There is no equivalent to Select *
  • A common error occurs if you try to do something with a field that wasn’t included in the statement. However, to assign values you don’t have to include them in the search
  • Operators: =, !=, >, <, >=, <=, LIKE, IN/ NOT IN, AND, OR , NOT
  • You can traverse up to 5 relationships in a SOQL statement
  • Bound Variables – Create a set of Strings/IDS then you can SOQL to query all of them in one go i.e. Select Name from Account where Name in: names
Aggregation in SOQL
  • Count
  • Count Distinct
  • AVG – Average
  • MIN – Min/Smallest value
  • MAX – Maximum value
  • SUM – Total sum of a numeric field
Amazing fact of the day - There is no easy way to do a Count all in SOQL. If you do a COUNT statement, the SOQL needs to query all of the fields to get the count so you could quickly go through 50,000 records.

Roll up summary fields are one way around this.

Day 2

Started with a recap of Day 1.

With the current Workflow tool you can update a field if it is part of a Master-Detail relationship – Process Builder will let you do even more.

Variables names specified within a For Loop will only remain while you are still in the loop.

Use rather than Parse date in Apex.

Apex ignores restrictions imposed by CRUD or Field Level Security. Therefore your code needs to take into account security concerns.

All Apex runs as System Context (without sharing) meaning they have access to all records whereas Anonymous Blocks run as User Context (with sharing). So, if you went to Execute Anonymous Code and tried to access hidden data it would fail.

SOSL – Salesforce Object Search Language – Only has “Find” as a command. Not that commonly used in development.

Sidebar fields – These are the Recently Used items in Salesforce – so you could restrict a SOSL statement to only look at your most recent fields.

SOSL has much lower transactional limits that SOQL – but bear in mind this is for usability – i.e. user is unlikely to paginate through more than 2,000 records at a time.

SOSL might be needed if you ever have a custom VF page which brings back X records – and then you might want to add a custom button to do something on those records.

Select ID from Account will not access deleted rows – If you change this to Select ID from Account ALL ROWS then it will bring back all data included deleted.

DML – Insert

Standard behaviour when you use insert accounts is that either all records are valid and will be inserted – or none of them will. You can use a variation of insert to insert some of the records if there are any issues with some of the records.

DML Savepoints and Rollbacks – a way of saving a database operation point in time. I.e. insert a record, save the Savepoint, delete a record, then call a Rollback to the Savepoint and the record will be undeleted.

Chatter EntitySubscription – This is the object that controls which records are followed in Chatter. EntitySubscription takes 2 arguments, the ID of the object to be followed and the ID of the follower.

Never do Inserts in Loops

Trigger Types

  1. before insert,
  2. before update,
  3. before delete,
  4. after insert,
  5. after update,
  6. after delete,
  7. after undelete

There are 2 types

Before triggers modify values before they are saved to the database

After triggers can be used to access field values that are set automatically. After triggers are useful ways to amend other records because they have an ID value

Triggers are available all of the time, you don’t have to be in a Trigger to refer to the Trigger class. Some of the Context variables include:

  • isInsert
  • isBefore 
  • new
  • newMap
  • old
  • oldMap
  • size
  • isExecuting
You can use VLookup in a Validation rule – i.e. you could have a list of valid US States in a table and then check against them.

VLOOKUP (returned_associated_value, key_of_the_lookup_table, value_to_lookup)

Too many SOQL queries = Error 101

Order of Execution of Code – this will be covered in the multiple choice exam – make sure you know it

There are approx 13 steps in the High Level Overview of the Order of Execution – refer to this on Slide 216.

Workflow rules are quite far through the order of execution. So, you could use a Workflow Rule to do a field update that wouldn’t pass custom validation on its own but as you are doing it far through the execution then it will proceed.

N.B A Workflow field update will always trigger before update and after update Triggers but it won’t do this if the data wasn’t changed.

Sharing Rule – You cannot put custom people into a Sharing Rule – you can only specify people and groups. If you do not know who needs to have access to the record in advance you will probably have to do a trigger.

Sharing Table in Salesforce named “Position__Share”

Every object in Salesforce has its own Sharing Table so AccountShare, OportunityShare et cetera.

Workflow method IsChanged is the same as looking at oldMap in Triggers

If (Trigger.isInsert) – New record going into the database

If (Trigger.isUpdate) - Updated record

Position Share table

· parentID – What is the ID of the object you need to share

· userOrGroupID – What is the ID of the person/group who needs access

· rowCause – What’s the human-readable reason for this share

Trigger.New loads all of the fields on the Object that it sits. So even if you didn’t query Billing City etc you could refer to it in a Trigger.

Day 3

SOSL – Searches across all objects

Starts with the FIND keyword

SOSL will search all fields unless you specify IN NAME and tell it which columns to include

You can filter different record types in a FIND statement (Accounts where name is ACME, Opportunities where account is greater than) etc.

You can issue 20 SOSL statements in a single transaction and return 2,000 records. The maximum Heap/Memory size is 6MB.

There are 6 DML commands:

1. Insert

2. Update

3. Upsert

4. Delete

5. Undelete

6. Merge

SaveResult table contains

isSucess, getID, and getErrors

So, was record saved? If it was, what is its ID, and what errors were reported?

Savepoint sp1 = Database.setSavepoint ()


150 DML statements can be issued in a single transaction affecting 10,000 records

200 is a magic number in Salesforce – putting items into lists automatically brings back data into 200 record chunks.

SOSL always returns a 2-dimensional list of sObjects

A trigger will normally run in System Context meaning it can see all data but if you utilise a Class with sharing then you can get them to behave within normal security.

Any Before triggers do not have Ids for the record – After triggers are Read Only

Before Triggers modify data before it is inserted into the Database

Comparing values:

Current variable compared to oldMap variable e.g

Site.status__c != Trigger.oldMap.get(

addError() method – allows you to do validation rules within Triggers – lets you put error messages within your trigger to tell people what’s going on

The Maximum Trigger depth in Salesforce is 10

If you need a Record ID then the trigger will have to be an After one

You can write triggers that take a maximum of 10 seconds of CPU time on Salesforce.

Debug – View Log Panels – Execution Overview – Shows a nice colour coded chart showing you what happened in a code sequence.

Possibly in future, you’ll be able to walk through your Apex Code line by line – watch out for this in future.

Day 4

Unit Tests

All have 3 steps:

1. Initialise and prepare test inputs,

2. Execute operation,

3. Verify results

Ideally, when doing test scripts in Apex you should put 201 test records in – this will make sure you’ve tested bulkificiation successfully.

Code coverage can differ between Development Console and the overall Code Coverage figure given in the Apex Classes screen. It may also be different from the final amount given when you deploy code.

@isTest(seeAllData=true) lets you run test classes against data that is already in the ORG.

This isn’t recommended as your tests then become reliant on the data in your ORG. So, if someone deletes some data your test classes might pass/fail incorrectly.

You could upload a Static Resource file with rows of data in them to get better test results.

Test Data Factories

These are small reusable bits of code to generate, for example, Contacts, Accounts etc. These can then be used in multiple locations.

When running Test Classes don’t select a User Profile from your actual system. Instead, mock up a user so that you have control over the data.

System.runAs() – this lets you do tests as different roles. Dev 501 expects you to use different contexts to check that standard users can/cannot do a certain action.


Sometimes it isn’t possible to cover all lines of code in a test class. This could be due to the fact that your trigger is using the outbound message or certain other features. The way around this is to surround some of your code with Test.isRunningTest commands.

Deploying Code IDE has a way to take a snapshot of your current ORG before you do any deployments.

Deployments with an ID instead of a name have been submitted by Apache ANT or ECLIPSE

@future – do something in future when Sales has available resources

If you ever need to do a Web service callout you have to use @future, otherwise you’ll get an error saying “pending work”.

@future blocks not necessarily run in order

Salesforce standard SOAP that ships only handles CRUD operations so many people do their own.

WSDL – Web Services Description Language

SOAP is great but very verbose. Bear in mind that the URLs do not change with SOAP, data being exchanged is embedded in the body of the message.

Outbound SOAP

Before you do any outbound messaging or SOAP calls you have to add the site to Remote Site Settings.

You can generate Apex classes from WSDL files sent over from another company/developer. However, there are different standards so you have to use the same one or you will get errors.


REST – Representational State Transfer

Uses HTTP verbs such as POST, GET, PUT, and DELETE – these are comparable to CRUD

REST can simply send and receive XML or JSON (JavaScript Over Notation) over HTTP

Postman is a good tool for testing REST service commands

Set up a VisualForce page that shows your current Session ID in the browser. This is useful for testing.

REST types and their usage

· @httpDelete = Delete

· @httpGet = Select

· @httpPatch= Update

· @httpPost - Insert

· @httpPut = Upsert

Salesforce Login Servers

· Production =

· Sandbox =

· Pre Release =

Test data factories encapsulate reusable code blocks for creating the smallest unit of reusable data – i.e. inserting 201 contacts, accounts etc.

startTest and stopTest can only be used once in each Test Class IDE lets you apply code between ORGs whereas Change Sets have controls to check that the ORGs are related.

@future is a command that lets you schedule code asynchronously in future – as soon as the resource is available.

Try and Catch statements are memory intensive. There were a few occasions where the example code had the Try and Catch in them but it would have been better to read items into a list and check whether the resulting list is empty or not.

There are limits on how many emails per day you can send via Salesforce

The Salesforce email limits count duplicate emails – so if you sent 1500 to yourself then you would use their limit.

If you send an email to a registered Salesforce user then it doesn’t count towards the 1500. To correctly set it as an internal email you need to specify a target object.

There is no bulkification on emails – they only ever process one at a time.

How to write an email handler

1. Create shell email class

2. Set up email service

3. Generate email address

4. Complete the email handler class

5. Test

Dynamic Apex

Dynamic Apex gives you the ability to query the metadata within Salesforce – i.e. describe the Account object and then use the results in your code. So, you could build up code dynamically to do an update on the Account object.

SOQL Injection attack – when people insert queries directly into text boxes and this code would execute.

You can prevent this by using string.escapeSingleQuotes(string) to ensure no quotes come through on a text field input.

Dynamic Apex is supported by Schema Describe code which lets you query the database shape from within the code.

Custom Settings can be accessed repeatedly in Salesforce without ever hitting governor limits

There are 2 types of Custom Settings

Lists (think ZIP lists, custom greetings etc) and Hierarchical Settings (user settings)

Custom Settings query – you can run getAll() command or getInstance()

You’re allowed 10MB to store all of your Custom Settings in the ORG


Currently over 120 tags available for VF, more being added all of the time

VF pages are metadata-aware – the pages render based on the field type that is stored in the database

· Data Binding – taking data from a controller and displaying it on a page

· Action Bindings – Save a record, delete etc

· Component bindings – Allows another component to be referenced

Types of Actions on VF pages

1. Cancel

2. Delete

3. Edit

4. Quicksave

5. Save

6. View

Standard List Controllers are always asked about in Dev 501

Elevate Salesforce training – Free training sessions

Day 5

Reviewed week so far

Lots of conversation about Schema commands – allows you to dynamically query the database structure/fields.

Schema.SObjectType and others

Batch Apex lets you go through 50 Million records = much higher limit than live Triggers

Database.Batchable takes 3 arguments

1. Start()

2. Execute()

3. Finish()

Custom Settings are max 10MB – as those field values are stored in memory throughout your whole session.

Visualforce all begins with apex:prefix

If you want error messages to appear at the top of a page in Apex you need to add Apex:Messages to your custom VisualForce page

You cannot create a button to call Apex. You have to create a button that calls a Visualforce page that calls the Apex.

Every step in a multiple page Wizard is its own VF page

When you do multiple pages of Visualforce all of the variables get transmitted between pages. This can build up size rapidly but you can add Keyword Transient to mark certain variables as not needing saving between each page.

There is such a thing as Dynamic Visualforce – this allows Visualforce to generate other Visualforce

Remember the Execution Timeline view in the Developer Console – allows you to see what is happening on your page in the graphical form.