6

I came across the following code. Is there any reason why it has used used return this?

public class EmailUtil {
       private Messaging.SingleEmailMessage singleEmailMessage;
       private final List<String> toAddresses;

       //optional parameters set to default        
       private String subject = '';
       private String htmlBody = ''; 
       private Boolean useSignature = false;
       private List<Messaging.EmailFileAttachment> fileAttachments = null;
       //defaults to current user's first name + last name
       private String senderDisplayName = UserInfo.getFirstName()+' '+UserInfo.getLastName();
       //get the current user in context
       User currentUser = [Select email from User where username = :UserInfo.getUserName() limit 1];        
       //replyTo defaults to current user's email 
       private String replyTo = currentUser.email;
       private String plainTextBody = '';

       public EmailUtil(List<String> addresses) {
           this.toAddresses = addresses;
       }

       public EmailUtil senderDisplayName(String val) {
           senderDisplayName = val;
           return this;
       }

       public EmailUtil subject(String val) {
           subject = val;
           return this;
       }

       public EmailUtil htmlBody(String val) {
           htmlBody = val;
           return this;
       }

       public EmailUtil useSignature(Boolean bool) {
           useSignature = bool;
           return this;
       }

       public EmailUtil replyTo(String val) {
           replyTo = val;
           return this;
       }

       public EmailUtil plainTextBody(String val) {
           plainTextBody = val;
           return this;
       }

       public EmailUtil fileAttachments(List<Messaging.Emailfileattachment> val) {
           fileAttachments = val;
           return this;
       }

       //where it all comes together
       //this method is private and is called from sendEmail()
       private EmailUtil build() {
           singleEmailMessage = new Messaging.SingleEmailMessage();
           singleEmailMessage.setToAddresses(this.toAddresses);
           singleEmailMessage.setSenderDisplayName(this.senderDisplayName);
           singleEmailMessage.setSubject(this.subject);
           singleEmailMessage.setHtmlBody(this.htmlBody);
           singleEmailMessage.setUseSignature(this.useSignature);
           singleEmailMessage.setReplyTo(this.replyTo);
           singleEmailMessage.setPlainTextBody(this.plainTextBody);
           singleEmailMessage.setFileAttachments(this.fileAttachments);
           return this;
       }

       //send the email message
       public void sendEmail() {
              try {
                  //call build first to create the email message object
                  build();
                  Messaging.sendEmail(new Messaging.SingleEmailMessage[] { singleEmailMessage });
              } catch (Exception ex) {
                  throw new GenericException('There was a problem while calling Messaging.sendEmail()');
              }                
       }    

   } 

Source : http://developer.force.com/cookbook/recipe/email-utility-class

7
  • 1
    I don't see any reason why that's useful to return this. I think that's probably really bad design. All these methods should be void. Commented Jan 24, 2017 at 13:54
  • I agree, I do not see any reason. Can you give an example where return this is useful? Commented Jan 24, 2017 at 13:57
  • 4
    Method chaining - Its a design pattern for a specific type of problem!
    – Raul
    Commented Jan 24, 2017 at 13:59
  • I don't see any problem when calling each method on a new line. That's just developer laziness :D Commented Jan 24, 2017 at 14:03
  • 1
    @MartinLezer Note the link Rahul gave. It's to solve a SPECIFIC type of problem. Note that these are private variables with no setters or getters. VOID methods wouldn't do what you'd expect them to do since the variables haven't been declared as apex properties.
    – crmprogdev
    Commented Jan 24, 2017 at 14:19

2 Answers 2

15

This way you can call your methods "as a flow" to generate an object:

EmailUtil email = new EmailUtil(new String[] {})
  .subject('My subject')
  .htmlBody('my body')
  .senderDisplayName('My name');

Because you return the current object with this you can access it and its methods/attributes.

I personally like this way to do.

9
  • 2
    Wow I never thought of that. That's great. What about performance? Is there any impact possible? Commented Jan 24, 2017 at 13:59
  • Performances are the ~same (depending of the use case)
    – Simonp
    Commented Jan 24, 2017 at 14:03
  • 1
    Ok I will try some tests with this class :D See you in 2 hours. Commented Jan 24, 2017 at 14:04
  • 2
    @MartinLezer Some food for though: premature optimization is the root of all evil.
    – Keith C
    Commented Jan 24, 2017 at 14:08
  • 1
    A good use case for this pattern is (but is not on Salesforce) HTTPRequest setting. It is more readable to do so: HTTPRequest request = new HTTPRequest().setMethod('GET').setEndpoint('www.salesforce.com').setHeader('Xx', 'Yy').setTimeout(2000);
    – Simonp
    Commented Jan 24, 2017 at 15:03
5

It's called Fluent Pattern, and as already mentioned, it enables chaining. You can see it demonstrated in the Composite pattern in Apex Design Patterns.

It's worth reading the excellent answers on Why Would I Not Enable Chaining? for a deeper dive into the impact, but it's incredibly useful for building data. For example, I use it in my SObjectFactory library to simplify specification of multiple fields.

List<Opportunity> records = new SObjectBuilder(Opportunity.sObjectType)
    .put (Opportunity.AccountId, SObjectFactory.provideGenericParent(Account.sObjectType))
    .put(Opportunity.CloseDate, Date.today())
    .count (Limits.getLimitQueries() + 1)
    .create().getRecords();

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .