ADX-231-v.1-Spring 20-Excercise Guide
ADX-231-v.1-Spring 20-Excercise Guide
Lightning Platform
SFADX-231v1-EG
Introduction to Object-Oriented
Programming Using Apex on the
Lightning Platform
Exercise Guide
Exercise Guide
Introduction to Object-Oriented Programming Using Apex on the Lightning Platform
Table of Contents
Exercise 0-1: Preparing Your Training Org 2
Exercise 0-2: Creating a Sandbox Organization 3
Exercise 1-1: Retrieving the Apex Developer Guide 4
Exercise 1-2: Sight-Reading Apex 5
Exercise 2-1: Execute Anonymous in the Developer Console 9
Exercise 3-1: Identifying Constructs 11
Exercise 3-2: Executing Operators in the Developer Console 14
Exercise 3-3: Branching Code with IF Control Statements 16
Exercise 3-4: Iterating Through Code with a FOR Loop 18
Exercise 3-5: Branching code with a Switch Statement instead of an IF ELSE construct 19
Exercise 4-1: Calculating Data with Primitives 20
Exercise 4-2: Iterating Over Lists 22
Exercise 5-1: Creating a Class 24
Exercise 5-2: Using the this Keyword 26
Exercise 6-1: Constructing Objects from Classes 27
Exercise 7-1: Identifying Scope 28
Exercise 9-1: Referencing sObjects in Apex 32
Exercise 9-2: Saving sObjects in Apex 33
Exercise 10-1: Creating SOQL to Return Data to Apex 34
Exercise 11-1: Coding a Trigger Part I 36
Exercise 11-2: Coding a Trigger Part II 38
Exercise 11-3: Refactoring a Trigger Using a Class 40
Exercise 12-1: Debugging Problematic Code 42
Exercise 12-2: Handling Exceptions 45
Exercise 13-1: Programming a Unit Test 47
Exercise 14-1: Deploying to Production 48
Exercise 16-1: Sight-Reading Apex 50
Exercise 16-2: Coding the Final Project 54
Goal:
Prepare your org for classroom activities and access after class.
Scenario:
Universal Containers wants you to do development tasks for them. You have been given a
Salesforce organization that you need to set up to begin your work. You want to make sure that
all system messages from the org come to you.
Tasks:
1. Update the email address on your user record.
2. Optional: Install the Salesforce mobile application.
3. Download and extract the lab files.
Time:
10 minutes
Instructions:
1. Update the email address on your user record.
A. In a browser, go to http://login.salesforce.com.
B. Enter the login credentials provided by your instructor.
C. Click Admin Avatar | Settings | Personal Information.
i. Email: Enter an email you can access from the classroom
ii. First Name: Enter your first name
iii. Last Name: Enter your last name
D. Click Save.
Optional: Install the Salesforce mobile application.
E. Navigate to the app store on your supported device.
F. Search for Salesforce.
G. Install the app on your device.
Note: The time it takes to complete the full copy will depend on the length of the queue at
the time requested. You will receive an email (sent to the email address specified in your
user profile) letting you know when it has been completed.
Review
Review
1. What type of information can you find in the Reference section of the Developer’s
Guide?
2. Does the Developer’s Guide contain the full specifications for SOQL syntax?
1. Read the code block on the following page. Fill out the worksheet with your guess as to
what you believe is happening on each corresponding line of code. Note: The code line
numbers correspond with the worksheet line numbers.
Review
1. How is the code in lines 1–14 fundamentally different from lines 15–33?
Code
Worksheet
01 __________________________________________________________________
02 __________________________________________________________________
03 __________________________________________________________________
04 __________________________________________________________________
05 __________________________________________________________________
06 __________________________________________________________________
07 __________________________________________________________________
08 __________________________________________________________________
09 __________________________________________________________________
10 __________________________________________________________________
11 __________________________________________________________________
12 __________________________________________________________________
13 __________________________________________________________________
14 __________________________________________________________________
15 __________________________________________________________________
16 __________________________________________________________________
17 __________________________________________________________________
18 __________________________________________________________________
19 __________________________________________________________________
20 __________________________________________________________________
21 __________________________________________________________________
22 __________________________________________________________________
23 __________________________________________________________________
24 __________________________________________________________________
25 __________________________________________________________________
26 __________________________________________________________________
27 __________________________________________________________________
28 __________________________________________________________________
29 __________________________________________________________________
30 __________________________________________________________________
31 __________________________________________________________________
32 __________________________________________________________________
33 __________________________________________________________________
Review
2. Do anonymous blocks execute under the privileges of the System or the current user?
Part A – Match the code snippet with its construct name (Note: There are 3 of each
construct):
a. class
b. method
c. attribute
d. comment
e. constant
f. keyword
1 contactDedupe()
2 ContactDedupe{}
3 CONTACT_DEDUPE
4 Protected
5 contactDedupe
6 // contactDedupe
7 Public
8 ADD_PRODUCT
9 AddProduct{}
10 addProduct()
11 /* addProduct */
12 addProduct
13 // commissionCalc
14 commissionCalc
15 Private
16 COMMISSION_CALC
17 CommissionCalc{}
18 commissionCalc()
Part B – Draw in curly braces around code blocks where needed (or use the file in the
Exercises folder).
01 List<Contact> contactList = new List<Contact>();
02 for(Integer iCounter=0; iCounter <= 5; iCounter++)
03 for(Integer jCounter=0; jCounter <= 10; jCounter++)
04 if(iCounter < jCounter)
05 System.debug('iCounter is less than jCounter');
06 Integer k=iCounter;
07 while(k < jCounter)
08 System.debug('k < jCounter');
09 k++;
10
11
12 else
13 System.debug('iCounter is not less than jCounter');
14
15
16
17 public class ContactCounter
18 public void countSmithContacts(List<Contact> listOfContacts)
19 // the code of the method goes here…
20 Integer smithCounter = 0;
21 for(Contact c : listOfContacts)
22 if(c.lastname=='Smith')
23 smithCounter++;
24 System.debug('Smith #' + smithCounter);
25
26
27
28
Review
1. What are the two ways to write comments into your code? What is the difference
between the two different methods of writing comments?
2. Are the naming conventions used in Part A requirements or are they best practices?
D. If you see the Debug view, navigate to Debug | Switch Perspective | Log Only
(Predefined) to see just the logs.
E. Note the result in the log. If you prefer, select the Debug Only checkbox to filter your
results and only show the output of the System.debug statements. How did it
compare to your guess?
F. Before entering the following in the Execute Anonymous Window, try to guess what
the outcome of the following statements will be. Then click Execute to execute the
code when ready:
Guessed Actual
# Snippet
Outcome? Outcome
2 System.debug(true || false);
3 System.debug(-2 + 2);
4 System.debug('truthi' + 'ness');
5 System.debug('a' == 'a');
6 System.debug('a' != 'aa');
8 System.debug((3*5)>=(30/2));
9 System.debug(!(5*5 == 25));
10 System.debug((5*5 != 25)||(true));
11 System.debug('test' != 'test');
Review
E. What will be output to the log if you execute the code? ______________
F. Click Execute to execute your code, and then close the Execute Anonymous
Window to check the run log.
Review
1. How do we structure our IF control blocks to execute a default block of code when the
IF logic tests all evaluate to false?
2. If, like the exercise, we want to check for all 50 states, do we have to use repetitive IF-
ELSE blocks or can we use a switch/case structure?
1. Create an anonymous block that contains a FOR loop that iterates over an integer from
0 to 6 (i.e., 7 total passes through the loop), and outputs the corresponding day of the
week.
A. Click the Developer Console from the Gear icon.
B. Type CTRL+E to open the Execute Anonymous Window.
C. Copy the code from the 3-5.IteratingWithFORLoops.txt file in the Exercises folder
and paste it into the Execute Anonymous Window (replacing any default text).
D. Complete the TODO: sections as required.
E. Click Execute to execute the code, and then close the Execute Anonymous Window
to view the logs. Do you see all the days of the week in the execution log?
F. To close all open windows, type CTRL+ALT+/.
G. Close the Developer Console and return to your org.
2. Extra Credit: Create an anonymous block of code that uses a loop to calculate and
output the unique Fibonacci numbers less than 100. Fibonacci numbers are: 0, 1, 1, 2,
3, 5, 8, 13, 21, 34, 55, etc.
A. Click the Developer Console from the Gear icon.
B. Type CTRL+E to open the Execute Anonymous Window.
C. Write code to calculate and output the Fibonacci numbers under 100.
D. Click Execute to execute the code, and then close the Execute Anonymous Window
to view the logs.
E. To close all open windows, type CTRL+ALT+/.
F. Close the Developer Console and return to your org.
Review
1. How would we perform the same loop, but count down from 7 to 1 instead?
Exercise 3-5: Branching code with a Switch Statement instead of an IF ELSE construct
Boolean b;
Boolean bIsNull;
if(b == null){
bIsNull = true;
} else {
bIsNull = false;
}
System.debug(bIsNull);
D. Close the Execute Anonymous Window and note the result. How did it compare to
your guess? Now repeat step C, completing the TODOs, for each of the following
code snippets:
i.
/* TODO: Declare a string = 'he' */
/* TODO: Declare a string = 'llo' */
/* TODO: Add the two strings you declared above together into a
variable named s */
Boolean b;
if(s=='hello'){
b = true;
} else {
b = false;
}
System.debug(b);
ii.
Integer i = 1;
Integer j = 2;
while(i < 3){
/* TODO: Set j equal to i multiplied by j */
/* TODO: Increment the i variable by 1 */
}
System.debug('The integer j = ' + j);
Review
D. Close the Execute Anonymous Window and note the result. How did it compare to
your guess? Now repeat step C, completing the TODOs, for each of the following
code snippets:
i.
String myFirstString = 'Hello';
String mySecondString = 'World!';
List<String> myStringList = new List<String>();
myStringList.add(myFirstString);
myStringList.add(mySecondString);
String allTogether = '';
/* TODO: Loop through myStringList by incrementing an
integer variable until it reaches the size of
myStringList */
/* TODO: Inside the loop, retrieve the element from the list
corresponding to the integer variable and add it to the
allTogether variable */
System.debug(allTogether);
ii.
String myFirstString = 'Hello';
String mySecondString = 'World!';
List<String> myStringList = new List<String>();
myStringList.add(myFirstString);
myStringList.add(mySecondString);
String allTogether = '';
/* TODO: Loop through myStringList without using an integer
variable, but instead using a String variable */
/* TODO: Inside the loop, take the current element of the list
and add it to the allTogether variable */
System.debug(allTogether);
Review
1. When we use the add() method to add elements to a List, in what order does the new
element get added?
C. Close the Execute Anonymous Window and note the result. How did it compare to
your guess?
D. Try to make Fido sit and wag his tail, as well.
E. To close all open windows, type CTRL+ALT+/.
F. Close the Developer Console and return to your Salesforce org.
3. Extra Credit: Assign the dog a gender and adjust the wagTail() method to say
'wagging his tail' or 'wagging her tail'. For further extra credit, make
gender an Enum instead of a String.
Review
1. What happens if we change the first line of our anonymous block (step 2-a) to read Dog
myDogFido;?
2. Why does the getStatus() method in the Dog class return a String instead of void?
1. Modify the class named Dog, giving it name and playmate attributes. Update the
play()method to receive a Dog as a parameter and set the playmate attribute equal to
the Dog passed in.
A. Click the Developer Console from the Gear icon.
B. Type CTRL+SHIFT+O to bring up the Open Resource dialog.
C. Type Dog to filter the list, then select the Dog.apxc Apex class and click Open.
D. Copy the code from the 5-2.PassingMethodParameters.txt file in the Exercises folder
and paste it into the Developer Console (replacing any default text).
E. Complete the TODO sections as required.
F. Save the class by typing CTRL+S. Check the Problems tab at the bottom of the
Developer Console to see if you have any errors in your class that prevented the
class from saving to the server.
3. Extra credit: Use the play() method on the dog’s playmate to get the dogs to
play together. Use the 05-2.Extra.PassingMethodParameters.txt and 05-
2.Extra.PassingMethodParameters_ExecuteAnonymous.txt files. Be careful
of infinite loops.
Review
1. What does the this keyword represent when used in the play method?
Review
1. In the one-parameter constructor, is it necessary to use the this keyword to set the
name attribute?
2. What term do we use to describe two or more methods with the same name in a class?
1. Review the sample code below and answer all the review questions.
Code
42 status = 'Sitting';
43 }
44
45 public void play(Dog newPlaymate){
46 status = 'Playing';
47 // need the IF condition to avoid an infinite loop
48 if(playmate != newPlaymate) {
49 playmate = newPlaymate;
50 newPlaymate.play(this);
51 }
52 }
53
54 public void wagTail(){
55 status = 'Wagging Tail';
56 }
57 }
Review
3. Is the name attribute accessible from outside the org of the Dog class? Why?
4. Can an instance of the Dog class be declared outside the application that the Dog class
is a part of if the Dog class’ application is installed in the Salesforce org? Why?
5. What is the outcome of the following code (assume it is run in the Execute Anonymous
window)?
Dog fido = new Dog('Fido');
Dog toby = new Dog('Toby');
fido.playmate = Toby;
6. What is the outcome of the following code (assume it is run in the Execute Anonymous
window)?
Dog fido = new Dog('Fido');
Dog toby = new Dog('Toby');
fido.play(toby);
System.debug(fido.playmate.name);
7. What is the outcome of the following code (assume it is run in the Execute Anonymous
window)?
Dog fido = new Dog('Fido');
Dog toby = new Dog('Toby');
fido.play(toby);
System.debug(fido.getPlaymateName());
8. What is the outcome of the following code (assume it is run in the Execute Anonymous
window)?
Dog fido = new Dog('Fido');
fido.sit();
fido.setColor('Red');
System.debug(fido.status);
System.debug(fido.getColor());
9. What is the outcome of the following code (assume it is run in the Execute Anonymous
window)?
Dog fido = new Dog('Fido');
fido.setColor('Red');
System.debug(fido.getColor());
10. What is the outcome of the following code (assume it is run in the Execute Anonymous
window)?
Dog fido = new Dog();
Dog toby = new Dog('Toby');
fido.play(toby);
String s = toby.getPlaymateName();
System.debug(s);
3. Extra credit: Modify the class and anonymous block to return the Id of the newly
created record:
Review
1. In an sObject, what is accessed on the right side of the dot in dot notation?
Review
2. Consider the code below. How many Database.SaveResult objects are returned?
List<Account> newAccounts = new List<Account>();
Account newAccountOne = new Account(Name='Acme');
newAccounts.add(newAccountOne);
Account newAccountTwo = new Account(Name='XYX Inc.');
newAccounts.add(newAccountTwo);
Database.SaveResult[] results = Database.insert(newAccounts);
System.debug(results.size());
4. Extra credit: Output the list of candidates, including the Id, First Name, and Last Name.
Review
1. If the fields in the SELECT list were replaced with a count() what would be returned?
2. What had to be modified with the query in order for it to work in the class?
Review
Review
2. Why is it important to develop the trigger to handle bulk data from the beginning?
2. Create the JobAppForCandidate trigger (skip this step if the trigger exists).
A. In the Developer Console, navigate to File | New | Apex Trigger.
B. Enter the following information:
i. Name: JobAppForCandidate
ii. sObject: Candidate__c
C. Click Submit.
Review
1. What is prevented by declaring a List object to store and insert all of the modified
records instead of calling Database.Insert each record inside of the FOR loop?
2. Why is the looping done in the createJobAppForCandidate method and not the
trigger, as in the previous exercise?
Review
public JobPostingManager() {
//Default constructor does nothing
}
2. What is missing from the code in this exercise that could help you debug the issues?
3. Test the class and the exception using the anonymous block window.
A. Write a few lines of code using the Execute Anonymous window to call each of the
methods in the ProgrammingLanguageChecker class.
Note: Make sure to catch the ProgrammingLanguageCheckerException.
B. To close all open windows, type CTRL+ALT+/.
C. Close the Developer Console and return to your org.
Review
Review
1. Implicitly, what other “code” that was previously created does this test class test?
2. What are three things that can be added to this test to make it a better test?
1. Authorize your sandbox org to deploy change sets to your production org.
A. Log in to your production org.
B. From the Gear icon, navigate to Setup | Environments | Deploy | Deployment
Settings.
C. Click Continue.
D. In Deployment Connects, click Edit next to the entry for your sandbox org (named
Dev).
E. In the Upload Authorization Direction section, select Allow Inbound Changes.
F. Click Save.
G. Log out of your production organization.
receive an email (sent to the email address specified in your user profile) letting you
know when it has been completed.
Review
You have seen this code before at the beginning of class. You will now take this mini-quiz
again to see what kind of progress you have made in your ability to read and understand
Apex code.
Read the code block on the following page. Fill out the worksheet with your guess as to
what is happening on each corresponding line of code.
Note: The code line numbers correspond with the worksheet line numbers.
Review
1. How is the code in lines 1–14 fundamentally different from lines 15–33?
Code
Worksheet
01 __________________________________________________________________
02 __________________________________________________________________
03 __________________________________________________________________
04 __________________________________________________________________
05 __________________________________________________________________
06 __________________________________________________________________
07 __________________________________________________________________
08 __________________________________________________________________
09 __________________________________________________________________
10 __________________________________________________________________
11 __________________________________________________________________
12 __________________________________________________________________
13 __________________________________________________________________
14 __________________________________________________________________
15 __________________________________________________________________
16 __________________________________________________________________
17 __________________________________________________________________
18 __________________________________________________________________
19 __________________________________________________________________
20 __________________________________________________________________
21 __________________________________________________________________
22 __________________________________________________________________
23 __________________________________________________________________
24 __________________________________________________________________
25 __________________________________________________________________
26 __________________________________________________________________
27 __________________________________________________________________
28 __________________________________________________________________
29 __________________________________________________________________
30 __________________________________________________________________
31 __________________________________________________________________
32 __________________________________________________________________
33 __________________________________________________________________
Overview Instructions:
There are two versions of the UCAutomate and UCAutomateTest files in the Exercises
folder that will guide you through creating all the code—an easier version and a harder one.
Please copy and paste your desired version into the IDE to help you get started.
Create Candidates
Log in to Salesforce and create two Candidates. Confirm that two corresponding
Contacts were created. Create a third Candidate with an email address that matches an
existing Contact. Confirm that there is no corresponding new Contact created for this
Candidate.
The following scenarios should only be completed once all the above steps have been
successfully implemented.
There are many moving parts involved because of the need to send an email to the
associated Interviewer. There are four objects at play: Job_Application__c, Review__c,
Position__c and Interviewer__c.
The code needs to cater for the fact that a Job Application can be made without
specifying a Position. Furthermore, there may very well be Positions without associated
Interviewers. Such Job Applications are assigned to a generic Interviewer.
Finally, an email message needs to be sent to the Interviewer to inform him/her that a
Review has been created. In order to accomplish this, a pre-existing class will be used.
Copy the code from the file 16-2.Email.txt, located in the Exercises folder, into a new class
named Email. Save the class.
Further Considerations:
1. The file 16-2.UCAutomateTestHarder.txt contains two test methods that will fail for the
current UCAutomate class. What adjustments can be made to ensure that these
methods execute successfully?
2. The triggers currently instantiate objects of the UCAutomate class and call methods of
the class using the instantiated object. What considerations should be taken into
account when choosing between this approach and using static methods?
3. The code ensures that a Contact that already contains a new Candidate’s email address
is not duplicated. What changes could be made to the code to cater for many
Candidates being inserted using Dataloader where multiple Candidates share the same
email address?